From 36e3798d8c888f08a1910f5a8eb144371c72bc22 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Fri, 17 Sep 2010 23:12:05 +0200
Subject: [PATCH] Incorporated distinction between original and final envelope
 recipient in Sieve interpreter, as recently introduced in Dovecot.

---
 src/lib-sieve/ext-envelope.c                  |  7 +-
 src/lib-sieve/ext-reject.c                    |  2 +-
 .../plugins/enotify/mailto/ntfy-mailto.c      |  6 +-
 src/lib-sieve/plugins/vacation/cmd-vacation.c |  2 +-
 src/lib-sieve/sieve-message.c                 | 73 ++++++++++++++-----
 src/lib-sieve/sieve-message.h                 |  8 +-
 src/lib-sieve/sieve-types.h                   |  3 +-
 src/plugins/lda-sieve/lda-sieve-plugin.c      |  3 +-
 src/sieve-tools/sieve-test.c                  | 20 +++--
 src/testsuite/testsuite-message.c             |  6 +-
 10 files changed, 91 insertions(+), 39 deletions(-)

diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index 92064737e..0d2a3d769 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -219,7 +219,7 @@ static const struct sieve_address *const *_to_part_get_addresses
 {
 	ARRAY_DEFINE(envelope_values, const struct sieve_address *);
 	const struct sieve_address *address = 
-		sieve_message_get_recipient_address(renv->msgctx);	
+		sieve_message_get_orig_recipient_address(renv->msgctx);	
 
 	if ( address != NULL && address->local_part != NULL ) {
 		t_array_init(&envelope_values, 2);
@@ -240,8 +240,8 @@ static const char *const *_to_part_get_values
 
 	t_array_init(&envelope_values, 2);
 
-	if ( renv->msgdata->to_address != NULL ) {
-        array_append(&envelope_values, &renv->msgdata->to_address, 1);
+	if ( renv->msgdata->orig_envelope_to != NULL ) {
+        array_append(&envelope_values, &renv->msgdata->orig_envelope_to, 1);
 	}
 
 	(void)array_append_space(&envelope_values);
@@ -249,7 +249,6 @@ static const char *const *_to_part_get_values
 	return array_idx(&envelope_values, 0);
 }
 
-
 static const char *const *_auth_part_get_values
 (const struct sieve_runtime_env *renv)
 {
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index e942b8523..d2b23ac30 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -503,7 +503,7 @@ static bool act_reject_commit
 	struct act_reject_context *rj_ctx =
 		(struct act_reject_context *) action->context;
 	const char *sender = sieve_message_get_sender(aenv->msgctx);
-	const char *recipient = sieve_message_get_recipient(aenv->msgctx);
+	const char *recipient = sieve_message_get_final_recipient(aenv->msgctx);
 
 	if ( recipient == NULL ) {
 		sieve_result_global_warning(aenv, 
diff --git a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c
index 5e4dd4992..e4470b6ab 100644
--- a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c
+++ b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c
@@ -551,7 +551,7 @@ static bool ntfy_mailto_action_execute
 {
 	const char *const *headers;
 	const char *sender = sieve_message_get_sender(nenv->msgctx);
-	const char *recipient = sieve_message_get_recipient(nenv->msgctx);
+	const char *recipient = sieve_message_get_final_recipient(nenv->msgctx);
 
 	/* Is the recipient unset? 
 	 */
@@ -571,8 +571,8 @@ static bool ntfy_mailto_action_execute
 			if ( strcasecmp(*hdsp, "no") != 0 ) {
 				sieve_enotify_global_info(nenv, 
 					"not sending notification for auto-submitted message from <%s>", 
-					str_sanitize(sender, 128));	
-					return TRUE;				 
+					str_sanitize(sender, 128));
+					return TRUE;
 			}
 			hdsp++;
 		}
diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c
index bbabae3da..61a4ea1a9 100644
--- a/src/lib-sieve/plugins/vacation/cmd-vacation.c
+++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c
@@ -974,7 +974,7 @@ static bool act_vacation_commit
 	unsigned char dupl_hash[MD5_RESULTLEN];
 	const char *const *headers;
 	const char *sender = sieve_message_get_sender(aenv->msgctx);
-	const char *recipient = sieve_message_get_recipient(aenv->msgctx);
+	const char *recipient = sieve_message_get_final_recipient(aenv->msgctx);
 	const char *reply_from = NULL;
 
 	/* Is the recipient unset? 
diff --git a/src/lib-sieve/sieve-message.c b/src/lib-sieve/sieve-message.c
index 1ff42a197..d2f0f0a89 100644
--- a/src/lib-sieve/sieve-message.c
+++ b/src/lib-sieve/sieve-message.c
@@ -50,7 +50,9 @@ struct sieve_message_context {
 	bool envelope_parsed;
 
 	const struct sieve_address *envelope_sender;
-	const struct sieve_address *envelope_recipient;
+	const struct sieve_address *envelope_orig_recipient;
+	const struct sieve_address *envelope_final_recipient;
+
 	
 	/* Context data for extensions */
 	ARRAY_DEFINE(ext_contexts, void *); 
@@ -101,7 +103,8 @@ void sieve_message_context_flush(struct sieve_message_context *msgctx)
 	pool = pool_alloconly_create("sieve_message_context", 1024);
 	msgctx->pool = pool;
 
-	msgctx->envelope_recipient = NULL;
+	msgctx->envelope_orig_recipient = NULL;
+	msgctx->envelope_final_recipient = NULL;
 	msgctx->envelope_sender = NULL;
 	msgctx->envelope_parsed = FALSE;
 
@@ -142,43 +145,70 @@ const void *sieve_message_context_extension_get
 
 static void sieve_message_envelope_parse(struct sieve_message_context *msgctx)
 {
+	const struct sieve_message_data *msgdata = msgctx->msgdata;
 	struct sieve_instance *svinst = msgctx->svinst;
 
 	/* FIXME: log parse problems properly; logs only 'failure' now */
 
-	msgctx->envelope_recipient = sieve_address_parse_envelope_path
-		(msgctx->pool, msgctx->msgdata->to_address);	
+	msgctx->envelope_orig_recipient = sieve_address_parse_envelope_path
+		(msgctx->pool, msgdata->orig_envelope_to);	
 
-	if ( msgctx->envelope_recipient == NULL ) {
+	if ( msgctx->envelope_orig_recipient == NULL ) {
 		sieve_sys_error(svinst,
-			"envelope recipient address '%s' is unparsable",
-			msgctx->msgdata->to_address); 
-	} else if ( msgctx->envelope_recipient->local_part == NULL ) {
+			"original envelope recipient address '%s' is unparsable",
+			msgdata->orig_envelope_to); 
+	} else if ( msgctx->envelope_orig_recipient->local_part == NULL ) {
 		sieve_sys_error(svinst,
-			"envelope recipient address '%s' is a null path",
-			msgctx->msgdata->to_address);
+			"original envelope recipient address '%s' is a null path",
+			msgdata->orig_envelope_to);
 	} 
 
+	msgctx->envelope_final_recipient = sieve_address_parse_envelope_path
+		(msgctx->pool, msgdata->final_envelope_to);	
+	
+	if ( msgctx->envelope_final_recipient == NULL ) {
+		if ( msgctx->envelope_orig_recipient != NULL ) {
+			sieve_sys_error(svinst,
+				"final envelope recipient address '%s' is unparsable",
+				msgdata->final_envelope_to);
+		} 
+	} else if ( msgctx->envelope_final_recipient->local_part == NULL ) {
+		if ( strcmp(msgdata->orig_envelope_to, msgdata->final_envelope_to) != 0 ) {
+			sieve_sys_error(svinst,
+				"final envelope recipient address '%s' is a null path",
+				msgdata->final_envelope_to);
+		}
+	}
+
 	msgctx->envelope_sender = sieve_address_parse_envelope_path
-		(msgctx->pool, msgctx->msgdata->return_path);	
+		(msgctx->pool, msgdata->return_path);	
 
 	if ( msgctx->envelope_sender == NULL ) {
 		sieve_sys_error(svinst, 
 			"envelope sender address '%s' is unparsable", 
-			msgctx->msgdata->return_path);
+			msgdata->return_path);
 	}
 
 	msgctx->envelope_parsed = TRUE;
 }
 
-const struct sieve_address *sieve_message_get_recipient_address
+const struct sieve_address *sieve_message_get_orig_recipient_address
 (struct sieve_message_context *msgctx)
 {
 	if ( !msgctx->envelope_parsed ) 
 		sieve_message_envelope_parse(msgctx);
 
-	return msgctx->envelope_recipient;
-} 
+	return msgctx->envelope_orig_recipient;
+}
+
+const struct sieve_address *sieve_message_get_final_recipient_address
+(struct sieve_message_context *msgctx)
+{
+	if ( !msgctx->envelope_parsed ) 
+		sieve_message_envelope_parse(msgctx);
+
+	return msgctx->envelope_final_recipient;
+}
 
 const struct sieve_address *sieve_message_get_sender_address
 (struct sieve_message_context *msgctx)
@@ -189,13 +219,22 @@ const struct sieve_address *sieve_message_get_sender_address
 	return msgctx->envelope_sender;	
 } 
 
