From: Stephan Bosch Date: Wed, 1 Mar 2017 23:03:50 +0000 (+0100) Subject: lib-lda: smtp-client: Make sure only the first error determines the tempfail status. X-Git-Tag: 2.3.0.rc1~1973 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8ac67bc3b77575484aa7c9f4eebcb5ee06589382;p=thirdparty%2Fdovecot%2Fcore.git 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. --- diff --git a/src/lib-lda/smtp-client.c b/src/lib-lda/smtp-client.c index 779395ba30..591365c391 100644 --- a/src/lib-lda/smtp-client.c +++ b/src/lib-lda/smtp-client.c @@ -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;