From f32da22a3305cdf8e08bb94508e8dafe227cca8e Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Fri, 8 Jan 2010 12:18:20 +0100
Subject: [PATCH] Vacation extension: subject is now only MIME-encoded when it
 contains 8bit characters.

---
 Makefile.am                                   |  1 +
 src/lib-sieve/plugins/vacation/cmd-vacation.c | 45 ++++++++++-----
 tests/extensions/vacation/utf-8.svtest        | 56 +++++++++++++++++--
 3 files changed, 82 insertions(+), 20 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index a3e4df130..cf42cc56c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -88,6 +88,7 @@ test_cases = \
 	tests/extensions/vacation/execute.svtest \
 	tests/extensions/vacation/message.svtest \
 	tests/extensions/vacation/smtp.svtest \
+	tests/extensions/vacation/utf-8.svtest \
 	tests/extensions/enotify/basic.svtest \
 	tests/extensions/enotify/encodeurl.svtest \
 	tests/extensions/enotify/valid_notify_method.svtest \
diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c
index 255f4173d..d123bb0eb 100644
--- a/src/lib-sieve/plugins/vacation/cmd-vacation.c
+++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c
@@ -855,6 +855,17 @@ static inline bool _contains_my_address
 	return result;
 }
 
+static bool _contains_8bit(const char *text)
+{
+	const unsigned char *p = (const unsigned char *) text;
+
+	for (; *p != '\0'; p++) {
+		if ((*p & 0x80) != 0)
+			return TRUE;
+	}
+	return FALSE;
+}
+
 static bool act_vacation_send	
 (const struct sieve_action_exec_env *aenv, struct act_vacation_context *ctx,
 	const char *sender, const char *recipient)
@@ -865,6 +876,7 @@ static bool act_vacation_send
 	FILE *f;
  	const char *outmsgid;
  	const char *const *headers;
+	const char *subject;
 	int ret;
 
 	/* Check smpt functions just to be sure */
@@ -874,6 +886,21 @@ static bool act_vacation_send
 		return TRUE;
 	}
 
+	/* Make sure we have a subject for our reply */
+
+	if ( ctx->subject == NULL || *(ctx->subject) == '\0' ) {		
+		if ( mail_get_headers_utf8
+			(msgdata->mail, "subject", &headers) >= 0 && headers[0] != NULL ) {
+			subject = t_strconcat("Auto: ", headers[0], NULL);
+		}	else {
+			subject = "Automated reply";
+		}
+	}	else {
+		subject = ctx->subject;
+	}
+
+	subject = str_sanitize(subject, 256);
+
 	/* Open smtp session */
 
 	smtp_handle = sieve_smtp_open(senv, sender, NULL, &f);
@@ -897,8 +924,10 @@ static bool act_vacation_send
 	 */
 	rfc2822_header_field_printf(f, "To", "<%s>", sender);
 
-	rfc2822_header_field_utf8_printf(f, "Subject", "%s", 
-		str_sanitize(ctx->subject, 256));
+	if ( _contains_8bit(subject) )
+		rfc2822_header_field_utf8_printf(f, "Subject", "%s", subject);
+	else 
+		rfc2822_header_field_printf(f, "Subject", "%s", subject);
 
 	/* Compose proper in-reply-to and references headers */
 	
@@ -969,7 +998,6 @@ static bool act_vacation_commit
 	const char *const *headers;
 	const char *sender = sieve_message_get_sender(aenv->msgctx);
 	const char *recipient = sieve_message_get_recipient(aenv->msgctx);
-	pool_t pool;
 
 	/* Is the recipient unset? 
 	 */
@@ -1094,17 +1122,6 @@ static bool act_vacation_commit
 			recipient );	
 		return TRUE;				 
 	}	
-		
-	/* Make sure we have a subject for our reply */
-	if ( ctx->subject == NULL || *(ctx->subject) == '\0' ) {
-		if ( mail_get_headers_utf8
-			(msgdata->mail, "subject", &headers) >= 0 && headers[0] != NULL ) {
-			pool = sieve_result_pool(aenv->result);
-			ctx->subject = p_strconcat(pool, "Auto: ", headers[0], NULL);
-		}	else {
-			ctx->subject = "Automated reply";
-		}
-	}	
 	
 	/* Send the message */
 	
diff --git a/tests/extensions/vacation/utf-8.svtest b/tests/extensions/vacation/utf-8.svtest
index 2a7d329c8..f378a9f0c 100644
--- a/tests/extensions/vacation/utf-8.svtest
+++ b/tests/extensions/vacation/utf-8.svtest
@@ -13,30 +13,74 @@ To: nico@vestingbar.nl
 Frop
 .
 ;
+
 test "UTF-8 Subject" {
 	/* Trigger vacation response with rediculous Russian subject */
 	vacation :subject "Auto: Я могу есть стекло, оно мне не вредит."
 		"I am not in today"; 
 
 	/* Execute Sieve result (sending message to dummy SMTP) */
-    if not test_result_execute {
-        test_fail "execution of result failed";
-    }
+	if not test_result_execute {
+		test_fail "execution of result failed";
+	}
 
 	/* Retrieve message from dummy SMTP and set it as the active message under
 	 * test.
 	 */
-    test_message :smtp 0;
+	test_message :smtp 0;
 
 	set "expected" "Auto: Я могу есть стекло, оно мне не вредит.";
 	if not header :is "subject" "${expected}" {
 		if header :matches "subject" "*" { set "subject" "${1}"; }
 
-        test_fail text:
+		test_fail text:
+subject header is not encoded/decoded properly:
+expected: ${expected}
+decoded: ${subject}
+.
+;
+	}
+}
+
+test_result_reset;
+
+test_set "message" text:
+From: stephan@rename-it.nl
+Subject: frop
+References: <1234@local.machine.example> <3456@example.net>
+ <435444@ttms.com> <4223@froop.nl> <m345444444@message-id.exp>
+Message-ID: <432df324@rename-it.nl>
+To: nico@vestingbar.nl
+
+Frop
+.
+;
+
+
+test "MIME Encoded Subject" {
+	/* Trigger vacation response with rediculous Russian subject */
+	vacation :subject "=?utf-8?b?w4TDlsOc?= sadasd"
+		"I am not in today"; 
+
+	/* Execute Sieve result (sending message to dummy SMTP) */
+	if not test_result_execute {
+		test_fail "execution of result failed";
+	}
+
+	/* Retrieve message from dummy SMTP and set it as the active message under
+	 * test.
+	 */
+	test_message :smtp 0;
+
+	set "expected" "ÄÖÜ sadasd";
+	if not header :is "subject" "${expected}" {
+		if header :matches "subject" "*" { set "subject" "${1}"; }
+
+		test_fail text:
 subject header is not encoded/decoded properly:
 expected: ${expected}
 decoded: ${subject}
 .
 ;
-    }
+	}
 }
-- 
GitLab