From 5c77bc111bab0ea414754d3e8e75d96693cab9d1 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan.bosch@dovecot.fi> Date: Sat, 7 Jul 2018 17:51:42 +0200 Subject: [PATCH] lib-sieve: vacation extension: Make construction of default message subject configurable. --- src/lib-sieve/plugins/vacation/cmd-vacation.c | 41 ++++++- .../plugins/vacation/ext-vacation-common.c | 10 ++ .../plugins/vacation/ext-vacation-common.h | 2 + tests/extensions/vacation/message.svtest | 105 ++++++++++++++++++ 4 files changed, 154 insertions(+), 4 deletions(-) diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index bacb180ca..2f6806f27 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -10,6 +10,7 @@ #include "ostream.h" #include "message-address.h" #include "message-date.h" +#include "var-expand.h" #include "ioloop.h" #include "mail-storage.h" @@ -947,23 +948,54 @@ static int _get_full_reply_recipient return SIEVE_EXEC_OK; } +static const struct var_expand_table * +_get_var_expand_table(const struct sieve_action_exec_env *aenv ATTR_UNUSED, + const char *subject) +{ + const struct var_expand_table stack_tab[] = { + { '$', subject, "subject" }, + { '\0', NULL, NULL } + }; + return p_memdup(unsafe_data_stack_pool, stack_tab, sizeof(stack_tab)); +} + static int act_vacation_get_default_subject(const struct sieve_action_exec_env *aenv, + const struct ext_vacation_config *config, const char **subject_r) { const struct sieve_message_data *msgdata = aenv->msgdata; - const char *header; + const char *header, *error; + string_t *str; + const struct var_expand_table *tab; int ret; - *subject_r = "Automated reply"; + *subject_r = (config->default_subject == NULL ? + "Automated reply" : config->default_subject); if ((ret=mail_get_first_header_utf8(msgdata->mail, "subject", &header)) < 0 ) { return sieve_result_mail_error( aenv, msgdata->mail, "vacation action: " "failed to read header field `subject'"); } - if (ret >= 0) + if (ret == 0) + return SIEVE_EXEC_OK; + if (config->default_subject_template == NULL) { *subject_r = t_strconcat("Auto: ", header, NULL); + return SIEVE_EXEC_OK; + } + + str = t_str_new(256); + tab = _get_var_expand_table(aenv, header); + if (var_expand(str, config->default_subject_template, + tab, &error) <= 0) { + i_error("Failed to expand deliver_log_format=%s: %s", + config->default_subject_template, error); + *subject_r = t_strconcat("Auto: ", header, NULL); + return SIEVE_EXEC_OK; + } + + *subject_r = str_c(str); return SIEVE_EXEC_OK; } @@ -995,7 +1027,8 @@ static int act_vacation_send /* Make sure we have a subject for our reply */ if ( ctx->subject == NULL || *(ctx->subject) == '\0' ) { - if ((ret=act_vacation_get_default_subject(aenv, &subject)) <= 0) + if ((ret=act_vacation_get_default_subject(aenv, config, + &subject)) <= 0) return ret; } else { subject = ctx->subject; diff --git a/src/lib-sieve/plugins/vacation/ext-vacation-common.c b/src/lib-sieve/plugins/vacation/ext-vacation-common.c index 67c2513bf..089d8481a 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation-common.c +++ b/src/lib-sieve/plugins/vacation/ext-vacation-common.c @@ -19,6 +19,7 @@ bool ext_vacation_load bool use_original_recipient, dont_check_recipient, send_from_recipient, to_header_ignore_envelope; unsigned long long max_subject_codepoints; + const char *default_subject, *default_subject_template; if ( *context != NULL ) { ext_vacation_unload(ext); @@ -52,6 +53,11 @@ bool ext_vacation_load "sieve_vacation_max_period"); } + default_subject = sieve_setting_get( + svinst, "sieve_vacation_default_subject"); + default_subject_template = sieve_setting_get( + svinst, "sieve_vacation_default_subject_template"); + if ( !sieve_setting_get_uint_value (svinst, "sieve_vacation_max_subject_codepoints", &max_subject_codepoints) ) { max_subject_codepoints = EXT_VACATION_DEFAULT_MAX_SUBJECT_CODEPOINTS; @@ -83,6 +89,8 @@ bool ext_vacation_load config->max_period = max_period; config->default_period = default_period; config->max_subject_codepoints = max_subject_codepoints; + config->default_subject = i_strdup_empty(default_subject); + config->default_subject_template = i_strdup_empty(default_subject_template); config->use_original_recipient = use_original_recipient; config->dont_check_recipient = dont_check_recipient; config->send_from_recipient = send_from_recipient; @@ -99,5 +107,7 @@ void ext_vacation_unload struct ext_vacation_config *config = (struct ext_vacation_config *) ext->context; + i_free(config->default_subject); + i_free(config->default_subject_template); i_free(config); } diff --git a/src/lib-sieve/plugins/vacation/ext-vacation-common.h b/src/lib-sieve/plugins/vacation/ext-vacation-common.h index e82c40c42..3a38cf631 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation-common.h +++ b/src/lib-sieve/plugins/vacation/ext-vacation-common.h @@ -17,6 +17,8 @@ struct ext_vacation_config { unsigned int max_period; unsigned int default_period; unsigned long long max_subject_codepoints; + char *default_subject; + char *default_subject_template; bool use_original_recipient; bool dont_check_recipient; bool send_from_recipient; diff --git a/tests/extensions/vacation/message.svtest b/tests/extensions/vacation/message.svtest index d062ed2f7..861605e7e 100644 --- a/tests/extensions/vacation/message.svtest +++ b/tests/extensions/vacation/message.svtest @@ -61,6 +61,100 @@ test "Subject - explicit" { } } +/* + * Subject - configured, no subject + */ + +test_set "message" text: +From: stephan@example.org +To: nico@frop.example.org + +Frop +. +; + +test_config_set "sieve_vacation_default_subject" "Something colorful"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Subject - configured, no subject" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Something colorful" { + test_fail "Subject header is incorrect"; + } +} + +/* + * Subject - configured + */ + +test_set "message" text: +From: stephan@example.org +Subject: Bloemetjes +To: nico@frop.example.org + +Frop +. +; + +test_config_set "sieve_vacation_default_subject_template" + "Automatisch bericht: %$"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Subject - configured" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Automatisch bericht: Bloemetjes" { + test_fail "Subject header is incorrect"; + } +} + +/* + * Subject - configured, full variable + */ + +test_set "message" text: +From: stephan@example.org +Subject: Bloemetjes +To: nico@frop.example.org + +Frop +. +; + +test_config_set "sieve_vacation_default_subject_template" + "Automatisch bericht: %{subject}"; +test_config_reload :extension "vacation"; + +test_result_reset; +test "Subject - configured, full variable" { + vacation "I am not in today!"; + + if not test_result_execute { + test_fail "execution of result failed"; + } + + test_message :smtp 0; + + if not header :is "subject" "Automatisch bericht: Bloemetjes" { + test_fail "Subject header is incorrect"; + } +} + /* * No subject */ @@ -108,6 +202,10 @@ Frop . ; +test_config_set "sieve_vacation_default_subject_template" ""; +test_config_set "sieve_vacation_default_subject" ""; +test_config_reload :extension "vacation"; + test_result_reset; test "Extremely long subject" { vacation "I am not in today!"; @@ -167,6 +265,10 @@ Frop . ; +test_config_set "sieve_vacation_default_subject_template" ""; +test_config_set "sieve_vacation_default_subject" ""; +test_config_reload :extension "vacation"; + test_result_reset; test "Extremely long japanese subject" { vacation "I am not in today!"; @@ -227,6 +329,9 @@ Frop . ; + +test_config_set "sieve_vacation_default_subject_template" ""; +test_config_set "sieve_vacation_default_subject" ""; test_config_set "sieve_vacation_max_subject_codepoints" "20"; test_config_reload :extension "vacation"; -- GitLab