Timo Sirainen wrote: > On Tue, 2007-07-03 at 21:13 +0300, Uldis Pakuls wrote: > >>> http://article.gmane.org/gmane.mail.imap.dovecot/20813/match >>> >>> Thanks, >>> >> I wrote this patch about 6 moth ago. As far, as I tested it, it works as >> expected. Other users reports only success with this path too. >> Timo: My be it's good idea to include this patch in CVS version? Anyway >> original code only reports "generic error" as "notify" method is >> unimplemented, and produces bounce messages. >> > > Yes .. Although I have another version by Petr Smotek <[EMAIL PROTECTED]> as > well. I haven't looked closely either of your patches, so want to tell > me which one would be better? :) Attached the other one. > > I have "looked closely" at both and here is result - new patch:)
1. Peter removed sieve action report from notify message... this my be confusing as actions are not only "keep". notify my be sent for forward, reject etc. actions, so I left this list at end of message as is. 2. Peter's patch tries to mark sent messages with duplicate_mark() but never used any check... Actually I dot see any reason for such marking, as notify message are not stored anywhere in mail storage - it is sent directly to external "sendmail_bin" and discarded from memory. new things added: 1. headers "Auto-Submitted: Precedence:" for better handing by auto-responders. 2. check for 8bit characters in message. and most important things: 1. notify now always reports SIEVE_OK as notify failure is not delivery failure. all notify failures are reported in log. Also "SIEVE_ERROR" aborts script execution, but there is no reason to abort on notify error. 2. sieve plugin returns "-1" if script failed load or on any error. i think it is wrong; if no scripts are executed or it is aborted for some reason - it is not fatal delivery error; this just means "nothing is done" by script. so i changed plugin always return "0" on errors. but one problem still remains... if script is executed and mail is delivered to mailbox, but next action failed (e.g. notify, vocation, etc.) deliver incorrectly sends bounce messages while mail is successfully delivered. sample script: { keep; notify :method...[...]; <- failed action } result is: 1. message is delivered 2. bounce message sent... to fix this I wrote small patch for deliver too... my be you find this "useful"...:) Uldis
--- /dovecot-org/src/deliver/deliver.c 2007-05-15 20:27:28.000000000 +0300 +++ /dovecot-new/src/deliver/deliver.c 2007-07-06 19:13:50.000000000 +0300 @@ -50,6 +50,7 @@ /* FIXME: these two should be in some context struct instead of as globals.. */ static const char *default_mailbox_name = NULL; static bool tried_default_save = FALSE; +static bool default_save_ok = FALSE; static bool no_mailbox_autocreate = FALSE; static struct module *modules; @@ -139,11 +140,17 @@ ret = mailbox_transaction_commit(&t, 0); msgid = mail_get_first_header(mail, "Message-ID"); - i_info(ret < 0 ? "msgid=%s: save failed to %s" : - "msgid=%s: saved mail to %s", + if (ret < 0) { + i_info("msgid=%s: save failed to %s", msgid == NULL ? "" : str_sanitize(msgid, 80), str_sanitize(mailbox_get_name(box), 80)); - + default_save_ok = TRUE; + }else{ + i_info("msgid=%s: saved mail to %s", + msgid == NULL ? "" : str_sanitize(msgid, 80), + str_sanitize(mailbox_get_name(box), 80)); + default_save_ok = FALSE; + } mailbox_close(&box); return ret; } @@ -687,9 +694,13 @@ deliver_mail(storage, mail, destination, mailbox); if (ret == 0 || (ret < 0 && !tried_default_save)) { - /* plugins didn't handle this. save into the default mailbox. */ - i_stream_seek(input, 0); - ret = deliver_save(storage, mailbox, mail, 0, NULL); + if (!default_save_ok){ + /* plugins didn't handle this. save into the default mailbox. */ + i_stream_seek(input, 0); + ret = deliver_save(storage, mailbox, mail, 0, NULL); + }else{ + ret = 0; + } } if (ret < 0 && strcasecmp(mailbox, "INBOX") != 0) { /* still didn't work. try once more to save it
--- dovecot-sieve-1.0.1-org/src/sieve-cmu.c 2006-10-10 22:44:54.000000000 +0300 +++ dovecot-sieve-1.0.1-new/src/sieve-cmu.c 2007-07-06 19:05:29.000000000 +0300 @@ -18,9 +18,12 @@ #include <fcntl.h> #include <unistd.h> +#include <stdlib.h> #include <sys/stat.h> #include <sys/wait.h> +static int contains_8bit(const char *msg); + /* data per script */ typedef struct script_data { const char *username; @@ -252,30 +255,84 @@ return SIEVE_OK; } -static int sieve_notify(void *ac __attr_unused__, - void *interp_context __attr_unused__, - void *script_context __attr_unused__, - void *mc __attr_unused__, - const char **errmsg __attr_unused__) -{ -#if 0 - const char *notifier = config_getstring(IMAPOPT_SIEVENOTIFIER); - - if (notifier) { - sieve_notify_context_t *nc = (sieve_notify_context_t *) ac; - script_data_t *sd = (script_data_t *) script_context; - int nopt = 0; - - /* count options */ - while (nc->options[nopt]) nopt++; - - /* "default" is a magic value that implies the default */ - notify(!strcmp("default",nc->method) ? notifier : nc->method, - "SIEVE", nc->priority, sd->username, NULL, - nopt, nc->options, nc->message); +static int sieve_notify(void *ac, + void *ic __attr_unused__, + void *sc __attr_unused__, + void *mc, + const char **errmsg) +{ + sieve_notify_context_t *nc = (sieve_notify_context_t *) ac; + sieve_msgdata_t *m = mc; + + int nopt = 0; + FILE *f; + struct smtp_client *smtp_client; + const char *outmsgid; + + /* "default" is "mailto" as only one... */ + if (!strcasecmp(nc->method, "default")) nc->method = "mailto"; + /* check method */ + if (strcasecmp(nc->method, "mailto")) { + *errmsg = "Unknown [unimplemented] notify method"; + i_info("SIEVE ERROR: Unknown [unimplemented] notify method <%s>", + nc->method); + //return SIEVE_FAIL; + //just log error, failed notify is not reason to abort all script. + //it is not delivery error too... + return SIEVE_OK; + } + /* count options */ + while (nc->options[nopt]) { + smtp_client = smtp_client_open(nc->options[nopt], NULL, &f); + outmsgid = deliver_get_new_message_id(); + fprintf(f, "Message-ID: %s\r\n", outmsgid); + fprintf(f, "Date: %s\r\n", message_date_create(ioloop_time)); + fprintf(f, "X-Sieve: %s\r\n", SIEVE_VERSION); + if ( strcasecmp(nc->priority, "high") == 0 ) { + fprintf(f, "X-Priority: 1 (Highest)\r\n"); + fprintf(f, "Importance: High\r\n"); + } else if ( strcasecmp(nc->priority, "normal") == 0 ) { + fprintf(f, "X-Priority: 3 (Normal)\r\n"); + fprintf(f, "Importance: Normal\r\n"); + } else if ( strcasecmp(nc->priority, "low") == 0 ) { + fprintf(f, "X-Priority: 5 (Lowest)\r\n"); + fprintf(f, "Importance: Low\r\n"); + // RFC: If no importance is given, the default value is "2 (Normal)" + } else { + fprintf(f, "X-Priority: 3 (Normal)\r\n"); + fprintf(f, "Importance: Normal\r\n"); + } + fprintf(f, "From: Postmaster <%s>\r\n", getenv("POSTMASTER_ADDRESS")); + fprintf(f, "To: <%s>\r\n", nc->options[nopt]); + fprintf(f, "Subject: [SIEVE] New mail notification\r\n"); + fprintf(f, "Auto-Submitted: auto-generated (notify)\r\n"); + fprintf(f, "Precedence: bulk\r\n"); + if (contains_8bit(nc->message)) { + fprintf(f, "MIME-Version: 1.0\r\n"); + fprintf(f, "Content-Type: text/plain; charset=UTF-8\r\n"); + fprintf(f, "Content-Transfer-Encoding: 8bit\r\n"); + } + fprintf(f, "\r\n"); + fprintf(f, "%s\r\n", nc->message); + if (smtp_client_close(smtp_client) == 0) { + i_info("msgid=%s: sent notification to <%s> (method=%s)", + m->id == NULL ? "" : str_sanitize(m->id, 80), + str_sanitize(nc->options[nopt], 80), + nc->method + ); + } else { + i_info("msgid=%s: ERROR sending notification to <%s> (method=%s)", + m->id == NULL ? "" : str_sanitize(m->id, 80), + str_sanitize(nc->options[nopt], 80), + nc->method); + *errmsg = "Error sending notify mail"; + //return SIEVE_FAIL; + //just log error, failed notify is not reson to abort all script... + //it is not delivery error too... + } + nopt = nopt + 1; } -#endif - return SIEVE_FAIL; + return SIEVE_OK; } static int autorespond(void *ac, @@ -567,12 +624,30 @@ if ((ret = sieve_script_load(compiled_path, &bytecode)) != SIEVE_OK) { i_error("sieve_script_load(%s) failed: %d", compiled_path, ret); - return -1; + return 0; } if (sieve_execute_bytecode(bytecode, interp, - &sdata, &mdata) != SIEVE_OK) - return -1; - + &sdata, &mdata) != SIEVE_OK) { + i_error("sieve_execute_bytecode(%s) failed; script aborted", compiled_path); + return 0; + } return 1; } + +static int contains_8bit(const char * msg) +{ + int res = 0; + if (msg) { + const unsigned char *s = (const unsigned char *)msg; + while (*s) { + if (0 != (*s & 0x80)) { + res = 1; + break ; + } + s++; + } + } + return res; +} +