-const char *sieve_message_get_recipient
+const char *sieve_message_get_orig_recipient
+(struct sieve_message_context *msgctx)
+{
+	if ( !msgctx->envelope_parsed ) 
+		sieve_message_envelope_parse(msgctx);
+
+	return sieve_address_to_string(msgctx->envelope_orig_recipient);
+}
+
+const char *sieve_message_get_final_recipient
 (struct sieve_message_context *msgctx)
 {
 	if ( !msgctx->envelope_parsed ) 
 		sieve_message_envelope_parse(msgctx);
 
-	return sieve_address_to_string(msgctx->envelope_recipient);
+	return sieve_address_to_string(msgctx->envelope_final_recipient);
 }
 
 const char *sieve_message_get_sender
diff --git a/src/lib-sieve/sieve-message.h b/src/lib-sieve/sieve-message.h
index 47a275623..471d0db28 100644
--- a/src/lib-sieve/sieve-message.h
+++ b/src/lib-sieve/sieve-message.h
@@ -37,13 +37,17 @@ const void *sieve_message_context_extension_get
 
 /* Envelope */
 
-const struct sieve_address *sieve_message_get_recipient_address
+const struct sieve_address *sieve_message_get_final_recipient_address
+	(struct sieve_message_context *msgctx);
+const struct sieve_address *sieve_message_get_orig_recipient_address
 	(struct sieve_message_context *msgctx);
 
 const struct sieve_address *sieve_message_get_sender_address
 	(struct sieve_message_context *msgctx);
 
