diff --git a/Makefile.am b/Makefile.am index c5794b9a7d82c26b831664ed8a524ec1ff585f75..832e2806ed2ffdaa06c9e7c4f711ab33eeea0079 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,6 +78,7 @@ test_cases = \ tests/extensions/subaddress/rfc.svtest \ tests/extensions/vacation/errors.svtest \ tests/extensions/vacation/execute.svtest \ + tests/extensions/vacation/references.svtest \ $(ENOTIFY_TESTS) if HAVE_DOVECOT_LIBS diff --git a/TODO b/TODO index 6a901579d17d5c7b1d7fee9074d2c4cfb9a4ae03..4fab9cc7261c91faab1e73736846af48d95fb397 100644 --- a/TODO +++ b/TODO @@ -18,8 +18,6 @@ Next (in order of descending priority/precedence): any vacation response that is generated. UTF-8 characters can be used in the string argument; implementations MUST convert the string to [RFC2047] encoded words if and only if non-ASCII characters are present. - - Vacation: properly implement construction of a References header from - the original message. - Body: contains various issues that need to be resolved for standards compliance. Body test support currently matches but barely exceeds the original CMU Sieve implentation in terms of standards compliance. diff --git a/src/lib-sieve/plugins/enotify/ntfy-mailto.c b/src/lib-sieve/plugins/enotify/ntfy-mailto.c index 927b116d01f2681ccf55d2ccbf87c201426b7498..360a64b377c2e0da0bdcf68f49ccade651e8f344 100644 --- a/src/lib-sieve/plugins/enotify/ntfy-mailto.c +++ b/src/lib-sieve/plugins/enotify/ntfy-mailto.c @@ -423,7 +423,6 @@ static bool ntfy_mailto_action_execute (const struct sieve_action_exec_env *aenv, const struct sieve_enotify_context *nctx) { - const struct sieve_message_data *msgdata = aenv->msgdata; const struct sieve_script_env *senv = aenv->scriptenv; struct ntfy_mailto_context *mtctx = (struct ntfy_mailto_context *) nctx->method_context; diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index d1b1dc5daafea68847f01ce340a970258129f5c7..b07d581c06e7c81d10d156cdf3299c0948625d35 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -2,6 +2,8 @@ */ #include "lib.h" +#include "str.h" +#include "strfuncs.h" #include "md5.h" #include "hostpid.h" #include "str-sanitize.h" @@ -9,6 +11,8 @@ #include "message-date.h" #include "ioloop.h" +#include "rfc2822.h" + #include "sieve-common.h" #include "sieve-code.h" #include "sieve-address.h" @@ -796,6 +800,9 @@ static bool act_vacation_send void *smtp_handle; FILE *f; const char *outmsgid; + const char *const *headers; + string_t *out = t_str_new(256); + int references; /* Check smpt functions just to be sure */ @@ -820,12 +827,25 @@ static bool act_vacation_send fprintf(f, "To: <%s>\r\n", msgdata->return_path); fprintf(f, "Subject: %s\r\n", str_sanitize(ctx->subject, 80)); - + + references = mail_get_headers_utf8 + (aenv->msgdata->mail, "references", &headers); + if ( msgdata->id != NULL ) { fprintf(f, "In-Reply-To: %s\r\n", msgdata->id); - - /* FIXME: Update References header */ + + if ( references >= 0 ) + rfc2822_header_add_folded + (out, "References", t_strconcat(headers[0], " ", msgdata->id, NULL)); + else + rfc2822_header_add_folded(out, "References", msgdata->id); + + fwrite(str_c(out), str_len(out), 1, f); + } else if ( references > 0 ) { + rfc2822_header_add_folded(out, "References", headers[0]); + fwrite(str_c(out), str_len(out), 1, f); } + fprintf(f, "Auto-Submitted: auto-replied (vacation)\r\n"); fprintf(f, "X-Sieve: %s\r\n", SIEVE_IMPLEMENTATION); diff --git a/src/lib-sieve/rfc2822.c b/src/lib-sieve/rfc2822.c index 329432a6c550687e781b0b13ec8b046197dc53ef..8f30b746e4d221003664d82bc0613d0e26b19a74 100644 --- a/src/lib-sieve/rfc2822.c +++ b/src/lib-sieve/rfc2822.c @@ -2,9 +2,12 @@ */ #include "lib.h" +#include "str.h" #include "rfc2822.h" +#include <ctype.h> + /* NOTE: much of the functionality implemented here should eventually appear * somewhere in Dovecot itself. */ @@ -31,3 +34,40 @@ bool rfc2822_header_field_name_verify return TRUE; } +void rfc2822_header_add_folded +(string_t *out, const char *name, const char *body) +{ + const char *sp = body, *bp = body, *wp; + unsigned int len = str_len(out); + + /* Add properly formatted header field name first */ + str_append_c(out, i_toupper(name[0])); + str_append(out, t_str_lcase(name+1)); + + /* Add separating colon */ + str_append(out, ": "); + + /* Add folded field body */ + len = str_len(out) - len; + while ( *bp != '\0' ) { + while ( *bp != '\0' && (wp == NULL || len < 80) ) { + if ( *bp == ' ' || *bp == '\t' ) + wp = bp; + + bp++; len++; + } + + if ( *bp == '\0' ) break; + + str_append_n(out, sp, wp-sp); + str_append(out, "\r\n"); + + len = bp - wp; + sp = wp; + wp = NULL; + } + + str_append_n(out, sp, bp-sp); + str_append(out, "\r\n"); +} + diff --git a/src/lib-sieve/rfc2822.h b/src/lib-sieve/rfc2822.h index 3748c950f0902ffe70d4974a546c9ccc7df149ae..b16e65522ad203cde4321964e8a870144b0b2543 100644 --- a/src/lib-sieve/rfc2822.h +++ b/src/lib-sieve/rfc2822.h @@ -9,4 +9,7 @@ bool rfc2822_header_field_name_verify (const char *field_name, unsigned int len); +void rfc2822_header_add_folded + (string_t *out, const char *name, const char *body); + #endif /* __RFC2822_H */ diff --git a/tests/extensions/vacation/references.sieve b/tests/extensions/vacation/references.sieve new file mode 100644 index 0000000000000000000000000000000000000000..77658f2fa0b0e4f50ffacb6c8ab3b43e2054c701 --- /dev/null +++ b/tests/extensions/vacation/references.sieve @@ -0,0 +1,4 @@ +require "vacation"; + +vacation "I am on vacation."; +discard; diff --git a/tests/extensions/vacation/references.svtest b/tests/extensions/vacation/references.svtest new file mode 100644 index 0000000000000000000000000000000000000000..f67b1e69643c9c86056d6a35897fc9f2cfd30182 --- /dev/null +++ b/tests/extensions/vacation/references.svtest @@ -0,0 +1,18 @@ +require "vnd.dovecot.testsuite"; +require "vacation"; + +test_set "message" text: +From: stephan@rename-it.nl +Subject: frop +References: <1234@local.machine.example> <3456@example.net> + <435444@ttms.com> <4223@froop.nl> <m345444444@message-id.exp> +Message-ID: <432df324@rename-it.nl> +To: nico@vestingbar.nl + +Frop +. +; + +test "References" { + vacation "I am not in today!"; +}