smtp-multi.c (4671B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 /* <DESC> 26 * Send SMTP email with the multi interface 27 * </DESC> 28 */ 29 30 #include <string.h> 31 #include <curl/curl.h> 32 33 /* This is an example showing how to send mail using libcurl's SMTP 34 * capabilities. It builds on the smtp-mail.c example to demonstrate how to use 35 * libcurl's multi interface. 36 */ 37 38 #define FROM_MAIL "<sender@example.com>" 39 #define TO_MAIL "<recipient@example.com>" 40 #define CC_MAIL "<info@example.com>" 41 42 static const char *payload_text = 43 "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" 44 "To: " TO_MAIL "\r\n" 45 "From: " FROM_MAIL "\r\n" 46 "Cc: " CC_MAIL "\r\n" 47 "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@" 48 "rfcpedant.example.org>\r\n" 49 "Subject: SMTP example message\r\n" 50 "\r\n" /* empty line to divide headers from body, see RFC 5322 */ 51 "The body of the message starts here.\r\n" 52 "\r\n" 53 "It could be a lot of lines, could be MIME encoded, whatever.\r\n" 54 "Check RFC 5322.\r\n"; 55 56 struct upload_status { 57 size_t bytes_read; 58 }; 59 60 static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) 61 { 62 struct upload_status *upload_ctx = (struct upload_status *)userp; 63 const char *data; 64 size_t room = size * nmemb; 65 66 if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { 67 return 0; 68 } 69 70 data = &payload_text[upload_ctx->bytes_read]; 71 72 if(data) { 73 size_t len = strlen(data); 74 if(room < len) 75 len = room; 76 memcpy(ptr, data, len); 77 upload_ctx->bytes_read += len; 78 79 return len; 80 } 81 82 return 0; 83 } 84 85 int main(void) 86 { 87 CURL *curl; 88 CURLM *mcurl; 89 int still_running = 1; 90 struct curl_slist *recipients = NULL; 91 struct upload_status upload_ctx = { 0 }; 92 93 curl_global_init(CURL_GLOBAL_DEFAULT); 94 95 curl = curl_easy_init(); 96 if(!curl) 97 return 1; 98 99 mcurl = curl_multi_init(); 100 if(!mcurl) 101 return 2; 102 103 /* This is the URL for your mailserver */ 104 curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.example.com"); 105 106 /* Note that this option is not strictly required, omitting it results in 107 * libcurl sending the MAIL FROM command with empty sender data. All 108 * autoresponses should have an empty reverse-path, and should be directed 109 * to the address in the reverse-path which triggered them. Otherwise, they 110 * could cause an endless loop. See RFC 5321 Section 4.5.5 for more details. 111 */ 112 curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_MAIL); 113 114 /* Add two recipients, in this particular case they correspond to the 115 * To: and Cc: addressees in the header, but they could be any kind of 116 * recipient. */ 117 recipients = curl_slist_append(recipients, TO_MAIL); 118 recipients = curl_slist_append(recipients, CC_MAIL); 119 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); 120 121 /* We are using a callback function to specify the payload (the headers and 122 * body of the message). You could just use the CURLOPT_READDATA option to 123 * specify a FILE pointer to read from. */ 124 curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); 125 curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); 126 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); 127 128 /* Tell the multi stack about our easy handle */ 129 curl_multi_add_handle(mcurl, curl); 130 131 do { 132 CURLMcode mc = curl_multi_perform(mcurl, &still_running); 133 134 if(still_running) 135 /* wait for activity, timeout or "nothing" */ 136 mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL); 137 138 if(mc) 139 break; 140 141 } while(still_running); 142 143 /* Free the list of recipients */ 144 curl_slist_free_all(recipients); 145 146 /* Always cleanup */ 147 curl_multi_remove_handle(mcurl, curl); 148 curl_multi_cleanup(mcurl); 149 curl_easy_cleanup(curl); 150 curl_global_cleanup(); 151 152 return 0; 153 }