1 /*****************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
9 * This is an example application source code sending SMTP mail using the
14 #include <curl/curl.h>
17 * This is the list of basic details you need to tweak to get things right.
19 #define USERNAME "user@example.com"
20 #define PASSWORD "123qwerty"
21 #define SMTPSERVER "smtp.example.com"
22 #define SMTPPORT ":587" /* it is a colon+port string, but you can set it
23 to "" to use the default port */
24 #define RECEPIENT "receipient@example.com"
25 #define MAILFROM "<realuser@example.com>"
27 #define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
29 /* Note that you should include the actual meta data headers here as well if
30 you want the mail to have a Subject, another From:, show a To: or whatever
31 you think your mail should feature! */
32 static const char *text[]={
36 " Hello, this is CURL email SMTP\n",
44 static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
46 struct WriteThis *pooh = (struct WriteThis *)userp;
52 data = text[pooh->counter];
55 size_t len = strlen(data);
56 memcpy(ptr, data, len);
57 pooh->counter++; /* advance pointer */
60 return 0; /* no more data left to deliver */
63 static struct timeval tvnow(void)
66 ** time() returns the value of time in seconds since the Epoch.
69 now.tv_sec = (long)time(NULL);
74 static long tvdiff(struct timeval newer, struct timeval older)
76 return (newer.tv_sec-older.tv_sec)*1000+
77 (newer.tv_usec-older.tv_usec)/1000;
84 int still_running = 1;
85 struct timeval mp_start;
87 struct WriteThis pooh;
88 struct curl_slist* rcpt_list = NULL;
92 curl_global_init(CURL_GLOBAL_DEFAULT);
94 curl = curl_easy_init();
98 mcurl = curl_multi_init();
102 rcpt_list = curl_slist_append(rcpt_list, RECEPIENT);
103 /* more addresses can be added here
104 rcpt_list = curl_slist_append(rcpt_list, "others@example.com");
107 curl_easy_setopt(curl, CURLOPT_URL, "smtp://" SMTPSERVER SMTPPORT);
108 curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME);
109 curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD);
110 curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
111 curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM);
112 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt_list);
113 curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
114 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER,0);
115 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
116 curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);
117 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
118 curl_easy_setopt(curl, CURLOPT_SSLVERSION, 0);
119 curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0);
120 curl_multi_add_handle(mcurl, curl);
125 /* we start some action by calling perform right away */
126 curl_multi_perform(mcurl, &still_running);
128 while(still_running) {
129 struct timeval timeout;
130 int rc; /* select() return code */
137 long curl_timeo = -1;
143 /* set a suitable timeout to play around with */
147 curl_multi_timeout(mcurl, &curl_timeo);
148 if(curl_timeo >= 0) {
149 timeout.tv_sec = curl_timeo / 1000;
150 if(timeout.tv_sec > 1)
153 timeout.tv_usec = (curl_timeo % 1000) * 1000;
156 /* get file descriptors from the transfers */
157 curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
159 /* In a real-world program you OF COURSE check the return code of the
160 function calls. On success, the value of maxfd is guaranteed to be
161 greater or equal than -1. We call select(maxfd + 1, ...), specially in
162 case of (maxfd == -1), we call select(0, ...), which is basically equal
165 rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
167 if (tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
168 fprintf(stderr, "ABORTING TEST, since it seems "
169 "that it would have run forever.\n");
177 case 0: /* timeout */
178 default: /* action */
179 curl_multi_perform(mcurl, &still_running);
184 curl_slist_free_all(rcpt_list);
185 curl_multi_remove_handle(mcurl, curl);
186 curl_multi_cleanup(mcurl);
187 curl_easy_cleanup(curl);
188 curl_global_cleanup();