From e66eddcdba79212142553b21969e1b3d084864ae Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Wed, 21 Oct 2015 23:27:36 +0200
Subject: [PATCH] lib-sieve: Created generic implementation for parsing an
 envelope_from setting, such as sieve_redirect_envelope_from. Also adds a new
 source for the envelope_from address called "postmaster". This means that the
 value is obtained from the postmaster_address LDA setting.

---
 INSTALL                        |  9 ++--
 src/lib-sieve/cmd-redirect.c   | 22 +++++-----
 src/lib-sieve/sieve-common.h   | 20 ++++++---
 src/lib-sieve/sieve-settings.c | 78 ++++++++++++++++++++--------------
 src/lib-sieve/sieve-settings.h |  4 ++
 5 files changed, 81 insertions(+), 52 deletions(-)

diff --git a/INSTALL b/INSTALL
index 2fe76b91a..39bd9822d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -229,14 +229,15 @@ plugin section of the config file (default values are shown if applicable):
    appears to originate from the original sender. The following values are
    supported for this setting:
    
-     "sender"         - The sender address is used (default)
-     "recipient"      - The final recipient address is used
-     "orig_recipient" - The original recipient is used
+     "sender"         - The sender address is used (default).
+     "recipient"      - The final recipient address is used.
+     "orig_recipient" - The original recipient is used.
+     "postmaster"     - The postmaster_address configured for the LDA.
      "<user@domain>"  - Redirected messages are always sent from user@domain.
                         The angle brackets are mandatory. The null "<>" address
                         is also supported.
 
-	 When the envelope sender of the processed message is the null address "<>",
+   When the envelope sender of the processed message is the null address "<>",
    the envelope sender of the redirected message is also always "<>",
    irrespective of what is configured for this setting. 
 
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 50cc28917..deb81acdd 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -317,8 +317,8 @@ static int act_redirect_send
 	const struct sieve_script_env *senv = aenv->scriptenv;
 	const char *sender = sieve_message_get_sender(msgctx);
 	const char *recipient = sieve_message_get_final_recipient(msgctx);
-	enum sieve_redirect_envelope_from env_from =
-		aenv->svinst->redirect_from;
+	struct sieve_mail_sender *env_from =
+		&aenv->svinst->redirect_from;
 	struct istream *input;
 	struct ostream *output;
 	const char *error;
@@ -350,20 +350,22 @@ static int act_redirect_send
 		 when then returns a delivery status notification that also ends up
 		 being redirected to the same invalid address.
 	 */
