mirror of
https://github.com/curl/curl.git
synced 2026-07-24 21:37:17 +03:00
smtp: Allow RCPT TO command to fail for some recipients
Introduces CURLOPT_MAIL_RCPT_ALLLOWFAILS. Verified with the new tests 3002-3007 Closes #4816
This commit is contained in:
parent
23a17e039d
commit
4a4609bf3c
22 changed files with 483 additions and 26 deletions
|
|
@ -5,7 +5,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
|
@ -2391,6 +2391,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
/* Set the list of mail recipients */
|
||||
data->set.mail_rcpt = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
case CURLOPT_MAIL_RCPT_ALLLOWFAILS:
|
||||
/* allow RCPT TO command to fail for some recipients */
|
||||
data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CURLOPT_SASL_AUTHZID:
|
||||
|
|
|
|||
50
lib/smtp.c
50
lib/smtp.c
|
|
@ -5,7 +5,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
|
@ -915,25 +915,53 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
|||
CURLcode result = CURLE_OK;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
bool is_smtp_err = FALSE;
|
||||
bool is_smtp_blocking_err = FALSE;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(smtpcode/100 != 2) {
|
||||
failf(data, "RCPT failed: %d", smtpcode);
|
||||
result = CURLE_SEND_ERROR;
|
||||
is_smtp_err = (smtpcode/100 != 2) ? TRUE : FALSE;
|
||||
|
||||
/* If there's multiple RCPT TO to be issued, it's possible to ignore errors
|
||||
and proceed with only the valid addresses. */
|
||||
is_smtp_blocking_err =
|
||||
(is_smtp_err && !data->set.mail_rcpt_allowfails) ? TRUE : FALSE;
|
||||
|
||||
if(is_smtp_err) {
|
||||
/* Remembering the last failure which we can report if all "RCPT TO" have
|
||||
failed and we cannot proceed. */
|
||||
smtp->rcpt_last_error = smtpcode;
|
||||
|
||||
if(is_smtp_blocking_err) {
|
||||
failf(data, "RCPT failed: %d", smtpcode);
|
||||
result = CURLE_SEND_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Some RCPT TO commands have succeeded. */
|
||||
smtp->rcpt_had_ok = TRUE;
|
||||
}
|
||||
|
||||
if(!is_smtp_blocking_err) {
|
||||
smtp->rcpt = smtp->rcpt->next;
|
||||
|
||||
if(smtp->rcpt)
|
||||
/* Send the next RCPT TO command */
|
||||
result = smtp_perform_rcpt_to(conn);
|
||||
else {
|
||||
/* Send the DATA command */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
|
||||
/* We weren't able to issue a successful RCPT TO command while going
|
||||
over recipients (potentially multiple). Sending back last error. */
|
||||
if(!smtp->rcpt_had_ok) {
|
||||
failf(data, "RCPT failed: %d (last error)", smtp->rcpt_last_error);
|
||||
result = CURLE_SEND_ERROR;
|
||||
}
|
||||
else {
|
||||
/* Send the DATA command */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_DATA);
|
||||
if(!result)
|
||||
state(conn, SMTP_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1287,6 +1315,12 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
|||
/* Store the first recipient (or NULL if not specified) */
|
||||
smtp->rcpt = data->set.mail_rcpt;
|
||||
|
||||
/* Track of whether we've successfully sent at least one RCPT TO command */
|
||||
smtp->rcpt_had_ok = FALSE;
|
||||
|
||||
/* Track of the last error we've received by sending RCPT TO command */
|
||||
smtp->rcpt_last_error = 0;
|
||||
|
||||
/* Initial data character is the first character in line: it is implicitly
|
||||
preceded by a virtual CRLF. */
|
||||
smtp->trailing_crlf = TRUE;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2009 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
|
@ -55,6 +55,9 @@ struct SMTP {
|
|||
curl_pp_transfer transfer;
|
||||
char *custom; /* Custom Request */
|
||||
struct curl_slist *rcpt; /* Recipient list */
|
||||
bool rcpt_had_ok; /* Whether any of RCPT TO commands (depends on
|
||||
total number of recipients) succeeded so far */
|
||||
int rcpt_last_error; /* The last error received for RCPT TO command */
|
||||
size_t eob; /* Number of bytes of the EOB (End Of Body) that
|
||||
have been received so far */
|
||||
bool trailing_crlf; /* Specifies if the tailing CRLF is present */
|
||||
|
|
|
|||
|
|
@ -1791,6 +1791,8 @@ struct UserDefined {
|
|||
BIT(doh); /* DNS-over-HTTPS enabled */
|
||||
BIT(doh_get); /* use GET for DoH requests, instead of POST */
|
||||
BIT(http09_allowed); /* allow HTTP/0.9 responses */
|
||||
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
|
||||
recipients */
|
||||
};
|
||||
|
||||
struct Names {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue