diff --git a/doc/man/sieve-test.1 b/doc/man/sieve-test.1 index a2de66c1ddcb49b29db1ab96d981148bfc00113c..a5f860a732c691f095a53b97ba7df463140c99e0 100644 --- a/doc/man/sieve-test.1 +++ b/doc/man/sieve-test.1 @@ -1,8 +1,18 @@ -.TH "SIEVE-TEST" "1" "21 December 2008" +.TH "SIEVE-TEST" "1" "6 Januari 2009" .SH NAME sieve-test \- Sieve script tester for the Dovecot secure IMAP server .SH SYNOPSIS -sieve-test [\fB-r\fR \fIrecipient-address\fR] [\fB-f\fR \fIenvelope-sender\fR] [\fB-m\fR \fImailbox\fR] [\fB-d\fR \fIdump-file\fR] [\fB-c\fR] [\fB-t\fR] [\fB-x\fR "\fIextension extension ...\fR"] [\fB-s\fR \fIscript-file\fR] +sieve-test +[\fB-c\fR] +[\fB-d\fR \fIdump-file\fR] +[\fB-e\fR] +[\fB-f\fR \fIenvelope-sender\fR] +[\fB-l\fR \fImail-location\fR] +[\fB-m\fR \fIdefault-mailbox\fR] +[\fB-r\fR \fIrecipient-address\fR] +[\fB-s\fR \fIscript-file\fR] +[\fB-t\fR] +[\fB-x\fR "\fIextension extension ...\fR"] \fIscript-file\fR \fImail-file\fR .SH DESCRIPTION .PP @@ -13,31 +23,26 @@ architecture and operating system. The language cannot execute external programs its basic form it does not provide the means to cause infinite loops, making it suitable for running securely on mail servers where mail users have no permission run arbitrary programs. .PP -Using the \fBsieve-test\fR command, the execution of Sieve scripts can be tested. This evaluates -the script for the provided message, but it does not store or forward the message anywere. -In stead, it prints what actions would normally take place. This is a very useful tool to -debug the execution of Sieve scripts. +Using the \fBsieve-test\fP command, the execution of Sieve scripts can be tested. This evaluates +the script for the provided message, yielding a set of Sieve actions. Unless the \fB-e\fP option is +specified, it does not actually execute these actions, meaning that it does not store or forward the +message anywere. In stead, it prints a detailed list of what actions would normally take place. +Note that, even when \fB-e\fP is specified, no messages are never transmitted to remote SMTP +recipients. The outgoing messages are printed to \fBstdout\fP in stead. .PP -The command has two mandatory arguments: the \fIscript-file\fR argument, which specifies the -script to (compile and) execute, and the \fImail-file\fR argument, which specifies the file containing -the e-mail message to filter. +This is a very useful tool to debug the execution of Sieve scripts. It can be used to verify +newly installed scripts for the intended behaviour and it can provide more detailed information +about script execution problems that are reported by the Sieve plugin. +.PP +The command has two mandatory arguments: the \fIscript-file\fP argument, which specifies the +script to (compile and) execute, and the \fImail-file\fP argument, which specifies the file +containing the e-mail message to filter. + +Note that this tool looks for a pre-compiled binary file with a \fI.svbin\fP extension and +with basename and path identical to the specified script. Use the \fB-c\fP option to disable this +behavior by forcing the script to be compiled into a new binary. .SH OPTIONS .TP -\fB-r\fP \fIrecipient-address\fP -The envelope recipient address. This is what Sieve's envelope test will compare to when the "to" -envelope part is requested. -.TP -\fB-f\fP \fIenvelope-sender\fP -The envelope sender. This is what Sieve's envelope test will compare to when the "from" envelope -part is requested. -.TP -\fB-m\fP \fImailbox\fP -The mailbox where the keep action would store. This is "INBOX" by default. -.TP -\fB-d\fP \fIdump-file\fP -Causes a dump of the generated code to be written to the specified file. This is identical to the -dump produced by \fBsieved\fR(1). Using '-' as filename causes the dump to be written to \fBstdout\fP. -.TP \fB-c\fP Force compilation. By default, the compiled binary is stored on disk. When this binary is found during the next execution of \fBsieve-test\fP and its modification time is more recent than the @@ -45,17 +50,45 @@ script file, it is used and the script is not compiled again. This option forces compiled, thus ignoring any present binary. Refer to \fBsievec\fP(1) for more information about Sieve compilation. .TP -\fB-t\fP -Enable simple trace debugging; prints all encountered byte code instructions on \fBstdout\fP. +\fB-d\fP \fIdump-file\fP +Causes a dump of the generated code to be written to the specified file. This is identical to the +dump produced by \fBsieved\fR(1). Using '-' as filename causes the dump to be written to \fBstdout\fP. .TP -\fB-x\fP "\fIextension extension ...\fP" -Set the available extensions. The parameter is a space-separated list of the active extensions. -Unknown extensions are ignored, but a warning is produced. +\fB-e\fP +Turns on true execution of the set of actions that results from running the script. In combination +with the \fB-l\fP parameter, the actual delivery of messages can be tested. Note that this will +not transmit any messages to remote SMTP recipients. Such actions only print the outgoing message +to \fBstdout\fP. +.TP +\fB-f\fP \fIenvelope-sender\fP +The envelope sender or return path. This is what Sieve's envelope test will compare to when the +"from" envelope part is requested. Also, this is where response messages are sent to. +.TP +\fB-l\fP \fImail-location\fP +The location of the user's mail store. The syntax of this option's \fImail-location\fP parameter +is identical to what is used for the mail_location setting in the Dovecot config file. This +parameter is typically used in combination with \fB-e\fP to test the actual delivery of messages. +If \fB-l\fP is omitted when \fB-e\fP is specified, mail store actions like fileinto and keep are +skipped. +.TP +\fB-m\fP \fIdefault-mailbox\fP +The mailbox where the keep action stores the message. This is "INBOX" by default. .TP -\fB-s\fP \fIscript-file\fP (not implemented) +\fB-r\fP \fIrecipient-address\fP +The envelope recipient address. This is what Sieve's envelope test will compare to when the "to" +envelope part is requested. Some tests and actions will also use this as the owner's e-mail address. +.TP +\fB-s\fP \fIscript-file\fP Specify additional scripts to be executed before the main script. Multiple \fB-s\fP arguments are allowed and the specified scripts are executed sequentially in the order specified at the command line. +.TP +\fB-t\fP +Enable simple trace debugging; prints all encountered byte code instructions to \fBstdout\fP. +.TP +\fB-x\fP "\fIextension extension ...\fP" +Set the available extensions. The option's parameter is a space-separated list of the active +extensions. Unknown extensions are ignored, but a warning is produced. .SH AUTHOR .PP The Sieve implementation for Dovecot was written by Stephan Bosch <stephan@rename-it.nl>. diff --git a/doc/man/sievec.1 b/doc/man/sievec.1 index a34b3733da97f8312164ff696dd52f6f9e1c8772..4f2982a576d484de08587b68b65ed38261dfde63 100644 --- a/doc/man/sievec.1 +++ b/doc/man/sievec.1 @@ -1,4 +1,4 @@ -.TH "SIEVEC" "1" "21 December 2008" +.TH "SIEVEC" "1" "6 January 2009" .SH NAME sievec \- Sieve script compiler for the Dovecot secure IMAP server .SH SYNOPSIS diff --git a/doc/man/sieved.1 b/doc/man/sieved.1 index 17a2735950e2ad4d470154f15c2c5bf44821c0c4..9037a1b2baa74d00cd73dee57d69a8be73c41f19 100644 --- a/doc/man/sieved.1 +++ b/doc/man/sieved.1 @@ -1,4 +1,4 @@ -.TH "SIEVED" "1" "11 November 2008" +.TH "SIEVED" "1" "6 January 2009" .SH NAME sieved \- Sieve script binary dump tool for the Dovecot secure IMAP server .SH SYNOPSIS diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c index 6b5e7504750044180501037a1fc305563113ee50..eb97b21303216b1debe5319c0199a816b46d9130 100644 --- a/src/lib-sieve/cmd-discard.c +++ b/src/lib-sieve/cmd-discard.c @@ -66,7 +66,7 @@ static bool act_discard_commit const struct sieve_action act_discard = { "discard", 0, - NULL, NULL, + NULL, NULL, NULL, act_discard_print, NULL, NULL, act_discard_commit, diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c index ef6696bfe981642b4c0e7efe42419a0310911d93..2b9c928acc4d2574e65bf60ae0b6600e1aacdc2d 100644 --- a/src/lib-sieve/sieve-result.c +++ b/src/lib-sieve/sieve-result.c @@ -71,6 +71,7 @@ struct sieve_result { struct sieve_action_exec_env action_env; const struct sieve_action *keep_action; + const struct sieve_action *failure_action; unsigned int action_count; struct sieve_result_action *first_action; @@ -100,6 +101,7 @@ struct sieve_result *sieve_result_create result->action_env.result = result; result->keep_action = &act_store; + result->failure_action = &act_store; result->action_count = 0; result->first_action = NULL; @@ -561,6 +563,12 @@ void sieve_result_set_keep_action result->keep_action = action; } +void sieve_result_set_failure_action +(struct sieve_result *result, const struct sieve_action *action) +{ + result->failure_action = action; +} + /* * Result printing */ @@ -743,7 +751,12 @@ static bool _sieve_result_implicit_keep bool dummy = TRUE; struct sieve_result_side_effect *rsef, *rsef_first = NULL; void *tr_context = NULL; - const struct sieve_action *act_keep = result->keep_action; + const struct sieve_action *act_keep; + + if ( rollback ) + act_keep = result->failure_action; + else + act_keep = result->keep_action; /* If keep is a non-action, return right away */ if ( act_keep == NULL ) return TRUE; diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h index 6457d1655140a57b04e66f02dda4dc18fb87e14c..afe96fcaaaf31a130b71d2a744bca23f67828d00 100644 --- a/src/lib-sieve/sieve-result.h +++ b/src/lib-sieve/sieve-result.h @@ -93,6 +93,8 @@ int sieve_result_add_keep void sieve_result_set_keep_action (struct sieve_result *result, const struct sieve_action *action); +void sieve_result_set_failure_action + (struct sieve_result *result, const struct sieve_action *action); /* * Result execution diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 13f26ce3109928d2ff341efc913eae1f98f27e89..4eec615413b62f7269ffaf432ed1e59b477ef4c5 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -419,7 +419,7 @@ bool sieve_multiscript_execute if ( mscript->status >= 0 ) { bool keep = FALSE; - + if ( mscript->status > 0 ) mscript->status = sieve_result_execute (mscript->result, mscript->msgdata, mscript->scriptenv, &keep); diff --git a/src/sieve-tools/Makefile.am b/src/sieve-tools/Makefile.am index b29025ec464bd0f824ae8df07d232ad4baa3c834..361feb1795b15c3d5a8ff44ce1d4ff764d912a11 100644 --- a/src/sieve-tools/Makefile.am +++ b/src/sieve-tools/Makefile.am @@ -1,6 +1,6 @@ pkglibexecdir = $(libexecdir)/dovecot -bin_PROGRAMS = sievec sieved sieve-test sieve-exec +bin_PROGRAMS = sievec sieved sieve-test AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib-sieve \ @@ -15,7 +15,6 @@ AM_CPPFLAGS = \ sievec_LDFLAGS = -export-dynamic -Wl,--start-group sieved_LDFLAGS = -export-dynamic -Wl,--start-group sieve_test_LDFLAGS = -export-dynamic -Wl,--start-group -sieve_exec_LDFLAGS = -export-dynamic -Wl,--start-group libs = \ $(top_srcdir)/src/lib-sieve/libsieve.la \ @@ -39,12 +38,10 @@ ldadd = \ sievec_LDADD = $(ldadd) sieved_LDADD = $(ldadd) sieve_test_LDADD = $(ldadd) -sieve_exec_LDADD = $(ldadd) sievec_DEPENDENCIES = $(libs) sieved_DEPENDENCIES = $(libs) sieve_test_DEPENDENCIES = $(libs) -sieve_exec_DEPENDENCIES = $(libs) sievec_SOURCES = \ sievec.c @@ -55,7 +52,4 @@ sieved_SOURCES = \ sieve_test_SOURCES = \ sieve-test.c -sieve_exec_SOURCES = \ - sieve-exec.c - noinst_HEADERS = diff --git a/src/sieve-tools/sieve-exec.c b/src/sieve-tools/sieve-exec.c deleted file mode 100644 index 912ed5a5759010d95f6d4bc9b60970e1ee803360..0000000000000000000000000000000000000000 --- a/src/sieve-tools/sieve-exec.c +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file - */ - -#include "lib.h" -#include "ostream.h" -#include "mail-namespace.h" -#include "mail-storage.h" -#include "env-util.h" - -#include "sieve.h" -#include "sieve-binary.h" - -#include "mail-raw.h" -#include "sieve-tool.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <pwd.h> - -#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail" -#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON" - -/* - * Dummy SMTP session - */ - -static void *sieve_smtp_open(const char *destination, - const char *return_path, FILE **file_r) -{ - i_info("sending message from <%s> to <%s>:", - return_path == NULL || *return_path == '\0' ? "" : return_path, - destination); - printf("\nSTART MESSAGE:\n"); - - *file_r = stdout; - - return NULL; -} - -static bool sieve_smtp_close(void *handle ATTR_UNUSED) -{ - printf("END MESSAGE\n\n"); - return TRUE; -} - -/* - * Dummy duplicate check implementation - */ - -static int duplicate_check(const void *id ATTR_UNUSED, size_t id_size ATTR_UNUSED, - const char *user) -{ - i_info("checked duplicate for user %s.\n", user); - return 0; -} - -static void duplicate_mark -(const void *id ATTR_UNUSED, size_t id_size ATTR_UNUSED, const char *user, - time_t time ATTR_UNUSED) -{ - i_info("marked duplicate for user %s.\n", user); -} - -/* - * Print help - */ - -static void print_help(void) -{ - printf( -"Usage: sieve-exec [-r <recipient address>][-f <envelope sender>]\n" -" [-m <mailbox>][-d <dump filename>][-l <mail location>]\n" -" <scriptfile> <mailfile>\n" - ); -} - -/* - * Tool implementation - */ - -int main(int argc, char **argv) -{ - const char *scriptfile, *recipient, *sender, *mailbox, *dumpfile, *mailfile; - const char *mailloc; - const char *user, *home; - int i; - struct mail_raw *mailr; - struct mail_namespace *ns = NULL; - struct mail_user *mail_user = NULL; - struct sieve_binary *sbin; - struct sieve_message_data msgdata; - struct sieve_script_env scriptenv; - struct sieve_exec_status estatus; - struct sieve_error_handler *ehandler; - - /* Parse arguments */ - scriptfile = recipient = sender = mailbox = dumpfile = mailfile = NULL; - mailloc = NULL; - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-r") == 0) { - /* recipient address */ - i++; - if (i == argc) - i_fatal("Missing -r argument"); - recipient = argv[i]; - } else if (strcmp(argv[i], "-f") == 0) { - /* envelope sender */ - i++; - if (i == argc) - i_fatal("Missing -f argument"); - sender = argv[i]; - } else if (strcmp(argv[i], "-m") == 0) { - /* default mailbox (keep box) */ - i++; - if (i == argc) - i_fatal("Missing -m argument"); - mailbox = argv[i]; - } else if (strcmp(argv[i], "-d") == 0) { - /* dump file */ - i++; - if (i == argc) - i_fatal("Missing -d argument"); - dumpfile = argv[i]; - } else if (strcmp(argv[i], "-l") == 0) { - /* mail location */ - i++; - if (i == argc) - i_fatal("Missing -l argument"); - mailloc = argv[i]; - } else if ( scriptfile == NULL ) { - scriptfile = argv[i]; - } else if ( mailfile == NULL ) { - mailfile = argv[i]; - } else { - print_help(); - i_fatal("Unknown argument: %s", argv[i]); - } - } - - if ( scriptfile == NULL ) { - print_help(); - i_fatal("Missing <scriptfile> argument"); - } - - if ( mailfile == NULL ) { - print_help(); - i_fatal("Missing <mailfile> argument"); - } - - sieve_tool_init(); - - /* Compile sieve script */ - sbin = sieve_tool_script_open(scriptfile); - - /* Dump script */ - sieve_tool_dump_binary_to(sbin, dumpfile); - - user = sieve_tool_get_user(); - home = getenv("HOME"); - - /* Initialize mail storages */ - mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL); - mail_storage_init(); - mail_storage_register_all(); - mailbox_list_register_all(); - - /* Obtain mail namespaces from -l argument */ - if ( mailloc != NULL ) { - env_put(t_strdup_printf("NAMESPACE_1=%s", mailloc)); - env_put("NAMESPACE_1_INBOX=1"); - env_put("NAMESPACE_1_LIST=1"); - env_put("NAMESPACE_1_SEP=."); - env_put("NAMESPACE_1_SUBSCRIPTIONS=1"); - - mail_user = mail_user_init(user); - mail_user_set_home(mail_user, home); - if (mail_namespaces_init(mail_user) < 0) - i_fatal("Namespace initialization failed"); - - ns = mail_user->namespaces; - } - - /* Initialize raw mail object from file */ - mail_raw_init(user); - mailr = mail_raw_open_file(mailfile); - - sieve_tool_get_envelope_data(mailr->mail, &recipient, &sender); - - if ( mailbox == NULL ) - mailbox = "INBOX"; - - /* Collect necessary message data */ - memset(&msgdata, 0, sizeof(msgdata)); - msgdata.mail = mailr->mail; - msgdata.return_path = sender; - msgdata.to_address = recipient; - msgdata.auth_user = "nico"; - (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); - - memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.default_mailbox = "INBOX"; - scriptenv.namespaces = ns; - scriptenv.username = user; - scriptenv.hostname = "host.example.com"; - scriptenv.postmaster_address = "postmaster@example.com"; - scriptenv.smtp_open = sieve_smtp_open; - scriptenv.smtp_close = sieve_smtp_close; - scriptenv.duplicate_mark = duplicate_mark; - scriptenv.duplicate_check = duplicate_check; - scriptenv.exec_status = &estatus; - - ehandler = sieve_stderr_ehandler_create(0); - sieve_error_handler_accept_infolog(ehandler, TRUE); - - /* Run */ - switch ( sieve_execute(sbin, &msgdata, &scriptenv, ehandler) ) { - case SIEVE_EXEC_OK: - i_info("final result: success"); - break; - case SIEVE_EXEC_FAILURE: - i_info("final result: failed; resolved with successful implicit keep"); - break; - case SIEVE_EXEC_BIN_CORRUPT: - i_info("corrupt binary deleted."); - (void) unlink(sieve_binary_path(sbin)); - case SIEVE_EXEC_KEEP_FAILED: - i_info("final result: utter failure (caller please handle implicit keep!)"); - break; - default: - i_info("final result: unrecognized return value?!"); - } - - sieve_close(&sbin); - sieve_error_handler_unref(&ehandler); - - /* De-initialize raw mail object */ - mail_raw_close(mailr); - mail_raw_deinit(); - - /* De-initialize mail user object */ - if ( mail_user != NULL ) - mail_user_unref(&mail_user); - - /* De-intialize mail storages */ - mail_storage_deinit(); - mail_users_deinit(); - - sieve_tool_deinit(); - - return 0; -} - diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c index 755ce8166112f3d5fdaa276b429c74db6e5ed851..9b42473ada825dca32c69e8f10fdcec90f856be1 100644 --- a/src/sieve-tools/sieve-test.c +++ b/src/sieve-tools/sieve-test.c @@ -6,6 +6,7 @@ #include "array.h" #include "mail-namespace.h" #include "mail-storage.h" +#include "env-util.h" #include "sieve.h" #include "sieve-binary.h" @@ -45,6 +46,47 @@ static void print_help(void) ); } +/* + * Dummy SMTP session + */ + +static void *sieve_smtp_open(const char *destination, + const char *return_path, FILE **file_r) +{ + i_info("sending message from <%s> to <%s>:", + return_path == NULL || *return_path == '\0' ? "" : return_path, + destination); + printf("\nSTART MESSAGE:\n"); + + *file_r = stdout; + + return NULL; +} + +static bool sieve_smtp_close(void *handle ATTR_UNUSED) +{ + printf("END MESSAGE\n\n"); + return TRUE; +} + +/* + * Dummy duplicate check implementation + */ + +static int duplicate_check(const void *id ATTR_UNUSED, size_t id_size ATTR_UNUSED, + const char *user) +{ + i_info("checked duplicate for user %s.\n", user); + return 0; +} + +static void duplicate_mark +(const void *id ATTR_UNUSED, size_t id_size ATTR_UNUSED, const char *user, + time_t time ATTR_UNUSED) +{ + i_info("marked duplicate for user %s.\n", user); +} + /* * Tool implementation */ @@ -53,17 +95,19 @@ int main(int argc, char **argv) { ARRAY_DEFINE(scriptfiles, const char *); const char *scriptfile, *recipient, *sender, *mailbox, *dumpfile, *mailfile, - *extensions; - const char *user; + *mailloc, *extensions; + const char *user, *home; int i; struct mail_raw *mailr; - struct sieve_binary *main_sbin; + struct mail_namespace *ns = NULL; + struct mail_user *mail_user = NULL; + struct sieve_binary *main_sbin, *sbin = NULL; 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; + struct ostream *teststream = NULL; + bool force_compile = FALSE, execute = FALSE; bool trace = FALSE; int ret; @@ -72,8 +116,8 @@ int main(int argc, char **argv) t_array_init(&scriptfiles, 16); /* Parse arguments */ - scriptfile = recipient = sender = mailbox = dumpfile = mailfile = extensions - = NULL; + scriptfile = recipient = sender = mailbox = dumpfile = mailfile = mailloc = + extensions = NULL; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-r") == 0) { /* recipient address */ @@ -99,6 +143,12 @@ int main(int argc, char **argv) if (i == argc) i_fatal("Missing -d argument"); dumpfile = argv[i]; + } else if (strcmp(argv[i], "-l") == 0) { + /* mail location */ + i++; + if (i == argc) + i_fatal("Missing -l argument"); + mailloc = argv[i]; } else if (strcmp(argv[i], "-x") == 0) { /* extensions */ i++; @@ -118,6 +168,9 @@ int main(int argc, char **argv) } else if (strcmp(argv[i], "-c") == 0) { /* force compile */ force_compile = TRUE; + } else if (strcmp(argv[i], "-e") == 0) { + /* execute */ + execute = TRUE; #ifdef SIEVE_RUNTIME_TRACE } else if (strcmp(argv[i], "-t") == 0) { /* runtime trace */ @@ -159,12 +212,29 @@ int main(int argc, char **argv) sieve_tool_dump_binary_to(main_sbin, dumpfile); user = sieve_tool_get_user(); + home = getenv("HOME"); /* Initialize mail storages */ mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL); mail_storage_init(); mail_storage_register_all(); mailbox_list_register_all(); + + /* Obtain mail namespaces from -l argument */ + if ( mailloc != NULL ) { + env_put(t_strdup_printf("NAMESPACE_1=%s", mailloc)); + env_put("NAMESPACE_1_INBOX=1"); + env_put("NAMESPACE_1_LIST=1"); + env_put("NAMESPACE_1_SEP=."); + env_put("NAMESPACE_1_SUBSCRIPTIONS=1"); + + mail_user = mail_user_init(user); + mail_user_set_home(mail_user, home); + if (mail_namespaces_init(mail_user) < 0) + i_fatal("Namespace initialization failed"); + + ns = mail_user->namespaces; + } /* Initialize raw mail object */ mail_raw_init(user); @@ -184,36 +254,41 @@ int main(int argc, char **argv) (void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id); /* Create stream for test and trace output */ - - teststream = o_stream_create_fd(1, 0, FALSE); + if ( !execute || trace ) + teststream = o_stream_create_fd(1, 0, FALSE); /* Compose script environment */ memset(&scriptenv, 0, sizeof(scriptenv)); - scriptenv.default_mailbox = mailbox; + scriptenv.default_mailbox = "INBOX"; + scriptenv.namespaces = ns; scriptenv.username = user; + scriptenv.hostname = "host.example.com"; + scriptenv.postmaster_address = "postmaster@example.com"; + scriptenv.smtp_open = sieve_smtp_open; + scriptenv.smtp_close = sieve_smtp_close; + scriptenv.duplicate_mark = duplicate_mark; + scriptenv.duplicate_check = duplicate_check; scriptenv.trace_stream = ( trace ? teststream : NULL ); scriptenv.exec_status = &estatus; - + /* Create error handler */ ehandler = sieve_stderr_ehandler_create(0); + sieve_error_handler_accept_infolog(ehandler, TRUE); /* Run the test */ if ( array_count(&scriptfiles) == 0 ) { /* Single script */ + sbin = main_sbin; + main_sbin = NULL; - /* Test script */ - ret = sieve_test(main_sbin, &msgdata, &scriptenv, ehandler, teststream); - - if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { - i_info("Corrupt binary deleted."); - (void) unlink(sieve_binary_path(main_sbin)); - } - + /* Execute/Test script */ + if ( execute ) + ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler); + else + ret = sieve_test(sbin, &msgdata, &scriptenv, ehandler, teststream); } else { /* Multiple scripts */ - - struct sieve_binary *sbin = NULL; const char *const *sfiles; unsigned int i, count; struct sieve_multiscript *mscript = sieve_multiscript_start @@ -223,9 +298,10 @@ int main(int argc, char **argv) /* Execute scripts sequentially */ sfiles = array_get(&scriptfiles, &count); for ( i = 0; i < count && result > 0; i++ ) { - o_stream_send_str(teststream, - t_strdup_printf("\n## Executing script: %s\n", sfiles[i])); - + if ( teststream != NULL ) + o_stream_send_str(teststream, + t_strdup_printf("\n## Executing script: %s\n", sfiles[i])); + /* Close previous script */ if ( sbin != NULL ) sieve_close(&sbin); @@ -242,50 +318,83 @@ int main(int argc, char **argv) result = -1; break; } - - /* Dump script */ - sieve_tool_dump_binary_to(sbin, dumpfile); - /* Test script */ - result = ( sieve_multiscript_test(mscript, sbin, FALSE, teststream) ? - 1 : 0 ); + /* Execute/Test script */ + if ( execute ) + result = sieve_multiscript_execute(mscript, sbin, FALSE); + else + result = sieve_multiscript_test(mscript, sbin, FALSE, teststream); } - /* Execute main script */ - if ( result > 0 ) { - o_stream_send_str(teststream, - t_strdup_printf("## Executing script: %s\n", scriptfile)); + /* Execute/Test main script */ + switch ( result ) { + case TRUE: + if ( teststream != NULL ) + o_stream_send_str(teststream, + t_strdup_printf("## Executing script: %s\n", scriptfile)); /* Close previous script */ if ( sbin != NULL ) sieve_close(&sbin); sbin = main_sbin; - (void)sieve_multiscript_test(mscript, main_sbin, TRUE, teststream); + main_sbin = NULL; + + if ( execute ) + (void)sieve_multiscript_execute(mscript, sbin, TRUE); + else + (void)sieve_multiscript_test(mscript, sbin, TRUE, teststream); + + case FALSE: ret = sieve_multiscript_finish(&mscript); - } else { - ret = SIEVE_EXEC_FAILURE; - } + break; - if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { - i_info("Corrupt binary deleted."); - (void) unlink(sieve_binary_path(sbin)); + default: + ret = SIEVE_EXEC_FAILURE; } } + + /* Run */ + switch ( ret ) { + case SIEVE_EXEC_OK: + i_info("final result: success"); + break; + case SIEVE_EXEC_BIN_CORRUPT: + i_info("corrupt binary deleted."); + (void) unlink(sieve_binary_path(sbin)); + case SIEVE_EXEC_FAILURE: + i_info("final result: failed; resolved with successful implicit keep"); + break; + case SIEVE_EXEC_KEEP_FAILED: + i_info("final result: utter failure"); + break; + default: + i_info("final result: unrecognized return value?!"); + } - o_stream_destroy(&teststream); + if ( teststream != NULL ) + o_stream_destroy(&teststream); - sieve_close(&main_sbin); + /* Cleanup remaining binaries */ + sieve_close(&sbin); + if ( main_sbin != NULL ) sieve_close(&main_sbin); + + /* Cleanup error handler */ sieve_error_handler_unref(&ehandler); /* De-initialize raw mail object */ mail_raw_close(mailr); mail_raw_deinit(); + /* De-initialize mail user object */ + if ( mail_user != NULL ) + mail_user_unref(&mail_user); + /* De-initialize mail storages */ mail_storage_deinit(); mail_users_deinit(); - sieve_tool_deinit(); + sieve_tool_deinit(); + return 0; }