dovecot-2.0-sslstream: Added recipient_delimiter setting that LM...

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 13 02:56:19 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/51160ecbacaf
changeset: 10304:51160ecbacaf
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Nov 10 18:33:41 2009 -0500
description:
Added recipient_delimiter setting that LMTP server now uses.

diffstat:

4 files changed, 85 insertions(+), 38 deletions(-)
src/lib-lda/lda-settings.c |    7 ++
src/lib-lda/lda-settings.h |    1 
src/lmtp/client.h          |    3 -
src/lmtp/commands.c        |  112 +++++++++++++++++++++++++++++---------------

diffs (truncated from 321 to 300 lines):

diff -r 7d9cd9b7da08 -r 51160ecbacaf src/lib-lda/lda-settings.c
--- a/src/lib-lda/lda-settings.c	Tue Nov 10 15:09:10 2009 -0500
+++ b/src/lib-lda/lda-settings.c	Tue Nov 10 18:33:41 2009 -0500
@@ -24,6 +24,7 @@ static const struct setting_define lda_s
 	DEF(SET_STR, rejection_subject),
 	DEF(SET_STR, rejection_reason),
 	DEF(SET_STR, deliver_log_format),
+	DEF(SET_STR, recipient_delimiter),
 	DEF(SET_BOOL, quota_full_tempfail),
 	DEF(SET_BOOL, lda_mailbox_autocreate),
 	DEF(SET_BOOL, lda_mailbox_autosubscribe),
@@ -39,6 +40,7 @@ static const struct lda_settings lda_def
 	MEMBER(rejection_reason)
 		"Your message to <%t> was automatically rejected:%n%r",
 	MEMBER(deliver_log_format) "msgid=%m: %$",
+	MEMBER(recipient_delimiter) "",
 	MEMBER(quota_full_tempfail) FALSE,
 	MEMBER(lda_mailbox_autocreate) FALSE,
 	MEMBER(lda_mailbox_autosubscribe) FALSE
@@ -81,5 +83,10 @@ static bool lda_settings_check(void *_se
 		i_assert(my_hostname != NULL);
 		set->hostname = my_hostname;
 	}
+	if (*set->recipient_delimiter != '\0' &&
+	    set->recipient_delimiter[1] != '\0') {
+		*error_r = "recipient_delimiter must one character long";
+		return FALSE;
+	}
 	return TRUE;
 }
