diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index bf77a084eda98e31afae6698b24e3abe083138a5..22bd6db7a6be6d7def193103364b20cd391ba861 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -307,7 +307,8 @@ static void act_redirect_print
 
 static int act_redirect_send
 (const struct sieve_action_exec_env *aenv, struct mail *mail,
-	struct act_redirect_context *ctx)
+	struct act_redirect_context *ctx, const char *new_msg_id)
+	ATTR_NULL(4)
 {
 	static const char *hide_headers[] =
 		{ "Return-Path", "X-Sieve", "X-Sieve-Redirected-From" };
@@ -385,6 +386,11 @@ static int act_redirect_send
 			rfc2822_header_append
 				(hdr, "X-Sieve-Redirected-From", recipient, FALSE, NULL);
 		}
+
+		/* Add new Message-ID if message doesn't have one */
+		if ( new_msg_id != NULL )
+			rfc2822_header_write(hdr, "Message-ID", new_msg_id);
+
 		o_stream_send(output, str_data(hdr), str_len(hdr));
 	} T_END;
 
@@ -430,58 +436,69 @@ static int act_redirect_commit
 	const struct sieve_message_data *msgdata = aenv->msgdata;
 	const struct sieve_script_env *senv = aenv->scriptenv;
 	const char *orig_recipient = sieve_message_get_orig_recipient(aenv->msgctx);
-	const char *dupeid = NULL, *resent_id = NULL, *resent_from = NULL;
+	const char *msg_id = msgdata->id, *new_msg_id = NULL;
+	const char *dupeid = NULL, *resent_id = NULL;
 	const char *list_id = NULL;
 	int ret;
 
-	/* Prevent mail loops if possible */
+	/*
+	 * Prevent mail loops
+	 */
+
+	/* Read identifying headers */
 	if ( mail_get_first_header
 		(msgdata->mail, "resent-message-id", &resent_id) < 0 ) {
 		return sieve_result_mail_error(aenv, mail,
 			"failed to read header field `resent-message-id'");
 	}
+	if ( resent_id == NULL ) {
+		if ( mail_get_first_header
+			(msgdata->mail, "resent-from", &resent_id) < 0 ) {
+			return sieve_result_mail_error(aenv, mail,
+				"failed to read header field `resent-from'");
+		}
+	}
 	if ( mail_get_first_header
 		(msgdata->mail, "list-id", &list_id) < 0 ) {
 		return sieve_result_mail_error(aenv, mail,
 			"failed to read header field `list-id'");
 	}
-	if ( msgdata->id != NULL || resent_id != NULL ) {
-		if ( resent_id == NULL ) {
-			if ( mail_get_first_header
-				(msgdata->mail, "resent-from", &resent_from) < 0 ) {
-				return sieve_result_mail_error(aenv, mail,
-					"failed to read header field `resent-from'");
-			}
-		}
-		/* Base the duplicate ID on:
-		   - the message id
-		   - the recipient running this Sieve script
-		   - redirect target address
-		   - if this message is resent: the message-id or from-address of
-			   the original message
-		   - if the message came through a mailing list: the mailinglist ID
-		 */
-		dupeid = t_strdup_printf("%s-%s-%s-%s-%s",
-			(msgdata->id == NULL ? "" : msgdata->id),
-			orig_recipient, ctx->to_address,
-			(resent_id != NULL ?	
-				resent_id : (resent_from == NULL ? "" : resent_from)),
-			(list_id != NULL ? list_id : ""));
+
+	/* Create Message-ID for the message if it has none */
+	if ( msg_id == NULL ) {	
+		msg_id = new_msg_id =
+			sieve_message_get_new_id(aenv->svinst);
 	}
-	if ( dupeid != NULL ) {
-		/* Check whether we've seen this message before */
-		if (sieve_action_duplicate_check
-			(senv, dupeid, strlen(dupeid))) {
-			sieve_result_global_log(aenv,
-				"discarded duplicate forward to <%s>",
-				str_sanitize(ctx->to_address, 128));
-			*keep = FALSE;
-			return SIEVE_EXEC_OK;
-		}
+
+	/* Base the duplicate ID on:
+	   - the message id
+	   - the recipient running this Sieve script
+	   - redirect target address
+	   - if this message is resent: the message-id or from-address of
+		   the original message
+	   - if the message came through a mailing list: the mailinglist ID
+	 */
+	dupeid = t_strdup_printf("%s-%s-%s-%s-%s", msg_id,
+		orig_recipient, ctx->to_address,
+		(resent_id != NULL ? resent_id : ""),
+		(list_id != NULL ? list_id : ""));
+
+	/* Check whether we've seen this message before */
+	if (sieve_action_duplicate_check
+		(senv, dupeid, strlen(dupeid))) {
+		sieve_result_global_log(aenv,
+			"discarded duplicate forward to <%s>",
+			str_sanitize(ctx->to_address, 128));
+		*keep = FALSE;
+		return SIEVE_EXEC_OK;
 	}
 
-	/* Try to forward the message */
-	if ( (ret=act_redirect_send(aenv, mail, ctx)) == SIEVE_EXEC_OK) {
+	/*
+	 * Try to forward the message
+	 */
+
+	if ( (ret=act_redirect_send
+		(aenv, mail, ctx, new_msg_id)) == SIEVE_EXEC_OK) {
 
 		/* Mark this message id as forwarded to the specified destination */
 		if (dupeid != NULL) {