From 8643cbdebc1a2a2014395a30ec95971cc4746719 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan.bosch@dovecot.fi> Date: Thu, 24 Aug 2017 02:03:21 +0200 Subject: [PATCH] lib-sieve: vacation extension: Allow ignoring the envelope sender while composing the "To:" header for the reply. This adds a new setting "sieve_vacation_to_header_ignore_envelope". With this setting enabled, the "To:" header is always composed from the first "Sender", "Resent-From" or "From" header found in the message (in that order). Normally, the "To:" header is composed from the address found in the "Sender", "Resent-From" or "From" headers that is equal to the envelope sender. If none is then found, the bare envelope sender is used. The new setting allows ignoring the envelope, which is useful e.g. when SRS is used. --- doc/extensions/vacation.txt | 12 ++++++ src/lib-sieve/plugins/vacation/cmd-vacation.c | 33 ++++++++++------ .../plugins/vacation/ext-vacation-common.c | 10 ++++- .../plugins/vacation/ext-vacation-common.h | 1 + tests/extensions/vacation/message.svtest | 38 +++++++++++++++++++ 5 files changed, 81 insertions(+), 13 deletions(-) diff --git a/doc/extensions/vacation.txt b/doc/extensions/vacation.txt index 20f82b19a..9b9856f72 100644 --- a/doc/extensions/vacation.txt +++ b/doc/extensions/vacation.txt @@ -81,6 +81,18 @@ sieve_vacation_send_from_recipient = no situations for which a valid sender address is required and this setting can be used to accommodate for those. +sieve_vacation_to_header_ignore_envelope = no + With this setting disabled (the default), the "To:" header in the composed + vacation reply is determined by finding the envelope sender address in the + first "Sender:", "Resent-From:", or "From:" headers (in that order). The + matching address is used in the "To:" header of the reply, which then includes + the "phrase" part of the address; i.e., usually the name of the person + associated with that address. If no match is found, the bare envelope sender + address is used instead. In contrast, with this setting enabled, the envelope + is completely ignored for this purpose and the first address found from the + mentioned headers is always used. This is useful when the envelope sender is + mangled somehow; e.g. by the Sender Rewriting Scheme (SRS). + Invalid values for the settings above will make the Sieve interpreter log a warning and revert to the default values. diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index 50c55385a..3c033af94 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -817,9 +817,9 @@ static const char * const _my_address_headers[] = { */ static const char * const _sender_headers[] = { - "from", "sender", "resent-from", + "from", NULL }; @@ -899,6 +899,7 @@ static bool _contains_8bit(const char *text) static int _get_full_reply_recipient (const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, const char *smtp_to, const char **reply_to_r) { const struct sieve_message_data *msgdata = aenv->msgdata; @@ -926,16 +927,21 @@ static int _get_full_reply_recipient if ( addr->domain != NULL && !addr->invalid_syntax ) { struct sieve_address svaddr; const char *hdr_address; + bool matched = config->to_header_ignore_envelope; - i_assert(addr->mailbox != NULL); + if (!matched) { + i_assert(addr->mailbox != NULL); - i_zero(&svaddr); - svaddr.local_part = addr->mailbox; - svaddr.domain = addr->domain; + i_zero(&svaddr); + svaddr.local_part = addr->mailbox; + svaddr.domain = addr->domain; - hdr_address = sieve_address_to_string(&svaddr); - if ( sieve_address_compare - (hdr_address, smtp_to, TRUE) == 0 ) { + hdr_address = sieve_address_to_string(&svaddr); + matched = ( sieve_address_compare + (hdr_address, smtp_to, TRUE) == 0 ); + } + + if (matched) { struct message_address this_addr; this_addr = *addr; @@ -959,8 +965,11 @@ static int _get_full_reply_recipient } static int act_vacation_send -(const struct sieve_action_exec_env *aenv, struct act_vacation_context *ctx, - const char *smtp_to, const char *smtp_from, const char *reply_from) +(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, + struct act_vacation_context *ctx, + const char *smtp_to, const char *smtp_from, + const char *reply_from) { const struct sieve_message_data *msgdata = aenv->msgdata; const struct sieve_script_env *senv = aenv->scriptenv; @@ -1001,7 +1010,7 @@ static int act_vacation_send /* Obtain full To address for reply */ reply_to = smtp_to; - if ((ret=_get_full_reply_recipient(aenv, + if ((ret=_get_full_reply_recipient(aenv, config, smtp_to, &reply_to)) <= 0) return ret; @@ -1381,7 +1390,7 @@ static int act_vacation_commit /* Send the message */ T_BEGIN { - ret = act_vacation_send(aenv, ctx, sender, + ret = act_vacation_send(aenv, config, ctx, sender, (config->send_from_recipient ? smtp_from : NULL), reply_from); } T_END; diff --git a/src/lib-sieve/plugins/vacation/ext-vacation-common.c b/src/lib-sieve/plugins/vacation/ext-vacation-common.c index f07a57a9d..a556ebfac 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation-common.c +++ b/src/lib-sieve/plugins/vacation/ext-vacation-common.c @@ -16,7 +16,8 @@ bool ext_vacation_load struct sieve_instance *svinst = ext->svinst; struct ext_vacation_config *config; sieve_number_t min_period, max_period, default_period; - bool use_original_recipient, dont_check_recipient, send_from_recipient; + bool use_original_recipient, dont_check_recipient, send_from_recipient, + to_header_ignore_envelope; if ( *context != NULL ) { ext_vacation_unload(ext); @@ -65,6 +66,12 @@ bool ext_vacation_load send_from_recipient = FALSE; } + if ( !sieve_setting_get_bool_value(svinst, + "sieve_vacation_to_header_ignore_envelope", + &to_header_ignore_envelope) ) { + to_header_ignore_envelope = FALSE; + } + config = i_new(struct ext_vacation_config, 1); config->min_period = min_period; config->max_period = max_period; @@ -72,6 +79,7 @@ bool ext_vacation_load config->use_original_recipient = use_original_recipient; config->dont_check_recipient = dont_check_recipient; config->send_from_recipient = send_from_recipient; + config->to_header_ignore_envelope = to_header_ignore_envelope; *context = (void *) config; diff --git a/src/lib-sieve/plugins/vacation/ext-vacation-common.h b/src/lib-sieve/plugins/vacation/ext-vacation-common.h index 9433c3369..fffb61047 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation-common.h +++ b/src/lib-sieve/plugins/vacation/ext-vacation-common.h @@ -21,6 +21,7 @@ struct ext_vacation_config { bool use_original_recipient; bool dont_check_recipient; bool send_from_recipient; + bool to_header_ignore_envelope; }; /* diff --git a/tests/extensions/vacation/message.svtest b/tests/extensions/vacation/message.svtest index e2abbfdaa..4e26ffd42 100644 --- a/tests/extensions/vacation/message.svtest +++ b/tests/extensions/vacation/message.svtest @@ -189,6 +189,44 @@ test "Reply to unknown" { } } +/* + * Reply to (ignored envelope) + */ + +test_set "message" text: +From: "Stephan Bosch" <stephan@example.org> +Sender: "Hendrik-Jan Tuinman" <h.j.tuinman@example.org> +Subject: Reply to me +To: nico@frop.example.org + +Frop +. +; + +test_set "envelope.from" "srs0=hmc8=v7=example.com=arie@example.org"; + +test_config_set "sieve_vacation_to_header_ignore_envelope" "yes"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Reply to (ignored envelope)" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not address :is "to" "h.j.tuinman@example.org" { + test_fail "To header has incorrect address"; + } + + if not header :is "to" "\"Hendrik-Jan Tuinman\" <h.j.tuinman@example.org>" { + test_fail "To header is incorrect"; + } +} + /* * References */ -- GitLab