]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-lda: Fix deliver_log_format variables with Sieve
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 13 Feb 2017 18:47:51 +0000 (20:47 +0200)
committerGitLab <gitlab@git.dovecot.net>
Tue, 14 Feb 2017 12:57:34 +0000 (14:57 +0200)
With Sieve it was using src_mail for getting the values, which weren't
correct especially if Sieve had modified the mail.

src/lda/main.c
src/lib-lda/Makefile.am
src/lib-lda/mail-deliver.c
src/lib-lda/mail-deliver.h
src/lmtp/main.c

index 1dda36d012758466d9b08ab7fe228525cb7fc9e6..01ef837dcae0072e266cb6c7e0491494fbeaf624 100644 (file)
@@ -412,6 +412,7 @@ int main(int argc, char *argv[])
                MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS;
        storage_service = mail_storage_service_init(master_service, set_roots,
                                                    service_flags);
+       mail_deliver_hooks_init();
        /* set before looking up the user (or ideally we'd do this between
           _lookup() and _next(), but don't bother) */
        ctx.delivery_time_started = ioloop_timeval;
index ee5f3b245cfa03f169b358da79b726c020e45cb8..b02828508d93f10db3c16380a9fdfdc2c5d8a76c 100644 (file)
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-dns \
        -I$(top_srcdir)/src/lib-smtp \
+       -I$(top_srcdir)/src/lib-index \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-storage \
index 7a907611d284163d96345c3b9dc04b64dcf3404e..eefdb19713a0f798e851118f60c7c07a1a1564c2 100644 (file)
 #include "lda-settings.h"
 #include "mail-storage.h"
 #include "mail-namespace.h"
+#include "mail-storage-private.h"
 #include "duplicate.h"
 #include "mail-deliver.h"
 
+#define MAIL_DELIVER_USER_CONTEXT(obj) \
+       MODULE_CONTEXT(obj, mail_deliver_user_module)
+#define MAIL_DELIVER_STORAGE_CONTEXT(obj) \
+       MODULE_CONTEXT(obj, mail_deliver_storage_module)
+
+struct mail_deliver_user {
+       union mail_user_module_context module_ctx;
+       struct mail_deliver_context *deliver_ctx;
+};
+
 deliver_mail_func_t *deliver_mail = NULL;
 
 struct mail_deliver_cache {
@@ -35,6 +46,10 @@ static const char *lda_log_wanted_headers[] = {
 };
 static enum mail_fetch_field lda_log_wanted_fetch_fields =
        MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE;
+static MODULE_CONTEXT_DEFINE_INIT(mail_deliver_user_module,
+                                 &mail_user_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(mail_deliver_storage_module,
+                                 &mail_storage_module_register);
 
 const char *mail_deliver_get_address(struct mail *mail, const char *header)
 {
@@ -61,9 +76,9 @@ static void update_cache(struct mail_deliver_context *ctx,
 }
 
 static void
-mail_deliver_log_update_cache(struct mail_deliver_context *ctx)
+mail_deliver_log_update_cache(struct mail_deliver_context *ctx,
+                             struct mail *mail)
 {
-       struct mail *mail;
        const char *message_id = NULL, *subject = NULL, *from_envelope = NULL;
        const char *from;
 
@@ -73,8 +88,6 @@ mail_deliver_log_update_cache(struct mail_deliver_context *ctx)
                return;
        ctx->cache->filled = TRUE;
 
-       mail = ctx->dest_mail != NULL ? ctx->dest_mail : ctx->src_mail;
-
        if (mail_get_first_header(mail, "Message-ID", &message_id) > 0)
                message_id = str_sanitize(message_id, 200);
        update_cache(ctx, &ctx->cache->message_id, message_id);
@@ -100,9 +113,11 @@ const struct var_expand_table *
 mail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context *ctx,
                                          const char *message)
 {
+       struct mail *mail = ctx->dest_mail != NULL ?
+               ctx->dest_mail : ctx->src_mail;
        unsigned int delivery_time_msecs;
 
-       mail_deliver_log_update_cache(ctx);
+       mail_deliver_log_update_cache(ctx, mail);
        /* This call finishes a mail delivery. With Sieve there may be multiple
           mail deliveries. */
        ctx->cache->filled = FALSE;
@@ -363,10 +378,6 @@ int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox,
 
        if (mailbox_save_using_mail(&save_ctx, ctx->src_mail) < 0)
                ret = -1;
-       else {
-               /* fill the cache while we still have dest_mail */
-               mail_deliver_log_update_cache(ctx);
-       }
        if (kw != NULL)
                mailbox_keywords_unref(&kw);
 
@@ -439,8 +450,13 @@ static bool mail_deliver_is_tempfailed(struct mail_deliver_context *ctx,
 int mail_deliver(struct mail_deliver_context *ctx,
                 struct mail_storage **storage_r)
 {
+       struct mail_deliver_user *muser =
+               MAIL_DELIVER_USER_CONTEXT(ctx->dest_user);
        int ret;
 
+       i_assert(muser->deliver_ctx == NULL);
+
+       muser->deliver_ctx = ctx;
        *storage_r = NULL;
        if (deliver_mail == NULL)
                ret = -1;
@@ -455,22 +471,27 @@ int mail_deliver(struct mail_deliver_context *ctx,
                        ret = 0;
                }
                duplicate_deinit(&ctx->dup_ctx);
-               if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r))
+               if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) {
+                       muser->deliver_ctx = NULL;
                        return -1;
+               }
        }
 
        if (ret < 0 && !ctx->tried_default_save) {
                /* plugins didn't handle this. save into the default mailbox. */
                ret = mail_deliver_save(ctx, ctx->dest_mailbox_name, 0, NULL,
                                        storage_r);
-               if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r))
+               if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) {
+                       muser->deliver_ctx = NULL;
                        return -1;
+               }
        }
        if (ret < 0 && strcasecmp(ctx->dest_mailbox_name, "INBOX") != 0) {
                /* still didn't work. try once more to save it
                   to INBOX. */
                ret = mail_deliver_save(ctx, "INBOX", 0, NULL, storage_r);
        }
