aboutsummaryrefslogtreecommitdiff
path: root/lib/smtp.c
diff options
context:
space:
mode:
authorBill Nagel <wnagel@tycoint.com>2014-09-26 18:55:01 +0000
committerSteve Holme <steve_holme@hotmail.com>2014-09-30 21:36:27 +0100
commitee0958cb4d930cb4cdb167ea401699cbb9229afa (patch)
tree51fdcf94764d971202b2dbc39d69ec6f8ddca578 /lib/smtp.c
parent0e1590b3dd5107b7a3f65c19f9d84c4681975461 (diff)
smtp: Fixed intermittent "SSL3_WRITE_PENDING: bad write retry" error
This patch fixes the "SSL3_WRITE_PENDING: bad write retry" error that sometimes occurs when sending an email over SMTPS with OpenSSL. OpenSSL appears to require the same pointer on a write that follows a retry (CURLE_AGAIN) as discussed here: http://stackoverflow.com/questions/2997218/why-am-i-getting-error1409f07fssl-routinesssl3-write-pending-bad-write-retr
Diffstat (limited to 'lib/smtp.c')
-rw-r--r--lib/smtp.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/lib/smtp.c b/lib/smtp.c
index 9aa8b15bd..6d1aa0120 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -1807,7 +1807,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->req.protop;
struct pingpong *pp = &conn->proto.smtpc.pp;
- const char *eob;
+ char *eob;
ssize_t len;
ssize_t bytes_written;
@@ -1827,30 +1827,45 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
/* 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
- is "no mail data". RFC-5321, sect. 4.1.1.4. */
- eob = SMTP_EOB;
- len = SMTP_EOB_LEN;
+ is "no mail data". RFC-5321, sect. 4.1.1.4.
+
+ Note: As some SSL backends, such as OpenSSL, will cause Curl_write() to
+ fail when using a different pointer following a previous write, that
+ returned CURLE_AGAIN, we duplicate the EOB now rather than when the
+ bytes written doesn't equal len. */
if(smtp->trailing_crlf || !conn->data->state.infilesize) {
- eob += 2;
- len -= 2;
+ eob = strdup(SMTP_EOB + 2);
+ len = SMTP_EOB_LEN - 2;
+ }
+ else {
+ eob = strdup(SMTP_EOB);
+ len = SMTP_EOB_LEN;
}
+ if(!eob)
+ return CURLE_OUT_OF_MEMORY;
+
/* Send the end of block data */
result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
- if(result)
+ if(result) {
+ free(eob);
return result;
+ }
if(bytes_written != len) {
/* The whole chunk was not sent so keep it around and adjust the
pingpong structure accordingly */
- pp->sendthis = strdup(eob);
+ pp->sendthis = eob;
pp->sendsize = len;
pp->sendleft = len - bytes_written;
}
- else
+ else {
/* Successfully sent so adjust the response timeout relative to now */
pp->response = Curl_tvnow();
+ free(eob);
+ }
+
state(conn, SMTP_POSTDATA);
/* Run the state-machine