diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 2ac3d1e0e2517c3c530d2df8e1e4ac30442ed9e9..d37614c48af5ee2981d748d4d3c551c911bce6ac 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -87,6 +87,9 @@ act_redirect_check_duplicate(const struct sieve_runtime_env *renv, static void act_redirect_print(const struct sieve_action *action, const struct sieve_result_print_env *rpenv, bool *keep); + +static int +act_redirect_start(const struct sieve_action_exec_env *aenv, void **tr_context); static int act_redirect_execute(const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep); @@ -99,6 +102,7 @@ const struct sieve_action_def act_redirect = { .equals = act_redirect_equals, .check_duplicate = act_redirect_check_duplicate, .print = act_redirect_print, + .start = act_redirect_start, .execute = act_redirect_execute, .commit = act_redirect_commit, }; @@ -252,6 +256,11 @@ cmd_redirect_operation_execute(const struct sieve_runtime_env *renv, * Action implementation */ +struct act_redirect_transaction { + const char *msg_id, *new_msg_id; + const char *dupeid; +}; + static bool act_redirect_equals(const struct sieve_script_env *senv ATTR_UNUSED, const struct sieve_action *act1, @@ -519,6 +528,19 @@ act_redirect_check_loop_header(const struct sieve_action_exec_env *aenv, return SIEVE_EXEC_OK; } +static int +act_redirect_start(const struct sieve_action_exec_env *aenv, void **tr_context) +{ + struct act_redirect_transaction *trans; + pool_t pool = sieve_result_pool(aenv->result); + + /* Create transaction context */ + trans = p_new(pool, struct act_redirect_transaction, 1); + *tr_context = trans; + + return SIEVE_EXEC_OK; +} + static int act_redirect_execute(const struct sieve_action_exec_env *aenv ATTR_UNUSED, void *tr_context ATTR_UNUSED, bool *keep) @@ -538,12 +560,12 @@ act_redirect_commit(const struct sieve_action_exec_env *aenv, struct sieve_instance *svinst = eenv->svinst; struct act_redirect_context *ctx = (struct act_redirect_context *)action->context; + struct act_redirect_transaction *trans = tr_context; struct sieve_message_context *msgctx = aenv->msgctx; struct mail *mail = (action->mail != NULL ? action->mail : sieve_message_get_mail(msgctx)); const struct sieve_message_data *msgdata = eenv->msgdata; const struct sieve_script_env *senv = eenv->scriptenv; - const char *msg_id = msgdata->id, *new_msg_id = NULL; const char *dupeid = NULL; bool loop_detected = FALSE; int ret; @@ -553,14 +575,18 @@ act_redirect_commit(const struct sieve_action_exec_env *aenv, */ /* Create Message-ID for the message if it has none */ - if (msg_id == NULL) - msg_id = new_msg_id = sieve_message_get_new_id(eenv->svinst); + trans->msg_id = msgdata->id; + if (trans->msg_id == NULL) { + pool_t pool = sieve_result_pool(aenv->result); + trans->msg_id = trans->new_msg_id = + p_strdup(pool, sieve_message_get_new_id(svinst)); + } /* Create ID for duplicate database lookup */ - ret = act_redirect_get_duplicate_id(ctx, aenv, msg_id, &dupeid); + ret = act_redirect_get_duplicate_id(ctx, aenv, trans->msg_id, &dupeid); if (ret != SIEVE_EXEC_OK) return ret; - i_assert(dupeid != NULL); + i_assert(trans->dupeid != NULL); /* Check whether we've seen this message before */ if (sieve_action_duplicate_check(senv, dupeid, strlen(dupeid))) { @@ -587,11 +613,12 @@ act_redirect_commit(const struct sieve_action_exec_env *aenv, * Try to forward the message */ - ret = act_redirect_send(aenv, mail, ctx, new_msg_id); + ret = act_redirect_send(aenv, mail, ctx, trans->new_msg_id); if (ret == SIEVE_EXEC_OK) { /* Mark this message id as forwarded to the specified destination */ - sieve_action_duplicate_mark(senv, dupeid, strlen(dupeid), + sieve_action_duplicate_mark( + senv, trans->dupeid, strlen(trans->dupeid), ioloop_time + svinst->redirect_duplicate_period); eenv->exec_status->significant_action_executed = TRUE;