smtp: Added support for NOOP and RSET commands
This commit is contained in:
Родитель
4a9fe26837
Коммит
dac01ff6d7
95
lib/smtp.c
95
lib/smtp.c
|
@ -104,6 +104,7 @@ static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
|
||||||
static CURLcode smtp_setup_connection(struct connectdata *conn);
|
static CURLcode smtp_setup_connection(struct connectdata *conn);
|
||||||
static CURLcode smtp_parse_url_options(struct connectdata *conn);
|
static CURLcode smtp_parse_url_options(struct connectdata *conn);
|
||||||
static CURLcode smtp_parse_url_path(struct connectdata *conn);
|
static CURLcode smtp_parse_url_path(struct connectdata *conn);
|
||||||
|
static CURLcode smtp_parse_custom_request(struct connectdata *conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMTP protocol handler.
|
* SMTP protocol handler.
|
||||||
|
@ -314,6 +315,7 @@ static void state(struct connectdata *conn, smtpstate newstate)
|
||||||
"AUTH_XOAUTH2",
|
"AUTH_XOAUTH2",
|
||||||
"AUTH_CANCEL",
|
"AUTH_CANCEL",
|
||||||
"AUTH_FINAL",
|
"AUTH_FINAL",
|
||||||
|
"COMMAND",
|
||||||
"MAIL",
|
"MAIL",
|
||||||
"RCPT",
|
"RCPT",
|
||||||
"DATA",
|
"DATA",
|
||||||
|
@ -548,6 +550,28 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_command()
|
||||||
|
*
|
||||||
|
* Sends a SMTP based command.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_command(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct SMTP *smtp = data->req.protop;
|
||||||
|
|
||||||
|
/* Send the command */
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
|
||||||
|
smtp->custom && smtp->custom[0] != '\0' ?
|
||||||
|
smtp->custom : "NOOP");
|
||||||
|
if(!result)
|
||||||
|
state(conn, SMTP_COMMAND);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* smtp_perform_mail()
|
* smtp_perform_mail()
|
||||||
|
@ -1231,6 +1255,29 @@ static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For command responses */
|
||||||
|
static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
|
||||||
|
smtpstate instate)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct SMTP *smtp = data->req.protop;
|
||||||
|
|
||||||
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
|
if(smtpcode/100 != 2) {
|
||||||
|
failf(data, "%s failed: %d",
|
||||||
|
smtp->custom && smtp->custom[0] != '\0' ? smtp->custom : "NOOP",
|
||||||
|
smtpcode);
|
||||||
|
result = CURLE_RECV_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End of DO phase */
|
||||||
|
state(conn, SMTP_STOP);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* For MAIL responses */
|
/* For MAIL responses */
|
||||||
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
||||||
smtpstate instate)
|
smtpstate instate)
|
||||||
|
@ -1433,6 +1480,10 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
|
||||||
result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
|
result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SMTP_COMMAND:
|
||||||
|
result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
|
||||||
|
break;
|
||||||
|
|
||||||
case SMTP_MAIL:
|
case SMTP_MAIL:
|
||||||
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
|
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
|
||||||
break;
|
break;
|
||||||
|
@ -1596,7 +1647,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||||
conn->bits.close = TRUE; /* marked for closure */
|
conn->bits.close = TRUE; /* marked for closure */
|
||||||
result = status; /* use the already set error code */
|
result = status; /* use the already set error code */
|
||||||
}
|
}
|
||||||
else if(!data->set.connect_only) {
|
else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
|
||||||
/* Calculate the EOB taking into account any terminating CRLF from the
|
/* Calculate the EOB taking into account any terminating CRLF from the
|
||||||
previous line of the email or the CRLF of the DATA command when there
|
previous line of the email or the CRLF of the DATA command when there
|
||||||
is "no mail data". RFC-5321, sect. 4.1.1.4. */
|
is "no mail data". RFC-5321, sect. 4.1.1.4. */
|
||||||
|
@ -1645,31 +1696,38 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||||
*
|
*
|
||||||
* smtp_perform()
|
* smtp_perform()
|
||||||
*
|
*
|
||||||
* This is the actual DO function for SMTP. Send a mail according to the
|
* This is the actual DO function for SMTP. Transfer a mail or send a command
|
||||||
* options previously setup.
|
* according to the options previously setup.
|
||||||
*/
|
*/
|
||||||
static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
||||||
bool *dophase_done)
|
bool *dophase_done)
|
||||||
{
|
{
|
||||||
/* This is SMTP and no proxy */
|
/* This is SMTP and no proxy */
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
DEBUGF(infof(conn->data, "DO phase starts\n"));
|
DEBUGF(infof(conn->data, "DO phase starts\n"));
|
||||||
|
|
||||||
if(conn->data->set.opt_no_body) {
|
if(data->set.opt_no_body) {
|
||||||
/* Requested no body means no transfer */
|
/* Requested no body means no transfer */
|
||||||
struct SMTP *smtp = conn->data->req.protop;
|
struct SMTP *smtp = data->req.protop;
|
||||||
smtp->transfer = FTPTRANSFER_INFO;
|
smtp->transfer = FTPTRANSFER_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
*dophase_done = FALSE; /* not done yet */
|
*dophase_done = FALSE; /* not done yet */
|
||||||
|
|
||||||
/* Start the first command in the DO phase */
|
/* Start the first command in the DO phase */
|
||||||
|
if(data->set.upload && data->set.mail_rcpt)
|
||||||
|
/* MAIL transfer */
|
||||||
result = smtp_perform_mail(conn);
|
result = smtp_perform_mail(conn);
|
||||||
|
else
|
||||||
|
/* SMTP based command (NOOP or RSET) */
|
||||||
|
result = smtp_perform_command(conn);
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* run the state-machine */
|
/* Run the state-machine */
|
||||||
result = smtp_multi_statemach(conn, dophase_done);
|
result = smtp_multi_statemach(conn, dophase_done);
|
||||||
|
|
||||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||||
|
@ -1695,6 +1753,11 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
|
||||||
|
|
||||||
*done = FALSE; /* default to false */
|
*done = FALSE; /* default to false */
|
||||||
|
|
||||||
|
/* Parse the custom request */
|
||||||
|
result = smtp_parse_custom_request(conn);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
result = smtp_regular_transfer(conn, done);
|
result = smtp_regular_transfer(conn, done);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1910,6 +1973,26 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
|
||||||
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
|
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_parse_custom_request()
|
||||||
|
*
|
||||||
|
* Parse the custom request.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_parse_custom_request(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct SMTP *smtp = data->req.protop;
|
||||||
|
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
|
||||||
|
|
||||||
|
/* URL decode the custom request */
|
||||||
|
if(custom)
|
||||||
|
result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
|
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
|
||||||
{
|
{
|
||||||
/* When sending a SMTP payload we must detect CRLF. sequences making sure
|
/* When sending a SMTP payload we must detect CRLF. sequences making sure
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef enum {
|
||||||
SMTP_AUTH_XOAUTH2,
|
SMTP_AUTH_XOAUTH2,
|
||||||
SMTP_AUTH_CANCEL,
|
SMTP_AUTH_CANCEL,
|
||||||
SMTP_AUTH_FINAL,
|
SMTP_AUTH_FINAL,
|
||||||
|
SMTP_COMMAND, /* NOOP and RSET */
|
||||||
SMTP_MAIL, /* MAIL FROM */
|
SMTP_MAIL, /* MAIL FROM */
|
||||||
SMTP_RCPT, /* RCPT TO */
|
SMTP_RCPT, /* RCPT TO */
|
||||||
SMTP_DATA,
|
SMTP_DATA,
|
||||||
|
@ -61,6 +62,7 @@ typedef enum {
|
||||||
used. */
|
used. */
|
||||||
struct SMTP {
|
struct SMTP {
|
||||||
curl_pp_transfer transfer;
|
curl_pp_transfer transfer;
|
||||||
|
char *custom; /* Custom Request */
|
||||||
struct curl_slist *rcpt; /* Recipient list */
|
struct curl_slist *rcpt; /* Recipient list */
|
||||||
size_t eob; /* Number of bytes of the EOB (End Of Body) that
|
size_t eob; /* Number of bytes of the EOB (End Of Body) that
|
||||||
have been received so far */
|
have been received so far */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче