From bddf8c830c5fa27bdc3d4840d545e1f630ba6577 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 6 Dec 2007 17:45:44 +0100
Subject: [PATCH] Added mail-loop detection to the redirect action.

---
 README                       |  4 ++--
 src/lib-sieve/cmd-redirect.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/README b/README
index be068ccbf..525f38c2d 100644
--- a/README
+++ b/README
@@ -108,7 +108,7 @@ Extensions and their implementation status:
     fileinto: full
     reject: full
     envelope: full
-	encoded-character: planned (draft-ietf-sieve-3028bis)
+    encoded-character: planned (draft-ietf-sieve-3028bis)
 
   Other RFCs/drafts:
     subaddress: full
@@ -120,7 +120,7 @@ Extensions and their implementation status:
     imapflags: flag management works, but flags are not stored 
     copy: full
     include: planned (* first leave out variables support)  
-	variables: planned (* also amend previously implemented extensions)
+    variables: planned (* also amend previously implemented extensions)
     body: planned                        
     notify: planned (- lowest priority)
 
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index b06556283..93e39bf88 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -1,4 +1,5 @@
 #include "lib.h"
+#include "ioloop.h"
 #include "str-sanitize.h"
 #include "istream.h"
 #include "istream-header-filter.h"
@@ -14,6 +15,10 @@
 
 #include <stdio.h>
 
+/* Config */
+
+#define CMD_REDIRECT_DUPLICATE_KEEP (3600 * 24)
+
 /* Forward declarations */
 
 static bool cmd_redirect_opcode_dump
@@ -238,8 +243,31 @@ static bool act_redirect_commit
 	const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep)
 {
 	struct act_redirect_context *ctx = (struct act_redirect_context *) tr_context;
+	const struct sieve_message_data *msgdata = aenv->msgdata;
+	const struct sieve_mail_environment *mailenv = aenv->mailenv;
+	const char *dupeid;
 	
+	/* Prevent mail loops if possible */
+  dupeid = msgdata->id == NULL ? 
+  	NULL : t_strdup_printf("%s-%s", msgdata->id, ctx->to_address);
+	if (dupeid != NULL) {
+	  /* Check whether we've seen this message before */
+  	if (mailenv->duplicate_check(dupeid, strlen(dupeid), mailenv->username)) {
+      sieve_result_log(aenv, "discarded duplicate forward to <%s>",
+				str_sanitize(ctx->to_address, 80));
+			return TRUE;
+  	}
+  }
+	
+	/* Try to forward the message */
 	if ( act_redirect_send(aenv, ctx) ) {
+	
+		/* Mark this message id as forwarded to the specified destination */
+		if (dupeid != NULL) {
+			mailenv->duplicate_mark(dupeid, strlen(dupeid), mailenv->username,
+				ioloop_time + CMD_REDIRECT_DUPLICATE_KEEP);
+		}
+	
 		sieve_result_log(aenv, "forwarded to <%s>", 
 			str_sanitize(ctx->to_address, 80));	
 
-- 
GitLab