lda-sieve-plugin.c [plain text]
#include "lib.h"
#include "array.h"
#include "home-expand.h"
#include "eacces-error.h"
#include "mail-storage.h"
#include "mail-deliver.h"
#include "mail-user.h"
#include "duplicate.h"
#include "smtp-client.h"
#include "mail-send.h"
#include "lda-settings.h"
#include "sieve.h"
#include "sieve-script.h"
#include "sieve-script-file.h"
#include "lda-sieve-plugin.h"
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#define LDA_SIEVE_DEFAULT_LOCATION "~/.dovecot.sieve"
#define LDA_SIEVE_MAX_USER_ERRORS 30
static deliver_mail_func_t *next_deliver_mail;
static const char *lda_sieve_get_setting
(void *context, const char *identifier)
{
struct mail_deliver_context *mdctx = (struct mail_deliver_context *)context;
const char *value = NULL;
if ( mdctx == NULL )
return NULL;
if ( mdctx->dest_user == NULL ||
(value=mail_user_plugin_getenv(mdctx->dest_user, identifier)) == NULL ) {
if ( strcmp(identifier, "recipient_delimiter") == 0 )
value = mdctx->set->recipient_delimiter;
}
return value;
}
static const struct sieve_callbacks lda_sieve_callbacks = {
NULL,
lda_sieve_get_setting
};
static void *lda_sieve_smtp_open
(const struct sieve_script_env *senv, const char *destination,
const char *return_path, struct ostream **output_r)
{
struct mail_deliver_context *dctx =
(struct mail_deliver_context *) senv->script_context;
return (void *)smtp_client_open
(dctx->set, destination, return_path, output_r);
}
static bool lda_sieve_smtp_close
(const struct sieve_script_env *senv ATTR_UNUSED, void *handle)
{
struct smtp_client *smtp_client = (struct smtp_client *) handle;
return ( smtp_client_close(smtp_client) == 0 );
}
static int lda_sieve_reject_mail
(const struct sieve_script_env *senv, const char *recipient,
const char *reason)
{
struct mail_deliver_context *dctx =
(struct mail_deliver_context *) senv->script_context;
return mail_send_rejection(dctx, recipient, reason);
}
static int lda_sieve_duplicate_check
(const struct sieve_script_env *senv, const void *id, size_t id_size)
{
struct mail_deliver_context *dctx =
(struct mail_deliver_context *) senv->script_context;
return duplicate_check(dctx->dup_ctx, id, id_size, senv->user->username);
}
static void lda_sieve_duplicate_mark
(const struct sieve_script_env *senv, const void *id, size_t id_size,
time_t time)
{
struct mail_deliver_context *dctx =
(struct mail_deliver_context *) senv->script_context;
duplicate_mark(dctx->dup_ctx, id, id_size, senv->user->username, time);
}
struct lda_sieve_run_context {
struct sieve_instance *svinst;
struct mail_deliver_context *mdctx;
const char *home_dir;
struct sieve_script **scripts;
unsigned int script_count;
struct sieve_script *user_script;
struct sieve_script *main_script;
const struct sieve_message_data *msgdata;
const struct sieve_script_env *scriptenv;
struct sieve_error_handler *user_ehandler;
struct sieve_error_handler *master_ehandler;
const char *userlog;
};
static const char *lda_sieve_get_personal_location
(struct sieve_instance *svinst, struct mail_user *user)
{
const char *script_location;
script_location = mail_user_plugin_getenv(user, "sieve");
if (script_location != NULL) {
if (*script_location == '\0') {
if ( user->mail_debug )
sieve_sys_debug(svinst, "empty script location, disabled");
return NULL;
}
} else {
script_location = LDA_SIEVE_DEFAULT_LOCATION;
}
return script_location;
}
static const char *lda_sieve_get_default_location
(struct mail_user *user)
{
const char *script_location;
script_location = mail_user_plugin_getenv(user, "sieve_default");
if ( script_location == NULL ) {
script_location = mail_user_plugin_getenv(user, "sieve_global_path");
}
return script_location;
}
static int lda_sieve_multiscript_get_scripts
(struct sieve_instance *svinst, const char *label, const char *location,
struct sieve_error_handler *ehandler, ARRAY_TYPE(sieve_scripts) *scripts,
enum sieve_error *error_r)
{
struct sieve_directory *sdir;
ARRAY_TYPE(const_string) script_files;
const char *const *files;
unsigned int count, i;
const char *file;
if ( (sdir=sieve_directory_open(svinst, location, error_r)) == NULL )
return ( *error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1 );
t_array_init(&script_files, 16);
while ( (file=sieve_directory_get_scriptfile(sdir)) != NULL ) {
files = array_get(&script_files, &count);
for ( i = 0; i < count; i++ ) {
if ( strcmp(file, files[i]) < 0 )
break;
}
if ( i == count )
array_append(&script_files, &file, 1);
else
array_insert(&script_files, i, &file, 1);
}
sieve_directory_close(&sdir);
files = array_get(&script_files, &count);
for ( i = 0; i < count; i++ ) {
struct sieve_script *script = sieve_script_create_open
(svinst, files[i], NULL, ehandler, error_r);
if ( script == NULL ) {
switch ( *error_r ) {
case SIEVE_ERROR_NOT_FOUND:
sieve_sys_warning(svinst,
"%s script %s doesn't exist", label, files[i]);
break;
case SIEVE_ERROR_TEMP_FAILURE:
sieve_sys_error(svinst,
"failed to access %s script %s (temporary failure)",
label, files[i]);
return -1;
default:
sieve_sys_error(svinst,
"failed to access %s script %s", label, files[i]);
break;
}
continue;
}
array_append(scripts, &script, 1);
}
*error_r = SIEVE_ERROR_NONE;
return 1;
}
static void lda_sieve_binary_save
(struct lda_sieve_run_context *srctx, struct sieve_binary *sbin,
struct sieve_script *script)
{
enum sieve_error error;
if ( sieve_save(sbin, FALSE, &error) < 0 &&
error == SIEVE_ERROR_NO_PERMISSION && script != srctx->user_script ) {
sieve_sys_error(srctx->svinst,
"the lda sieve plugin does not have permission "
"to save global sieve script binaries; "
"global sieve scripts like %s need to be "
"pre-compiled using the sievec tool", sieve_script_location(script));
}
}
static struct sieve_binary *lda_sieve_open
(struct lda_sieve_run_context *srctx, struct sieve_script *script,
enum sieve_compile_flags cpflags, bool recompile, enum sieve_error *error_r)
{
struct sieve_instance *svinst = srctx->svinst;
struct sieve_error_handler *ehandler;
struct sieve_binary *sbin;
bool debug = srctx->mdctx->dest_user->mail_debug;
const char *compile_name = "compile";
if ( recompile ) {
sieve_sys_warning(svinst,
"encountered corrupt binary: re-compiling script %s",
sieve_script_location(script));
compile_name = "re-compile";
} else if ( debug ) {
sieve_sys_debug(svinst,
"loading script %s", sieve_script_location(script));
}
if ( script == srctx->user_script )
ehandler = srctx->user_ehandler;
else
ehandler = srctx->master_ehandler;
sieve_error_handler_reset(ehandler);
if ( recompile )
sbin = sieve_compile_script(script, ehandler, cpflags, error_r);
else
sbin = sieve_open_script(script, ehandler, cpflags, error_r);
if ( sbin == NULL ) {
switch ( *error_r ) {
case SIEVE_ERROR_NOT_FOUND:
if ( debug ) {
sieve_sys_debug(svinst, "script file %s is missing for %s",
sieve_script_location(script), compile_name);
}
break;
case SIEVE_ERROR_TEMP_FAILURE:
sieve_sys_error(svinst,
"failed to open script %s for %s (temporary failure)",
sieve_script_location(script), compile_name);
break;
case SIEVE_ERROR_NOT_VALID:
if (script == srctx->user_script && srctx->userlog != NULL ) {
sieve_sys_info(svinst, "failed to %s script %s "
"(view user logfile %s for more information)",
compile_name, sieve_script_location(script), srctx->userlog);
break;
}
sieve_sys_error(svinst, "failed to %s script %s",
compile_name, sieve_script_location(script));
break;
default:
sieve_sys_error(svinst, "failed to open script %s for %s",
sieve_script_location(script), compile_name);
break;
}
return NULL;
}
if (!recompile)
lda_sieve_binary_save(srctx, sbin, script);
return sbin;
}
static int lda_sieve_handle_exec_status
(struct lda_sieve_run_context *srctx, struct sieve_script *script, int status)
{
struct sieve_instance *svinst = srctx->svinst;
struct mail_deliver_context *mdctx = srctx->mdctx;
struct sieve_exec_status *estatus = srctx->scriptenv->exec_status;
const char *userlog_notice = "";
sieve_sys_error_func_t error_func, user_error_func;
enum mail_error mail_error = MAIL_ERROR_NONE;
int ret;
error_func = user_error_func = sieve_sys_error;
if ( estatus != NULL && estatus->last_storage != NULL ) {
mail_storage_get_last_error(estatus->last_storage, &mail_error);
if ( mail_error == MAIL_ERROR_NOSPACE ) {
error_func = sieve_sys_info;
user_error_func = sieve_sys_info;
}
}
if ( script == srctx->user_script && srctx->userlog != NULL ) {
userlog_notice = t_strdup_printf
(" (user logfile %s may reveal additional details)", srctx->userlog);
user_error_func = sieve_sys_info;
}
switch ( status ) {
case SIEVE_EXEC_FAILURE:
user_error_func(svinst,
"execution of script %s failed, but implicit keep was successful%s",
sieve_script_location(script), userlog_notice);
ret = 1;
break;
case SIEVE_EXEC_TEMP_FAILURE:
error_func(svinst,
"execution of script %s was aborted due to temporary failure%s",
sieve_script_location(script), userlog_notice);
if ( mail_error != MAIL_ERROR_TEMP && mdctx->tempfail_error == NULL ) {
mdctx->tempfail_error =
"Execution of Sieve filters was aborted due to temporary failure";
}
ret = -1;
break;
case SIEVE_EXEC_BIN_CORRUPT:
sieve_sys_error(svinst,
"!!BUG!!: binary compiled from %s is still corrupt; "
"bailing out and reverting to default delivery",
sieve_script_location(script));
ret = -1;
break;
case SIEVE_EXEC_KEEP_FAILED:
error_func(svinst,
"execution of script %s failed with unsuccessful implicit keep%s",
sieve_script_location(script), userlog_notice);
ret = -1;
break;
default:
ret = status > 0 ? 1 : -1;
break;
}
return ret;
}
static int lda_sieve_singlescript_execute
(struct lda_sieve_run_context *srctx)
{
struct sieve_instance *svinst = srctx->svinst;
struct sieve_script *script = srctx->scripts[0];
bool user_script = ( script == srctx->user_script );
struct sieve_error_handler *ehandler;
struct sieve_binary *sbin;
bool debug = srctx->mdctx->dest_user->mail_debug;
enum sieve_compile_flags cpflags = 0;
enum sieve_runtime_flags rtflags = 0;
enum sieve_error error;
int ret;
if ( user_script ) {
cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL;
rtflags |= SIEVE_RUNTIME_FLAG_NOGLOBAL;
ehandler = srctx->user_ehandler;
} else {
ehandler = srctx->master_ehandler;
}
sbin = lda_sieve_open(srctx, script, cpflags, FALSE, &error);
if ( sbin == NULL ) {
switch ( error ) {
case SIEVE_ERROR_NOT_FOUND:
return 0;
case SIEVE_ERROR_TEMP_FAILURE:
return lda_sieve_handle_exec_status
(srctx, script, SIEVE_EXEC_TEMP_FAILURE);
default:
return -1;
}
}
if ( debug )
sieve_sys_debug(svinst, "executing script from %s", sieve_get_source(sbin));
ret = sieve_execute
(sbin, srctx->msgdata, srctx->scriptenv, ehandler, rtflags, NULL);
if ( ret == SIEVE_EXEC_BIN_CORRUPT && sieve_is_loaded(sbin) ) {
sieve_close(&sbin);
sbin = lda_sieve_open(srctx, script, cpflags, TRUE, &error);
if ( sbin == NULL ) {
switch ( error ) {
case SIEVE_ERROR_NOT_FOUND:
return 0;
case SIEVE_ERROR_TEMP_FAILURE:
return lda_sieve_handle_exec_status
(srctx, script, SIEVE_EXEC_TEMP_FAILURE);
default:
return -1;
}
}
if ( debug )
sieve_sys_debug
(svinst, "executing script from %s", sieve_get_source(sbin));
ret = sieve_execute
(sbin, srctx->msgdata, srctx->scriptenv, ehandler, rtflags, NULL);
if ( ret != SIEVE_EXEC_BIN_CORRUPT )
lda_sieve_binary_save(srctx, sbin, script);
}
sieve_close(&sbin);
return lda_sieve_handle_exec_status(srctx, script, ret);
}
static int lda_sieve_multiscript_execute
(struct lda_sieve_run_context *srctx)
{
struct sieve_instance *svinst = srctx->svinst;
struct sieve_script *const *scripts = srctx->scripts;
unsigned int count = srctx->script_count;
struct sieve_multiscript *mscript;
struct sieve_error_handler *ehandler = srctx->master_ehandler;
bool debug = srctx->mdctx->dest_user->mail_debug;
struct sieve_script *last_script = NULL;
bool user_script = FALSE, more = TRUE, compile_error = FALSE;
enum sieve_error error;
unsigned int i;
int ret;
mscript = sieve_multiscript_start_execute
(svinst, srctx->msgdata, srctx->scriptenv);
for ( i = 0; i < count && more; i++ ) {
struct sieve_binary *sbin = NULL;
struct sieve_script *script = scripts[i];
enum sieve_compile_flags cpflags = 0;
enum sieve_runtime_flags rtflags = 0;
bool final = ( i == count - 1 );
user_script = ( script == srctx->user_script );
last_script = script;
if ( user_script ) {
cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL;
rtflags |= SIEVE_RUNTIME_FLAG_NOGLOBAL;
ehandler = srctx->user_ehandler;
} else {
ehandler = srctx->master_ehandler;
}
if ( debug ) {
sieve_sys_debug
(svinst, "opening script %d of %d from %s", i+1, count,
sieve_script_location(script));
}
sbin = lda_sieve_open(srctx, script, cpflags, FALSE, &error);
if ( sbin == NULL ) {
compile_error = TRUE;
break;
}
if ( debug ) {
sieve_sys_debug
(svinst, "executing script from %s", sieve_get_source(sbin));
}
more = sieve_multiscript_run(mscript, sbin, ehandler, rtflags, final);
if ( !more ) {
if ( sieve_multiscript_status(mscript) == SIEVE_EXEC_BIN_CORRUPT &&
sieve_is_loaded(sbin) ) {
sieve_close(&sbin);
sbin = lda_sieve_open(srctx, script, cpflags, TRUE, &error);
if ( sbin == NULL ) {
compile_error = TRUE;
break;
}
more = sieve_multiscript_run(mscript, sbin, ehandler, rtflags, final);
if ( more &&
sieve_multiscript_status(mscript) != SIEVE_EXEC_BIN_CORRUPT ) {
lda_sieve_binary_save(srctx, sbin, script);
}
}
}
sieve_close(&sbin);
}
if ( compile_error && error == SIEVE_ERROR_TEMP_FAILURE )
ret = sieve_multiscript_tempfail(&mscript, ehandler);
else
ret = sieve_multiscript_finish(&mscript, ehandler, NULL);
if ( compile_error && ret == SIEVE_EXEC_FAILURE ) {
sieve_sys_info(svinst,
"aborted script execution sequence with successful implicit keep");
return 1;
}
return lda_sieve_handle_exec_status(srctx, last_script, ret);
}
static int lda_sieve_find_scripts(struct lda_sieve_run_context *srctx)
{
struct mail_deliver_context *mdctx = srctx->mdctx;
struct sieve_instance *svinst = srctx->svinst;
struct sieve_error_handler *master_ehandler = srctx->master_ehandler;
const char *user_location, *default_location, *sieve_before, *sieve_after;
const char *setting_name;
enum sieve_error error;
ARRAY_TYPE(sieve_scripts) script_sequence;
struct sieve_script *const *scripts;
bool debug = mdctx->dest_user->mail_debug;
unsigned int after_index, count, i;
int ret = 1;
user_location = lda_sieve_get_personal_location(svinst, mdctx->dest_user);
if ( user_location != NULL ) {
srctx->user_script = sieve_script_create_open_as
(svinst, user_location, "main script", master_ehandler, &error);
if ( srctx->user_script == NULL ) {
switch ( error ) {
case SIEVE_ERROR_NOT_FOUND:
if ( debug ) {
sieve_sys_debug(svinst, "user's script %s doesn't exist "
"(trying default script location instead)", user_location);
}
break;
case SIEVE_ERROR_TEMP_FAILURE:
sieve_sys_error(svinst,
"failed to access user's Sieve script %s (temporary failure)",
user_location);
ret = -1;
break;
default:
sieve_sys_error(svinst,
"failed to access user's Sieve script %s "
"(trying default script location instead)",
user_location);
break;
}
} else {
srctx->main_script = srctx->user_script;
}
}
if ( ret >= 0 && srctx->user_script == NULL ) {
default_location = lda_sieve_get_default_location(mdctx->dest_user);
if ( default_location != NULL ) {
srctx->main_script = sieve_script_create_open_as
(svinst, default_location, "main script", master_ehandler, &error);
if ( srctx->main_script == NULL ) {
switch ( error ) {
case SIEVE_ERROR_NOT_FOUND:
if ( debug ) {
sieve_sys_debug(svinst, "default user script %s doesn't exist",
default_location);
}
break;
case SIEVE_ERROR_TEMP_FAILURE:
sieve_sys_error(svinst,
"failed to access default user script %s (temporary failure)",
default_location);
ret = -1;
break;
default:
sieve_sys_error(svinst, "failed to access default user script %s",
default_location);
break;
}
}
} else {
sieve_sys_debug(svinst, "no default script configured for user");
}
}
if ( debug && ret >= 0 && srctx->main_script == NULL ) {
sieve_sys_debug(svinst,
"user has no valid location for a personal script");
}
t_array_init(&script_sequence, 16);
if ( ret >= 0 ) {
i = 2;
setting_name = "sieve_before";
sieve_before = mail_user_plugin_getenv(mdctx->dest_user, setting_name);
while ( ret >= 0 && sieve_before != NULL && *sieve_before != '\0' ) {
ret = lda_sieve_multiscript_get_scripts(svinst, setting_name,
sieve_before, master_ehandler, &script_sequence, &error);
if ( ret < 0 && error == SIEVE_ERROR_TEMP_FAILURE ) {
ret = -1;
break;
} else if (ret == 0 && debug ) {
sieve_sys_debug(svinst, "%s location not found: %s",
setting_name, sieve_before);
}
ret = 0;
setting_name = t_strdup_printf("sieve_before%u", i++);
sieve_before = mail_user_plugin_getenv(mdctx->dest_user, setting_name);
}
if ( ret >= 0 && debug ) {
scripts = array_get(&script_sequence, &count);
for ( i = 0; i < count; i ++ ) {
sieve_sys_debug(svinst,
"executed before user's personal Sieve script(%d): %s",
i+1, sieve_script_location(scripts[i]));
}
}
}
if ( srctx->main_script != NULL ) {
array_append(&script_sequence, &srctx->main_script, 1);
if ( ret >= 0 && debug ) {
sieve_sys_debug(svinst,
"using the following location for user's Sieve script: %s",
sieve_script_location(srctx->main_script));
}
}
after_index = array_count(&script_sequence);
if ( ret >= 0 ) {
i = 2;
setting_name = "sieve_after";
sieve_after = mail_user_plugin_getenv(mdctx->dest_user, setting_name);
while ( sieve_after != NULL && *sieve_after != '\0' ) {
ret = lda_sieve_multiscript_get_scripts(svinst, setting_name,
sieve_after, master_ehandler, &script_sequence, &error);
if ( ret < 0 && error == SIEVE_ERROR_TEMP_FAILURE ) {
ret = -1;
break;
} else if (ret == 0 && debug ) {
sieve_sys_debug(svinst, "%s location not found: %s",
setting_name, sieve_after);
}
ret = 0;
setting_name = t_strdup_printf("sieve_after%u", i++);
sieve_after = mail_user_plugin_getenv(mdctx->dest_user, setting_name);
}
if ( ret >= 0 && debug ) {
scripts = array_get(&script_sequence, &count);
for ( i = after_index; i < count; i ++ ) {
sieve_sys_debug(svinst, "executed after user's Sieve script(%d): %s",
i+1, sieve_script_location(scripts[i]));
}
}
}
if (ret < 0) {
mdctx->tempfail_error =
"Temporarily unable to access necessary Sieve scripts";
}
srctx->scripts =
array_get_modifiable(&script_sequence, &srctx->script_count);
return ret;
}
static int lda_sieve_execute
(struct lda_sieve_run_context *srctx, struct mail_storage **storage_r)
{
struct mail_deliver_context *mdctx = srctx->mdctx;
struct sieve_instance *svinst = srctx->svinst;
struct sieve_message_data msgdata;
struct sieve_script_env scriptenv;
struct sieve_exec_status estatus;
bool debug = mdctx->dest_user->mail_debug;
int ret;
if ( srctx->script_count == 0 ) {
if ( debug ) {
sieve_sys_debug(svinst,
"no scripts to execute: reverting to default delivery.");
}
ret = 0;
} else {
if ( srctx->user_script != NULL ) {
const char *log_path = NULL;
if ( (log_path=mail_user_plugin_getenv
(mdctx->dest_user, "sieve_user_log")) == NULL ) {
const char *path;
if ( (path=sieve_file_script_get_path(srctx->user_script)) == NULL ) {
if ( srctx->home_dir != NULL ) {
log_path = t_strconcat
(srctx->home_dir, "/.dovecot.sieve.log", NULL);
}
} else {
log_path = t_strconcat(path, ".log", NULL);
}
} else if ( srctx->home_dir != NULL ) {
if ( log_path[0] == '~' ) {
log_path = home_expand_tilde(log_path, srctx->home_dir);
} else if ( log_path[0] != '/' ) {
log_path = t_strconcat(srctx->home_dir, "/", log_path, NULL);
}
}
if ( log_path != NULL ) {
srctx->userlog = log_path;
srctx->user_ehandler = sieve_logfile_ehandler_create
(svinst, srctx->userlog, LDA_SIEVE_MAX_USER_ERRORS);
}
}
memset(&msgdata, 0, sizeof(msgdata));
msgdata.mail = mdctx->src_mail;
msgdata.return_path = mail_deliver_get_return_address(mdctx);
msgdata.orig_envelope_to = mdctx->dest_addr;
msgdata.final_envelope_to = mdctx->final_dest_addr;
msgdata.auth_user = mdctx->dest_user->username;
(void)mail_get_first_header(msgdata.mail, "Message-ID", &msgdata.id);
srctx->msgdata = &msgdata;
memset(&scriptenv, 0, sizeof(scriptenv));
memset(&estatus, 0, sizeof(estatus));
scriptenv.action_log_format = mdctx->set->deliver_log_format;
scriptenv.default_mailbox = mdctx->dest_mailbox_name;
scriptenv.mailbox_autocreate = mdctx->set->lda_mailbox_autocreate;
scriptenv.mailbox_autosubscribe = mdctx->set->lda_mailbox_autosubscribe;
scriptenv.user = mdctx->dest_user;
scriptenv.postmaster_address = mdctx->set->postmaster_address;
scriptenv.smtp_open = lda_sieve_smtp_open;
scriptenv.smtp_close = lda_sieve_smtp_close;
scriptenv.duplicate_mark = lda_sieve_duplicate_mark;
scriptenv.duplicate_check = lda_sieve_duplicate_check;
scriptenv.reject_mail = lda_sieve_reject_mail;
scriptenv.script_context = (void *) mdctx;
scriptenv.exec_status = &estatus;
srctx->scriptenv = &scriptenv;
if ( srctx->script_count == 1 )
ret = lda_sieve_singlescript_execute(srctx);
else
ret = lda_sieve_multiscript_execute(srctx);
mdctx->tried_default_save = estatus.tried_default_save;
*storage_r = estatus.last_storage;
}
return ret;
}
static int lda_sieve_deliver_mail
(struct mail_deliver_context *mdctx, struct mail_storage **storage_r)
{
struct lda_sieve_run_context srctx;
bool debug = mdctx->dest_user->mail_debug;
struct sieve_environment svenv;
unsigned int i;
int ret = 0;
memset(&srctx, 0, sizeof(srctx));
srctx.mdctx = mdctx;
(void)mail_user_get_home(mdctx->dest_user, &srctx.home_dir);
memset((void*)&svenv, 0, sizeof(svenv));
svenv.username = mdctx->dest_user->username;
svenv.home_dir = srctx.home_dir;
svenv.hostname = mdctx->set->hostname;
svenv.base_dir = mdctx->dest_user->set->base_dir;
svenv.flags = SIEVE_FLAG_HOME_RELATIVE;
svenv.location = SIEVE_ENV_LOCATION_MDA;
svenv.delivery_phase = SIEVE_DELIVERY_PHASE_DURING;
srctx.svinst = sieve_init(&svenv, &lda_sieve_callbacks, mdctx, debug);
srctx.master_ehandler =
sieve_master_ehandler_create(srctx.svinst, mdctx->session_id, 0);
sieve_system_ehandler_set(srctx.master_ehandler);
sieve_error_handler_accept_infolog(srctx.master_ehandler, TRUE);
sieve_error_handler_accept_debuglog(srctx.master_ehandler, debug);
*storage_r = NULL;
T_BEGIN {
if (lda_sieve_find_scripts(&srctx) < 0)
ret = -1;
else
ret = lda_sieve_execute(&srctx, storage_r);
} T_END;
for ( i = 0; i < srctx.script_count; i++ )
sieve_script_unref(&srctx.scripts[i]);
if ( srctx.user_ehandler != NULL )
sieve_error_handler_unref(&srctx.user_ehandler);
sieve_error_handler_unref(&srctx.master_ehandler);
sieve_deinit(&srctx.svinst);
return ret;
}
const char *sieve_plugin_version = DOVECOT_ABI_VERSION;
const char sieve_plugin_binary_dependency[] = "lda lmtp";
void sieve_plugin_init(void)
{
next_deliver_mail = mail_deliver_hook_set(lda_sieve_deliver_mail);
}
void sieve_plugin_deinit(void)
{
mail_deliver_hook_set(next_deliver_mail);
}