1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://curl.haxx.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 ***************************************************************************/ 22/* This is an example application source code sending SMTP mail using the 23 * multi interface. 24 */ 25 26#include <string.h> 27#include <curl/curl.h> 28 29/* 30 * This is the list of basic details you need to tweak to get things right. 31 */ 32#define USERNAME "user@example.com" 33#define PASSWORD "123qwerty" 34#define SMTPSERVER "smtp.example.com" 35#define SMTPPORT ":587" /* it is a colon+port string, but you can set it 36 to "" to use the default port */ 37#define RECIPIENT "<recipient@example.com>" 38#define MAILFROM "<realuser@example.com>" 39 40#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000 41 42/* Note that you should include the actual meta data headers here as well if 43 you want the mail to have a Subject, another From:, show a To: or whatever 44 you think your mail should feature! */ 45static const char *text[]={ 46 "one\n", 47 "two\n", 48 "three\n", 49 " Hello, this is CURL email SMTP\n", 50 NULL 51}; 52 53struct WriteThis { 54 int counter; 55}; 56 57static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp) 58{ 59 struct WriteThis *pooh = (struct WriteThis *)userp; 60 const char *data; 61 62 if(size*nmemb < 1) 63 return 0; 64 65 data = text[pooh->counter]; 66 67 if(data) { 68 size_t len = strlen(data); 69 memcpy(ptr, data, len); 70 pooh->counter++; /* advance pointer */ 71 return len; 72 } 73 return 0; /* no more data left to deliver */ 74} 75 76static struct timeval tvnow(void) 77{ 78 /* 79 ** time() returns the value of time in seconds since the Epoch. 80 */ 81 struct timeval now; 82 now.tv_sec = (long)time(NULL); 83 now.tv_usec = 0; 84 return now; 85} 86 87static long tvdiff(struct timeval newer, struct timeval older) 88{ 89 return (newer.tv_sec-older.tv_sec)*1000+ 90 (newer.tv_usec-older.tv_usec)/1000; 91} 92 93int main(void) 94{ 95 CURL *curl; 96 CURLM *mcurl; 97 int still_running = 1; 98 struct timeval mp_start; 99 char mp_timedout = 0; 100 struct WriteThis pooh; 101 struct curl_slist* rcpt_list = NULL; 102 103 pooh.counter = 0; 104 105 curl_global_init(CURL_GLOBAL_DEFAULT); 106 107 curl = curl_easy_init(); 108 if(!curl) 109 return 1; 110 111 mcurl = curl_multi_init(); 112 if(!mcurl) 113 return 2; 114 115 rcpt_list = curl_slist_append(rcpt_list, RECIPIENT); 116 /* more addresses can be added here 117 rcpt_list = curl_slist_append(rcpt_list, "<others@example.com>"); 118 */ 119 120 curl_easy_setopt(curl, CURLOPT_URL, "smtp://" SMTPSERVER SMTPPORT); 121 curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME); 122 curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD); 123 curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); 124 curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM); 125 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt_list); 126 curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); 127 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 128 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); 129 curl_easy_setopt(curl, CURLOPT_READDATA, &pooh); 130 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 131 curl_easy_setopt(curl, CURLOPT_SSLVERSION, 0L); 132 curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L); 133 curl_multi_add_handle(mcurl, curl); 134 135 mp_timedout = 0; 136 mp_start = tvnow(); 137 138 /* we start some action by calling perform right away */ 139 curl_multi_perform(mcurl, &still_running); 140 141 while(still_running) { 142 struct timeval timeout; 143 int rc; /* select() return code */ 144 145 fd_set fdread; 146 fd_set fdwrite; 147 fd_set fdexcep; 148 int maxfd = -1; 149 150 long curl_timeo = -1; 151 152 FD_ZERO(&fdread); 153 FD_ZERO(&fdwrite); 154 FD_ZERO(&fdexcep); 155 156 /* set a suitable timeout to play around with */ 157 timeout.tv_sec = 1; 158 timeout.tv_usec = 0; 159 160 curl_multi_timeout(mcurl, &curl_timeo); 161 if(curl_timeo >= 0) { 162 timeout.tv_sec = curl_timeo / 1000; 163 if(timeout.tv_sec > 1) 164 timeout.tv_sec = 1; 165 else 166 timeout.tv_usec = (curl_timeo % 1000) * 1000; 167 } 168 169 /* get file descriptors from the transfers */ 170 curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd); 171 172 /* In a real-world program you OF COURSE check the return code of the 173 function calls. On success, the value of maxfd is guaranteed to be 174 greater or equal than -1. We call select(maxfd + 1, ...), specially in 175 case of (maxfd == -1), we call select(0, ...), which is basically equal 176 to sleep. */ 177 178 rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); 179 180 if (tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) { 181 fprintf(stderr, "ABORTING TEST, since it seems " 182 "that it would have run forever.\n"); 183 break; 184 } 185 186 switch(rc) { 187 case -1: 188 /* select error */ 189 break; 190 case 0: /* timeout */ 191 default: /* action */ 192 curl_multi_perform(mcurl, &still_running); 193 break; 194 } 195 } 196 197 curl_slist_free_all(rcpt_list); 198 curl_multi_remove_handle(mcurl, curl); 199 curl_multi_cleanup(mcurl); 200 curl_easy_cleanup(curl); 201 curl_global_cleanup(); 202 return 0; 203} 204 205 206