From a8c1aca00c5c43e170b7b32fbce74a6cc2596cdf Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sat, 25 Jul 2009 20:12:18 +0200 Subject: [PATCH] Sieve-filter: implemented expunging filtered messages in the source folder (move). --- src/lib-sieve/sieve-actions.c | 2 + src/lib-sieve/sieve-types.h | 5 +++ src/sieve-tools/sieve-filter.c | 75 +++++++++++++++++++++++++--------- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index fb7a67cad..f3882f572 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -456,6 +456,8 @@ static bool act_store_commit return TRUE; } else if ( trans->redundant ) { act_store_log_status(trans, aenv, FALSE, status); + aenv->exec_status->did_redundant_save = TRUE; + aenv->exec_status->message_saved = TRUE; return TRUE; } diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h index eebeabf4a..67938fde5 100644 --- a/src/lib-sieve/sieve-types.h +++ b/src/lib-sieve/sieve-types.h @@ -18,6 +18,10 @@ struct sieve_script; struct sieve_binary; +struct sieve_message_data; +struct sieve_script_env; +struct sieve_exec_status; + /* * Message data * @@ -87,6 +91,7 @@ struct sieve_exec_status { bool message_saved; bool message_forwarded; bool tried_default_save; + bool did_redundant_save; struct mail_storage *last_storage; }; diff --git a/src/sieve-tools/sieve-filter.c b/src/sieve-tools/sieve-filter.c index 8c41ce5f3..cd518e35e 100644 --- a/src/sieve-tools/sieve-filter.c +++ b/src/sieve-tools/sieve-filter.c @@ -39,20 +39,26 @@ static void print_help(void) static int filter_message (struct mail *mail, struct sieve_binary *main_sbin, struct sieve_script_env *senv, struct sieve_error_handler *ehandler, - const char *user) + bool move) { + struct sieve_exec_status estatus; struct sieve_binary *sbin; struct sieve_message_data msgdata; const char *recipient, *sender; + int ret; sieve_tool_get_envelope_data(mail, &recipient, &sender); + /* Initialize execution status */ + memset(&estatus, 0, sizeof(estatus)); + senv->exec_status = &estatus; + /* Collect necessary message data */ memset(&msgdata, 0, sizeof(msgdata)); msgdata.mail = mail; msgdata.return_path = sender; msgdata.to_address = recipient; - msgdata.auth_user = user; + msgdata.auth_user = senv->username; (void)mail_get_first_header(mail, "Message-ID", &msgdata.id); /* Single script */ @@ -60,28 +66,51 @@ static int filter_message main_sbin = NULL; /* Execute script */ - return sieve_execute(sbin, &msgdata, senv, ehandler, NULL); + ret = sieve_execute(sbin, &msgdata, senv, ehandler, NULL); + + if ( ret > 0 && move && !estatus.did_redundant_save ) { + sieve_info(ehandler, NULL, "message removed from source folder"); + mail_expunge(mail); + } + + return ret; +} + +/* FIXME: introduce this into Dovecot */ +static void mail_search_build_add_flags +(struct mail_search_args *args, enum mail_flags flags, bool not) +{ + struct mail_search_arg *arg; + + arg = p_new(args->pool, struct mail_search_arg, 1); + arg->type = SEARCH_FLAGS; + arg->value.flags = flags; + arg->not = not; + + arg->next = args->args; + args->args = arg; } static int filter_mailbox (struct mailbox *box, struct sieve_binary *main_sbin, struct sieve_script_env *senv, struct sieve_error_handler *ehandler, - const char *user) + bool move) { struct mail_search_args *search_args; + struct mail_search_arg *sarg; struct mailbox_transaction_context *t; struct mail_search_context *search_ctx; struct mail *mail; int ret = 1; + /* Search non-deleted messages in the indicated folder */ + search_args = mail_search_build_init(); - mail_search_build_add_all(search_args); + mail_search_build_add_flags(search_args, MAIL_DELETED, TRUE); + + /* Iterate through all requested messages */ - if ( mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST, 0, NULL) < 0 ) { - i_fatal("sync failed"); - } - - t = mailbox_transaction_begin(box, 0); + t = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_REFRESH); search_ctx = mailbox_search_init(t, search_args, NULL); mail_search_args_unref(&search_args); @@ -90,12 +119,14 @@ static int filter_mailbox const char *subject, *date; uoff_t size = 0; + /* Request message size */ if ( mail_get_virtual_size(mail, &size) < 0 ) { if ( mail->expunged ) continue; - i_fatal("failed to obtain message size"); + sieve_error(ehandler, NULL, "failed to obtain message size"); + continue; } (void)mail_get_first_header(mail, "date", &date); @@ -104,25 +135,30 @@ static int filter_mailbox if ( subject == NULL ) subject = ""; if ( date == NULL ) date = ""; - i_info("filering: [%s; %"PRIuUOFF_T" bytes] %s\n", date, size, subject); + sieve_info(ehandler, NULL, + "filtering: [%s; %"PRIuUOFF_T" bytes] %s", date, size, subject); - ret = filter_message(mail, main_sbin, senv, ehandler, user); + ret = filter_message(mail, main_sbin, senv, ehandler, move); } mail_free(&mail); + /* Cleanup */ + if ( mailbox_search_deinit(&search_ctx) < 0 ) { - i_error("failed to deinit search"); + ret = -1; } if ( mailbox_transaction_commit(&t) < 0 ) { - i_fatal("failed to commit transaction"); + ret = -1; } + + /* Synchronize mailbox */ if ( mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST, 0, NULL) < 0 ) { - i_fatal("sync failed"); + ret = -1; } - return FALSE; + return ret; } /* @@ -138,7 +174,6 @@ int main(int argc, char **argv) struct mail_user *mail_user = NULL; struct sieve_binary *main_sbin; struct sieve_script_env scriptenv; - struct sieve_exec_status estatus; struct sieve_error_handler *ehandler; struct mail_storage *dst_storage, *src_storage; struct mailbox *src_box; @@ -277,10 +312,10 @@ int main(int argc, char **argv) scriptenv.duplicate_mark = NULL; scriptenv.duplicate_check = NULL; scriptenv.trace_stream = NULL; - scriptenv.exec_status = &estatus; /* Apply Sieve filter to all messages found */ - filter_mailbox(src_box, main_sbin, &scriptenv, ehandler, user); + (void) filter_mailbox + (src_box, main_sbin, &scriptenv, ehandler, ( dst_ns == src_ns )); /* Close the mailbox */ if ( src_box != NULL ) -- GitLab