changeset 21779:2cfa5218955e

lib-lda: smtp-client: Make sure only the first error determines the tempfail status. The client is supposed to stop running the moment the first error occurs. However, there is a (very unlikely) possiblity that the encapsulated LMTP client issues both an RCPT and DATA error callback in sequence. In that case, the second callback should not override the tempfail status of the first (the second likely is a tempfail). If the server disconnects right after failing the last of at least two recipients, the lmtp-client would issue a DATA callback with a disconnection error. The disconnect error would set the client->tempfail flag, which caused smtp_client_deinit*() to always return -1 in this scenario.
author Stephan Bosch <stephan.bosch@dovecot.fi>
date Thu, 02 Mar 2017 00:03:50 +0100
parents 71298a01f82f
children e54c9d8d9936
files src/lib-lda/smtp-client.c
diffstat 1 files changed, 7 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-lda/smtp-client.c	Sat Nov 05 22:00:09 2016 +0100
+++ b/src/lib-lda/smtp-client.c	Thu Mar 02 00:03:50 2017 +0100
@@ -208,9 +208,11 @@
 }
 
 static void
-smtp_client_error(struct smtp_client *client, const char *error)
+smtp_client_error(struct smtp_client *client,
+		 bool tempfail, const char *error)
 {
 	if (client->error == NULL) {
+		client->tempfail = tempfail;
 		client->error = i_strdup_printf("smtp(%s): %s",
 			client->set->submission_host, error);
 	}
@@ -222,10 +224,8 @@
 	struct smtp_client *client = context;
 
 	if (result != LMTP_CLIENT_RESULT_OK) {
-		if (reply[0] != '5')
-			client->tempfail = TRUE;
-		smtp_client_error(client, t_strdup_printf(
-			"RCPT TO failed: %s", reply));
+		smtp_client_error(client, (reply[0] != '5'),
+			t_strdup_printf("RCPT TO failed: %s", reply));
 		smtp_client_send_finished(client);
 	}
 }
@@ -236,10 +236,8 @@
 	struct smtp_client *client = context;
 
 	if (result != LMTP_CLIENT_RESULT_OK) {
-		if (reply[0] != '5')
-			client->tempfail = TRUE;
-		smtp_client_error(client, t_strdup_printf(
-			"DATA failed: %s", reply));
+		smtp_client_error(client, (reply[0] != '5'),
+			t_strdup_printf("DATA failed: %s", reply));
 		smtp_client_send_finished(client);
 	} else {
 		client->success = TRUE;