-const char *sieve_message_get_recipient
+const char *sieve_message_get_orig_recipient
+	(struct sieve_message_context *msgctx);
+const char *sieve_message_get_final_recipient
 	(struct sieve_message_context *msgctx);
 
 const char *sieve_message_get_sender
diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h
index 459b17fc6..c75f87524 100644
--- a/src/lib-sieve/sieve-types.h
+++ b/src/lib-sieve/sieve-types.h
@@ -69,7 +69,8 @@ enum sieve_error {
 struct sieve_message_data {
 	struct mail *mail;
 	const char *return_path;
-	const char *to_address;
+	const char *orig_envelope_to;
+	const char *final_envelope_to;
 	const char *auth_user;
 	const char *id;
 };
diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c
index 6183dccdb..030033cee 100644
--- a/src/plugins/lda-sieve/lda-sieve-plugin.c
+++ b/src/plugins/lda-sieve/lda-sieve-plugin.c
@@ -588,7 +588,8 @@ static int lda_sieve_run
 
 	msgdata.mail = mdctx->src_mail;
 	msgdata.return_path = mail_deliver_get_return_address(mdctx);
-	msgdata.to_address = mdctx->dest_addr;
+	msgdata.orig_envelope_to = mdctx->dest_addr;
+	msgdata.final_envelope_to = mdctx->final_dest_addr;
 	msgdata.auth_user = mdctx->dest_user->username;
 	(void)mail_get_first_header(msgdata.mail, "Message-ID", &msgdata.id);
 
diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index b9ca7601b..157b3902a 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -105,8 +105,8 @@ int main(int argc, char **argv)
 {
 	struct sieve_instance *svinst;
 	ARRAY_TYPE (const_string) scriptfiles;
-	const char *scriptfile, *recipient, *sender, *mailbox, *dumpfile, *tracefile,
-		*mailfile, *mailloc; 
+	const char *scriptfile, *recipient, *final_recipient, *sender, *mailbox,
+		*dumpfile, *tracefile, *mailfile, *mailloc;
 	struct sieve_trace_config tr_config;
 	struct mail *mail;
 	struct sieve_binary *main_sbin, *sbin = NULL;
@@ -121,13 +121,13 @@ int main(int argc, char **argv)
 	int ret, c;
 
 	sieve_tool = sieve_tool_init
-		("sieve-test", &argc, &argv, "r:f:m:d:l:s:eCt:T:DP:x:u:", FALSE);
+		("sieve-test", &argc, &argv, "r:a:f:m:d:l:s:eCt:T:DP:x:u:", FALSE);
 
 	t_array_init(&scriptfiles, 16);
-	
+
 	/* Parse arguments */
-	scriptfile = recipient = sender = mailbox = dumpfile = tracefile =
-		mailfile = mailloc = NULL;
+	scriptfile = recipient = final_recipient = sender = mailbox = dumpfile =
+		tracefile = mailfile = mailloc = NULL;
 	memset(&tr_config, 0, sizeof(tr_config));
 	tr_config.level = SIEVE_TRLVL_ACTIONS;
 	while ((c = sieve_tool_getopt(sieve_tool)) > 0) {
@@ -136,6 +136,10 @@ int main(int argc, char **argv)
 			/* destination address */
 			recipient = optarg;
 			break;
+		case 'a':
+			/* final destination address */
+			final_recipient = optarg;
+			break;
 		case 'f':
 			/* envelope sender address */
 			sender = optarg;
@@ -243,7 +247,9 @@ int main(int argc, char **argv)
 		memset(&msgdata, 0, sizeof(msgdata));
 		msgdata.mail = mail;
 		msgdata.return_path = sender;
-		msgdata.to_address = recipient;
+		msgdata.orig_envelope_to = recipient;
+		msgdata.final_envelope_to =
+			( final_recipient == NULL ? recipient : final_recipient );
 		msgdata.auth_user = sieve_tool_get_username(sieve_tool);
 		(void)mail_get_first_header(mail, "Message-ID", &msgdata.id);
 
diff --git a/src/testsuite/testsuite-message.c b/src/testsuite/testsuite-message.c
index a87cbbb94..0c60d6dc8 100644
--- a/src/testsuite/testsuite-message.c
+++ b/src/testsuite/testsuite-message.c
@@ -65,7 +65,8 @@ static void testsuite_message_set_data(struct mail *mail)
 	testsuite_msgdata.mail = mail;
 	testsuite_msgdata.auth_user = sieve_tool_get_username(sieve_tool);
 	testsuite_msgdata.return_path = sender;
-	testsuite_msgdata.to_address = recipient;
+	testsuite_msgdata.orig_envelope_to = recipient;
+	testsuite_msgdata.final_envelope_to = recipient;
 
 	(void)mail_get_first_header(mail, "Message-ID", &testsuite_msgdata.id);
 }
@@ -137,7 +138,8 @@ void testsuite_envelope_set_recipient
 	if ( value != NULL )
 		str_append(envelope_to, value);
 
-	testsuite_msgdata.to_address = str_c(envelope_to);
+	testsuite_msgdata.orig_envelope_to = str_c(envelope_to);
+	testsuite_msgdata.final_envelope_to = str_c(envelope_to);
 
 	sieve_message_context_flush(renv->msgctx);
 }
-- 
GitLab