diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 6d1f23e00d151320782c14491bcde7a073f38afb..3b1a85091e0e2b4edc708bb35380bc0ef7fe0198 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -321,7 +321,7 @@ static int act_redirect_send struct istream *input; struct ostream *output; const char *error; - void *smtp_handle; + struct sieve_smtp_context *sctx; int ret; /* Just to be sure */ @@ -335,7 +335,7 @@ static int act_redirect_send return SIEVE_EXEC_TEMP_FAILURE; /* Open SMTP transport */ - smtp_handle = sieve_smtp_open(senv, ctx->to_address, sender, &output); + sctx = sieve_smtp_start_single(senv, ctx->to_address, sender, &output); /* Remove unwanted headers */ input = i_stream_create_header_filter @@ -358,7 +358,7 @@ static int act_redirect_send i_stream_unref(&input); /* Close SMTP transport */ - if ( (ret=sieve_smtp_close(senv, smtp_handle, &error)) <= 0 ) { + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if ( ret < 0 ) { sieve_result_global_log_error(aenv, "failed to redirect message to <%s>: %s " diff --git a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c index e9490f0e449f05b450ccd8adedc65e65dd3a176b..1272ee7e35b981f057feacf586edb9e346915319 100644 --- a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c +++ b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c @@ -385,10 +385,10 @@ static bool ntfy_mailto_send const char *from = NULL, *from_smtp = NULL; const char *subject = mtctx->uri->subject; const char *body = mtctx->uri->body; - string_t *to, *cc; + string_t *to, *cc, *all; const struct uri_mailto_recipient *recipients; const struct uri_mailto_header_field *headers; - void *smtp_handle; + struct sieve_smtp_context *sctx; struct ostream *output; string_t *msg; unsigned int count, i, hcount, h; @@ -445,6 +445,7 @@ static bool ntfy_mailto_send /* Compose To and Cc headers */ to = NULL; cc = NULL; + all = t_str_new(256); for ( i = 0; i < count; i++ ) { if ( recipients[i].carbon_copy ) { if ( cc == NULL ) { @@ -463,6 +464,15 @@ static bool ntfy_mailto_send str_append(to, recipients[i].full); } } + if ( i < 3) { + if ( i > 0 ) + str_append(all, ", "); + str_append_c(all, '<'); + str_append(all, str_sanitize(recipients[i].normalized, 256)); + str_append_c(all, '>'); + } else if (i == 3) { + str_printfa(all, ", ... (%u total)", count); + } } msg = t_str_new(512); @@ -534,30 +544,28 @@ static bool ntfy_mailto_send str_append(msg, "\r\nNotification of new message.\r\n"); } + sctx = sieve_smtp_start(senv, from_smtp); + /* Send message to all recipients */ - for ( i = 0; i < count; i++ ) { - smtp_handle = sieve_smtp_open - (senv, recipients[i].normalized, from_smtp, &output); + for ( i = 0; i < count; i++ ) + sieve_smtp_add_rcpt(sctx, recipients[i].normalized); - o_stream_send(output, str_data(msg), str_len(msg)); + output = sieve_smtp_send(sctx); + o_stream_send(output, str_data(msg), str_len(msg)); - if ( (ret=sieve_smtp_close(senv, smtp_handle, &error)) <= 0 ) { - if (ret < 0) { - sieve_enotify_global_log_error(nenv, - "failed to send mail notification to <%s>: %s (temporary failure)", - str_sanitize(recipients[i].normalized, 256), - str_sanitize(error, 512)); - } else { - sieve_enotify_global_error(nenv, - "failed to send mail notification to <%s>: %s (permanent failure)", - str_sanitize(recipients[i].normalized, 256), - str_sanitize(error, 512)); - } + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { + if (ret < 0) { + sieve_enotify_global_log_error(nenv, + "failed to send mail notification to %s: %s (temporary failure)", + str_c(all), str_sanitize(error, 512)); } else { - sieve_enotify_global_info(nenv, - "sent mail notification to <%s>", - str_sanitize(recipients[i].normalized, 256)); + sieve_enotify_global_error(nenv, + "failed to send mail notification to %s: %s (permanent failure)", + str_c(all), str_sanitize(error, 512)); } + } else { + sieve_enotify_global_info(nenv, + "sent mail notification to %s", str_c(all)); } return TRUE; diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c index ffdb3b5b78b015760903200ab021dacfb2af17b4..090dea8a2f367ccd124f40bd67fd196cea7dc31b 100644 --- a/src/lib-sieve/plugins/notify/cmd-notify.c +++ b/src/lib-sieve/plugins/notify/cmd-notify.c @@ -689,12 +689,11 @@ static bool act_notify_send { const struct sieve_script_env *senv = aenv->scriptenv; const struct ext_notify_recipient *recipients; - void *smtp_handle; + struct sieve_smtp_context *sctx; unsigned int count, i; struct ostream *output; - string_t *msg; + string_t *msg, *to, *all; const char *outmsgid, *error; - size_t hdr_size; int ret; /* Get recipients */ @@ -706,7 +705,7 @@ static bool act_notify_send } /* Just to be sure */ - if ( senv->smtp_open == NULL || senv->smtp_close == NULL ) { + if ( !sieve_smtp_available(senv) ) { sieve_result_global_warning(aenv, "notify action has no means to send mail"); return TRUE; @@ -753,45 +752,54 @@ static bool act_notify_send rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit"); } - hdr_size = str_len(msg); + outmsgid = sieve_message_get_new_id(aenv->svinst); + rfc2822_header_write(msg, "Message-ID", outmsgid); - /* Send message to all recipients */ + if ( sieve_message_get_sender(aenv->msgctx) != NULL ) + sctx = sieve_smtp_start(senv, senv->postmaster_address); + else + sctx = sieve_smtp_start(senv, NULL); + + /* Add all recipients (and compose To header field) */ + to = t_str_new(128); + all = t_str_new(256); for ( i = 0; i < count; i++ ) { - if ( sieve_message_get_sender(aenv->msgctx) != NULL ) - smtp_handle = sieve_smtp_open - (senv, recipients[i].normalized, senv->postmaster_address, &output); - else - smtp_handle = sieve_smtp_open - (senv, recipients[i].normalized, NULL, &output); - - str_truncate(msg, hdr_size); - - outmsgid = sieve_message_get_new_id(aenv->svinst); - rfc2822_header_write(msg, "Message-ID", outmsgid); - rfc2822_header_write(msg, "To", recipients[i].full); - - /* Generate message body */ - str_printfa(msg, "\r\n%s\r\n", act->message); - - o_stream_send(output, str_data(msg), str_len(msg)); - - if ( (ret=sieve_smtp_close(senv, smtp_handle, &error)) <= 0 ) { - if (ret < 0) { - sieve_result_global_log_error(aenv, - "failed to send mail notification to <%s>: %s (temporary failure)", - str_sanitize(recipients[i].normalized, 256), - str_sanitize(error, 512)); - } else { - sieve_result_global_error(aenv, - "failed to send mail notification to <%s>: %s (permanent failure)", - str_sanitize(recipients[i].normalized, 256), - str_sanitize(error, 512)); - } + sieve_smtp_add_rcpt(sctx, recipients[i].normalized); + if ( i > 0 ) + str_append(to, ", "); + str_append(to, recipients[i].full); + if ( i < 3) { + if ( i > 0 ) + str_append(all, ", "); + str_append_c(all, '<'); + str_append(all, str_sanitize(recipients[i].normalized, 256)); + str_append_c(all, '>'); + } else if (i == 3) { + str_printfa(all, ", ... (%u total)", count); + } + } + + rfc2822_header_write(msg, "To", str_c(to)); + + /* Generate message body */ + str_printfa(msg, "\r\n%s\r\n", act->message); + + output = sieve_smtp_send(sctx); + o_stream_send(output, str_data(msg), str_len(msg)); + + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { + if (ret < 0) { + sieve_result_global_log_error(aenv, + "failed to send mail notification to %s: %s (temporary failure)", + str_c(all), str_sanitize(error, 512)); } else { - sieve_result_global_log(aenv, - "sent mail notification to <%s>", - str_sanitize(recipients[i].normalized, 256)); + sieve_result_global_error(aenv, + "failed to send mail notification to %s: %s (permanent failure)", + str_c(all), str_sanitize(error, 512)); } + } else { + sieve_result_global_log(aenv, + "sent mail notification to %s", str_c(all)); } return TRUE; diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index 64a2ca72c42b00acc126c1ed7e8cd9369dce324f..3a36859bbe20d3ed3c419392f7207180136d0c36 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -901,7 +901,7 @@ static bool act_vacation_send { const struct sieve_message_data *msgdata = aenv->msgdata; const struct sieve_script_env *senv = aenv->scriptenv; - void *smtp_handle; + struct sieve_smtp_context *sctx; struct ostream *output; string_t *msg; const char *const *headers; @@ -933,7 +933,8 @@ static bool act_vacation_send /* Open smtp session */ - smtp_handle = sieve_smtp_open(senv, reply_to, smtp_from, &output); + sctx = sieve_smtp_start_single(senv, reply_to, smtp_from, &output); + outmsgid = sieve_message_get_new_id(aenv->svinst); /* Produce a proper reply */ @@ -992,7 +993,7 @@ static bool act_vacation_send o_stream_send(output, str_data(msg), str_len(msg)); /* Close smtp session */ - if ( (ret=sieve_smtp_close(senv, smtp_handle, &error)) <= 0 ) { + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if ( ret < 0 ) { sieve_result_global_log_error(aenv, "failed to send vacation response to <%s>: %s (temporary error)", diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 4bcf4a8416f76957753398b6d95bc52804e34d6c..9e39fac426c08a28341d489c089a144f7aa264ed 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -783,20 +783,20 @@ static bool sieve_action_do_reject_mail const struct sieve_message_data *msgdata = aenv->msgdata; struct istream *input; struct ostream *output; - void *smtp_handle; + struct sieve_smtp_context *sctx; const char *new_msgid, *boundary, *header, *error; string_t *hdr; int ret; + sctx = sieve_smtp_start_single(senv, sender, NULL, &output); + /* Just to be sure */ - if ( !sieve_smtp_available(senv) ) { + if ( sctx == NULL ) { sieve_result_global_warning (aenv, "reject action has no means to send mail"); return TRUE; } - smtp_handle = sieve_smtp_open(senv, sender, NULL, &output); - new_msgid = sieve_message_get_new_id(svinst); boundary = t_strdup_printf("%s/%s", my_pid, svinst->hostname); @@ -874,7 +874,7 @@ static bool sieve_action_do_reject_mail str_printfa(hdr, "\r\n\r\n--%s--\r\n", boundary); o_stream_send(output, str_data(hdr), str_len(hdr)); - if ( (ret=sieve_smtp_close(senv, smtp_handle, &error)) <= 0 ) { + if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) { if ( ret < 0 ) { sieve_result_global_log_error(aenv, "failed to send rejection message to <%s>: %s " @@ -885,7 +885,6 @@ static bool sieve_action_do_reject_mail "failed to send rejection message to <%s>: %s " "(permanent failure)", str_sanitize(sender, 256), str_sanitize(error, 512)); - } return FALSE; } diff --git a/src/lib-sieve/sieve-smtp.c b/src/lib-sieve/sieve-smtp.c index 3ffdcb6c939eab403362beeb412e1d97694b87f0..335a8abdc5f7d50b260ce42d3fe295b7e84cc35f 100644 --- a/src/lib-sieve/sieve-smtp.c +++ b/src/lib-sieve/sieve-smtp.c @@ -5,28 +5,75 @@ #include "sieve-common.h" #include "sieve-smtp.h" +struct sieve_smtp_context { + const struct sieve_script_env *senv; + void *handle; + + unsigned int sent:1; +}; + bool sieve_smtp_available (const struct sieve_script_env *senv) { - return ( senv->smtp_open != NULL && senv->smtp_close != NULL ); + return ( senv->smtp_start != NULL && senv->smtp_add_rcpt != NULL && + senv->smtp_send != NULL && senv->smtp_finish != NULL ); } -void *sieve_smtp_open -(const struct sieve_script_env *senv, const char *destination, - const char *return_path, struct ostream **output_r) +struct sieve_smtp_context *sieve_smtp_start +(const struct sieve_script_env *senv, const char *return_path) { + struct sieve_smtp_context *sctx; + void *handle; + if ( !sieve_smtp_available(senv) ) return NULL; - return senv->smtp_open(senv, destination, return_path, output_r); + handle = senv->smtp_start(senv, return_path); + i_assert( handle != NULL ); + + sctx = i_new(struct sieve_smtp_context, 1); + sctx->senv = senv; + sctx->handle = handle; + + return sctx; +} + +void sieve_smtp_add_rcpt +(struct sieve_smtp_context *sctx, const char *address) +{ + i_assert(!sctx->sent); + sctx->senv->smtp_add_rcpt(sctx->handle, address); +} + +struct ostream *sieve_smtp_send +(struct sieve_smtp_context *sctx) +{ + i_assert(!sctx->sent); + sctx->sent = TRUE; + + return sctx->senv->smtp_send(sctx->handle); +} + +struct sieve_smtp_context *sieve_smtp_start_single +(const struct sieve_script_env *senv, const char *destination, + const char *return_path, struct ostream **output_r) +{ + struct sieve_smtp_context *sctx; + + sctx = sieve_smtp_start(senv, return_path); + sieve_smtp_add_rcpt(sctx, destination); + *output_r = sieve_smtp_send(sctx); + + return sctx; } -int sieve_smtp_close -(const struct sieve_script_env *senv, void *handle, - const char **error_r) +int sieve_smtp_finish +(struct sieve_smtp_context *sctx, const char **error_r) { - i_assert( sieve_smtp_available(senv) ); + const struct sieve_script_env *senv = sctx->senv; + void *handle = sctx->handle; - return senv->smtp_close(senv, handle, error_r); + i_free(sctx); + return senv->smtp_finish(handle, error_r); } diff --git a/src/lib-sieve/sieve-smtp.h b/src/lib-sieve/sieve-smtp.h index fa68bb239b6d99a6649e6c16bbdf165029015a5f..d8684ead7dd37a35d377fac8c14853c7958140df 100644 --- a/src/lib-sieve/sieve-smtp.h +++ b/src/lib-sieve/sieve-smtp.h @@ -9,12 +9,20 @@ bool sieve_smtp_available (const struct sieve_script_env *senv); -// FIXME: support multiple recipients -void *sieve_smtp_open +struct sieve_smtp_context; + +struct sieve_smtp_context *sieve_smtp_start + (const struct sieve_script_env *senv, const char *return_path); +void sieve_smtp_add_rcpt + (struct sieve_smtp_context *sctx, const char *address); +struct ostream *sieve_smtp_send + (struct sieve_smtp_context *sctx); + +struct sieve_smtp_context *sieve_smtp_start_single (const struct sieve_script_env *senv, const char *destination, - const char *return_path, struct ostream **output_r); -int sieve_smtp_close - (const struct sieve_script_env *senv, void *handle, - const char **error_r); + const char *return_path, struct ostream **output_r); + +int sieve_smtp_finish + (struct sieve_smtp_context *sctx, const char **error_r); #endif /* __SIEVE_SMTP_H */ diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h index ed902313990b2b139f182dffb3a480c57aefd072..bd9de2187f2a6bd93d23a1a52e44822e3bfec48b 100644 --- a/src/lib-sieve/sieve-types.h +++ b/src/lib-sieve/sieve-types.h @@ -192,13 +192,15 @@ struct sieve_script_env { /* Callbacks */ /* Interface for sending mail */ - void *(*smtp_open) - (const struct sieve_script_env *senv, const char *destination, - const char *return_path, struct ostream **output_r); + void *(*smtp_start) + (const struct sieve_script_env *senv, const char *return_path); + /* Add a new recipient */ + void (*smtp_add_rcpt) (void *handle, const char *address); + /* Get an output stream where the message can be written to. The recipients + must already be added before calling this. */ + struct ostream *(*smtp_send)(void *handle); /* Returns 1 on success, 0 on permanent failure, -1 on temporary failure. */ - int (*smtp_close) - (const struct sieve_script_env *senv, void *handle, - const char **error_r); + int (*smtp_finish)(void *handle, const char **error_r); /* Interface for marking and checking duplicates */ int (*duplicate_check) diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c index a426c961fa470501667e7276db51d86f17204a7f..b48edb0fdc3fbe0d052f7b6c86913954bb70649f 100644 --- a/src/plugins/lda-sieve/lda-sieve-plugin.c +++ b/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -68,20 +68,31 @@ static const struct sieve_callbacks lda_sieve_callbacks = { * Mail transmission */ -static void *lda_sieve_smtp_open -(const struct sieve_script_env *senv, const char *destination, - const char *return_path, struct ostream **output_r) +static void *lda_sieve_smtp_start +(const struct sieve_script_env *senv, const char *return_path) { struct mail_deliver_context *dctx = (struct mail_deliver_context *) senv->script_context; - return (void *)smtp_client_init - (dctx->set, destination, return_path, output_r); + return (void *)smtp_client_init(dctx->set, return_path); } -static int lda_sieve_smtp_close -(const struct sieve_script_env *senv ATTR_UNUSED, void *handle, - const char **error_r) +static void lda_sieve_smtp_add_rcpt(void *handle, const char *address) +{ + struct smtp_client *smtp_client = (struct smtp_client *) handle; + + smtp_client_add_rcpt(smtp_client, address); +} + +static struct ostream *lda_sieve_smtp_send(void *handle) +{ + struct smtp_client *smtp_client = (struct smtp_client *) handle; + + return smtp_client_send(smtp_client); +} + +static int lda_sieve_smtp_finish +(void *handle, const char **error_r) { struct smtp_client *smtp_client = (struct smtp_client *) handle; @@ -864,8 +875,10 @@ static int lda_sieve_execute scriptenv.mailbox_autosubscribe = mdctx->set->lda_mailbox_autosubscribe; scriptenv.user = mdctx->dest_user; scriptenv.postmaster_address = mdctx->set->postmaster_address; - scriptenv.smtp_open = lda_sieve_smtp_open; - scriptenv.smtp_close = lda_sieve_smtp_close; + scriptenv.smtp_start = lda_sieve_smtp_start; + scriptenv.smtp_add_rcpt = lda_sieve_smtp_add_rcpt; + scriptenv.smtp_send = lda_sieve_smtp_send; + scriptenv.smtp_finish = lda_sieve_smtp_finish; scriptenv.duplicate_mark = lda_sieve_duplicate_mark; scriptenv.duplicate_check = lda_sieve_duplicate_check; scriptenv.reject_mail = lda_sieve_reject_mail; diff --git a/src/sieve-tools/sieve-filter.c b/src/sieve-tools/sieve-filter.c index 466277543d4db0cccaaa030e80f0423f0fdbfec6..b5e420600ba8235139ea30a9b05faf8dab67d757 100644 --- a/src/sieve-tools/sieve-filter.c +++ b/src/sieve-tools/sieve-filter.c @@ -534,8 +534,6 @@ int main(int argc, char **argv) scriptenv.default_mailbox = dst_mailbox; scriptenv.user = mail_user; scriptenv.postmaster_address = "postmaster@example.com"; - scriptenv.smtp_open = NULL; - scriptenv.smtp_close = NULL; /* Compose filter context */ memset(&sfdata, 0, sizeof(sfdata)); diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c index 59ec4d70997afeabcf85f6b1c1f135309756eb17..3de246aeb202da1e13f057f39a3739c7c0051b94 100644 --- a/src/sieve-tools/sieve-test.c +++ b/src/sieve-tools/sieve-test.c @@ -56,22 +56,34 @@ static void print_help(void) * Dummy SMTP session */ -static void *sieve_smtp_open -(const struct sieve_script_env *senv ATTR_UNUSED, const char *destination, - const char *return_path, struct ostream **output_r) +static void *sieve_smtp_start +(const struct sieve_script_env *senv ATTR_UNUSED, + const char *return_path) { - i_info("sending message from <%s> to <%s>:", - ( return_path == NULL ? "" : return_path ), destination); - printf("\nSTART MESSAGE:\n"); + struct ostream *output; - *output_r = o_stream_create_fd(STDOUT_FILENO, (size_t)-1, FALSE); + i_info("sending message from <%s>:", + ( return_path == NULL ? "" : return_path )); - return (void*)*output_r; + output = o_stream_create_fd(STDOUT_FILENO, (size_t)-1, FALSE); + return (void*)output; } -static int sieve_smtp_close -(const struct sieve_script_env *senv ATTR_UNUSED, void *handle, - const char **error_r ATTR_UNUSED) +static void sieve_smtp_add_rcpt +(void *handle ATTR_UNUSED, const char *address) +{ + printf("\nRECIPIENT: %s\n", address); +} + +static struct ostream *sieve_smtp_send(void *handle) +{ + printf("START MESSAGE:\n"); + + return (struct ostream *)handle; +} + +static int sieve_smtp_finish +(void *handle, const char **error_r ATTR_UNUSED) { struct ostream *output = (struct ostream *)handle; @@ -273,8 +285,10 @@ int main(int argc, char **argv) scriptenv.default_mailbox = mailbox; scriptenv.user = sieve_tool_get_mail_user(sieve_tool); scriptenv.postmaster_address = "postmaster@example.com"; - scriptenv.smtp_open = sieve_smtp_open; - scriptenv.smtp_close = sieve_smtp_close; + scriptenv.smtp_start = sieve_smtp_start; + scriptenv.smtp_add_rcpt = sieve_smtp_add_rcpt; + scriptenv.smtp_send = sieve_smtp_send; + scriptenv.smtp_finish = sieve_smtp_finish; scriptenv.duplicate_mark = duplicate_mark; scriptenv.duplicate_check = duplicate_check; scriptenv.trace_stream = tracestream; diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c index 7a842241ab06a0e3768585fac1ea48ace4fccbf3..b3d24fcc55ec7ebbe00eb6bb7e8112fd9c943cd5 100644 --- a/src/testsuite/testsuite-script.c +++ b/src/testsuite/testsuite-script.c @@ -110,8 +110,10 @@ bool testsuite_script_run(const struct sieve_runtime_env *renv) memset(&scriptenv, 0, sizeof(scriptenv)); scriptenv.default_mailbox = "INBOX"; scriptenv.postmaster_address = "postmaster@example.com"; - scriptenv.smtp_open = NULL; - scriptenv.smtp_close = NULL; + scriptenv.smtp_start = NULL; + scriptenv.smtp_add_rcpt = NULL; + scriptenv.smtp_send = NULL; + scriptenv.smtp_finish = NULL; scriptenv.duplicate_mark = NULL; scriptenv.duplicate_check = NULL; scriptenv.user = renv->scriptenv->user; @@ -181,8 +183,10 @@ bool testsuite_script_multiscript memset(&scriptenv, 0, sizeof(scriptenv)); scriptenv.default_mailbox = "INBOX"; scriptenv.postmaster_address = "postmaster@example.com"; - scriptenv.smtp_open = NULL; - scriptenv.smtp_close = NULL; + scriptenv.smtp_start = NULL; + scriptenv.smtp_add_rcpt = NULL; + scriptenv.smtp_send = NULL; + scriptenv.smtp_finish = NULL; scriptenv.duplicate_mark = NULL; scriptenv.duplicate_check = NULL; scriptenv.user = renv->scriptenv->user; diff --git a/src/testsuite/testsuite-smtp.c b/src/testsuite/testsuite-smtp.c index fc9878d261c7e23f1caec6ec014ebf93c5c7a195..d2944fa95347522b2750c5eb6fc8c0dd1bef4113 100644 --- a/src/testsuite/testsuite-smtp.c +++ b/src/testsuite/testsuite-smtp.c @@ -68,48 +68,66 @@ void testsuite_smtp_reset(void) */ struct testsuite_smtp { - const char *tmp_path; + char *msg_file, *return_path; struct ostream *output; }; -void *testsuite_smtp_open -(const struct sieve_script_env *senv ATTR_UNUSED, const char *destination, - const char *return_path, struct ostream **output_r) +void testsuite_smtp_add_rcpt(void *handle, const char *address); +struct ostream *testsuite_smtp_send(void *handle); +int testsuite_smtp_finish + (void *handle, const char **error_r); + + +void *testsuite_smtp_start +(const struct sieve_script_env *senv ATTR_UNUSED, const char *return_path) { - struct testsuite_smtp_message smtp_msg; struct testsuite_smtp *smtp; unsigned int smtp_count = array_count(&testsuite_smtp_messages); int fd; - smtp_msg.file = p_strdup_printf(testsuite_smtp_pool, - "%s/%d.eml", testsuite_smtp_tmp, smtp_count); - smtp_msg.envelope_from = - ( return_path != NULL ? p_strdup(testsuite_smtp_pool, return_path) : NULL ); - smtp_msg.envelope_to = p_strdup(testsuite_smtp_pool, destination); - - array_append(&testsuite_smtp_messages, &smtp_msg, 1); - - smtp = t_new(struct testsuite_smtp, 1); - smtp->tmp_path = smtp_msg.file; + smtp = i_new(struct testsuite_smtp, 1); - if ( (fd=open(smtp->tmp_path, O_WRONLY | O_CREAT, 0600)) < 0 ) { + smtp->msg_file = i_strdup_printf("%s/%d.eml", testsuite_smtp_tmp, smtp_count); + smtp->return_path = i_strdup(return_path); + + if ( (fd=open(smtp->msg_file, O_WRONLY | O_CREAT, 0600)) < 0 ) { i_fatal("failed create tmp file for SMTP simulation: open(%s) failed: %m", - smtp->tmp_path); + smtp->msg_file); } smtp->output = o_stream_create_fd(fd, (size_t)-1, TRUE); - *output_r = smtp->output; return (void *) smtp; } -int testsuite_smtp_close -(const struct sieve_script_env *senv ATTR_UNUSED, void *handle, - const char **error_r ATTR_UNUSED) +void testsuite_smtp_add_rcpt(void *handle, const char *address) +{ + struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; + struct testsuite_smtp_message *msg; + + msg = array_append_space(&testsuite_smtp_messages); + + msg->file = p_strdup(testsuite_smtp_pool, smtp->msg_file); + msg->envelope_from = p_strdup(testsuite_smtp_pool, smtp->return_path); + msg->envelope_to = p_strdup(testsuite_smtp_pool, address); +} + +struct ostream *testsuite_smtp_send(void *handle) +{ + struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; + + return smtp->output; +} + +int testsuite_smtp_finish +(void *handle, const char **error_r ATTR_UNUSED) { struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle; o_stream_unref(&smtp->output); + i_free(smtp->msg_file); + i_free(smtp->return_path); + i_free(smtp); return 1; } diff --git a/src/testsuite/testsuite-smtp.h b/src/testsuite/testsuite-smtp.h index 249f1a8d3ec60c46eefb34b66d54c008c10aeb10..3a028f466bbb5e8723512b127c19062336834953 100644 --- a/src/testsuite/testsuite-smtp.h +++ b/src/testsuite/testsuite-smtp.h @@ -12,11 +12,13 @@ void testsuite_smtp_reset(void); * Simulated SMTP out */ -void *testsuite_smtp_open - (const struct sieve_script_env *senv ATTR_UNUSED, const char *destination, - const char *return_path, struct ostream **output_r); -int testsuite_smtp_close - (const struct sieve_script_env *senv, void *handle, const char **error_r); +void *testsuite_smtp_start + (const struct sieve_script_env *senv ATTR_UNUSED, + const char *return_path); +void testsuite_smtp_add_rcpt(void *handle, const char *address); +struct ostream *testsuite_smtp_send(void *handle); +int testsuite_smtp_finish + (void *handle, const char **error_r); /* * Access diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 11b3a5c0520d421f1ab6ef1c10cb577fe07f8852..d53eafbc80786476a2a27876545aec1cc6d9dddc 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -179,8 +179,10 @@ int main(int argc, char **argv) scriptenv.user = sieve_tool_get_mail_user(sieve_tool); scriptenv.default_mailbox = "INBOX"; scriptenv.postmaster_address = "postmaster@example.com"; - scriptenv.smtp_open = testsuite_smtp_open; - scriptenv.smtp_close = testsuite_smtp_close; + scriptenv.smtp_start = testsuite_smtp_start; + scriptenv.smtp_add_rcpt = testsuite_smtp_add_rcpt; + scriptenv.smtp_send = testsuite_smtp_send; + scriptenv.smtp_finish = testsuite_smtp_finish; scriptenv.trace_stream = tracestream; scriptenv.trace_config = tr_config; diff --git a/tests/deprecated/notify/mailto.svtest b/tests/deprecated/notify/mailto.svtest index cdbddf2dd4198dff7ef248450787c6a409db7c46..172433984f30ddfc12fa61c257fd0652e5c65afe 100644 --- a/tests/deprecated/notify/mailto.svtest +++ b/tests/deprecated/notify/mailto.svtest @@ -84,8 +84,8 @@ test "Multiple recipients" { test_fail "auto-submitted header not found for third message"; } - if not address :count "eq" :comparator "i;ascii-numeric" "to" "1" { - test_fail "too many recipients in To header"; + if not address :count "eq" :comparator "i;ascii-numeric" "to" "3" { + test_fail "wrong number of recipients in To header"; } if not address :count "eq" :comparator "i;ascii-numeric" "cc" "0" {