changeset 21551:8351a4c497cc

lib-lda: Fix deliver_log_format variables with Sieve With Sieve it was using src_mail for getting the values, which weren't correct especially if Sieve had modified the mail.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 13 Feb 2017 20:47:51 +0200
parents 0a4e672c70a1
children f48743eb38c6
files 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
diffstat 5 files changed, 101 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/lda/main.c	Mon Feb 13 20:46:16 2017 +0200
+++ b/src/lda/main.c	Mon Feb 13 20:47:51 2017 +0200
@@ -408,6 +408,7 @@
 		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;
--- a/src/lib-lda/Makefile.am	Mon Feb 13 20:46:16 2017 +0200
+++ b/src/lib-lda/Makefile.am	Mon Feb 13 20:47:51 2017 +0200
@@ -6,6 +6,7 @@
 	-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
--- a/src/lib-lda/mail-deliver.c	Mon Feb 13 20:46:16 2017 +0200
+++ b/src/lib-lda/mail-deliver.c	Mon Feb 13 20:47:51 2017 +0200
@@ -12,9 +12,20 @@
 #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 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
-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 @@
 		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 @@
 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;
@@ -360,10 +375,6 @@
 
 	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);
 
@@ -436,8 +447,13 @@
 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;
@@ -452,22 +468,27 @@
 			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;
 }
 
@@ -478,3 +499,65 @@
 	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);
+}
--- a/src/lib-lda/mail-deliver.h	Mon Feb 13 20:46:16 2017 +0200
+++ b/src/lib-lda/mail-deliver.h	Mon Feb 13 20:47:51 2017 +0200
@@ -113,4 +113,7 @@
    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
--- a/src/lmtp/main.c	Mon Feb 13 20:46:16 2017 +0200
+++ b/src/lmtp/main.c	Mon Feb 13 20:47:51 2017 +0200
@@ -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"
@@ -63,6 +64,7 @@
 		(void)client_create(STDIN_FILENO, STDOUT_FILENO, &conn);
 	}
 	dns_client_socket_path = t_abspath(DNS_CLIENT_SOCKET_PATH);
+	mail_deliver_hooks_init();
 }
 
 static void main_deinit(void)