Git init
[external/curl.git] / docs / examples / smtp-multi.c
1 /*****************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  *
9  * This is an example application source code sending SMTP mail using the
10  * multi interface.
11  */
12
13 #include <string.h>
14 #include <curl/curl.h>
15
16 /*
17  * This is the list of basic details you need to tweak to get things right.
18  */
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>"
26
27 #define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000
28
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[]={
33   "one\n",
34   "two\n",
35   "three\n",
36   " Hello, this is CURL email SMTP\n",
37   NULL
38 };
39
40 struct WriteThis {
41   int counter;
42 };
43
44 static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
45 {
46   struct WriteThis *pooh = (struct WriteThis *)userp;
47   const char *data;
48
49   if(size*nmemb < 1)
50     return 0;
51
52   data = text[pooh->counter];
53
54   if(data) {
55     size_t len = strlen(data);
56     memcpy(ptr, data, len);
57     pooh->counter++; /* advance pointer */
58     return len;
59   }
60   return 0;                         /* no more data left to deliver */
61 }
62
63 static struct timeval tvnow(void)
64 {
65   /*
66   ** time() returns the value of time in seconds since the Epoch.
67   */
68   struct timeval now;
69   now.tv_sec = (long)time(NULL);
70   now.tv_usec = 0;
71   return now;
72 }
73
74 static long tvdiff(struct timeval newer, struct timeval older)
75 {
76   return (newer.tv_sec-older.tv_sec)*1000+
77     (newer.tv_usec-older.tv_usec)/1000;
78 }
79
80 int main(void)
81 {
82    CURL *curl;
83    CURLM *mcurl;
84    int still_running = 1;
85    struct timeval mp_start;
86    char mp_timedout = 0;
87    struct WriteThis pooh;
88    struct curl_slist* rcpt_list = NULL;
89
90    pooh.counter = 0;
91
92    curl_global_init(CURL_GLOBAL_DEFAULT);
93
94    curl = curl_easy_init();
95    if(!curl)
96      return 1;
97
98    mcurl = curl_multi_init();
99    if(!mcurl)
100      return 2;
101
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");
105    */
106
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);
121
122    mp_timedout = 0;
123    mp_start = tvnow();
124
125   /* we start some action by calling perform right away */
126   curl_multi_perform(mcurl, &still_running);
127
128   while(still_running) {
129     struct timeval timeout;
130     int rc; /* select() return code */
131
132     fd_set fdread;
133     fd_set fdwrite;
134     fd_set fdexcep;
135     int maxfd = -1;
136
137     long curl_timeo = -1;
138
139     FD_ZERO(&fdread);
140     FD_ZERO(&fdwrite);
141     FD_ZERO(&fdexcep);
142
143     /* set a suitable timeout to play around with */
144     timeout.tv_sec = 1;
145     timeout.tv_usec = 0;
146
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)
151         timeout.tv_sec = 1;
152       else
153         timeout.tv_usec = (curl_timeo % 1000) * 1000;
154     }
155
156     /* get file descriptors from the transfers */
157     curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
158
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
163        to sleep. */
164
165     rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
166
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");
170       break;
171     }
172
173     switch(rc) {
174     case -1:
175       /* select error */
176       break;
177     case 0: /* timeout */
178     default: /* action */
179       curl_multi_perform(mcurl, &still_running);
180       break;
181     }
182   }
183
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();
189   return 0;
190 }
191
192