* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, 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
#include "transfer.h"
#include "escape.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "mime.h"
#include "socks.h"
#include "smtp.h"
#include "strtoofft.h"
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
PORT_SMTP, /* defport */
CURLPROTO_SMTP, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
PORT_SMTPS, /* defport */
CURLPROTO_SMTPS, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_SSL
};
#endif
-#ifndef CURL_DISABLE_HTTP
-/*
- * HTTP-proxyed SMTP protocol handler.
- */
-
-static const struct Curl_handler Curl_handler_smtp_proxy = {
- "SMTP", /* scheme */
- Curl_http_setup_conn, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_getsock */
- ZERO_NULL, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- ZERO_NULL, /* perform_getsock */
- ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
- PORT_SMTP, /* defport */
- CURLPROTO_HTTP, /* protocol */
- PROTOPT_NONE /* flags */
-};
-
-#ifdef USE_SSL
-/*
- * HTTP-proxyed SMTPS protocol handler.
- */
-
-static const struct Curl_handler Curl_handler_smtps_proxy = {
- "SMTPS", /* scheme */
- Curl_http_setup_conn, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- ZERO_NULL, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_getsock */
- ZERO_NULL, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- ZERO_NULL, /* perform_getsock */
- ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
- PORT_SMTPS, /* defport */
- CURLPROTO_HTTP, /* protocol */
- PROTOPT_NONE /* flags */
-};
-#endif
-#endif
-
/* SASL parameters for the smtp protocol */
static const struct SASLproto saslsmtp = {
"smtp", /* The service name */
*/
static void smtp_get_message(char *buffer, char **outptr)
{
- size_t len = 0;
+ size_t len = strlen(buffer);
char *message = NULL;
- /* Find the start of the message */
- for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
- ;
-
- /* Find the end of the message */
- for(len = strlen(message); len--;)
- if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
- message[len] != '\t')
- break;
-
- /* Terminate the message */
- if(++len) {
- message[len] = '\0';
+ if(len > 4) {
+ /* Find the start of the message */
+ len -= 4;
+ for(message = buffer + 4; *message == ' ' || *message == '\t';
+ message++, len--)
+ ;
+
+ /* Find the end of the message */
+ for(; len--;)
+ if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+ message[len] != '\t')
+ break;
+
+ /* Terminate the message */
+ if(++len) {
+ message[len] = '\0';
+ }
}
+ else
+ /* junk input => zero length output */
+ message = &buffer[len];
*outptr = message;
}
}
}
+ /* Prepare the mime data if some. */
+ if(data->set.mimepost.kind != MIMEKIND_NONE) {
+ /* Use the whole structure as data. */
+ data->set.mimepost.flags &= ~MIME_BODY_ONLY;
+
+ /* Add external headers and mime version. */
+ curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+ NULL, MIMESTRATEGY_MAIL);
+
+ if(!result)
+ if(!Curl_checkheaders(conn, "Mime-Version"))
+ result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
+ "Mime-Version: 1.0");
+
+ /* Make sure we will read the entire mime structure. */
+ if(!result)
+ result = Curl_mime_rewind(&data->set.mimepost);
+
+ if(result) {
+ free(from);
+ free(auth);
+ return result;
+ }
+
+ data->state.infilesize = Curl_mime_size(&data->set.mimepost);
+
+ /* Read from mime structure. */
+ data->state.fread_func = (curl_read_callback) Curl_mime_read;
+ data->state.in = (void *) &data->set.mimepost;
+ }
+
/* Calculate the optional SIZE parameter */
- if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
+ if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) {
size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
if(!size) {
if(!smtp || !pp->conn)
return CURLE_OK;
+ /* Cleanup our per-request based variables */
+ Curl_safefree(smtp->custom);
+
if(status) {
connclose(conn, "SMTP done with bad status"); /* marked for closure */
result = status; /* use the already set error code */
}
- else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
+ else if(!data->set.connect_only && data->set.mail_rcpt &&
+ (data->set.upload || data->set.mimepost.kind)) {
/* 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.
}
else {
/* Successfully sent so adjust the response timeout relative to now */
- pp->response = Curl_tvnow();
+ pp->response = Curl_now();
free(eob);
}
result = smtp_block_statemach(conn);
}
- /* Cleanup our per-request based variables */
- Curl_safefree(smtp->custom);
-
/* Clear the transfer mode for the next request */
smtp->transfer = FTPTRANSFER_BODY;
/* Store the first recipient (or NULL if not specified) */
smtp->rcpt = data->set.mail_rcpt;
+ /* Initial data character is the first character in line: it is implicitly
+ preceded by a virtual CRLF. */
+ smtp->trailing_crlf = TRUE;
+ smtp->eob = 2;
+
/* Start the first command in the DO phase */
- if(data->set.upload && data->set.mail_rcpt)
+ if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
result = smtp_perform_mail(conn);
else
/* Clear the TLS upgraded flag */
conn->tls_upgraded = FALSE;
- /* Set up the proxy if necessary */
- if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
- /* Unless we have asked to tunnel SMTP operations through the proxy, we
- switch and use HTTP operations only */
-#ifndef CURL_DISABLE_HTTP
- if(conn->handler == &Curl_handler_smtp)
- conn->handler = &Curl_handler_smtp_proxy;
- else {
-#ifdef USE_SSL
- conn->handler = &Curl_handler_smtps_proxy;
-#else
- failf(data, "SMTPS not supported!");
- return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
- }
- /* set it up as a HTTP connection instead */
- return conn->handler->setup_connection(conn);
-
-#else
- failf(data, "SMTP over http proxy requires HTTP support built-in!");
- return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
- }
-
/* Initialise the SMTP layer */
result = smtp_init(conn);
if(result)
if(!scratch || data->set.crlf) {
oldscratch = scratch;
- scratch = newscratch = malloc(2 * BUFSIZE);
+ scratch = newscratch = malloc(2 * data->set.buffer_size);
if(!newscratch) {
failf(data, "Failed to alloc scratch buffer!");