diff -r 7d9cd9b7da08 -r 51160ecbacaf src/lib-lda/lda-settings.h
--- a/src/lib-lda/lda-settings.h	Tue Nov 10 15:09:10 2009 -0500
+++ b/src/lib-lda/lda-settings.h	Tue Nov 10 18:33:41 2009 -0500
@@ -10,6 +10,7 @@ struct lda_settings {
 	const char *rejection_subject;
 	const char *rejection_reason;
 	const char *deliver_log_format;
+	const char *recipient_delimiter;
 	bool quota_full_tempfail;
 	bool lda_mailbox_autocreate;
 	bool lda_mailbox_autosubscribe;
diff -r 7d9cd9b7da08 -r 51160ecbacaf src/lmtp/client.h
--- a/src/lmtp/client.h	Tue Nov 10 15:09:10 2009 -0500
+++ b/src/lmtp/client.h	Tue Nov 10 18:33:41 2009 -0500
@@ -6,7 +6,8 @@
 #define CLIENT_MAIL_DATA_MAX_INMEMORY_SIZE (1024*128)
 
 struct mail_recipient {
-	const char *name;
+	const char *address;
+	const char *detail; /* +detail part is also in address */
 	struct mail_storage_service_user *service_user;
 };
 
diff -r 7d9cd9b7da08 -r 51160ecbacaf src/lmtp/commands.c
--- a/src/lmtp/commands.c	Tue Nov 10 15:09:10 2009 -0500
+++ b/src/lmtp/commands.c	Tue Nov 10 18:33:41 2009 -0500
@@ -114,12 +114,12 @@ int cmd_mail(struct client *client, cons
 	return 0;
 }
 
-static bool rcpt_is_duplicate(struct client *client, const char *name)
+static bool rcpt_is_duplicate(struct client *client, const char *address)
 {
 	const struct mail_recipient *rcpt;
 
 	array_foreach(&client->state.rcpt_to, rcpt) {
-		if (strcmp(rcpt->name, name) == 0)
+		if (strcmp(rcpt->address, address) == 0)
 			return TRUE;
 	}
 	return FALSE;
@@ -192,13 +192,14 @@ client_proxy_is_ourself(const struct cli
 	return TRUE;
 }
 
-static bool client_proxy_rcpt(struct client *client, const char *address)
+static bool client_proxy_rcpt(struct client *client, const char *address,
+			      const char *username)
 {
 	struct auth_master_connection *auth_conn;
 	struct lmtp_proxy_settings set;
 	struct auth_user_info info;
 	struct mail_storage_service_input input;
-	const char *args, *const *fields, *orig_address = address;
+	const char *args, *const *fields, *orig_username = username;
 	pool_t pool;
 	int ret;
 
@@ -215,7 +216,7 @@ static bool client_proxy_rcpt(struct cli
 
 	pool = pool_alloconly_create("auth lookup", 1024);
 	auth_conn = mail_storage_service_get_auth_conn(storage_service);
-	ret = auth_master_pass_lookup(auth_conn, address, &info,
+	ret = auth_master_pass_lookup(auth_conn, username, &info,
 				      pool, &fields);
 	if (ret <= 0) {
 		pool_unref(&pool);
@@ -234,15 +235,16 @@ static bool client_proxy_rcpt(struct cli
 	set.protocol = LMTP_CLIENT_PROTOCOL_LMTP;
 	set.timeout_msecs = LMTP_PROXY_DEFAULT_TIMEOUT_MSECS;
 
-	if (!client_proxy_rcpt_parse_fields(&set, fields, &address)) {
+	if (!client_proxy_rcpt_parse_fields(&set, fields, &username)) {
 		/* not proxying this user */
 		pool_unref(&pool);
 		return FALSE;
 	}
-	if (strcmp(address, orig_address) == 0 &&
+	if (strcmp(username, orig_username) == 0 &&
 	    client_proxy_is_ourself(client, &set)) {
-		i_error("Proxying to <%s> loops to itself", address);
-		client_send_line(client, "554 5.4.6 Proxying loops to itself");
+		i_error("Proxying to <%s> loops to itself", username);
+		client_send_line(client, "554 5.4.6 <%s> "
+				 "Proxying loops to itself", address);
 		pool_unref(&pool);
 		return FALSE;
 	}
@@ -300,11 +302,37 @@ static const char *lmtp_unescape_address
 	return str_c(str);
 }
 
+static void rcpt_address_parse(struct client *client, const char *address,
+			       const char **username_r, const char **detail_r)
+{
+	const char *p, *p2;
+
+	*username_r = address;
+	*detail_r = "";
+
+	if (*client->set->recipient_delimiter == '\0')
+		return;
+
+	p = strchr(address, *client->set->recipient_delimiter);
+	if (p != NULL) {
+		/* user+detail at domain */
+		*username_r = t_strdup_until(*username_r, p);
+		p2 = strchr(p, '@');
+		if (p2 == NULL)
+			*detail_r = p+1;
+		else {
+			*detail_r = t_strdup_until(p+1, p2);
+			*username_r = t_strconcat(*username_r, p2, NULL);
+		}
+	}
+}
+
 int cmd_rcpt(struct client *client, const char *args)
 {
 	struct mail_recipient rcpt;
 	struct mail_storage_service_input input;
-	const char *name, *error = NULL, *addr, *const *argv;
+	const char *address, *username, *detail;
+	const char *error = NULL, *arg, *const *argv;
 	unsigned int len;
 	int ret = 0;
 
@@ -315,21 +343,21 @@ int cmd_rcpt(struct client *client, cons
 
 	argv = t_strsplit(args, " ");
 	if (argv == NULL)
-		addr = "";
+		arg = "";
 	else {
-		addr = argv[0];
+		arg = argv[0];
 		argv++;
 	}
-	len = strlen(addr);
-	if (strncasecmp(addr, "TO:<", 4) != 0 || addr[len-1] != '>') {
+	len = strlen(arg);
+	if (strncasecmp(arg, "TO:<", 4) != 0 || arg[len-1] != '>') {
 		client_send_line(client, "501 5.5.4 Invalid parameters");
 		return 0;
 	}
 
 	memset(&rcpt, 0, sizeof(rcpt));
-	name = lmtp_unescape_address(t_strndup(addr + 4, len - 5));
-
-	if (rcpt_is_duplicate(client, name)) {
+	address = lmtp_unescape_address(t_strndup(arg + 4, len - 5));
+
+	if (rcpt_is_duplicate(client, address)) {
 		client_send_line(client, "250 2.1.5 OK, ignoring duplicate");
 		return 0;
 	}
@@ -338,16 +366,17 @@ int cmd_rcpt(struct client *client, cons
 		client_send_line(client, "501 5.5.4 Unsupported options");
 		return 0;
 	}
+	rcpt_address_parse(client, address, &username, &detail);
 
 	if (client->lmtp_set->lmtp_proxy) {
-		if (client_proxy_rcpt(client, name))
+		if (client_proxy_rcpt(client, address, username))
 			return 0;
 	}
 
 	memset(&input, 0, sizeof(input));
 	input.service = "lmtp";
 	input.module = "lda";
-	input.username = name;
+	input.username = username;
 	input.local_ip = client->local_ip;
 	input.remote_ip = client->remote_ip;
 
@@ -356,16 +385,18 @@ int cmd_rcpt(struct client *client, cons
 
 	if (ret < 0) {
 		i_error("User lookup failed: %s", error);
-		client_send_line(client, ERRSTR_TEMP_USERDB_FAIL, name);
+		client_send_line(client, ERRSTR_TEMP_USERDB_FAIL, username);
 		return 0;
 	}
 	if (ret == 0) {
 		client_send_line(client,
-				 "550 5.1.1 <%s> User doesn't exist", name);
-		return 0;
-	}
-
-	rcpt.name = p_strdup(client->state_pool, name);
+				 "550 5.1.1 <%s> User doesn't exist: %s",
+				 address, username);
+		return 0;
+	}
+
+	rcpt.address = p_strdup(client->state_pool, address);
+	rcpt.detail = p_strdup(client->state_pool, detail);
 	array_append(&client->state.rcpt_to, &rcpt, 1);
 
 	client_send_line(client, "250 2.1.5 OK");
@@ -403,18 +434,23 @@ client_deliver(struct client *client, co
 {
 	struct mail_deliver_context dctx;
 	struct mail_storage *storage;
+	const struct mail_storage_service_input *input;
 	void **sets;
-	const char *error;
+	const char *error, *username;
 	enum mail_error mail_error;
 	int ret;
 
+	input = mail_storage_service_user_get_input(rcpt->service_user);
+	username = t_strdup(input->username);
+
 	i_set_failure_prefix(t_strdup_printf("lmtp(%s, %s): ",
-					     my_pid, rcpt->name));
+					     my_pid, username));
 	if (mail_storage_service_next(storage_service, rcpt->service_user,
 				      &client->state.dest_user,
 				      &error) < 0) {
 		i_error("%s", error);
-		client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL, rcpt->name);
+		client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
+				 rcpt->address);
 		return -1;
 	}
 	sets = mail_storage_service_user_get_set(rcpt->service_user);
@@ -426,8 +462,8 @@ client_deliver(struct client *client, co
 	dctx.src_mail = src_mail;
 	dctx.src_envelope_sender = client->state.mail_from;
 	dctx.dest_user = client->state.dest_user;
-	dctx.dest_addr = rcpt->name;
-	dctx.dest_mailbox_name = "INBOX";
+	dctx.dest_addr = rcpt->address;
+	dctx.dest_mailbox_name = *rcpt->detail == '\0' ? "INBOX" : rcpt->detail;
 	dctx.save_dest_mail = array_count(&client->state.rcpt_to) > 1 &&
 		client->state.first_saved_mail == NULL;
 
@@ -437,13 +473,13 @@ client_deliver(struct client *client, co
 			client->state.first_saved_mail = dctx.dest_mail;
 		}
 		client_send_line(client, "250 2.0.0 <%s> %s Saved",
-				 rcpt->name, client->state.session_id);
+				 rcpt->address, client->state.session_id);
 		ret = 0;
 	} else if (storage == NULL) {
 		/* This shouldn't happen */
 		i_error("BUG: Saving failed to unknown storage");
 		client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
-				 rcpt->name);
+				 rcpt->address);
 		ret = -1;
 	} else {
 		error = mail_storage_get_last_error(storage, &mail_error);
@@ -451,10 +487,10 @@ client_deliver(struct client *client, co
 			client_send_line(client, "%s <%s> %s",
 					 dctx.set->quota_full_tempfail ?
 					 "452 4.2.2" : "552 5.2.2",
-					 rcpt->name, error);
+					 rcpt->address, error);
 		} else {
 			client_send_line(client, "451 4.2.0 <%s> %s",
-					 rcpt->name, error);
+					 rcpt->address, error);
 		}
 		ret = -1;
 	}
@@ -488,8 +524,10 @@ static void client_rcpt_fail_all(struct 


More information about the dovecot-cvs mailing list