dovecot-2.0-sslstream: lmtp: Add Received: header, with a sessio...

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


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/ba3574ed9f74
changeset: 10257:ba3574ed9f74
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Nov 05 17:27:46 2009 -0500
description:
lmtp: Add Received: header, with a session ID. Log the session ID also.

diffstat:

5 files changed, 108 insertions(+), 14 deletions(-)
src/lib-lda/mail-deliver.c |    2 
src/lib-lda/mail-deliver.h |    2 
src/lmtp/client.c          |   16 +++++++
src/lmtp/client.h          |    3 +
src/lmtp/commands.c        |   99 +++++++++++++++++++++++++++++++++++++-------

diffs (251 lines):

diff -r b2925a5d9cf7 -r ba3574ed9f74 src/lib-lda/mail-deliver.c
--- a/src/lib-lda/mail-deliver.c	Thu Nov 05 17:03:47 2009 -0500
+++ b/src/lib-lda/mail-deliver.c	Thu Nov 05 17:27:46 2009 -0500
@@ -66,6 +66,8 @@ void mail_deliver_log(struct mail_delive
 	msg = t_strdup_vprintf(fmt, args);
 
 	str = t_str_new(256);
+	if (ctx->session_id != NULL)
+		str_printfa(str, "%s: ", ctx->session_id);
 	var_expand(str, ctx->set->deliver_log_format,
 		   get_log_var_expand_table(ctx, msg));
 	i_info("%s", str_c(str));
diff -r b2925a5d9cf7 -r ba3574ed9f74 src/lib-lda/mail-deliver.h
--- a/src/lib-lda/mail-deliver.h	Thu Nov 05 17:03:47 2009 -0500
+++ b/src/lib-lda/mail-deliver.h	Thu Nov 05 17:27:46 2009 -0500
@@ -10,6 +10,8 @@ struct mail_deliver_context {
 
 	struct duplicate_context *dup_ctx;
 
+	/* Session ID, used as log line prefix if non-NULL. */
+	const char *session_id;
 	/* Mail to save */
 	struct mail *src_mail;
 	/* Envelope sender, if known. */
diff -r b2925a5d9cf7 -r ba3574ed9f74 src/lmtp/client.c
--- a/src/lmtp/client.c	Thu Nov 05 17:03:47 2009 -0500
+++ b/src/lmtp/client.c	Thu Nov 05 17:27:46 2009 -0500
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "array.h"
+#include "base64.h"
 #include "str.h"
 #include "llist.h"
 #include "istream.h"
@@ -165,6 +166,18 @@ static void client_read_settings(struct 
 	client->lmtp_set = sets[2];
 }
 
+static void client_generate_session_id(struct client *client)
+{
+	uint8_t guid[MAIL_GUID_128_SIZE];
+	string_t *id = t_str_new(30);
+
+	mail_generate_guid_128(guid);
+	base64_encode(guid, sizeof(guid), id);
+	i_assert(str_c(id)[str_len(id)-2] == '=');
+	str_truncate(id, str_len(id)-2); /* drop trailing "==" */
+	client->state.session_id = p_strdup(client->state_pool, str_c(id));
+}
+
 struct client *client_create(int fd_in, int fd_out,
 			     const struct master_service_connection *conn)
 {
@@ -196,6 +209,7 @@ struct client *client_create(int fd_in, 
 	client->state.mail_data_fd = -1;
 	client_read_settings(client);
 	client_raw_user_create(client);
+	client_generate_session_id(client);
 
 	DLLIST_PREPEND(&clients, client);
 	clients_count++;
@@ -288,6 +302,8 @@ void client_state_reset(struct client *c
 	memset(&client->state, 0, sizeof(client->state));
 	p_clear(client->state_pool);
 	client->state.mail_data_fd = -1;
+
+	client_generate_session_id(client);
 }
 
 void client_send_line(struct client *client, const char *fmt, ...)
diff -r b2925a5d9cf7 -r ba3574ed9f74 src/lmtp/client.h
--- a/src/lmtp/client.h	Thu Nov 05 17:03:47 2009 -0500
+++ b/src/lmtp/client.h	Thu Nov 05 17:27:46 2009 -0500
@@ -11,6 +11,8 @@ struct mail_recipient {
 };
 
 struct client_state {
+	const char *lhlo;
+	const char *session_id;
 	const char *mail_from;
 	ARRAY_DEFINE(rcpt_to, struct mail_recipient);
 	unsigned int rcpt_idx;
@@ -22,6 +24,7 @@ struct client_state {
 	buffer_t *mail_data;
 	int mail_data_fd;
 	struct ostream *mail_data_output;
+	const char *received_line;
 
 	struct mailbox *raw_box;
 	struct mailbox_transaction_context *raw_trans;
diff -r b2925a5d9cf7 -r ba3574ed9f74 src/lmtp/commands.c
--- a/src/lmtp/commands.c	Thu Nov 05 17:03:47 2009 -0500
+++ b/src/lmtp/commands.c	Thu Nov 05 17:27:46 2009 -0500
@@ -6,10 +6,13 @@
 #include "str.h"
 #include "strescape.h"
 #include "istream.h"
+#include "istream-concat.h"
 #include "ostream.h"
 #include "istream-dot.h"
 #include "safe-mkstemp.h"
 #include "master-service.h"
+#include "rfc822-parser.h"
+#include "message-date.h"
 #include "auth-master.h"
 #include "mail-storage-service.h"
 #include "index/raw/raw-storage.h"
@@ -28,13 +31,43 @@
 
 #define LMTP_PROXY_DEFAULT_TIMEOUT_MSECS (1000*30)
 
-int cmd_lhlo(struct client *client, const char *args ATTR_UNUSED)
-{
+int cmd_lhlo(struct client *client, const char *args)
+{
+	struct rfc822_parser_context parser;
+	string_t *domain = t_str_new(128);
+	const char *p;
+	int ret;
+
+	if (*args == '\0') {
+		client_send_line(client, "501 Missing hostname");
+		return 0;
+	}
+
+	/* domain / address-literal */
+	rfc822_parser_init(&parser, (const unsigned char *)args, strlen(args),
+			   NULL);
+	if (*args != '[')
+		ret = rfc822_parse_dot_atom(&parser, domain);
+	else {
+		for (p = args+1; *p != ']'; p++) {
+			if (*p == '\\' || *p == '[')
+				break;
+		}
+		if (strcmp(p, "]") != 0)
+			ret = -1;
+	}
+	if (ret < 0) {
+		str_truncate(domain, 0);
+		str_append(domain, "invalid");
+	}
+
 	client_state_reset(client);
 	client_send_line(client, "250-%s", client->my_domain);
 	client_send_line(client, "250-8BITMIME");
 	client_send_line(client, "250-ENHANCEDSTATUSCODES");
 	client_send_line(client, "250 PIPELINING");
+
+	client->state.lhlo = p_strdup(client->state_pool, str_c(domain));
 	return 0;
 }
 
@@ -382,6 +415,7 @@ client_deliver(struct client *client, co
 	memset(&dctx, 0, sizeof(dctx));
 	dctx.pool = pool_alloconly_create("mail delivery", 1024);
 	dctx.set = sets[1];
+	dctx.session_id = client->state.session_id;
 	dctx.src_mail = src_mail;
 	dctx.src_envelope_sender = client->state.mail_from;
 	dctx.dest_user = client->state.dest_user;
@@ -395,7 +429,8 @@ client_deliver(struct client *client, co
 			i_assert(client->state.first_saved_mail == NULL);
 			client->state.first_saved_mail = dctx.dest_mail;
 		}
-		client_send_line(client, "250 2.0.0 <%s> Saved", rcpt->name);
+		client_send_line(client, "250 2.0.0 <%s> %s Saved",
+				 rcpt->name, client->state.session_id);
 		ret = 0;
 	} else if (storage == NULL) {
 		/* This shouldn't happen */
@@ -452,18 +487,29 @@ static void client_rcpt_fail_all(struct 
 
 static struct istream *client_get_input(struct client *client)
 {
-	struct istream *input;
-
-	if (client->state.mail_data_output != NULL) {
-		o_stream_unref(&client->state.mail_data_output);
-		input = i_stream_create_fd(client->state.mail_data_fd,
-					   MAIL_READ_FULL_BLOCK_SIZE, FALSE);
-		i_stream_set_init_buffer_size(input, MAIL_READ_FULL_BLOCK_SIZE);
+	struct client_state *state = &client->state;
+	struct istream *cinput, *inputs[3];
+
+	inputs[0] = i_stream_create_from_data(state->received_line,
+					      strlen(state->received_line));
+
+	if (state->mail_data_output != NULL) {
+		o_stream_unref(&state->mail_data_output);
+		inputs[1] = i_stream_create_fd(state->mail_data_fd,
+					       MAIL_READ_FULL_BLOCK_SIZE,
+					       FALSE);
+		i_stream_set_init_buffer_size(inputs[1],
+					      MAIL_READ_FULL_BLOCK_SIZE);
 	} else {
-		input = i_stream_create_from_data(client->state.mail_data->data,
-						  client->state.mail_data->used);
-	}
-	return input;
+		inputs[1] = i_stream_create_from_data(state->mail_data->data,
+						      state->mail_data->used);
+	}
+	inputs[2] = NULL;
+
+	cinput = i_stream_create_concat(inputs);
+	i_stream_unref(&inputs[0]);
+	i_stream_unref(&inputs[1]);
+	return cinput;
 }
 
 static int client_open_raw_mail(struct client *client, struct istream *input)
@@ -557,12 +603,37 @@ static void client_proxy_finish(void *co
 	client_input_data_finish(client);
 }
 
+static const char *client_get_received_line(struct client *client)
+{
+	string_t *str = t_str_new(200);
+	const char *host;
+
+	str_printfa(str, "Received: from %s", client->state.lhlo);
+	if ((host = net_ip2addr(&client->remote_ip)) != NULL)
+		str_printfa(str, " ([%s])", host);
+	str_printfa(str, "\r\n\tby %s ("PACKAGE_NAME") with LMTP id %s",
+		    client->my_domain, client->state.session_id);
+
+	str_append(str, "\r\n\t");
+	if (array_count(&client->state.rcpt_to) == 1) {
+		const struct mail_recipient *rcpt =
+			array_idx(&client->state.rcpt_to, 0);
+
+		str_printfa(str, "for <%s>", rcpt->name);
+	}
+	str_printfa(str, "; %s\r\n", message_date_create(ioloop_time));
+	return str_c(str);
+}
+
 static bool client_input_data_write(struct client *client)
 {
 	struct istream *input;
 	bool ret = TRUE;
 
 	i_stream_destroy(&client->dot_input);
+
+	client->state.received_line =
+		p_strdup(client->state_pool, client_get_received_line(client));
 
 	input = client_get_input(client);
 	client_input_data_write_local(client, input);


More information about the dovecot-cvs mailing list