bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "lib.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "ioloop.h"
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen#include "array.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "str.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "str-sanitize.h"
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen#include "time-util.h"
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen#include "unichar.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "var-expand.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "message-address.h"
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch#include "smtp-address.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "lda-settings.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "mail-storage.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "mail-namespace.h"
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen#include "mail-storage-private.h"
f41f6294f438bd16a35be64cef3bc90d2b66e0eaStephan Bosch#include "mail-duplicate.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen#include "mail-deliver.h"
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
f41f6294f438bd16a35be64cef3bc90d2b66e0eaStephan Bosch#define DUPLICATE_DB_NAME "lda-dupes"
f41f6294f438bd16a35be64cef3bc90d2b66e0eaStephan Bosch
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen#define MAIL_DELIVER_USER_CONTEXT(obj) \
79c7e806276f4eab6a48ec5dcd5e7c1378aae246Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, mail_deliver_user_module)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen#define MAIL_DELIVER_STORAGE_CONTEXT(obj) \
79c7e806276f4eab6a48ec5dcd5e7c1378aae246Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, mail_deliver_storage_module)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstruct mail_deliver_user {
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen union mail_user_module_context module_ctx;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mail_deliver_context *deliver_ctx;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen bool want_storage_id;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen};
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainendeliver_mail_func_t *deliver_mail = NULL;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainenstruct mail_deliver_cache {
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen bool filled;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const char *message_id;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const char *subject;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const char *from;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const char *from_envelope;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const char *storage_id;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen uoff_t psize, vsize;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen};
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainenstruct mail_deliver_mailbox {
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen union mailbox_module_context module_ctx;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen};
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainenstruct mail_deliver_transaction {
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen union mailbox_transaction_module_context module_ctx;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_cache cache;
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen};
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainenstatic const char *lda_log_wanted_headers[] = {
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen "From", "Message-ID", "Subject",
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen NULL
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen};
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainenstatic enum mail_fetch_field lda_log_wanted_fetch_fields =
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_deliver_user_module,
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen &mail_user_module_register);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_deliver_storage_module,
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen &mail_storage_module_register);
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Boschconst struct smtp_address *
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Boschmail_deliver_get_address(struct mail *mail, const char *header)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct message_address *addr;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen const char *str;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
16d8197506b63d2ca7e38447df9faf1612c1f288Timo Sirainen if (mail_get_first_header(mail, header, &str) <= 0)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen return NULL;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen addr = message_address_parse(pool_datastack_create(),
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen (const unsigned char *)str,
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen strlen(str), 1, FALSE);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen return addr == NULL || addr->mailbox == NULL || addr->domain == NULL ||
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen *addr->mailbox == '\0' || *addr->domain == '\0' ?
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch NULL : smtp_address_create_from_msg_temp(addr);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainenstatic void update_cache(pool_t pool, const char **old_str, const char *new_str)
0783364679d85752a759de55b3dfd108fc72d957Timo Sirainen{
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen if (new_str == NULL || new_str[0] == '\0')
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen *old_str = NULL;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen else if (*old_str == NULL || strcmp(*old_str, new_str) != 0)
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen *old_str = p_strdup(pool, new_str);
0783364679d85752a759de55b3dfd108fc72d957Timo Sirainen}
0783364679d85752a759de55b3dfd108fc72d957Timo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainenstatic void
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainenmail_deliver_log_update_cache(struct mail_deliver_cache *cache, pool_t pool,
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mail *mail)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const char *message_id = NULL, *subject = NULL, *from_envelope = NULL;
796d1ca5e01126f1328ac4cdec0c23491d0e3f10Timo Sirainen const char *from;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen if (cache->filled)
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen return;
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen cache->filled = TRUE;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen if (mail_get_first_header(mail, "Message-ID", &message_id) > 0)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen message_id = str_sanitize(message_id, 200);
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen update_cache(pool, &cache->message_id, message_id);
82727bef77e1e3abf7ae1b46290503b7899d8d92Timo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (mail_get_first_header_utf8(mail, "Subject", &subject) > 0)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen subject = str_sanitize(subject, 80);
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen update_cache(pool, &cache->subject, subject);
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch from = smtp_address_encode(mail_deliver_get_address(mail, "From"));
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen update_cache(pool, &cache->from, from);
82727bef77e1e3abf7ae1b46290503b7899d8d92Timo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE, &from_envelope) > 0)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen from_envelope = str_sanitize(from_envelope, 80);
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen update_cache(pool, &cache->from_envelope, from_envelope);
fd42aa358abc9fbd8c25b7625cc2a1dc3ecbcffdTimo Sirainen
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen if (mail_get_physical_size(mail, &cache->psize) < 0)
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen cache->psize = 0;
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen if (mail_get_virtual_size(mail, &cache->vsize) < 0)
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen cache->vsize = 0;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainenconst struct var_expand_table *
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainenmail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context *ctx,
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen const char *message)
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen{
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen unsigned int delivery_time_msecs;
6b6011c2242e470b41316f92512b282b5e306dacTimo Sirainen
2a494f93f48424d391552a419ad8872fbc771eb5Timo Sirainen /* If a mail was saved/copied, the cache is already filled and the
2a494f93f48424d391552a419ad8872fbc771eb5Timo Sirainen following call is ignored. Otherwise, only the source mail exists. */
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen if (ctx->cache == NULL)
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen ctx->cache = p_new(ctx->pool, struct mail_deliver_cache, 1);
d609c2ffca2b61556980b46e1de2303c662ad0f7Timo Sirainen mail_deliver_log_update_cache(ctx->cache, ctx->pool, ctx->src_mail);
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen /* This call finishes a mail delivery. With Sieve there may be multiple
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen mail deliveries. */
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen ctx->cache->filled = FALSE;
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen io_loop_time_refresh();
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen delivery_time_msecs = timeval_diff_msecs(&ioloop_timeval,
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen &ctx->delivery_time_started);
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const struct var_expand_table stack_tab[] = {
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { '$', message, NULL },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { 'm', ctx->cache->message_id != NULL ?
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen ctx->cache->message_id : "unspecified", "msgid" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { 's', ctx->cache->subject, "subject" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { 'f', ctx->cache->from, "from" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { 'e', ctx->cache->from_envelope, "from_envelope" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { 'p', dec2str(ctx->cache->psize), "size" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { 'w', dec2str(ctx->cache->vsize), "vsize" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { '\0', dec2str(delivery_time_msecs), "delivery_time" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { '\0', dec2str(ctx->session_time_msecs), "session_time" },
de0971aff3009fe6906c3631e8322908658a5e93Stephan Bosch { '\0', smtp_address_encode(ctx->rcpt_params.orcpt.addr), "to_envelope" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { '\0', ctx->cache->storage_id, "storage_id" },
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen { '\0', NULL, NULL }
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen };
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen return p_memdup(unsafe_data_stack_pool, stack_tab, sizeof(stack_tab));
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen}
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainenvoid mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen va_list args;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen string_t *str;
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen const struct var_expand_table *tab;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen const char *msg, *error;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
95fa94ecca92614f0c86455ce293b9d3ca7d15a5Timo Sirainen if (*ctx->set->deliver_log_format == '\0')
95fa94ecca92614f0c86455ce293b9d3ca7d15a5Timo Sirainen return;
95fa94ecca92614f0c86455ce293b9d3ca7d15a5Timo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen va_start(args, fmt);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen msg = t_strdup_vprintf(fmt, args);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen str = t_str_new(256);
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen tab = mail_deliver_ctx_get_log_var_expand_table(ctx, msg);
12e28ffc2655b6d0efce628eb7d93fa74fbd345bTimo Sirainen if (var_expand(str, ctx->set->deliver_log_format, tab, &error) <= 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen i_error("Failed to expand deliver_log_format=%s: %s",
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen ctx->set->deliver_log_format, error);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen i_info("%s", str_c(str));
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen va_end(args);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainenstruct mail_deliver_session *mail_deliver_session_init(void)
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen{
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen struct mail_deliver_session *session;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen pool_t pool;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen pool = pool_alloconly_create("mail deliver session", 1024);
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen session = p_new(pool, struct mail_deliver_session, 1);
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen session->pool = pool;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen return session;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen}
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainenvoid mail_deliver_session_deinit(struct mail_deliver_session **_session)
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen{
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen struct mail_deliver_session *session = *_session;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen *_session = NULL;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen pool_unref(&session->pool);
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen}
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainenint mail_deliver_save_open(struct mail_deliver_save_open_context *ctx,
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen const char *name, struct mailbox **box_r,
258adfa09081ea8600a39759d486e678b5aa5f60Timo Sirainen enum mail_error *error_r, const char **error_str_r)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mailbox *box;
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch enum mailbox_flags flags = 0;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen *box_r = NULL;
258adfa09081ea8600a39759d486e678b5aa5f60Timo Sirainen *error_r = MAIL_ERROR_NONE;
258adfa09081ea8600a39759d486e678b5aa5f60Timo Sirainen *error_str_r = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (!uni_utf8_str_is_valid(name)) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen *error_str_r = "Mailbox name not valid UTF-8";
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen *error_r = MAIL_ERROR_PARAMS;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return -1;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch if (ctx->lda_mailbox_autocreate)
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch flags |= MAILBOX_FLAG_AUTO_CREATE;
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch if (ctx->lda_mailbox_autosubscribe)
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch flags |= MAILBOX_FLAG_AUTO_SUBSCRIBE;
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch *box_r = box = mailbox_alloc_delivery(ctx->user, name, flags);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (mailbox_open(box) == 0)
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen return 0;
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi *error_str_r = mailbox_get_last_internal_error(box, error_r);
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch return -1;
ed51404d355ae65d762cee68aefdbf900903a658Timo Sirainen}
ed51404d355ae65d762cee68aefdbf900903a658Timo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainenstatic bool mail_deliver_check_duplicate(struct mail_deliver_session *session,
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen struct mailbox *box)
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen{
4dd0cbd517dc5d1210956a7c3e9e1ae714451dd8Timo Sirainen struct mailbox_metadata metadata;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen const guid_128_t *guid;
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen
4dd0cbd517dc5d1210956a7c3e9e1ae714451dd8Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen /* just play it safe and assume a duplicate */
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen return TRUE;
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen }
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen /* there shouldn't be all that many recipients,
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen so just do a linear search */
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen if (!array_is_created(&session->inbox_guids))
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen p_array_init(&session->inbox_guids, session->pool, 8);
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen array_foreach(&session->inbox_guids, guid) {
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen if (memcmp(metadata.guid, *guid, sizeof(metadata.guid)) == 0)
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen return TRUE;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen }
4dd0cbd517dc5d1210956a7c3e9e1ae714451dd8Timo Sirainen array_append(&session->inbox_guids, &metadata.guid, 1);
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen return FALSE;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen}
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainenvoid mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *session,
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainen struct mail_save_context *save_ctx)
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen{
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainen struct mailbox_transaction_context *trans =
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainen mailbox_save_get_transaction(save_ctx);
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainen struct mailbox *box = mailbox_transaction_get_mailbox(trans);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t guid;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainen if (strcmp(mailbox_get_name(box), "INBOX") != 0)
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen return;
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen /* avoid storing duplicate GUIDs to delivered mails to INBOX. this
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen happens if mail is delivered to same user multiple times within a
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen session. the problem with this is that if GUIDs are used as POP3
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen UIDLs, some clients can't handle the duplicates well. */
dbffb9e8b87b771851700a1acc353aa62b5ab7d7Timo Sirainen if (mail_deliver_check_duplicate(session, box)) {
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_generate(guid);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen mailbox_save_set_guid(save_ctx, guid_128_to_string(guid));
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen }
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen}
44f3f472a49078312432b785fddcfe7b95928391Timo Sirainen
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainenstatic struct mail *
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainenmail_deliver_open_mail(struct mailbox *box, uint32_t uid,
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen enum mail_fetch_field wanted_fields,
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen struct mailbox_transaction_context **trans_r)
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen{
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen struct mailbox_transaction_context *t;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen struct mail *mail;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen *trans_r = NULL;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST) < 0)
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen return NULL;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi t = mailbox_transaction_begin(box, 0, __func__);
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen mail = mail_alloc(t, wanted_fields, NULL);
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainen if (!mail_set_uid(mail, uid)) {
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen mail_free(&mail);
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen mailbox_transaction_rollback(&t);
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen }
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen *trans_r = t;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen return mail;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen}
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainenint mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen enum mail_flags flags, const char *const *keywords,
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mail_storage **storage_r)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen struct mail_deliver_save_open_context open_ctx;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mailbox *box;
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen enum mailbox_transaction_flags trans_flags;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mailbox_transaction_context *t;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mail_save_context *save_ctx;
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen struct mailbox_header_lookup_ctx *headers_ctx;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mail_keywords *kw;
04ca05320ecb84008aa1886e27020a4423b246c0Timo Sirainen struct mail *dest_mail;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen enum mail_error error;
9c550becf78b542a514fcf62ab7da0ff2a3d78f6Timo Sirainen const char *mailbox_name, *errstr, *guid;
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen struct mail_transaction_commit_changes changes;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen bool default_save;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen int ret = 0;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
f4704cef6ccb64d390198d0e0fddb9f2235a4d0bTimo Sirainen i_assert(ctx->dest_mail == NULL);
f4704cef6ccb64d390198d0e0fddb9f2235a4d0bTimo Sirainen
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch default_save = strcmp(mailbox, ctx->rcpt_default_mailbox) == 0;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen if (default_save)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ctx->tried_default_save = TRUE;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&open_ctx);
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch open_ctx.user = ctx->rcpt_user;
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen open_ctx.lda_mailbox_autocreate = ctx->set->lda_mailbox_autocreate;
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen open_ctx.lda_mailbox_autosubscribe = ctx->set->lda_mailbox_autosubscribe;
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen
f185133819c115c8cbc1c7e96804f237e23d255cTimo Sirainen mailbox_name = str_sanitize(mailbox, 80);
258adfa09081ea8600a39759d486e678b5aa5f60Timo Sirainen if (mail_deliver_save_open(&open_ctx, mailbox, &box,
258adfa09081ea8600a39759d486e678b5aa5f60Timo Sirainen &error, &errstr) < 0) {
16a92d0c84869c86c3d5e4cbb9fe1d455ff59457Timo Sirainen if (box != NULL) {
16a92d0c84869c86c3d5e4cbb9fe1d455ff59457Timo Sirainen *storage_r = mailbox_get_storage(box);
f9db221d0793f05c4631885e71f98145428a7e1bTimo Sirainen mailbox_free(&box);
16a92d0c84869c86c3d5e4cbb9fe1d455ff59457Timo Sirainen }
2f0c5d4567351c0752ec9dd809c8f0cdfe7f0e73Timo Sirainen mail_deliver_log(ctx, "save failed to open mailbox %s: %s",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_name, errstr);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen return -1;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *storage_r = mailbox_get_storage(box);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen trans_flags = MAILBOX_TRANSACTION_FLAG_EXTERNAL;
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen if (ctx->save_dest_mail)
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen trans_flags |= MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS;
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi t = mailbox_transaction_begin(box, trans_flags, __func__);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen kw = str_array_length(keywords) == 0 ? NULL :
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen mailbox_keywords_create_valid(box, keywords);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen save_ctx = mailbox_save_alloc(t);
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch if (ctx->mail_from != NULL) {
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch mailbox_save_set_from_envelope(save_ctx,
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch smtp_address_encode(ctx->mail_from));
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch }
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen mailbox_save_set_flags(save_ctx, flags, kw);
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen headers_ctx = mailbox_header_lookup_init(box, lda_log_wanted_headers);
04ca05320ecb84008aa1886e27020a4423b246c0Timo Sirainen dest_mail = mailbox_save_get_dest_mail(save_ctx);
04ca05320ecb84008aa1886e27020a4423b246c0Timo Sirainen mail_add_temp_wanted_fields(dest_mail, lda_log_wanted_fetch_fields, NULL);
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen mailbox_header_lookup_unref(&headers_ctx);
21fdf5394fbc307673b6c4b33f2497751a9ca1feTimo Sirainen mail_deliver_deduplicate_guid_if_needed(ctx->session, save_ctx);
291f1e54dcb8c7f38e5b78afc1eaf518e3756692Timo Sirainen
4f9b0e8c6ae16b23cfd33c0b762353442d7cfbc0Timo Sirainen if (mailbox_save_using_mail(&save_ctx, ctx->src_mail) < 0)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ret = -1;
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen if (kw != NULL)
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen mailbox_keywords_unref(&kw);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen if (ret < 0)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen mailbox_transaction_rollback(&t);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen else
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen ret = mailbox_transaction_commit_get_changes(&t, &changes);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen if (ret == 0) {
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ctx->saved_mail = TRUE;
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen if (ctx->save_dest_mail) {
9c550becf78b542a514fcf62ab7da0ff2a3d78f6Timo Sirainen /* copying needs the message body. with maildir we also
9c550becf78b542a514fcf62ab7da0ff2a3d78f6Timo Sirainen need to get the GUID in case the message gets
9562831b85e433ae92edd3ea42294578239eff98Timo Sirainen expunged. get these early so the copying won't fail
9562831b85e433ae92edd3ea42294578239eff98Timo Sirainen later on. */
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainen i_assert(array_count(&changes.saved_uids) == 1);
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainen const struct seq_range *range =
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainen array_idx(&changes.saved_uids, 0);
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainen i_assert(range->seq1 == range->seq2);
a9791113953195d1ed52d9b5bf63f1869758742dTimo Sirainen ctx->dest_mail = mail_deliver_open_mail(box, range->seq1,
6f3244c59907273651b775d7fa00c8e3166a96c2Timo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_GUID, &t);
9562831b85e433ae92edd3ea42294578239eff98Timo Sirainen if (ctx->dest_mail == NULL) {
9562831b85e433ae92edd3ea42294578239eff98Timo Sirainen i_assert(t == NULL);
9562831b85e433ae92edd3ea42294578239eff98Timo Sirainen } else if (mail_get_special(ctx->dest_mail, MAIL_FETCH_GUID, &guid) < 0) {
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen mail_free(&ctx->dest_mail);
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen mailbox_transaction_rollback(&t);
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen }
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen }
85b6e401b7461a833e94c1ab54161f8696e090b5Timo Sirainen mail_deliver_log(ctx, "saved mail to %s", mailbox_name);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen pool_unref(&changes.pool);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen } else {
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen mail_deliver_log(ctx, "save failed to %s: %s", mailbox_name,
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi mail_storage_get_last_internal_error(*storage_r, &error));
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen }
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
2ef5254ab6b446b93ce7733bc96eeefa6f731ee4Timo Sirainen if (ctx->dest_mail == NULL)
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen mailbox_free(&box);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen return ret;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Boschconst struct smtp_address *
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Boschmail_deliver_get_return_address(struct mail_deliver_context *ctx)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch struct message_address *addr;
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch const char *path;
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch int ret;
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch
a1f1ff107e2b8fd098990399344a912750416dddStephan Bosch if (!smtp_address_isnull(ctx->mail_from))
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch return ctx->mail_from;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch if ((ret=mail_get_first_header(ctx->src_mail,
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch "Return-Path", &path)) <= 0) {
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch if (ret < 0) {
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch struct mailbox *box = ctx->src_mail->box;
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch i_warning("Failed read return-path header: %s",
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch mailbox_get_last_internal_error(box, NULL));
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch }
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch return NULL;
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch }
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch if (message_address_parse_path(pool_datastack_create(),
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch (const unsigned char *)path,
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch strlen(path), &addr) < 0) {
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch i_warning("Failed to parse return-path header");
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch return NULL;
3d7828efd92ecc0d08049f727d9be0154d1d681bStephan Bosch }
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch
9d606eb5019bc237cf4add562d54e2345b756f50Stephan Bosch return smtp_address_create_from_msg(ctx->pool, addr);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainenconst char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen static int count = 0;
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch struct mail_user *user = ctx->rcpt_user;
a9f821804fb50da03c454cd136ed9fe445a4d1d2Stephan Bosch const struct mail_storage_settings *mail_set =
a9f821804fb50da03c454cd136ed9fe445a4d1d2Stephan Bosch mail_user_set_get_storage_set(user);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen return t_strdup_printf("<dovecot-%s-%s-%d@%s>",
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen dec2str(ioloop_timeval.tv_sec),
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen dec2str(ioloop_timeval.tv_usec),
a9f821804fb50da03c454cd136ed9fe445a4d1d2Stephan Bosch count++, mail_set->hostname);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainenstatic bool mail_deliver_is_tempfailed(struct mail_deliver_context *ctx,
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen struct mail_storage *storage)
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen{
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen enum mail_error error;
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen if (ctx->tempfail_error != NULL)
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen return TRUE;
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen if (storage != NULL) {
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen (void)mail_storage_get_last_error(storage, &error);
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen return error == MAIL_ERROR_TEMP;
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen }
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen return FALSE;
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen}
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainenint mail_deliver(struct mail_deliver_context *ctx,
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen struct mail_storage **storage_r)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen{
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mail_deliver_user *muser =
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch MAIL_DELIVER_USER_CONTEXT(ctx->rcpt_user);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen int ret;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen i_assert(muser->deliver_ctx == NULL);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen muser->want_storage_id =
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen var_has_key(ctx->set->deliver_log_format, '\0', "storage_id");
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen muser->deliver_ctx = ctx;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen *storage_r = NULL;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen if (deliver_mail == NULL)
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ret = -1;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen else {
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch ctx->dup_db = mail_duplicate_db_init(ctx->rcpt_user,
f41f6294f438bd16a35be64cef3bc90d2b66e0eaStephan Bosch DUPLICATE_DB_NAME);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen if (deliver_mail(ctx, storage_r) <= 0) {
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen /* if message was saved, don't bounce it even though
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen the script failed later. */
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ret = ctx->saved_mail ? 0 : -1;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen } else {
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen /* success. message may or may not have been saved. */
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ret = 0;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen }
f41f6294f438bd16a35be64cef3bc90d2b66e0eaStephan Bosch mail_duplicate_db_deinit(&ctx->dup_db);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) {
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen muser->deliver_ctx = NULL;
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen return -1;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen }
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen }
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen if (ret < 0 && !ctx->tried_default_save) {
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen /* plugins didn't handle this. save into the default mailbox. */
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch ret = mail_deliver_save(ctx, ctx->rcpt_default_mailbox, 0, NULL,
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen storage_r);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) {
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen muser->deliver_ctx = NULL;
b9dce659b9135c87c7708b2bb0f14e8742db7e15Timo Sirainen return -1;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen }
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen }
a77f136d3603a36f6cdd2e3685a5b18dd3712d79Stephan Bosch if (ret < 0 && strcasecmp(ctx->rcpt_default_mailbox, "INBOX") != 0) {
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen /* still didn't work. try once more to save it
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen to INBOX. */
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen ret = mail_deliver_save(ctx, "INBOX", 0, NULL, storage_r);
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen }
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen muser->deliver_ctx = NULL;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen return ret;
58c61ac5650583d21c891e61e051c614290d31fbTimo Sirainen}
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainendeliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook)
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen{
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen deliver_mail_func_t *old_hook = deliver_mail;
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen deliver_mail = new_hook;
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen return old_hook;
92e6bb6497f8c9d57bff334a5c9f31bc2f040394Timo Sirainen}
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic int mail_deliver_save_finish(struct mail_save_context *ctx)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen{
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mailbox *box = ctx->transaction->box;
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mail_deliver_user *muser =
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen MAIL_DELIVER_USER_CONTEXT(box->storage->user);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_transaction *dt =
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen MAIL_DELIVER_STORAGE_CONTEXT(ctx->transaction);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen if (mbox->module_ctx.super.save_finish(ctx) < 0)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen return -1;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen /* initialize most of the fields from dest_mail */
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen mail_deliver_log_update_cache(&dt->cache, muser->deliver_ctx->pool,
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen ctx->dest_mail);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen return 0;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen}
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic int mail_deliver_copy(struct mail_save_context *ctx, struct mail *mail)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen{
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mailbox *box = ctx->transaction->box;
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mail_deliver_user *muser =
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen MAIL_DELIVER_USER_CONTEXT(box->storage->user);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_transaction *dt =
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen MAIL_DELIVER_STORAGE_CONTEXT(ctx->transaction);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen if (mbox->module_ctx.super.copy(ctx, mail) < 0)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen return -1;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen /* initialize most of the fields from dest_mail */
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen mail_deliver_log_update_cache(&dt->cache, muser->deliver_ctx->pool,
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen ctx->dest_mail);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen return 0;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen}
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainenstatic void
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainenmail_deliver_cache_update_post_commit(struct mailbox *orig_box, uint32_t uid)
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen{
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen struct mail_deliver_user *muser =
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen MAIL_DELIVER_USER_CONTEXT(orig_box->storage->user);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen struct mailbox *box;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen struct mailbox_transaction_context *t;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen struct mail *mail;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen const char *storage_id;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen if (!muser->want_storage_id)
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen return;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen /* getting storage_id requires a whole new mailbox view that is
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen synced, so it'll contain the newly written mail. this is racy, so
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen it's possible another process has already deleted the mail. */
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen box = mailbox_alloc(orig_box->list, orig_box->vname, 0);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen mailbox_set_reason(box, "lib-lda storage-id");
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen mail = mail_deliver_open_mail(box, uid, MAIL_FETCH_STORAGE_ID, &t);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen if (mail != NULL) {
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen if (mail_get_special(mail, MAIL_FETCH_STORAGE_ID, &storage_id) < 0 ||
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen storage_id[0] == '\0')
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen storage_id = NULL;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen muser->deliver_ctx->cache->storage_id =
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen p_strdup(muser->deliver_ctx->pool, storage_id);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen mail_free(&mail);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen (void)mailbox_transaction_commit(&t);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen } else {
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen muser->deliver_ctx->cache->storage_id = NULL;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen }
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen mailbox_free(&box);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen}
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainenstatic struct mailbox_transaction_context *
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainenmail_deliver_transaction_begin(struct mailbox *box,
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi enum mailbox_transaction_flags flags,
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi const char *reason)
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen{
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_user *muser =
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen MAIL_DELIVER_USER_CONTEXT(box->storage->user);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mailbox_transaction_context *t;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_transaction *dt;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen i_assert(muser->deliver_ctx != NULL);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi t = mbox->module_ctx.super.transaction_begin(box, flags, reason);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen dt = p_new(muser->deliver_ctx->pool, struct mail_deliver_transaction, 1);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen MODULE_CONTEXT_SET(t, mail_deliver_storage_module, dt);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen return t;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen}
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainenstatic int
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainenmail_deliver_transaction_commit(struct mailbox_transaction_context *ctx,
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen struct mail_transaction_commit_changes *changes_r)
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen{
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen struct mailbox *box = ctx->box;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_transaction *dt = MAIL_DELIVER_STORAGE_CONTEXT(ctx);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen struct mail_deliver_user *muser =
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen MAIL_DELIVER_USER_CONTEXT(box->storage->user);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen i_assert(muser->deliver_ctx != NULL);
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen /* sieve creates multiple transactions, saves the mails and
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen then commits all of them at the end. we'll need to keep
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen switching the deliver_ctx->cache for each commit.
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen we also want to do this only for commits generated by sieve.
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen other plugins or storage backends may be creating transactions as
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen well, which we need to ignore. */
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch if ((box->flags & MAILBOX_FLAG_POST_SESSION) != 0)
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen muser->deliver_ctx->cache = &dt->cache;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen if (mbox->module_ctx.super.transaction_commit(ctx, changes_r) < 0)
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen return -1;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen if (array_count(&changes_r->saved_uids) > 0) {
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen const struct seq_range *range =
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen array_idx(&changes_r->saved_uids, 0);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen mail_deliver_cache_update_post_commit(box, range->seq1);
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen }
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen return 0;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen}
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic void mail_deliver_mail_user_created(struct mail_user *user)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen{
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mail_deliver_user *muser;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen muser = p_new(user->pool, struct mail_deliver_user, 1);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen MODULE_CONTEXT_SET(user, mail_deliver_user_module, muser);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen}
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic void mail_deliver_mailbox_allocated(struct mailbox *box)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen{
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen struct mailbox_vfuncs *v = box->vlast;
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen struct mail_deliver_mailbox *mbox;
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi struct mail_deliver_user *muser =
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi MAIL_DELIVER_USER_CONTEXT(box->storage->user);
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi /* we are doing something other than lda/lmtp delivery
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi and should not be involved */
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi if (muser->deliver_ctx == NULL)
23070cb7c58e32af755dae0426493608a28a4209Aki Tuomi return;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch if ((box->flags & MAILBOX_FLAG_POST_SESSION) != 0)
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch mailbox_set_reason(box, "lib-lda delivery");
fe6a2885e07818ae9145ab5dbfb36a9c1b6bd54aStephan Bosch
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen mbox = p_new(box->pool, struct mail_deliver_mailbox, 1);
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen mbox->module_ctx.super = *v;
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen box->vlast = &mbox->module_ctx.super;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen v->save_finish = mail_deliver_save_finish;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen v->copy = mail_deliver_copy;
87dae9ffcd43023361019ca803709dbf5b8119bcTimo Sirainen v->transaction_begin = mail_deliver_transaction_begin;
b3523787a7c3b9e82fd9dfe9d1b4687a3b0000b0Timo Sirainen v->transaction_commit = mail_deliver_transaction_commit;
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
2e35ede0f3afa8b4528cc530a6efba239d77a022Timo Sirainen MODULE_CONTEXT_SET(box, mail_deliver_storage_module, mbox);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen }
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenstatic struct mail_storage_hooks mail_deliver_hooks = {
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen .mail_user_created = mail_deliver_mail_user_created,
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen .mailbox_allocated = mail_deliver_mailbox_allocated
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen};
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainenvoid mail_deliver_hooks_init(void)
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen{
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen mail_storage_hooks_add_internal(&mail_deliver_hooks);
eed56fe22f1fc61f2003d5e66373d03dacbc9aaaTimo Sirainen}