diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c index 41fa21ff0abe9822201c7a2ed87b7558ca4538c1..759ac3cd554aad67eba41012208a638d2d65e25e 100644 --- a/src/lib-sieve/plugins/notify/cmd-notify.c +++ b/src/lib-sieve/plugins/notify/cmd-notify.c @@ -27,7 +27,9 @@ #include "ext-notify-common.h" #include "ext-notify-limits.h" -/* Notify command +#include <ctype.h> + +/* Notify command (DEPRECATED) * * Syntax: * notify [":method" string] [":id" string] [":options" string-list] @@ -464,6 +466,80 @@ static bool cmd_notify_operation_dump /* * Code execution */ + +static void cmd_notify_construct_message +(const struct sieve_runtime_env *renv, const char *msg_format, + string_t *out_msg) +{ + const struct sieve_message_data *msgdata = renv->msgdata; + const char *p; + + if ( msg_format == NULL ) + msg_format = "$from$: $subject$"; + + /* Scan message for substitutions */ + p = msg_format; + while ( *p != '\0' ) { + const char *const *header; + + if ( strncasecmp(p, "$from$", 6) == 0 ) { + p += 6; + + /* Fetch sender from oriinal message */ + if ( mail_get_headers_utf8(msgdata->mail, "from", &header) >= 0 ) + str_append(out_msg, header[0]); + + } else if ( strncasecmp(p, "$env-from$", 10) == 0 ) { + p += 10; + + if ( msgdata->return_path != NULL ) + str_append(out_msg, msgdata->return_path); + + } else if ( strncasecmp(p, "$subject$", 9) == 0 ) { + p += 9; + + /* Fetch sender from oriinal message */ + if ( mail_get_headers_utf8(msgdata->mail, "subject", &header) >= 0 ) + str_append(out_msg, header[0]); + + } else if ( strncasecmp(p, "$text", 5) == 0 + && (p[5] == '[' || p[5] == '$') ) { + size_t num = 0; + const char *begin = p; + bool valid = TRUE; + + p += 5; + if ( *p == '[' ) { + p += 1; + + while ( i_isdigit(*p) ) { + num = num * 10 + (*p - '0'); + p++; + } + + if ( *p++ != ']' || *p++ != '$' ) { + str_append_n(out_msg, begin, p-begin); + valid = FALSE; + } + } else { + p += 1; + } + + if ( valid ) { + str_append(out_msg, "<body extraction not supported>"); + } + } else { + size_t len; + + /* Find next substitution */ + len = strcspn(p + 1, "$") + 1; + + /* Copy normal text */ + str_append_n(out_msg, p, len); + p += len; + } + } +} static int cmd_notify_operation_execute (const struct sieve_operation *op ATTR_UNUSED, @@ -542,19 +618,27 @@ static int cmd_notify_operation_execute sieve_runtime_trace(renv, "NOTIFY action"); - /* Normalize and verify all :options addresses */ + /* Compose action */ if ( options != NULL ) { string_t *raw_address; + string_t *out_message; bool result; pool = sieve_result_pool(renv->result); act = p_new(pool, struct ext_notify_action, 1); if ( id != NULL ) act->id = p_strdup(pool, str_c(id)); - if ( message != NULL ) - act->message = p_strdup(pool, str_c(message)); - act->importance = importance; - + act->importance = importance; + + /* Process message */ + + out_message = t_str_new(1024); + cmd_notify_construct_message + (renv, (message == NULL ? NULL : str_c(message)), out_message); + act->message = p_strdup(pool, str_c(out_message)); + + /* Normalize and verify all :options addresses */ + sieve_coded_stringlist_reset(options); p_array_init(&act->recipients, pool, 4);