+       muser->deliver_ctx = NULL;
        return ret;
 }
 
@@ -481,3 +502,65 @@ deliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook)
        deliver_mail = new_hook;
        return old_hook;
 }
+
+static int mail_deliver_save_finish(struct mail_save_context *ctx)
+{
+       struct mailbox *box = ctx->transaction->box;
+       union mailbox_module_context *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
+       struct mail_deliver_user *muser =
+               MAIL_DELIVER_USER_CONTEXT(box->storage->user);
+
+       if (mbox->super.save_finish(ctx) < 0)
+               return -1;
+
+       /* initialize most of the fields from dest_mail */
+       mail_deliver_log_update_cache(muser->deliver_ctx, ctx->dest_mail);
+       return 0;
+}
+
+static int mail_deliver_copy(struct mail_save_context *ctx, struct mail *mail)
+{
+       struct mailbox *box = ctx->transaction->box;
+       union mailbox_module_context *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box);
+       struct mail_deliver_user *muser =
+               MAIL_DELIVER_USER_CONTEXT(box->storage->user);
+
+       if (mbox->super.copy(ctx, mail) < 0)
+               return -1;
+
+       /* initialize most of the fields from dest_mail */
+       mail_deliver_log_update_cache(muser->deliver_ctx, ctx->dest_mail);
+       return 0;
+}
+
+static void mail_deliver_mail_user_created(struct mail_user *user)
+{
+       struct mail_deliver_user *muser;
+
+       muser = p_new(user->pool, struct mail_deliver_user, 1);
+       MODULE_CONTEXT_SET(user, mail_deliver_user_module, muser);
+}
+
+static void mail_deliver_mailbox_allocated(struct mailbox *box)
+{
+       struct mailbox_vfuncs *v = box->vlast;
+       union mailbox_module_context *mbox;
+
+       mbox = p_new(box->pool, union mailbox_module_context, 1);
+       mbox->super = *v;
+       box->vlast = &mbox->super;
+       v->save_finish = mail_deliver_save_finish;
+       v->copy = mail_deliver_copy;
+
+       MODULE_CONTEXT_SET_SELF(box, mail_deliver_storage_module, mbox);
+ }
+
+static struct mail_storage_hooks mail_deliver_hooks = {
+       .mail_user_created = mail_deliver_mail_user_created,
+       .mailbox_allocated = mail_deliver_mailbox_allocated
+};
+
+void mail_deliver_hooks_init(void)
+{
+       mail_storage_hooks_add_internal(&mail_deliver_hooks);
+}
index 436a584524991e3501a8bf0c5c49f0027e5ca1b7..a49406647e248f1ed6534b58901d46243a478ef5 100644 (file)
@@ -113,4 +113,7 @@ int mail_deliver(struct mail_deliver_context *ctx,
    which the new_hook should call if it's non-NULL. */
 deliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook);
 
+/* Must be called before any storage is created. */
+void mail_deliver_hooks_init(void);
+
 #endif
index 5f7841453addeb04648114b470ef14c63ab813d0..2ef0dd81d84c189f2b61832ac07fb4ea753b3d22 100644 (file)
@@ -11,6 +11,7 @@
 #include "master-service.h"
 #include "master-service-settings.h"
 #include "master-interface.h"
+#include "mail-deliver.h"
 #include "mail-storage-service.h"
 #include "lda-settings.h"
 #include "lmtp-settings.h"
@@ -68,6 +69,7 @@ static void main_init(void)
                i_fatal("t_abspath(%s) failed: %s", DNS_CLIENT_SOCKET_PATH, error);
        }
        dns_client_socket_path = i_strdup(tmp_socket_path);
+       mail_deliver_hooks_init();
 }
 
 static void main_deinit(void)