1 /* $Id: test_ncbi_sendmail.c,v 6.36 2014/12/08 16:44:27 kazimird Exp $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  Anton Lavrentiev
27  *
28  * File Description:
29  *   Simple test for CORE_Sendmail
30  *
31  */
32 
33 #include <connect/ncbi_connutil.h>
34 #include <connect/ncbi_sendmail.h>
35 #include "../ncbi_ansi_ext.h"
36 #include "../ncbi_priv.h"               /* CORE logging facilities */
37 #include <errno.h>
38 #include <stdlib.h>
39 #include <time.h>
40 
41 #include "test_assert.h"  /* This header must go last */
42 
43 #define TEST_HUGE_BODY_SIZE     (1024*100)
44 
45 
main(int argc,const char * argv[])46 int main(int argc, const char* argv[])
47 {
48     static const char custom_body[] =
49         "Subject: Custom sized body\n"
50         "\n"
51         "Custom sized body\n"
52         "0123456789\n"; /* these 11 chars to ignore */
53     const char* mx_host;
54     SSendMailInfo info;
55     const char* retval;
56     STimeout mx_tmo;
57     char* huge_body;
58     short mx_port;
59     char val[32];
60     FILE* fp;
61     size_t n;
62 
63     g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND;
64     srand(g_NCBI_ConnectRandomSeed);
65 
66     CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
67                            fLOG_OmitNoteLevel | fLOG_DateTime);
68     CORE_SetLOGFILE(stderr, 0/*false*/);
69 
70     ConnNetInfo_GetValue(0, REG_CONN_DEBUG_PRINTOUT, val, sizeof(val),
71                          DEF_CONN_DEBUG_PRINTOUT);
72     if (ConnNetInfo_Boolean(val)
73         ||  (*val  &&  (strcasecmp(val, "all")  == 0  ||
74                         strcasecmp(val, "some") == 0  ||
75                         strcasecmp(val, "data") == 0))) {
76         SOCK_SetDataLoggingAPI(eOn);
77     }
78 
79     SendMailInfo_InitEx(&info, 0, eCORE_UsernameReal);
80     CORE_LOGF(eLOG_Note, ("REAL: <%s>", info.from));
81     SendMailInfo_InitEx(&info, 0, eCORE_UsernameLogin);
82     CORE_LOGF(eLOG_Note, ("LOGIN: <%s>", info.from));
83     SendMailInfo_InitEx(&info, 0, eCORE_UsernameCurrent);
84     CORE_LOGF(eLOG_Note, ("CURRENT: <%s>", info.from));
85 
86 #if 1
87     strcpy(info.from, "@");
88     SendMailInfo_InitEx(&info, info.from, eCORE_UsernameCurrent);
89     CORE_LOGF(eLOG_Note, ("@ - <%s>", info.from));
90     assert(!*info.from);
91 
92     strcpy(val, "@");
93     SendMailInfo_InitEx(&info, val, eCORE_UsernameCurrent);
94     CORE_LOGF(eLOG_Note, ("@ - <%s>", info.from));
95     assert(!*info.from);
96 
97     strcpy(info.from, "user0");
98     SendMailInfo_InitEx(&info, info.from, eCORE_UsernameCurrent);
99     CORE_LOGF(eLOG_Note, ("user0 - <%s>", info.from));
100     assert(strcmp(info.from, "user0") == 0);
101 
102     strcpy(val, "user1");
103     SendMailInfo_InitEx(&info, val, eCORE_UsernameCurrent);
104     CORE_LOGF(eLOG_Note, ("user1 - <%s>", info.from));
105     assert(strcmp(info.from, "user1") == 0);
106 
107     strcpy(info.from, "user2@");
108     SendMailInfo_InitEx(&info, info.from, eCORE_UsernameCurrent);
109     CORE_LOGF(eLOG_Note, ("user2@ - <%s>", info.from));
110     assert(strncmp(info.from, "user2@", 6) == 0);
111 
112     strcpy(val, "user3@");
113     SendMailInfo_InitEx(&info, val, eCORE_UsernameCurrent);
114     CORE_LOGF(eLOG_Note, ("user3@ - <%s>", info.from));
115     assert(strncmp(info.from, "user3@", 6) == 0);
116 
117     strcpy(info.from, "@host4.net");
118     SendMailInfo_InitEx(&info, info.from, eCORE_UsernameLogin);
119     CORE_LOGF(eLOG_Note, ("@host4.net - <%s>", info.from));
120     assert(*info.from != '@' && !strcmp(strchr(info.from, '@'), "@host4.net"));
121 
122     strcpy(val, "@host5.net");
123     SendMailInfo_InitEx(&info, val, eCORE_UsernameLogin);
124     CORE_LOGF(eLOG_Note, ("@host5.net - <%s>", info.from));
125     assert(*info.from != '@' && !strcmp(strchr(info.from, '@'), "@host5.net"));
126 
127     strcpy(info.from, "user6@host6.net");
128     SendMailInfo_InitEx(&info, info.from, eCORE_UsernameReal);
129     CORE_LOGF(eLOG_Note, ("user6@host6.net - <%s>", info.from));
130     assert(strcmp(info.from, "user6@host6.net") == 0);
131 
132     strcpy(val, "user7@host7.net");
133     SendMailInfo_InitEx(&info, val, eCORE_UsernameReal);
134     CORE_LOGF(eLOG_Note, ("user7@host7.net - <%s>", info.from));
135     assert(strcmp(info.from, "user7@host7.net") == 0);
136 
137     SendMailInfo_InitEx(&info, 0, eCORE_UsernameReal);
138     CORE_LOGF(eLOG_Note, ("NULL - <%s>", info.from));
139     assert(info.from[0]  &&  info.from[0] != '@'  &&  strchr(info.from, '@'));
140 
141     if ((huge_body = (char*) malloc(TEST_HUGE_BODY_SIZE)) != 0) {
142 
143         strcpy(huge_body, "user8@");
144         for (n = 0;  n < TEST_HUGE_BODY_SIZE - 6;  n++)
145             huge_body[n + 6] = "abcdefghijklmnopqrstuvwxyz."[rand() % 27];
146         huge_body[TEST_HUGE_BODY_SIZE - 1] = '\0';
147         SendMailInfo_InitEx(&info, huge_body, eCORE_UsernameCurrent);
148         CORE_LOGF(eLOG_Note, ("HUGE user8@host - <%s>", info.from));
149         assert(strcmp(info.from, "user8") == 0);
150 
151         SendMailInfo_InitEx(&info, huge_body + 5, eCORE_UsernameLogin);
152         CORE_LOGF(eLOG_Note, ("HUGE @hostA - <%s>", info.from));
153         assert(!strchr(info.from, '@'));
154 
155         huge_body[4] = 'B';
156         huge_body[5] = '_';
157         for (n = 6;  n < sizeof(info.from) + 1;  n++) {
158             if (huge_body[n] == '.')
159                 huge_body[n]  = '_';
160         }
161         huge_body[sizeof(info.from) + 1] = '@';
162         SendMailInfo_InitEx(&info, huge_body, eCORE_UsernameReal);
163         CORE_LOGF(eLOG_Note, ("HUGE userB - <%s>", info.from));
164         assert(strncmp(info.from, huge_body, sizeof(info.from) - 1) == 0);
165         assert(strlen(info.from) == sizeof(info.from) - 1);
166         assert(!strchr(info.from, '@'));
167 
168         huge_body[4] = 'C';
169         huge_body[sizeof(info.from) - 10]  = '@';
170         SendMailInfo_InitEx(&info, huge_body, eCORE_UsernameReal);
171         CORE_LOGF(eLOG_Note, ("LONG userC - <%s>", info.from));
172         assert(strncmp(info.from, huge_body, sizeof(info.from) - 10) == 0);
173         assert(strlen(info.from) == sizeof(info.from) - 10);
174         assert(!strchr(info.from, '@'));
175 
176         memcpy(huge_body + sizeof(info.from) - 10, "userD", 5);
177         huge_body[sizeof(info.from) << 1] = '\0';
178         SendMailInfo_InitEx(&info, huge_body + sizeof(info.from) - 10,
179                             eCORE_UsernameReal);
180         CORE_LOGF(eLOG_Note, ("LONG userD - <%s>", info.from));
181         assert(strncmp(info.from, "userD", 5) == 0);
182 
183         SendMailInfo_InitEx(&info, huge_body + sizeof(info.from) + 1,
184                             eCORE_UsernameReal);
185         CORE_LOGF(eLOG_Note, ("LONG @hostE - <%s>", info.from));
186         assert(!strchr(info.from, '@'));
187 
188         free(huge_body);
189     }
190 #endif
191 
192 #if 0
193     if (argc > 1) {
194         CORE_LOG(eLOG_Note, "Special test requested");
195         SendMailInfo_InitEx(&info, "@", eCORE_UsernameCurrent);
196         strcpy(info.from, "Friend <>");
197         info.header = "Sender: \"Your Sender\" <lavr@ncbi.nlm.nih.gov>\n"
198                       "Reply-To: Coremake <coremake@ncbi.nlm.nih.gov>";
199         if ((fp = fopen(argv[1], "rb")) != 0          &&
200             fseek(fp, 0, SEEK_END) == 0               &&
201             (n = ftell(fp)) != (size_t)(-1)           &&
202             fseek(fp, 0, SEEK_SET) == 0               &&
203             (huge_body = (char*) malloc(n + 1)) != 0  &&
204             fread(huge_body, n, 1, fp) == 1) {
205             huge_body[n] = '\0';
206             CORE_LOGF(eLOG_Note, ("Sending file (%lu bytes)",
207                                   (unsigned long) n));
208             retval = CORE_SendMailEx("lavr", "File", huge_body, &info);
209             if (retval) {
210                 CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
211             } else {
212                 CORE_LOG(eLOG_Note, "Test passed");
213             }
214         } else
215             CORE_LOG_ERRNO(eLOG_Error, errno, "Test failed");
216         return 0;
217     }
218 #endif
219 
220 #if 0
221     {
222         static const char* body[] = {
223             "This is a simple test",
224             "This is a test with\n.",
225             0,
226             ".",
227             "\n.\n",
228             ".\n",
229             "",
230             "a\nb\nc\nd\n.",
231             "a\r\n\rb\r\nc\r\nd\r\n.",
232             ".\na"
233         };
234         static const char* subject[] = {
235             0,
236             "CORE_SendMail Test",
237             "",
238         };
239         static const char* to[] = {
240             "lavr",
241             "lavr@pavo",
242             " \"Anton Lavrentiev\"   <lavr@pavo>  , lavr, <lavr>   ",
243         };
244         size_t i, j, k, m = 0;
245 
246         CORE_LOG(eLOG_Note, "Phase 1 of 2: Testing CORE_SendMail");
247 
248         n = (sizeof(to)/sizeof(to[0]))*
249             (sizeof(subject)/sizeof(subject[0]))*
250             (sizeof(body)/sizeof(body[0]));
251         for (i = 0;  i < sizeof(to) / sizeof(to[0]);  ++i) {
252             for (j = 0;  j < sizeof(subject) / sizeof(subject[0]);  ++j)
253                 for (k = 0;  k < sizeof(body) / sizeof(body[0]);  ++k) {
254                     CORE_LOGF(eLOG_Note, ("  Test %u of %u",
255                                           (unsigned int) ++m,
256                                           (unsigned int) n));
257                     retval = CORE_SendMail(to[i], subject[j], body[k]);
258                     if (retval != 0)
259                         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
260                 }
261         }
262     }
263 #else
264     CORE_LOG(eLOG_Note, "Phase 1 of 2: Skipping CORE_SendMail tests");
265 #endif
266 
267     if (argc > 1) {
268     CORE_LOG(eLOG_Note, "Phase 2 of 2: Testing CORE_SendMailEx");
269 
270     SendMailInfo_Init(&info);
271     mx_host = info.mx_host;
272     mx_port = info.mx_port;
273     mx_tmo  = info.mx_timeout;
274 
275     info.mx_host = "localhost";
276 
277     CORE_LOG(eLOG_Note, "Testing bad port");
278     info.mx_port = 10/*BAD*/;
279     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Bad port", &info);
280     if (!retval)
281         CORE_LOG(eLOG_Fatal, "Test failed");
282     CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
283 
284     CORE_LOG(eLOG_Note, "Testing bad protocol");
285     info.mx_port = CONN_PORT_FTP;
286     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Protocol", &info);
287     if (!retval)
288         CORE_LOG(eLOG_Fatal, "Test failed");
289     CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
290 
291     CORE_LOG(eLOG_Note, "Testing timeout");
292     info.mx_host = "www.ncbi.nlm.nih.gov";
293     info.mx_timeout.sec = 5;
294     info.mx_port = CONN_PORT_HTTP;
295     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Timeout", &info);
296     if (!retval)
297         CORE_LOG(eLOG_Error, "Test failed");
298     else
299         CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
300 
301     info.mx_port = mx_port;
302     info.mx_timeout = mx_tmo;
303 
304     CORE_LOG(eLOG_Note, "Testing bad host");
305     info.mx_host = "abrakadabra";
306     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Bad host", &info);
307     if (!retval)
308         CORE_LOG(eLOG_Fatal, "Test failed");
309     CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
310 
311     info.mx_host = "localhost";
312 
313     CORE_LOG(eLOG_Note, "Testing cc");
314     info.cc = "vakatov";
315     retval = CORE_SendMailEx("", "CORE_SendMailEx", "CC", &info);
316     if (retval)
317         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
318     CORE_LOG(eLOG_Note, "Test passed");
319 
320     CORE_LOG(eLOG_Note, "Testing bcc");
321     info.cc = 0;
322     info.bcc = "vakatov";
323     retval = CORE_SendMailEx(0, "CORE_SendMailEx", "Bcc", &info);
324     if (retval)
325         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
326     CORE_LOG(eLOG_Note, "Test passed");
327 
328     CORE_LOG(eLOG_Note, "Testing huge body");
329     info.cc = 0;
330     info.bcc = 0;
331     if (!(huge_body = (char*) malloc(TEST_HUGE_BODY_SIZE)))
332         CORE_LOG(eLOG_Fatal, "Test failed: Cannot allocate memory");
333     for (n = 0;  n < TEST_HUGE_BODY_SIZE - 1;  ++n)
334         huge_body[n] = "0123456789\nABCDEFGHIJKLMNOPQRSTUVWXYZ ."[rand() % 39];
335     huge_body[n] = 0;
336     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", huge_body, &info);
337     if (retval)
338         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
339     if (!(fp = fopen("test_ncbi_sendmail.out", "w")) ||
340         fwrite(huge_body, TEST_HUGE_BODY_SIZE - 1, 1, fp) != 1) {
341         CORE_LOG(eLOG_Error, "Test failed: Cannot store huge body to file");
342     } else {
343         fclose(fp);
344         CORE_LOG(eLOG_Note, "Success: Check test_ncbi_sendmail.out");
345     }
346     free(huge_body);
347 
348     CORE_LOG(eLOG_Note, "Testing custom headers");
349     info.header = "Organization: NCBI/NLM/NIH\nReference: abcdefghijk";
350     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Custom header",&info);
351     if (retval)
352         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
353     CORE_LOG(eLOG_Note, "Test passed");
354 
355     CORE_LOG(eLOG_Note, "Testing no recipients");
356     retval = CORE_SendMailEx(0, "CORE_SendMailEx", "No recipients", &info);
357     if (!retval)
358         CORE_LOG(eLOG_Fatal, "Test failed");
359     CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
360 
361     CORE_LOG(eLOG_Note, "Testing AS-IS message");
362     info.mx_options = fSendMail_NoMxHeader;
363     retval = CORE_SendMailEx("lavr",
364                              "BAD SUBJECT SHOULD NOT APPEAR BUT IGNORED",
365                              "From: yourself\n"
366                              "To: yourself\n"
367                              "Subject: AS-IS message\n"
368                              "\n"
369                              "AS-IS",
370                              &info);
371     if (retval)
372         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
373     CORE_LOG(eLOG_Note, "Test passed");
374 
375     CORE_LOG(eLOG_Note, "Testing AS-IS custom sized message");
376     info.body_size = strlen(custom_body) - 11/*to ignore*/;
377     retval = CORE_SendMailEx("<lavr@pavo>",
378                              "BAD SUBJECT SHOULD NOT APPEAR BUT IGNORED",
379                              custom_body,
380                              &info);
381     if (retval)
382         CORE_LOGF(eLOG_Fatal, ("Test failed: %s", retval));
383     CORE_LOG(eLOG_Note, "Test passed");
384 
385     info.body_size = 0;
386     info.mx_options = 0;
387     info.mx_host = mx_host;
388 
389     CORE_LOG(eLOG_Note, "Testing bad from");
390     strcpy(info.from, "blahblah@blahblah");
391     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Bad from",&info);
392     if (!retval)
393         CORE_LOG(eLOG_Error, "Test failed");
394     else
395         CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
396 
397     SendMailInfo_Init(&info);
398     CORE_LOG(eLOG_Note, "Testing drop no FQDN option");
399     info.mx_options |= fSendMail_StripNonFQDNHost;
400     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "No FQDN", &info);
401     if (retval)
402         CORE_LOGF(eLOG_Error, ("Test failed: %s", retval));
403     else
404         CORE_LOG(eLOG_Note, "Test passed");
405 
406     CORE_LOG(eLOG_Note, "Testing bad magic");
407     info.magic_cookie = 0;
408     retval = CORE_SendMailEx("lavr", "CORE_SendMailEx", "Bad Magic", &info);
409     if (!retval)
410         CORE_LOG(eLOG_Fatal, "Test failed");
411     CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
412     } else
413     CORE_LOG(eLOG_Note, "Phase 2 of 2: Skipping CORE_SendMailEx tests");
414 
415     CORE_LOG(eLOG_Note, "TEST completed successfully");
416     CORE_SetLOG(0);
417     return 0;
418 }
419