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
This commit is contained in:
		
							
								
								
									
										33
									
								
								lib/smtp.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Bill Nagel
					Bill Nagel