I'd like to put forward the following patch for dovecot-sieve. Essentially this just merges in some changes made in CMU sieve 2.3.8 and as such brings the behaviour more in line with RFC 3834 "Recommendations for Automatic Responses to Electronic Mail":
- fixes erroneous sender "-request" substring match - checks for existence of a selection of list-* headers - expands "named-as-recipient" header checks to "Resent-To", "Resent-CC" and "Resent-BCC" fields. Note that the appended patch also includes a fix for some missing parentheses in the "resent-to" test which resulted in some extra work being done but was otherwise harmless. The fix has been sent to <[EMAIL PROTECTED]> - prefixes subject in response with "Auto: " rather than (non-expanding) "Re: " I also, mostly for kicks, attach two sieve-like scripts that attempt to encapsulate the when-not-to-respond logic as implemented (if the patch were to be applied) and as advised by RFC 3834 respectively. I wrote these as an exercise to help me gain a better understanding of sieve and the CMU implementation. I'm not sure they are otherwise useful.
# # An attempt to render, as SIEVE, the actions of shouldRespond() from CMU # sieve/bc_eval.c as distributed with cyrus-imapd 2.3.8 # # This is not valid SIEVE; The following expansions must first be # performed: # # - %myaddrs% list of valid recipient addresses # - %envrcpt% the actual envelope recipient # # Example: # # sed -e 's/%myaddrs%/["[EMAIL PROTECTED]", "[EMAIL PROTECTED]"]/' \ # -e 's/%envrcpt%/"[EMAIL PROTECTED]"/' < vacation.sieve.in # require ["envelope"]; if anyof ( exists "list-id", exists "list-help", exists "list-subscribe", exists "list-unsubscribe", exists "list-post", exists "list-owner", exists "list-archive", # XXX bc_eval.c also skips leading whitespace not header :is "auto-submitted" "no", # XXX bc_eval.c also skips leading whitespace header :is "precedence" ["junk", "bulk", "list"], # XXX does this really catch null sender? envelope :all :is "from" "", # envelope sender equals envelope recipient; redundant if we assume # %envrcpt% is an element in %myaddrs% envelope :all :is "from" %envrcpt%, envelope :all :is "from" %myaddrs%, envelope :localpart :is "from" ["mailer-daemon", "listserv", "majordomo"], envelope :comparator "i;octet" :localpart :matches "from" ["*-request", "owner-*"], not address :all :is ["to", "cc", "bcc", "resent-to", "resent-cc", "resent-bcc"] %myaddrs% ) { discard; }
# # An attempt to render, as SIEVE, the advice from RFC 3834 section 2 "When # (not) to send automatic responses". Assumes we are a "Personal # Responder". # # This is not valid SIEVE; The following expansions must first be # performed: # # - %myaddrs% list of valid recipient addresses # - %untrusted% list of untrusted envelope senders # # Example: # # sed -e 's/%myaddrs%/["[EMAIL PROTECTED]", "[EMAIL PROTECTED]"]/' \ # -e 's/%untrusted%/["[EMAIL PROTECTED]"]/' < rfc3834.sieve.in # require ["envelope"]; if anyof ( # Fails to account for syntax defined in section 5.1 # SHOULD NOT not header :is "auto-submitted" "no", # SHOULD NOT not address :all :is ["to", "cc", "bcc", "resent-to", "resent-cc", "resent-bcc"] %myaddrs%, # MAY envelope :all :is "from" %untrusted%, # XXX Not clear if this correctly expresses a null sender # MUST NOT envelope :all :is "from" "", # Strictly speaking localparts are case-sensitive hence the # use of :comparator. In reality the default "i;ascii-casemap" # comparator almost certainly make more sense. # MAY envelope :comparator "i;octet" :localpart :is "from" ["MAILER-DAEMON"], envelope :comparator "i;octet" :localpart :matches "from" ["*-request", "owner-*"], # XXX no such recommendation is actually made # MAY header :is "precedence" "list", # Mentions List-* and references RFC2369. Not possible to # express "list-*" as a header match in sieve. Instead just # enumerate the RFC2369 and RFC2919 (List-ID) defined headers. # MAY exists "list-help", exists "list-unsubscribe", exists "list-subscribe", exists "list-post", exists "list-owner", exists "list-archive", exists "list-id" ) { discard; }
# HG changeset patch # User <[EMAIL PROTECTED]> # Date 1186514697 -3600 # Node ID 5132f4b25eb08437f22ce2458bfa6b1e4d27ae9c # Parent 9137442dd18a511023a29fc50062cdb0091e3b1b Merge in changes from CMU sieve 2.3.8 diff -r 9137442dd18a -r 5132f4b25eb0 src/libsieve/bc_eval.c --- a/src/libsieve/bc_eval.c Wed Aug 01 15:02:51 2007 +0300 +++ b/src/libsieve/bc_eval.c Tue Aug 07 20:24:57 2007 +0100 @@ -124,7 +124,7 @@ static int sysaddr(const char *addr) if (!strncasecmp(addr, "majordomo", 9)) return 1; - if (strstr(addr, "-request")) + if (strstr(addr, "-request@")) return 1; if (!strncmp(addr, "owner-", 6)) @@ -186,6 +186,17 @@ static char* look_for_me(char *myaddr, i return found; } + +static char *list_fields[] = { + "list-id", + "list-help", + "list-subscribe", + "list-unsubscribe", + "list-post", + "list-owner", + "list-archive", + NULL +}; /* Determine if we should respond to a vacation message */ static int shouldRespond(void * m, sieve_interp_t *interp, @@ -195,14 +206,28 @@ static int shouldRespond(void * m, sieve const char **body; char buf[128]; char *myaddr = NULL; - int l = SIEVE_OK; + int l = SIEVE_OK, j; void *data = NULL, *marker = NULL; char *tmp; int curra, x; char *found=NULL; char *reply_to=NULL; - /* is there an Auto-Submitted keyword other than "no"? */ + /* Implementations SHOULD NOT respond to any message that contains a + "List-Id" [RFC2919], "List-Help", "List-Subscribe", "List- + Unsubscribe", "List-Post", "List-Owner" or "List-Archive" [RFC2369] + header field. */ + for (j = 0; list_fields[j]; j++) { + strcpy(buf, list_fields[j]); + if (interp->getheader(m, buf, &body) == SIEVE_OK) { + l = SIEVE_DONE; + break; + } + } + + /* Implementations SHOULD NOT respond to any message that has an + "Auto-submitted" header field with a value other than "no". + This header field is described in [RFC3834]. */ strcpy(buf, "auto-submitted"); if (interp->getheader(m, buf, &body) == SIEVE_OK) { /* we don't deal with comments, etc. here */ @@ -212,6 +237,7 @@ static int shouldRespond(void * m, sieve } /* is there a Precedence keyword of "junk | bulk | list"? */ + /* XXX non-standard header, but worth checking */ strcpy(buf, "precedence"); if (interp->getheader(m, buf, &body) == SIEVE_OK) { /* we don't deal with comments, etc. here */ @@ -282,7 +308,7 @@ static int shouldRespond(void * m, sieve if (l == SIEVE_OK) { /* ok, we're willing to respond to the sender. but is this message to me? that is, is my address - in the TO, CC or BCC fields? */ + in the [Resent]-To, [Resent]-Cc or [Resent]-Bcc fields? */ if (strcpy(buf, "to"), interp->getheader(m, buf, &body) == SIEVE_OK) found = look_for_me(myaddr, numaddresses ,bc, i, body); @@ -290,6 +316,15 @@ static int shouldRespond(void * m, sieve (interp->getheader(m, buf, &body) == SIEVE_OK))) found = look_for_me(myaddr, numaddresses, bc, i, body); if (!found && (strcpy(buf, "bcc"), + (interp->getheader(m, buf, &body) == SIEVE_OK))) + found = look_for_me(myaddr, numaddresses, bc, i, body); + if (!found && (strcpy(buf, "resent-to"), + (interp->getheader(m, buf, &body) == SIEVE_OK))) + found = look_for_me(myaddr, numaddresses ,bc, i, body); + if (!found && (strcpy(buf, "resent-cc"), + (interp->getheader(m, buf, &body) == SIEVE_OK))) + found = look_for_me(myaddr, numaddresses, bc, i, body); + if (!found && (strcpy(buf, "resent-bcc"), (interp->getheader(m, buf, &body) == SIEVE_OK))) found = look_for_me(myaddr, numaddresses, bc, i, body); if (!found) @@ -1093,10 +1128,7 @@ int sieve_eval_bc(sieve_interp_t *i, con /* s[0] contains the original subject */ const char *origsubj = s[0]; - while (!strncasecmp(origsubj, "Re: ", 4)) - origsubj += 4; - - snprintf(subject, sizeof(subject), "Re: %s", origsubj); + snprintf(subject, sizeof(subject), "Auto: %s", origsubj); } } else { /* user specified subject */