]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-lda: smtp-client: Make sure only the first error determines the tempfail status.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Wed, 1 Mar 2017 23:03:50 +0000 (00:03 +0100)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Fri, 3 Mar 2017 23:21:18 +0000 (00:21 +0100)
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.

src/lib-lda/smtp-client.c

index 779395ba30db19de07f9a84dbf37d2ca0737e0de..591365c391da5f84ce14201127130391e097a05c 100644 (file)
@@ -80,9 +80,11 @@ static void smtp_client_send_finished(void *context)
 }
 
 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);
        }
@@ -94,10 +96,8 @@ rcpt_to_callback(enum lmtp_client_result result, const char *reply, void *contex
        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);
        }
 }
@@ -108,10 +108,8 @@ data_callback(enum lmtp_client_result result, const char *reply, void *context)
        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;