1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*************************************************************************** 2e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * _ _ ____ _ 3e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Project ___| | | | _ \| | 4e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * / __| | | | |_) | | 5e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * | (__| |_| | _ <| |___ 6e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * \___|\___/|_| \_\_____| 7e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 80128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. 9e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which 11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms 128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html. 13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is 16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file. 17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied. 20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/ 228f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo 238f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo/* <DESC> 240128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes * Send e-mail with SMTP 258f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * </DESC> 268f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo */ 278f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo 28e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <stdio.h> 29e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <string.h> 30e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <curl/curl.h> 31e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 320128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes/* 330128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes * For an SMTP example using the multi interface please see smtp-multi.c. 340128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes */ 350128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes 360128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes/* The libcurl options want plain addresses, the viewable headers in the mail 370128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes * can very well get a full name as well. 38e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 390128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes#define FROM_ADDR "<sender@example.org>" 400128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes#define TO_ADDR "<addressee@example.net>" 410128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes#define CC_ADDR "<info@example.org>" 42e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 430128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes#define FROM_MAIL "Sender Person " FROM_ADDR 440128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes#define TO_MAIL "A Receiver " TO_ADDR 450128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes#define CC_MAIL "John CC Smith " CC_ADDR 46e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 47e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic const char *payload_text[] = { 48e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", 490128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes "To: " TO_MAIL "\r\n", 500128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes "From: " FROM_MAIL "\r\n", 510128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes "Cc: " CC_MAIL "\r\n", 528f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@" 538f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo "rfcpedant.example.org>\r\n", 54e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "Subject: SMTP example message\r\n", 55e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "\r\n", /* empty line to divide headers from body, see RFC5322 */ 56e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "The body of the message starts here.\r\n", 57e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "\r\n", 58e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "It could be a lot of lines, could be MIME encoded, whatever.\r\n", 59e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "Check RFC5322.\r\n", 60e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET NULL 61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}; 62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstruct upload_status { 64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int lines_read; 65e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}; 66e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 67e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) 68e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 69e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct upload_status *upload_ctx = (struct upload_status *)userp; 70e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET const char *data; 71e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 72e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { 73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 74e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 75e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 76e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET data = payload_text[upload_ctx->lines_read]; 77e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 78e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(data) { 79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t len = strlen(data); 80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET memcpy(ptr, data, len); 81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET upload_ctx->lines_read++; 82e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 83e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return len; 84e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 85e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 86e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint main(void) 90e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 91e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURL *curl; 92e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLcode res = CURLE_OK; 93e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct curl_slist *recipients = NULL; 94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct upload_status upload_ctx; 95e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 96e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET upload_ctx.lines_read = 0; 97e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 98e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl = curl_easy_init(); 99e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(curl) { 100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* This is the URL for your mailserver */ 101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.example.com"); 102e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1038f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo /* Note that this option isn't strictly required, omitting it will result 1048f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * in libcurl sending the MAIL FROM command with empty sender data. All 105e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * autoresponses should have an empty reverse-path, and should be directed 1068f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * to the address in the reverse-path which triggered them. Otherwise, 1078f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more 1088f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * details. 109e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 1100128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_ADDR); 111e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Add two recipients, in this particular case they correspond to the 113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * To: and Cc: addressees in the header, but they could be any kind of 114e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * recipient. */ 1150128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes recipients = curl_slist_append(recipients, TO_ADDR); 1160128fe4043cdbb72cc0c5b8f817749e3f89a7b36Elliott Hughes recipients = curl_slist_append(recipients, CC_ADDR); 117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); 118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 119e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* We're using a callback function to specify the payload (the headers and 120e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * body of the message). You could just use the CURLOPT_READDATA option to 121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * specify a FILE pointer to read from. */ 122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); 123e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); 124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); 125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Send the message */ 127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET res = curl_easy_perform(curl); 128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Check for errors */ 130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(res != CURLE_OK) 131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stderr, "curl_easy_perform() failed: %s\n", 132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_strerror(res)); 133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Free the list of recipients */ 135e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_slist_free_all(recipients); 136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1378f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo /* curl won't send the QUIT command until you call cleanup, so you should 1388f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * be able to re-use this connection for additional messages (setting 139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT as required, and calling 140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * curl_easy_perform() again. It may not be a good idea to keep the 1418f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * connection open for a very long time though (more than a few minutes 1428f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * may result in the server timing out the connection), and you do want to 1438f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * clean up in the end. 144e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 145e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_cleanup(curl); 146e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 147e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return (int)res; 149e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 150