diff --git a/TODO b/TODO index 8243e4ca5260d89993249d48c4906eb56c17fbd5..b7f0e6a0f2a2471cc82340f8f5ec8034cf77749b 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,6 @@ Next (in order of descending priority/precedence): * Improve debugging and error handling: - Variables: dump variable identifiers in stead of storage indexes * Make sure cmusieve can be replaced seamlessly with the new plugin. - - Fileinto must optionally create missing folders. * Final issues: - Fix amd64 logging segfault - Fix/Report issues listed in 'doc/rfc/RFC Controversy.txt' diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index 88dc8f3d13d62c7544d0892cbc7065ec169328f3..77c6ad5db3cb3111214c2d87a543bff3298a27ce 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -115,12 +115,8 @@ static int cmd_keep_operation_execute sieve_runtime_trace(renv, "KEEP action"); /* Add store action (sieve-actions.h) to result */ - if ( renv->scriptenv != NULL && renv->scriptenv->inbox != NULL ) - ret = sieve_act_store_add_to_result - (renv, slist, renv->scriptenv->inbox, source_line); - else - ret = sieve_act_store_add_to_result - (renv, slist, "INBOX", source_line); + ret = sieve_act_store_add_to_result + (renv, slist, SIEVE_SCRIPT_DEFAULT_MAILBOX(renv->scriptenv), source_line); return ( ret >= 0 ); } diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 5f6393bcc6925a97764607fa5d536e55af23ac6a..ddd500d53e8c48e0b02a83ec2bf9e2b40d974990 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -340,6 +340,9 @@ static bool act_redirect_commit sieve_result_log(aenv, "forwarded to <%s>", str_sanitize(ctx->to_address, 128)); + /* Indicate that message was successfully forwarded */ + aenv->estatus->message_forwarded = TRUE; + /* Cancel implicit keep */ *keep = FALSE; diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index c9224c0ef5188f6ebb590984538d8ba03869323f..621e3691873017d18935102dca6333d61198d36e 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -506,7 +506,7 @@ bool ext_include_execute_include /* Activate and start the top-level included script */ result = ( sieve_interpreter_start (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, renv->result, - &interrupted) == 1 ); + renv->estatus, &interrupted) == 1 ); } else result = SIEVE_EXEC_BIN_CORRUPT; } @@ -567,7 +567,7 @@ bool ext_include_execute_include curctx->returned = FALSE; result = ( sieve_interpreter_start (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, - renv->result, &interrupted) == 1 ); + renv->result, renv->estatus, &interrupted) == 1 ); } else result = SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 57b118b75f963442c43f23bc03041672dfc46165..69170df78bd8491cbac974e215b69bcdddc42130 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -216,6 +216,11 @@ static bool act_store_execute if ( trans == NULL || trans->namespace == NULL || trans->box == NULL ) return FALSE; + + /* Mark attempt to store in default mailbox */ + if ( strcmp(trans->context->folder, + SIEVE_SCRIPT_DEFAULT_MAILBOX(aenv->scriptenv)) == 0 ) + aenv->estatus->tried_default_save = TRUE; /* Start mail transaction */ trans->mail_trans = mailbox_transaction_begin @@ -299,6 +304,9 @@ static bool act_store_commit /* Commit mailbox transaction */ status = mailbox_transaction_commit(&trans->mail_trans) == 0; + + if ( status ) + aenv->estatus->message_saved = TRUE; } /* Log our status */ diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index 915aca84290d1118306ede69af330e8625011d4a..ad6208f0db4afe81a7fbeb96b54c4095c9b330af 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -19,6 +19,7 @@ struct sieve_action_exec_env { struct sieve_result *result; const struct sieve_message_data *msgdata; const struct sieve_script_env *scriptenv; + struct sieve_exec_status *estatus; }; /* diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index d02a8195cfaba6249606e614920b108a8a007250..cb5ad14e45886f651d50511385fd7260084ba9e4 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -478,7 +478,8 @@ int sieve_interpreter_continue int sieve_interpreter_start (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_message_context *msgctx, - struct sieve_result *result, bool *interrupted) + struct sieve_result *result, struct sieve_exec_status *estatus, + bool *interrupted) { const struct sieve_interpreter_extension_reg *extrs; unsigned int ext_count, i; @@ -486,6 +487,7 @@ int sieve_interpreter_start interp->runenv.msgdata = msgdata; interp->runenv.result = result; interp->runenv.scriptenv = senv; + interp->runenv.estatus = estatus; if ( msgctx == NULL ) interp->runenv.msgctx = sieve_message_context_create(); @@ -506,11 +508,16 @@ int sieve_interpreter_start int sieve_interpreter_run (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result **result) + const struct sieve_script_env *senv, struct sieve_result **result, + struct sieve_exec_status *estatus) { bool is_topmost = ( *result == NULL ); int ret = 0; + sieve_interpreter_reset(interp); + + /* Reset execution status */ + memset(estatus, 0, sizeof(*estatus)); if ( is_topmost ) *result = sieve_result_create(interp->ehandler); @@ -518,13 +525,14 @@ int sieve_interpreter_run sieve_result_ref(*result); } - ret = sieve_interpreter_start(interp, msgdata, senv, NULL, *result, NULL); + ret = sieve_interpreter_start + (interp, msgdata, senv, NULL, *result, estatus, NULL); if ( ret >= 0 && is_topmost ) { if ( ret > 0 ) - ret = sieve_result_execute(*result, msgdata, senv); + ret = sieve_result_execute(*result, msgdata, senv, estatus); else { - if ( !sieve_result_implicit_keep(*result, TRUE) ) + if ( !sieve_result_implicit_keep(*result, msgdata, senv, estatus) ) return SIEVE_EXEC_KEEP_FAILED; } } diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index 30c6db92743ec00300d1cc3811a866c718ec2401..49089f06757031d92274dbeddcb8e2e17a621641 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -33,6 +33,8 @@ struct sieve_runtime_env { struct sieve_binary *sbin; struct sieve_result *result; + struct sieve_exec_status *estatus; + struct ostream *trace_stream; }; @@ -160,9 +162,11 @@ int sieve_interpreter_continue int sieve_interpreter_start (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_message_context *msgctx, - struct sieve_result *result, bool *interrupted); + struct sieve_result *result, struct sieve_exec_status *estatus, + bool *interrupted); int sieve_interpreter_run (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result **result); + const struct sieve_script_env *senv, struct sieve_result **result, + struct sieve_exec_status *estatus); #endif /* __SIEVE_INTERPRETER_H */ diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index c2c1f902981a12979edff7fb2e57f9c35a970a44..a8c13ae5e83d72dcc44812c3e83524183d541914 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -534,7 +534,7 @@ bool sieve_result_print * Result execution */ -bool sieve_result_implicit_keep +static bool _sieve_result_implicit_keep (struct sieve_result *result, bool rollback) { bool success = TRUE; @@ -543,7 +543,7 @@ bool sieve_result_implicit_keep struct sieve_result_side_effect *rsef, *rsef_first = NULL; void *tr_context; - ctx.folder = result->action_env.scriptenv->inbox; + ctx.folder = result->action_env.scriptenv->default_mailbox; /* Also apply any implicit side effects if applicable */ if ( !rollback && result->action_contexts != NULL ) { @@ -605,9 +605,20 @@ bool sieve_result_implicit_keep return FALSE; } +bool sieve_result_implicit_keep +(struct sieve_result *result, const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, struct sieve_exec_status *estatus) +{ + result->action_env.msgdata = msgdata; + result->action_env.scriptenv = senv; + result->action_env.estatus = estatus; + + return _sieve_result_implicit_keep(result, TRUE); +} + int sieve_result_execute - (struct sieve_result *result, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv) +(struct sieve_result *result, const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, struct sieve_exec_status *estatus) { bool implicit_keep = TRUE; bool success = TRUE, commit_ok; @@ -616,6 +627,7 @@ int sieve_result_execute result->action_env.msgdata = msgdata; result->action_env.scriptenv = senv; + result->action_env.estatus = estatus; /* * Transaction start @@ -736,7 +748,7 @@ int sieve_result_execute * was not canceled during transaction. */ if ( !commit_ok || implicit_keep ) { - if ( !sieve_result_implicit_keep(result, !commit_ok) ) + if ( !_sieve_result_implicit_keep(result, !commit_ok) ) return SIEVE_EXEC_KEEP_FAILED; return ( commit_ok ? diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h index e9b2326236436bb032ca9f36a25b550680589f8a..c0f8d0f8ddae95bbeb40457ba66fab2043a892c2 100644 --- a/src/lib-sieve/sieve-result.h +++ b/src/lib-sieve/sieve-result.h @@ -84,11 +84,12 @@ int sieve_result_add_action */ bool sieve_result_implicit_keep - (struct sieve_result *result, bool rollback); + (struct sieve_result *result, const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, struct sieve_exec_status *estatus); int sieve_result_execute (struct sieve_result *result, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv); + const struct sieve_script_env *senv, struct sieve_exec_status *estatus); /* * Side effects list diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h index 6b6d1c0857d5f983390a7c65759fec3eba14a58b..b44a81f39691db221e6d2a8463bb5d338a1f1d3f 100644 --- a/src/lib-sieve/sieve-types.h +++ b/src/lib-sieve/sieve-types.h @@ -43,8 +43,10 @@ struct sieve_message_data { struct sieve_script_env { /* Mail-related */ - const char *inbox; struct mail_namespace *namespaces; + const char *default_mailbox; + bool mailbox_autocreate; + bool mailbox_autosubscribe; /* System-related */ const char *username; @@ -63,7 +65,20 @@ struct sieve_script_env { (const void *id, size_t id_size, const char *user); void (*duplicate_mark) (const void *id, size_t id_size, const char *user, time_t time); -}; +}; + +#define SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) \ + (senv->default_mailbox == NULL ? "INBOX" : senv->default_mailbox ) + +/* + * Script executionstatus + */ + +struct sieve_exec_status { + bool message_saved; + bool message_forwarded; + bool tried_default_save; +}; /* * Execution exit codes diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 2657cb608417fa590748a72cb0fcf2698ceef436..39e1313737e0ff69a3b37dccdce1fb05bf2577f7 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -234,8 +234,9 @@ void sieve_dump(struct sieve_binary *sbin, struct ostream *stream) int sieve_test (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct ostream *stream, - struct sieve_error_handler *ehandler, struct ostream *trace_stream) + const struct sieve_script_env *senv, struct sieve_exec_status *estatus, + struct ostream *stream, struct sieve_error_handler *ehandler, + struct ostream *trace_stream) { struct sieve_result *sres = sieve_result_create(ehandler); struct sieve_interpreter *interp = @@ -244,8 +245,11 @@ int sieve_test if ( interp == NULL ) return SIEVE_EXEC_BIN_CORRUPT; + + /* Reset execution status */ + memset(estatus, 0, sizeof(*estatus)); - ret = sieve_interpreter_run(interp, msgdata, senv, &sres); + ret = sieve_interpreter_run(interp, msgdata, senv, &sres, estatus); if ( ret > 0 ) ret = sieve_result_print(sres, stream); @@ -261,8 +265,8 @@ int sieve_test int sieve_execute (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, - struct ostream *trace_stream) + const struct sieve_script_env *senv, struct sieve_exec_status *estatus, + struct sieve_error_handler *ehandler, struct ostream *trace_stream) { struct sieve_result *sres = NULL; struct sieve_interpreter *interp = @@ -271,8 +275,11 @@ int sieve_execute if ( interp == NULL ) return SIEVE_EXEC_BIN_CORRUPT; + + /* Reset execution status */ + memset(estatus, 0, sizeof(*estatus)); - ret = sieve_interpreter_run(interp, msgdata, senv, &sres); + ret = sieve_interpreter_run(interp, msgdata, senv, &sres, estatus); sieve_interpreter_free(&interp); return ret; diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index 84fdb1271251db092390436d11ef46f5744b0eb2..affd751e61b2744e6c8699198a639a1a1a45b649 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -92,8 +92,9 @@ void sieve_dump(struct sieve_binary *sbin, struct ostream *stream); */ int sieve_test (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct ostream *stream, - struct sieve_error_handler *ehandler, struct ostream *trace_stream); + const struct sieve_script_env *senv, struct sieve_exec_status *estatus, + struct ostream *stream, struct sieve_error_handler *ehandler, + struct ostream *trace_stream); /* * Script execution @@ -105,7 +106,7 @@ int sieve_test */ int sieve_execute (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, - struct ostream *trace_stream); + const struct sieve_script_env *senv, struct sieve_exec_status *estatus, + struct sieve_error_handler *ehandler, struct ostream *trace_stream); #endif diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c index 1c003d957f483a8d80ff856793274c007f4f9374..5d6fd4209fa75dd654bbb1bf8b9eebe1798d3b60 100644 --- a/src/plugins/lda-sieve/lda-sieve-plugin.c +++ b/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -102,6 +102,7 @@ static int lda_sieve_run bool debug = ( getenv("DEBUG") != NULL ); struct sieve_message_data msgdata; struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; struct sieve_error_handler *ehandler; struct sieve_binary *sbin; const char *scriptlog; @@ -147,7 +148,9 @@ static int lda_sieve_run /* Compose script execution environment */ memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.inbox = mailbox; + scriptenv.default_mailbox = mailbox; + scriptenv.mailbox_autocreate = deliver_set->mailbox_autocreate; + scriptenv.mailbox_autosubscribe = deliver_set->mailbox_autosubscribe; scriptenv.namespaces = namespaces; scriptenv.username = username; scriptenv.hostname = deliver_set->hostname; @@ -162,7 +165,13 @@ static int lda_sieve_run if ( debug ) sieve_sys_info("executing compiled script %s", script_path); - ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler, NULL); + ret = sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL); + + /* Record status */ + + tried_default_save = estatus.tried_default_save; + + /* Evaluate result */ if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { sieve_sys_warning("encountered corrupt binary: recompiling script %s", @@ -191,7 +200,11 @@ static int lda_sieve_run /* Execute again */ - ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler, NULL); + ret = sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL); + + /* Record status */ + + tried_default_save = estatus.tried_default_save; /* Save new version */ diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-bin/sieve-exec.c index cc52aca761a85ead79dc7f65a562eb458179b384..7720b7f4a403124d84e38865e52e6cc1a863d1d3 100644 --- a/src/sieve-bin/sieve-exec.c +++ b/src/sieve-bin/sieve-exec.c @@ -92,6 +92,7 @@ int main(int argc, char **argv) struct sieve_binary *sbin; struct sieve_message_data msgdata; struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; struct sieve_error_handler *ehandler; bin_init(); @@ -194,7 +195,7 @@ int main(int argc, char **argv) (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.inbox = "INBOX"; + scriptenv.default_mailbox = "INBOX"; scriptenv.namespaces = ns; scriptenv.username = user; scriptenv.hostname = "host.example.com"; @@ -208,7 +209,7 @@ int main(int argc, char **argv) sieve_error_handler_accept_infolog(ehandler, TRUE); /* Run */ - switch ( sieve_execute(sbin, &msgdata, &scriptenv, ehandler, NULL) ) { + switch ( sieve_execute(sbin, &msgdata, &scriptenv, &estatus, ehandler, NULL) ) { case SIEVE_EXEC_OK: i_info("Final result: success"); break; diff --git a/src/sieve-bin/sieve-test.c b/src/sieve-bin/sieve-test.c index b2e9ff8af6d9a47dace21812f6746ca4b31bad3e..0812184afc71d84a312e4978946e745ed0386850 100644 --- a/src/sieve-bin/sieve-test.c +++ b/src/sieve-bin/sieve-test.c @@ -55,6 +55,7 @@ int main(int argc, char **argv) struct sieve_binary *sbin; struct sieve_message_data msgdata; struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; struct sieve_error_handler *ehandler; struct ostream *teststream; bool force_compile = FALSE; @@ -150,7 +151,7 @@ int main(int argc, char **argv) (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.inbox = "INBOX"; + scriptenv.default_mailbox = "INBOX"; scriptenv.username = user; ehandler = sieve_stderr_ehandler_create(0); @@ -164,7 +165,7 @@ int main(int argc, char **argv) /* Run the test */ ret = sieve_test - (sbin, &msgdata, &scriptenv, teststream, ehandler, trace_stream); + (sbin, &msgdata, &scriptenv, &estatus, teststream, ehandler, trace_stream); if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { i_info("Corrupt binary deleted."); diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c index c0f563b70a61fb3cb97874277b0da34fba35d27e..a395c06ee74e1518f96f485aacf7e3f0642d6273 100644 --- a/src/testsuite/testsuite-common.c +++ b/src/testsuite/testsuite-common.c @@ -416,6 +416,7 @@ bool testsuite_script_compile(const char *script_path) bool testsuite_script_execute(const struct sieve_runtime_env *renv) { struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; struct sieve_result *result; struct sieve_interpreter *interp; int ret; @@ -430,7 +431,7 @@ bool testsuite_script_execute(const struct sieve_runtime_env *renv) /* Compose script execution environment */ memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.inbox = "INBOX"; + scriptenv.default_mailbox = "INBOX"; scriptenv.namespaces = NULL; scriptenv.username = "user"; scriptenv.hostname = "host.example.com"; @@ -448,7 +449,7 @@ bool testsuite_script_execute(const struct sieve_runtime_env *renv) if ( interp == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - ret = sieve_interpreter_run(interp, renv->msgdata, &scriptenv, &result); + ret = sieve_interpreter_run(interp, renv->msgdata, &scriptenv, &result, &estatus); sieve_interpreter_free(&interp); diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 9695895b5497d3b67c642a828f7887003e41762d..986de73a136c650c15ecdaa9ead74613743aa20b 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -149,6 +149,7 @@ static int testsuite_run (struct sieve_binary *sbin, const struct sieve_script_env *scriptenv, bool trace) { + struct sieve_exec_status estatus; struct sieve_error_handler *ehandler = sieve_stderr_ehandler_create(0); struct sieve_result *sres = sieve_result_create(ehandler); struct sieve_interpreter *interp; @@ -160,14 +161,16 @@ static int testsuite_run interp=sieve_interpreter_create(sbin, ehandler, tstream); if ( interp != NULL ) - ret = sieve_interpreter_run(interp, &testsuite_msgdata, scriptenv, &sres); + ret = sieve_interpreter_run + (interp, &testsuite_msgdata, scriptenv, &sres, &estatus); o_stream_destroy(&tstream); } else { interp=sieve_interpreter_create(sbin, ehandler, NULL); if ( interp != NULL ) - ret = sieve_interpreter_run(interp, &testsuite_msgdata, scriptenv, &sres); + ret = sieve_interpreter_run + (interp, &testsuite_msgdata, scriptenv, &sres, &estatus); } if ( interp != NULL ) @@ -244,7 +247,7 @@ int main(int argc, char **argv) testsuite_message_init(user); memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.inbox = "INBOX"; + scriptenv.default_mailbox = "INBOX"; scriptenv.username = user; /* Run the test */