smtp-multi.c 5.8 KB

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