Thanks Dan. I've made the changes you suggested. Good call about the date. I'll make sure to fix that. (Also, I am wanting it inline, so I removed that). In the actual code, I'll have it send the image in a better way like what you recommended, but will leave it alone for now since this program is more focused around the image. I tried running it again, and am still seeing the behavior. I tried removing the \r\n's from the image base64 encoding, but still no dice. I verified the image is valid by decoding my base64 encoded string and got back the image I was expecting. New code is attached.
---- On Sun, 26 Feb 2017 00:59:51 -0800 Dan Fandrich <[email protected]> wrote ---- On Sat, Feb 25, 2017 at 10:48:33PM -0800, Nicholas Chambers wrote: > Hello all! I'm writing a little thing which involves emailing an image after $x > amount of time. To make sure the code works, I wanted to put it in a separate > program and test it. Currently the code I have is attached as mail.c, and the > image I am trying to send is purple.jpeg. The email sends, and I get it in my > inbox, but the image fails to load. Could someone help me figure out why? > > Cheers, > Nicholas Chambers > > > > #include <stdio.h> > #include <string.h> > #include <curl/curl.h> > > #define FROM "<[email protected]>" > #define TO "<[email protected]>" > > static const char *payload_text[] = { > "To: " TO "\r\n", > "From: " FROM "\r\n", > "Subject: SMTPS Example\r\n", > "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", Naturally, you'll want to set this dynamically, since an old date will get lost in people's in-boxes and old dates are used by some systems as a spam indicator. > "User-Agent: My eMail Client\r\n", > "MIME-Version: 1.0\r\n", > "Content-Type: multipart/mixed;\r\n", > " boundary=\"------------030203080101020302070708\"\r\n", > "\r\nThis is a multi-part message in MIME format.\r\n", > "--------------030203080101020302070708\r\n", > "Content-Type: text/plain; charset=utf-8; format=flowed\r\n", > "Content-Transfer-Encoding: 7bit\r\n", > "\r\n", /* empty line to divide headers from body, see RFC5322 */ > "The body of the message starts here.\r\n", > "\r\n", > "--------------030203080101020302070708\r\n", > "Content-Type: text/jpeg; charset=utf-8; format=flowed\r\n", You want image/jpeg here. And charset and format are meaningless for that type. > "Content-Disposition: attachment;\r\n", If you use this, then the image won't be shown inline in most e-mail clients. Maybe that's what you want and maybe not. > " filename=\"purple.jpeg\"\r\n", > "\r\n", > "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIC\r\n", This header is only needed for the data: URL scheme. It's not a part of image/jpeg data and needs to be removed. [...] > "XPUfCNuI+MfCPjKXqB7Q8Z4Z4p4YF9OgqVKlfSEqVKlRlh8J6R8Z6x8Ohj0h4Q8IeEDAEMoEr9J+\r\n", > "jv1cR5jGMIbhxOJ2nP6f//Z\r\n", > "--------------030203080101020302070708--\r\n", > NULL > }; > > struct upload_status { > int lines_read; > }; > > static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) > { > struct upload_status *upload_ctx = (struct upload_status *)userp; > const char *data; > > if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { > return 0; > } > > data = payload_text[upload_ctx->lines_read]; > > if(data) { > size_t len = strlen(data); > memcpy(ptr, data, len); > upload_ctx->lines_read++; Sending data line-by-line works, but it's pretty inefficient. You could likely send the entirety of the message in a single callback. Rather than storing the message as an array of strings, I'd store it as a single string and send (size*nmemb) bytes of that string each time until it's all sent. > > return len; > } > > return 0; > } > > int main(void) > { > CURL *curl; > CURLcode res = CURLE_OK; > struct curl_slist *recipients = NULL; > struct upload_status upload_ctx; > > upload_ctx.lines_read = 0; > > curl = curl_easy_init(); > if(curl) { > /* This is the URL for your mailserver */ > curl_easy_setopt(curl, CURLOPT_URL, "smtp://localhost:25"); > > /* Note that this option isn't strictly required, omitting it will result > * in libcurl sending the MAIL FROM command with empty sender data. All > * autoresponses should have an empty reverse-path, and should be directed > * to the address in the reverse-path which triggered them. Otherwise, > * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more > * details. > */ > curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM); > > /* Add two recipients, in this particular case they correspond to the > * To: and Cc: addressees in the header, but they could be any kind of > * recipient. */ > recipients = curl_slist_append(recipients, TO); > curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); > > /* We're using a callback function to specify the payload (the headers and > * body of the message). You could just use the CURLOPT_READDATA option to > * specify a FILE pointer to read from. */ > curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); > curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); > curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); > > /* Send the message */ > res = curl_easy_perform(curl); > > /* Check for errors */ > if(res != CURLE_OK) > fprintf(stderr, "curl_easy_perform() failed: %s\n", > curl_easy_strerror(res)); > > /* Free the list of recipients */ > curl_slist_free_all(recipients); > > /* curl won't send the QUIT command until you call cleanup, so you should > * be able to re-use this connection for additional messages (setting > * CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling > * curl_easy_perform() again. It may not be a good idea to keep the > * connection open for a very long time though (more than a few minutes > * may result in the server timing out the connection), and you do want to > * clean up in the end. > */ > curl_easy_cleanup(curl); > } > > return (int)res; > } ------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.haxx.se/mail/etiquette.html
mail.c
Description: Binary data
------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.haxx.se/mail/etiquette.html