-	if ( sender != NULL &&
-		env_from != SIEVE_REDIRECT_ENVELOPE_FROM_SENDER ) {
-		switch ( env_from ) {
-		case SIEVE_REDIRECT_ENVELOPE_FROM_RECIPIENT:
+	if ( sender != NULL ) {
+		switch ( env_from->source ) {
+		case SIEVE_MAIL_SENDER_SOURCE_RECIPIENT:
 			sender = sieve_message_get_final_recipient(msgctx);
 			break;
-		case SIEVE_REDIRECT_ENVELOPE_FROM_ORIG_RECIPIENT:
+		case SIEVE_MAIL_SENDER_SOURCE_ORIG_RECIPIENT:
 			sender = sieve_message_get_orig_recipient(msgctx);
 			break;
-		case SIEVE_REDIRECT_ENVELOPE_FROM_EXPLICIT:
-			sender = aenv->svinst->redirect_from_explicit;
+		case SIEVE_MAIL_SENDER_SOURCE_POSTMASTER:
+			sender = senv->postmaster_address;
+			break;
+		case SIEVE_MAIL_SENDER_SOURCE_EXPLICIT:
+			sender = env_from->address;
 			break;
 		default:
-			i_unreached();
+			break;
 		}
 	}
 
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index fe75e45ed..6e39bc7b2 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -21,11 +21,18 @@ typedef uint32_t sieve_number_t;
 
 #define SIEVE_MAX_NUMBER ((sieve_number_t) -1)
 
-enum sieve_redirect_envelope_from {
-	SIEVE_REDIRECT_ENVELOPE_FROM_SENDER,
-	SIEVE_REDIRECT_ENVELOPE_FROM_RECIPIENT,
-	SIEVE_REDIRECT_ENVELOPE_FROM_ORIG_RECIPIENT,
-	SIEVE_REDIRECT_ENVELOPE_FROM_EXPLICIT
+enum sieve_mail_sender_source {
+	SIEVE_MAIL_SENDER_SOURCE_DEFAULT = 0,
+	SIEVE_MAIL_SENDER_SOURCE_SENDER,
+	SIEVE_MAIL_SENDER_SOURCE_RECIPIENT,
+	SIEVE_MAIL_SENDER_SOURCE_ORIG_RECIPIENT,
+	SIEVE_MAIL_SENDER_SOURCE_POSTMASTER,
+	SIEVE_MAIL_SENDER_SOURCE_EXPLICIT
+};
+
+struct sieve_mail_sender {
+	enum sieve_mail_sender_source source;
+	const char *address;
 };
 
 /*
@@ -206,8 +213,7 @@ struct sieve_instance {
 	size_t max_script_size;
 	unsigned int max_actions;
 	unsigned int max_redirects;
-	enum sieve_redirect_envelope_from redirect_from;
-	const char *redirect_from_explicit;
+	struct sieve_mail_sender redirect_from;
 };
 
 #endif /* __SIEVE_COMMON_H */
diff --git a/src/lib-sieve/sieve-settings.c b/src/lib-sieve/sieve-settings.c
index 0997a2e72..e5168d7cb 100644
--- a/src/lib-sieve/sieve-settings.c
+++ b/src/lib-sieve/sieve-settings.c
@@ -217,6 +217,48 @@ bool sieve_setting_get_duration_value
 	return TRUE;
 }
 
+bool sieve_setting_get_mail_sender_value
+(struct sieve_instance *svinst, pool_t pool, const char *setting,
+	struct sieve_mail_sender *sender)
+{
+	const char *str_value;
+	size_t set_len;
+
+	str_value = sieve_setting_get(svinst, setting);
+	if ( str_value == NULL )
+		return FALSE;
+
+	str_value = t_str_trim(str_value);
+	str_value = t_str_lcase(str_value);
+	set_len = strlen(str_value);
+	if ( set_len > 0 ) {
+		if ( strcmp(str_value, "default") == 0 ) {
+			sender->source = SIEVE_MAIL_SENDER_SOURCE_DEFAULT;
+		} else if ( strcmp(str_value, "sender") == 0 ) {
+			sender->source = SIEVE_MAIL_SENDER_SOURCE_SENDER;
+		} else if ( strcmp(str_value, "recipient") == 0 ) {
+			sender->source = SIEVE_MAIL_SENDER_SOURCE_RECIPIENT;
+		} else if ( strcmp(str_value, "orig_recipient") == 0 ) {
+			sender->source = SIEVE_MAIL_SENDER_SOURCE_ORIG_RECIPIENT;
+		} else if ( strcmp(str_value, "postmaster") == 0 ) {
+			sender->source = SIEVE_MAIL_SENDER_SOURCE_POSTMASTER;
+		} else if ( str_value[0] == '<' &&	str_value[set_len-1] == '>') {
+			sender->source = SIEVE_MAIL_SENDER_SOURCE_EXPLICIT;
+
+			str_value = t_str_trim(t_strndup(str_value+1, set_len-2));
+			sender->address = NULL;
+			if ( *str_value != '\0' )
+				sender->address = p_strdup(pool, str_value);
+		} else {
+			sieve_sys_warning(svinst,
+				"Invalid value for setting '%s': '%s'", setting,
+				str_value);
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
 /*
  * Main Sieve engine settings
  */
@@ -226,7 +268,6 @@ void sieve_settings_load
 {
 	unsigned long long int uint_setting;
 	size_t size_setting;
-	const char *str_setting;
 
 	svinst->max_script_size = SIEVE_DEFAULT_MAX_SCRIPT_SIZE;
 	if ( sieve_setting_get_size_value
@@ -246,36 +287,11 @@ void sieve_settings_load
 		svinst->max_redirects = (unsigned int) uint_setting;
 	}
 
-	svinst->redirect_from = SIEVE_REDIRECT_ENVELOPE_FROM_SENDER;
-	svinst->redirect_from_explicit = NULL;
-	if ( (str_setting=sieve_setting_get
-		(svinst, "sieve_redirect_envelope_from")) != NULL ) {
-		size_t set_len;
-
-		str_setting = t_str_trim(str_setting);
-		str_setting = t_str_lcase(str_setting);
-		set_len = strlen(str_setting);
-		if ( set_len > 0 ) {
-			if ( strcmp(str_setting, "sender") == 0 ) {
-				svinst->redirect_from = SIEVE_REDIRECT_ENVELOPE_FROM_SENDER;
-			} else if ( strcmp(str_setting, "recipient") == 0 ) {
-				svinst->redirect_from = SIEVE_REDIRECT_ENVELOPE_FROM_RECIPIENT;
-			} else if ( strcmp(str_setting, "orig_recipient") == 0 ) {
-				svinst->redirect_from = SIEVE_REDIRECT_ENVELOPE_FROM_ORIG_RECIPIENT;
-			} else if ( str_setting[0] == '<' &&	str_setting[set_len-1] == '>') {
-				svinst->redirect_from = SIEVE_REDIRECT_ENVELOPE_FROM_EXPLICIT;
-
-				str_setting = t_str_trim(t_strndup(str_setting+1, set_len-2));
-				if ( *str_setting != '\0' ) {
-					svinst->redirect_from_explicit =
-						p_strdup(svinst->pool, str_setting);
-				}
-			} else {
-				sieve_sys_warning(svinst,
-					"Invalid value `%s' for sieve_redirect_envelope_from setting",
-					str_setting);
-			}
-		}
+	if (!sieve_setting_get_mail_sender_value
+		(svinst, svinst->pool, "sieve_redirect_envelope_from",
+			&svinst->redirect_from)) {
+		svinst->redirect_from.source =
+			SIEVE_MAIL_SENDER_SOURCE_DEFAULT;
 	}
 }
 
diff --git a/src/lib-sieve/sieve-settings.h b/src/lib-sieve/sieve-settings.h
index af1b96f93..739a98650 100644
--- a/src/lib-sieve/sieve-settings.h
+++ b/src/lib-sieve/sieve-settings.h
@@ -37,6 +37,10 @@ bool sieve_setting_get_duration_value
 	(struct sieve_instance *svinst, const char *setting,
 		sieve_number_t *value_r);
 
+bool sieve_setting_get_mail_sender_value
+	(struct sieve_instance *svinst, pool_t pool, const char *setting,
+		struct sieve_mail_sender *sender);
+
 /*
  * Main Sieve engine settings
  */
-- 
GitLab