smtp-client
SMTP Client C Library
test.c
Go to the documentation of this file.
1 
15 #include <assert.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 
25 #define SMTP_INTERNAL_DEFINE
26 
27 #include "test.h"
28 
33 #define TMP_FILE_PATH "/tmp/test_smtp_file_get_contents.txt"
34 
38 #define SMTP_TEST_SUBJECT_LEN 100
39 
43 #define SMTP_TEST_BODY_LEN 1000
44 
48 #define SMTP_MAX_SERVER_LEN 255
49 
53 #define SMTP_MAX_CAFILE_PATH 255
54 
58 #define SMTP_MAX_PORT_LEN 10
59 
63 #define SMTP_MAX_EMAIL_LEN 255
64 
68 #define SMTP_MAX_PASS_LEN 255
69 
73 #define SMTP_MAX_ATTACHMENT_NAME_LEN 100
74 
79 #define SMTP_TEST_DEFAULT_CONNECTION_SECURITY SMTP_SECURITY_NONE
80 
85 #define SMTP_TEST_DEFAULT_AUTH_METHOD SMTP_AUTH_PLAIN
86 
91 #define SMTP_TEST_DEFAULT_FLAGS (enum smtp_flag)( \
92  SMTP_DEBUG | \
93  SMTP_NO_CERT_VERIFY)
94 
98 #define SMTP_TEST_DEFAULT_CAFILE NULL
99 
103 #define SMTP_TEST_DEFAULT_FROM_NAME "From Name"
104 
108 #define SMTP_TEST_DEFAULT_TO_NAME "To Name"
109 
113 #define SMTP_TEST_DEFAULT_CC_NAME "Cc Name"
114 
118 #define SMTP_TEST_DEFAULT_BCC_NAME "Bcc Name"
119 
123 #define STR_ALPHABET_LOWERCASE "abcdefghijklmnopqrstuvwxyz"
124 
135  struct smtp *smtp;
136 
141 
146 
147  /*
148  * The following fields get set by the configuration file.
149  */
150 
155 
160 
165 
170 
175 
180 
185 
190 
195 
200 };
201 
206 static enum smtp_status_code
207 g_rc;
208 
213 static struct smtp_test_config
214 g_config;
215 
230 static size_t
231 smtp_strlcpy(char *dest,
232  const char *src,
233  size_t destsz){
234  size_t src_idx;
235  int found_end;
236 
237  found_end = 0;
238 
239  src_idx = 0;
240  while(*src){
241  if(!found_end){
242  if(src_idx >= destsz - 1 || destsz == 0){
243  dest[src_idx] = '\0';
244  found_end = 1;
245  }
246  else{
247  dest[src_idx] = *src;
248  }
249  }
250  src_idx += 1;
251  src += 1;
252  }
253  if(!found_end){
254  dest[src_idx] = '\0';
255  }
256 
257  return src_idx;
258 }
259 
268 static char *
269 smtp_strndup(const char *s,
270  size_t n){
271  char *ns;
272  size_t newsz;
273 
274  newsz = sizeof(*ns) * (n + 1);
275  ns = malloc(newsz);
276  if(ns){
277  smtp_strlcpy(ns, s, newsz);
278  }
279 
280  return ns;
281 }
282 
293 static char *
294 smtp_str_repeat(const char *const s,
295  size_t n){
296  char *snew;
297  size_t slen;
298  size_t snewlen;
299  size_t i;
300 
301  slen = strlen(s);
302 
303  if(n < 1 || slen < 1){
304  return smtp_strdup("");
305  }
306 
307  snewlen = slen * n + 1;
308  if((snew = malloc(snewlen)) == NULL){
309  return NULL;
310  }
311 
312  for(i = 0; i < n; i++){
313  memcpy(&snew[slen * i], s, slen);
314  }
315  snew[snewlen - 1] = '\0';
316 
317  return snew;
318 }
319 
330  size_t n;
331 
335  char **slist;
336 };
337 
347 static int
349  const char *const s,
350  size_t n){
351  char **slist_alloc;
352  char *snew;
353 
354  if((slist_alloc = realloc(slist->slist,
355  sizeof(*slist->slist) * (slist->n + 1))) == NULL){
356  return -1;
357  }
358  slist->slist = slist_alloc;
359 
360  if((snew = smtp_strndup(s, n)) == NULL){
361  return -1;
362  }
363  slist->slist[slist->n] = snew;
364  slist->n += 1;
365  return 0;
366 }
367 
373 static void
374 smtp_str_list_free(struct smtp_str_list *const list){
375  size_t i;
376 
377  for(i = 0; i < list->n; i++){
378  free(list->slist[i]);
379  }
380  free(list->slist);
381  list->slist = NULL;
382  list->n = 0;
383 }
384 
402 static int
403 smtp_str_split(const char *const s,
404  size_t slen,
405  const char *const delimiter,
406  int limit,
407  struct smtp_str_list *slist){
408  size_t i;
409  size_t i1;
410  size_t i2;
411  size_t delimiter_len;
412  int split_idx;
413 
414  memset(slist, 0, sizeof(*slist));
415  delimiter_len = strlen(delimiter);
416 
417  if(slen == SIZE_MAX){
418  slen = strlen(s);
419  }
420 
421  split_idx = 0;
422 
423  i1 = 0;
424  for(i2 = 0; i2 < slen; i2++){
425  if(limit > 0 && limit - 1 <= split_idx){
426  if(smtp_str_list_append(slist, &s[i1], SIZE_MAX) < 0){
427  smtp_str_list_free(slist);
428  return -1;
429  }
430  return 0;
431  }
432  else if(strncmp(&s[i2], delimiter, delimiter_len) == 0){
433  if(i2 - i1 == 0 && s[i2] == '\0'){
434  break;
435  }
436  if(smtp_str_list_append(slist, &s[i1], i2 - i1) < 0){
437  smtp_str_list_free(slist);
438  return -1;
439  }
440  i1 = i2 + delimiter_len;
441  i2 = i1;
442  if(strncmp(&s[i2], delimiter, delimiter_len) == 0){
443  i2 -= 1;
444  }
445  split_idx += 1;
446  }
447  }
448 
449  if(smtp_str_list_append(slist, &s[i1], i2 - i1) < 0){
450  smtp_str_list_free(slist);
451  return -1;
452  }
453 
454  if(limit < 0){
455  for(i = 0; i < (size_t)abs(limit); i++){
456  free(slist->slist[slist->n - i - 1]);
457  }
458  slist->n -= i;
459  }
460 
461  return 0;
462 }
463 
473 static size_t
475  const void *const data,
476  size_t datasz){
477  size_t bytes_written;
478 
479  bytes_written = 0;
480 
481  if(datasz == SIZE_MAX){
482  bytes_written = strlen(data);
483  if(fputs(data, stream) == EOF){
484  bytes_written = 0;
485  }
486  }
487  else{
488  bytes_written = fwrite(data, 1, datasz, stream);
489  }
490 
491  return bytes_written;
492 }
493 
511 static size_t
512 smtp_file_put_contents(const char *const filename,
513  const void *const data,
514  size_t datasz,
515  int flags){
516  FILE *fp;
517  size_t bytes_written;
518  const char *mode;
519 
520  if(flags == 0){
521  mode = "w";
522  }
523  else if(flags == O_APPEND){
524  mode = "a";
525  }
526  else{
527  errno = EINVAL;
528  return 0;
529  }
530 
531  if((fp = fopen(filename, mode)) == NULL){
532  return 0;
533  }
534 
535  bytes_written = smtp_ffile_put_contents(fp, data, datasz);
536 
537  if(fclose(fp) == EOF){
538  return 0;
539  }
540 
541  return bytes_written;
542 }
543 
552 static void
553 smtp_test_sleep(unsigned int seconds){
554  fprintf(stderr, "TEST FRAMEWORK: sleeping for %u seconds\n", seconds);
555  assert(sleep(seconds) == 0);
556 }
557 
569 static void
570 smtp_unit_test_si_size_t(int (*si_fp)(const size_t a,
571  const size_t b,
572  size_t *const result),
573  size_t a,
574  size_t b,
575  size_t *result,
576  size_t expect_result,
577  int expect_wrap){
578  int wraps;
579 
580  wraps = si_fp(a, b, result);
581  assert(wraps == expect_wrap);
582  if(result){
583  assert(*result == expect_result);
584  }
585 }
586 
590 static void
592  size_t result;
593 
594  /* add */
595  smtp_unit_test_si_size_t(smtp_si_add_size_t, 0, 0, &result, 0, 0);
596  smtp_unit_test_si_size_t(smtp_si_add_size_t, 0, 1, &result, 1, 0);
597  smtp_unit_test_si_size_t(smtp_si_add_size_t, 1, 0, &result, 1, 0);
598  smtp_unit_test_si_size_t(smtp_si_add_size_t, 1, 1, &result, 2, 0);
603  smtp_unit_test_si_size_t(smtp_si_add_size_t, SIZE_MAX - 1, 2, &result, 0, 1);
606  SIZE_MAX / 2,
607  SIZE_MAX / 2,
608  &result,
609  SIZE_MAX - 1,
610  0);
611 
612  /* subtraction */
613  smtp_unit_test_si_size_t(smtp_si_sub_size_t, 0, 0, &result, 0, 0);
615  smtp_unit_test_si_size_t(smtp_si_sub_size_t, 1, 0, &result, 1, 0);
616  smtp_unit_test_si_size_t(smtp_si_sub_size_t, 1, 1, &result, 0, 0);
620 
621  /* multiply */
622  smtp_unit_test_si_size_t(smtp_si_mul_size_t, 0, 0, &result, 0, 0);
623  smtp_unit_test_si_size_t(smtp_si_mul_size_t, 0, 1, &result, 0, 0);
624  smtp_unit_test_si_size_t(smtp_si_mul_size_t, 1, 0, &result, 0, 0);
625  smtp_unit_test_si_size_t(smtp_si_mul_size_t, 1, 1, &result, 1, 0);
628  smtp_unit_test_si_size_t(smtp_si_mul_size_t, 100, 12, &result, 1200, 0);
631  SIZE_MAX,
632  2,
633  &result,
634  SIZE_MAX * 2,
635  1);
636 }
637 
645 static void
646 smtp_unit_test_base64_decode(const char *const buf,
647  const char *const expect_str,
648  size_t expect_str_len){
649  unsigned char *decode;
650  size_t str_len;
651 
652  str_len = smtp_base64_decode(buf, &decode);
653  if(expect_str){
654  assert(memcmp(decode, expect_str, str_len) == 0);
655  free(decode);
656  }
657  else{ /* NULL */
658  assert(decode == NULL);
659  }
660  assert(str_len == expect_str_len);
661 }
662 
666 static void
668  smtp_unit_test_base64_decode("" , "", 0);
669  smtp_unit_test_base64_decode("YQ==" , "a", 1);
670 
671  smtp_unit_test_base64_decode("YWE=" , "aa" , 2);
672  smtp_unit_test_base64_decode("YWFh" , "aaa" , 3);
673  smtp_unit_test_base64_decode("YWFhYQ==", "aaaa" , 4);
674  smtp_unit_test_base64_decode("YWFhYWE=", "aaaaa", 5);
675  smtp_unit_test_base64_decode("MTIzNDU=", "12345", 5);
676  smtp_unit_test_base64_decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=",
678  26);
679 
680  /* invalid inputs */
682  smtp_unit_test_base64_decode("^^^^" , NULL, SIZE_MAX);
683  smtp_unit_test_base64_decode("^^^\xFF", NULL, SIZE_MAX);
684 
685  /* Wrap when calculating the buffer length. */
687  smtp_unit_test_base64_decode("YQ==" , NULL, SIZE_MAX);
689 
693 }
694 
702 static void
703 smtp_unit_test_base64_encode(const char *const buf,
704  size_t buflen,
705  const char *const expect){
706  char *result;
707 
708  result = smtp_base64_encode(buf, buflen);
709  if(expect){
710  assert(strcmp(result, expect) == 0);
711  free(result);
712  }
713  else{ /* NULL */
714  assert(result == expect);
715  }
716 }
717 
721 static void
724  smtp_unit_test_base64_encode("a" , SIZE_MAX, "YQ==");
725  smtp_unit_test_base64_encode("aa" , SIZE_MAX, "YWE=");
726  smtp_unit_test_base64_encode("aaa" , SIZE_MAX, "YWFh");
727  smtp_unit_test_base64_encode("aaaa" , SIZE_MAX, "YWFhYQ==");
728  smtp_unit_test_base64_encode("aaaaa", SIZE_MAX, "YWFhYWE=");
729  smtp_unit_test_base64_encode("12345", SIZE_MAX, "MTIzNDU=");
731  SIZE_MAX,
732  "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=");
733 
734  /* binary data */
735  smtp_unit_test_base64_encode("a\0b\1c", 5, "YQBiAWM=");
736  smtp_unit_test_base64_encode("a\n\r\4bc", 6, "YQoNBGJj");
737 
738  /* Value would wrap */
744 
745  /* calloc */
749 }
750 
758 static void
759 smtp_unit_test_bin2hex(const char *const s,
760  size_t slen,
761  const char *const expect){
762  char *result;
763 
764  result = smtp_bin2hex((const unsigned char *const)s, slen);
765  if(expect){
766  assert(strcmp(result, expect) == 0);
767  }
768  else{
769  assert(result == expect);
770  }
771  free(result);
772 }
773 
777 static void
779  smtp_unit_test_bin2hex("" , 0, "" );
780  smtp_unit_test_bin2hex("0" , 0, "" );
781  smtp_unit_test_bin2hex("0" , 1, "30" );
782  smtp_unit_test_bin2hex("1" , 1, "31" );
783  smtp_unit_test_bin2hex("012345", 6, "303132333435");
784  smtp_unit_test_bin2hex("012345", 3, "303132" );
785  smtp_unit_test_bin2hex("000000", 6, "303030303030");
788  26,
789  "6162636465666768696a6b6c6d6e6f707172737475767778797a");
790  smtp_unit_test_bin2hex("\xFF", 1, "ff");
791  smtp_unit_test_bin2hex("\x00", 1, "00");
792 
793  /* Multiplication wrap. */
794  smtp_unit_test_bin2hex("", SIZE_MAX - 2, NULL);
795 
796  /* Addition wrap. */
798  smtp_unit_test_bin2hex("", SIZE_MAX / 2, NULL);
800 
802  smtp_unit_test_bin2hex("", 0, NULL);
804 
807  smtp_unit_test_bin2hex("0", 1, NULL);
809 
812  smtp_unit_test_bin2hex("0", 1, NULL);
814 }
815 
823 static void
824 smtp_unit_test_stpcpy(const char *const init,
825  const char *const s2,
826  const char *const expect){
827  char *buf;
828  size_t bufsz;
829  char *endptr;
830  char *expect_ptr;
831 
832  bufsz = strlen(init) + strlen(s2) + 1;
833  buf = malloc(bufsz);
834  assert(buf);
835 
836  strcpy(buf, init);
837  endptr = buf + strlen(init);
838 
839  endptr = smtp_stpcpy(endptr, s2);
840  expect_ptr = buf + bufsz - 1;
841  assert(endptr == expect_ptr);
842  assert(*endptr == '\0');
843  assert(strcmp(buf, expect) == 0);
844  free(buf);
845 }
846 
850 static void
852  smtp_unit_test_stpcpy("", "", "");
853  smtp_unit_test_stpcpy("", "a", "a");
854  smtp_unit_test_stpcpy("", "ab", "ab");
855  smtp_unit_test_stpcpy("", "abc", "abc");
856 
857  smtp_unit_test_stpcpy("a", "", "a");
858  smtp_unit_test_stpcpy("ab", "", "ab");
859  smtp_unit_test_stpcpy("abc", "", "abc");
860 
861  smtp_unit_test_stpcpy("a", "a", "aa");
862 }
863 
874 static void
876  size_t nmemb,
877  size_t size,
878  int expect_alloc){
879  void *result;
880 
881  result = smtp_reallocarray(ptr, nmemb, size);
882  if(expect_alloc){
883  assert(result);
884  free(result);
885  }
886  else{
887  assert(result == NULL);
888  }
889 }
890 
894 static void
896  smtp_unit_test_reallocarray(NULL, 1, 1, 1);
897  smtp_unit_test_reallocarray(NULL, 0, 1, 1);
898  smtp_unit_test_reallocarray(NULL, 1, 0, 1);
899 
900  /* unsigned wrapping */
902 
903  /* realloc */
905  smtp_unit_test_reallocarray(NULL, 1, 1, 0);
907 }
908 
915 static void
916 smtp_unit_test_strdup(const char *const s,
917  const char *const expect){
918  char *result;
919 
920  result = smtp_strdup(s);
921  if(expect){
922  assert(strcmp(result, expect) == 0);
923  free(result);
924  }
925  else{ /* NULL */
926  assert(result == expect);
927  }
928 }
929 
933 static void
935  smtp_unit_test_strdup("", "");
936  smtp_unit_test_strdup("a", "a");
937  smtp_unit_test_strdup("ab", "ab");
938 
939  /* Wrap when calculating the new strlen. */
942  smtp_unit_test_strdup("a", NULL);
945 
946  /* malloc */
948  smtp_unit_test_strdup("", NULL);
950 }
951 
960 static void
961 smtp_unit_test_str_replace(const char *const search,
962  const char *const replace,
963  const char *const s,
964  const char *const expect){
965  char *result;
966 
967  result = smtp_str_replace(search, replace, s);
968  if(expect){
969  assert(strcmp(result, expect) == 0);
970  free(result);
971  }
972  else{ /* NULL */
973  assert(result == expect);
974  }
975 }
976 
980 static void
982  int i;
983 
984  smtp_unit_test_str_replace("", "", "", "");
985  smtp_unit_test_str_replace("a", "b", "", "");
986  smtp_unit_test_str_replace("", "", "a b c", "a b c");
987  smtp_unit_test_str_replace("a", "", "a b c", " b c");
988  smtp_unit_test_str_replace("a", "a", "a", "a");
989  smtp_unit_test_str_replace("a", "b", "a", "b");
990  smtp_unit_test_str_replace("a", "bc", "a", "bc");
991  smtp_unit_test_str_replace("a", "b", "abc", "bbc");
992  smtp_unit_test_str_replace("A", "b", "a", "a");
993  smtp_unit_test_str_replace("b", "a", "abc", "aac");
994  smtp_unit_test_str_replace("string", "test", "test string", "test test");
995  smtp_unit_test_str_replace("a", "b", "a b a", "b b b");
996  smtp_unit_test_str_replace("a", "b", "a b a", "b b b");
997  smtp_unit_test_str_replace("a", "b", "a b a b a", "b b b b b");
998 
1001  smtp_unit_test_str_replace("a", "b", "a b c", NULL);
1004 
1005  for(i = 0; i < 10; i++){
1007  smtp_unit_test_str_replace("a", "b", "a b c", NULL);
1009 
1011  smtp_unit_test_str_replace("b", "a", "a b c", NULL);
1013  }
1014 
1016  smtp_unit_test_str_replace("a", "b", "a b c", NULL);
1018 
1020  smtp_unit_test_str_replace("b", "a", "a b c", NULL);
1022 }
1023 
1027 static void
1029  const char *utf8_str;
1030 
1031  assert(smtp_utf8_charlen('a') == 1);
1032 
1033  utf8_str = "щ";
1034  assert(smtp_utf8_charlen(utf8_str[0]) == 2);
1035 
1036  utf8_str = "€";
1037  assert(smtp_utf8_charlen(utf8_str[0]) == 3);
1038 
1039  utf8_str = "𠜎";
1040  assert(smtp_utf8_charlen(utf8_str[0]) == 4);
1041 }
1042 
1046 static void
1048  assert(smtp_str_has_nonascii_utf8("") == 0);
1049  assert(smtp_str_has_nonascii_utf8("abc") == 0);
1050  assert(smtp_str_has_nonascii_utf8("?") == 0);
1051  assert(smtp_str_has_nonascii_utf8("щ") == 1);
1052  assert(smtp_str_has_nonascii_utf8("abщ") == 1);
1053 }
1054 
1062 static void
1064  size_t maxlen,
1065  size_t expect){
1066  size_t slen;
1067 
1068  slen = smtp_strnlen_utf8(s, maxlen);
1069  assert(slen == expect);
1070 }
1071 
1075 static void
1077  smtp_unit_test_strnlen_utf8("" , 0, 0);
1078  smtp_unit_test_strnlen_utf8("" , 1, 0);
1079  smtp_unit_test_strnlen_utf8("a" , 0, 0);
1080  smtp_unit_test_strnlen_utf8("a" , 1, 1);
1081  smtp_unit_test_strnlen_utf8("a" , 2, 1);
1082  smtp_unit_test_strnlen_utf8("ab", 0, 0);
1083  smtp_unit_test_strnlen_utf8("ab", 1, 1);
1084  smtp_unit_test_strnlen_utf8("ab", 2, 2);
1085  smtp_unit_test_strnlen_utf8("ab", 3, 2);
1086 
1087  smtp_unit_test_strnlen_utf8("щ", 0, 0);
1088  smtp_unit_test_strnlen_utf8("щ", 1, 2);
1089  smtp_unit_test_strnlen_utf8("щ", 2, 2);
1090  smtp_unit_test_strnlen_utf8("щ", 3, 2);
1091 
1092  smtp_unit_test_strnlen_utf8("€", 0, 0);
1093  smtp_unit_test_strnlen_utf8("€", 1, 3);
1094  smtp_unit_test_strnlen_utf8("€", 2, 3);
1095  smtp_unit_test_strnlen_utf8("€", 3, 3);
1096 
1097  smtp_unit_test_strnlen_utf8("€€", 0, 0);
1098  smtp_unit_test_strnlen_utf8("€€", 1, 3);
1099  smtp_unit_test_strnlen_utf8("€€", 2, 3);
1100  smtp_unit_test_strnlen_utf8("€€", 3, 3);
1101  smtp_unit_test_strnlen_utf8("€€", 4, 6);
1102  smtp_unit_test_strnlen_utf8("€€", 5, 6);
1103  smtp_unit_test_strnlen_utf8("€€", 6, 6);
1104  smtp_unit_test_strnlen_utf8("€€", 7, 6);
1105 
1106  smtp_unit_test_strnlen_utf8("𠜎", 0, 0);
1107  smtp_unit_test_strnlen_utf8("𠜎", 1, 4);
1108  smtp_unit_test_strnlen_utf8("𠜎", 2, 4);
1109  smtp_unit_test_strnlen_utf8("𠜎", 3, 4);
1110 
1111  /* Invalid UTF-8 sequences. */
1114 }
1115 
1123 static void
1125  unsigned int maxlen,
1126  size_t expect){
1127  size_t result;
1128 
1129  result = smtp_fold_whitespace_get_offset(s, maxlen);
1130  assert(result == expect);
1131 }
1132 
1136 static void
1141 
1146 
1152 
1159 
1166 
1174 
1183 
1191 
1202 
1203  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 0, 5);
1204  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 1, 5);
1205  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 2, 5);
1206  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 3, 5);
1207  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 4, 5);
1208  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 5, 5);
1209  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 6, 5);
1210  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 7, 5);
1211  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 8, 5);
1212  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 9, 5);
1213  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 10, 9);
1214  smtp_unit_test_fold_whitespace_get_offset("\t ab\t cd\t ", 11, 10);
1215 
1216  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 0, 8);
1217  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 1, 8);
1218  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 2, 8);
1219  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 8, 8);
1220  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 9, 8);
1221  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 10, 8);
1222  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 10, 8);
1223  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 10, 8);
1224  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 10, 8);
1225  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 10, 8);
1226  smtp_unit_test_fold_whitespace_get_offset("Subject: Test Email WS", 10, 8);
1227 
1238  smtp_unit_test_fold_whitespace_get_offset("Subject:", 10, 8);
1239 
1240  smtp_unit_test_fold_whitespace_get_offset("Subject: ", 0, 8);
1241  smtp_unit_test_fold_whitespace_get_offset("Subject: ", 9, 8);
1242  smtp_unit_test_fold_whitespace_get_offset("Subject: ", 10, 9);
1243 }
1244 
1252 static void
1254  unsigned int maxlen,
1255  const char *const expect){
1256  char *result;
1257 
1258  result = smtp_fold_whitespace(s, maxlen);
1259  if(expect == NULL){
1260  assert(result == expect);
1261  }
1262  else{
1263  assert(strcmp(result, expect) == 0);
1264  free(result);
1265  }
1266 }
1267 
1271 static void
1273  int i;
1274 
1275  smtp_unit_test_fold_whitespace("Subject: Email Test",
1276  5,
1277  "Subject:\r\n"
1278  " Email\r\n"
1279  " Test");
1280  smtp_unit_test_fold_whitespace("Subject: Email Test",
1281  14,
1282  "Subject:\r\n"
1283  " Email Test");
1284  smtp_unit_test_fold_whitespace("Subject: Email Test",
1285  15,
1286  "Subject:\r\n"
1287  " Email Test");
1288  smtp_unit_test_fold_whitespace("Subject: Email Test",
1289  16,
1290  "Subject:\r\n"
1291  " Email Test");
1292  smtp_unit_test_fold_whitespace("Subject: Email Test",
1293  17,
1294  "Subject: Email\r\n"
1295  " Test");
1296  smtp_unit_test_fold_whitespace("Subject: Email Test",
1297  18,
1298  "Subject: Email\r\n"
1299  " Test");
1300  smtp_unit_test_fold_whitespace("Subject: Email Test",
1301  19,
1302  "Subject: Email\r\n"
1303  " Test");
1304  smtp_unit_test_fold_whitespace("Subject: Email Test",
1305  50,
1306  "Subject: Email Test");
1308  50,
1309  "");
1310  smtp_unit_test_fold_whitespace("Subject: Long Email Subject Line [123456789]",
1311  17,
1312  "Subject: Long\r\n"
1313  " Email Subject\r\n"
1314  " Line\r\n"
1315  " [123456789]");
1317  10,
1319 
1320  for(i = 0; i < 3; i++){
1322  smtp_unit_test_fold_whitespace("a b c", 2, NULL);
1324  }
1325 
1326  /* Memory allocation failure. */
1328  smtp_unit_test_fold_whitespace("a b c", 2, NULL);
1330 
1331  /* Memory allocation failure second loop. */
1333  smtp_unit_test_fold_whitespace("Subject: Email Test", 2, NULL);
1335 }
1336 
1345 static void
1346 smtp_unit_test_chunk_split(const char *const s,
1347  size_t chunklen,
1348  const char *const end,
1349  const char *const expect){
1350  char *result;
1351 
1352  result = smtp_chunk_split(s, chunklen, end);
1353  if(expect == NULL){
1354  assert(result == expect);
1355  }
1356  else{
1357  assert(strcmp(result, expect) == 0);
1358  free(result);
1359  }
1360 }
1361 
1365 static void
1367  int i;
1368 
1369  smtp_unit_test_chunk_split("", 0, "", NULL);
1370  smtp_unit_test_chunk_split("a", 0, "a", NULL);
1371  smtp_unit_test_chunk_split("", 1, "", "");
1372  smtp_unit_test_chunk_split("", 1, "a", "a");
1373  smtp_unit_test_chunk_split("", 2, "a", "a");
1374  smtp_unit_test_chunk_split("a", 1, "", "a");
1375  smtp_unit_test_chunk_split("abc", 1, "-", "a-b-c-");
1376  smtp_unit_test_chunk_split("abc", 2, "-", "ab-c-");
1377  smtp_unit_test_chunk_split("abc", 3, "-", "abc-");
1378  smtp_unit_test_chunk_split("abcdefghijklmnop",
1379  3,
1380  "-",
1381  "abc-def-ghi-jkl-mno-p-");
1382  smtp_unit_test_chunk_split("abc", 1, "-!@", "a-!@b-!@c-!@");
1383  smtp_unit_test_chunk_split("abcdefghijklmnop",
1384  3,
1385  "-!",
1386  "abc-!def-!ghi-!jkl-!mno-!p-!");
1387  smtp_unit_test_chunk_split("abc", 1, "\r\n", "a\r\nb\r\nc\r\n");
1389  10,
1390  "\r\n",
1391  "abcdefghij\r\nklmnopqrst\r\nuvwxyz\r\n");
1392 
1393  /*
1394  * UTF-8 characters
1395  * щ - 2 bytes
1396  * € - 3 bytes
1397  * 𠜎 - 4 bytes
1398  */
1399  smtp_unit_test_chunk_split("€€€", 1, "\r\n", "€\r\n€\r\n€\r\n");
1400  smtp_unit_test_chunk_split("€€€€€", 1, "\r\n", "€\r\n€\r\n€\r\n€\r\n€\r\n");
1401  smtp_unit_test_chunk_split("a€c", 1, "-", "a-€-c-");
1402  smtp_unit_test_chunk_split("a€c", 2, "-", "a€-c-");
1403  smtp_unit_test_chunk_split("€€€", 3, "-", "€-€-€-");
1404  smtp_unit_test_chunk_split("щbc", 3, "-", "щb-c-");
1405  smtp_unit_test_chunk_split("щbc", 4, "-", "щbc-");
1406  smtp_unit_test_chunk_split("aщ€𠜎e", 2, "-", "aщ-€-𠜎-e-");
1407  smtp_unit_test_chunk_split("aщ€𠜎e", 4, "-", "aщ€-𠜎-e-");
1408 
1409  /* Wrapping. */
1411  smtp_unit_test_chunk_split("abc", 1, "-", NULL);
1413  for(i = 0; i < 3; i++){
1415  smtp_unit_test_chunk_split("abc", 1, "-", NULL);
1417  }
1418 
1419  /* Memory allocation failure. */
1421  smtp_unit_test_chunk_split("abc", 1, "-", NULL);
1423 
1424  /* Invalid UTF-8 characters. */
1425  smtp_unit_test_chunk_split("\xBF", 1, "-", NULL);
1426  smtp_unit_test_chunk_split("\xC0", 1, "-", NULL);
1427 }
1428 
1436 static void
1438  size_t nbytes,
1439  const char *const expect){
1440  char *read_buf;
1441  size_t nbytes_rw;
1442 
1443  nbytes_rw = smtp_file_put_contents(TMP_FILE_PATH, s, nbytes, 0);
1444  assert(nbytes_rw == strlen(expect));
1445 
1446  read_buf = smtp_file_get_contents(TMP_FILE_PATH, &nbytes_rw);
1447  assert(read_buf);
1448 
1449  assert(memcmp(expect, read_buf, strlen(expect)) == 0);
1450  free(read_buf);
1451 }
1452 
1456 static void
1458  const char *test_str;
1459 
1461 
1462  test_str = "test";
1463  smtp_unit_test_file_get_contents(test_str, 0, "");
1464  smtp_unit_test_file_get_contents(test_str, strlen(test_str), test_str);
1465 
1466  test_str = "test\nnewline";
1467  smtp_unit_test_file_get_contents(test_str, strlen(test_str), test_str);
1468 
1469  test_str = "test";
1470  smtp_unit_test_file_get_contents(test_str, SIZE_MAX, test_str);
1471 
1472  test_str = STR_ALPHABET_LOWERCASE;
1473  smtp_unit_test_file_get_contents(test_str, strlen(test_str), test_str);
1474 
1475  /* smtp_file_get_contents - fopen */
1476  assert(smtp_file_get_contents("", NULL) == NULL);
1477 
1478  /* smtp_file_get_contents - fclose */
1480  assert(smtp_file_get_contents(TMP_FILE_PATH, NULL) == NULL);
1482 
1483  /* Wrap when increasing the buffer size. */
1485  assert(smtp_file_get_contents(TMP_FILE_PATH, NULL) == NULL);
1487 
1488  /* smtp_file_get_contents - realloc */
1490  assert(smtp_file_get_contents(TMP_FILE_PATH, NULL) == NULL);
1492 
1493  /* smtp_file_get_contents - ferror */
1495  assert(smtp_file_get_contents(TMP_FILE_PATH, NULL) == NULL);
1497 }
1498 
1508 static void
1509 smtp_unit_test_parse_cmd_line(const char *const line,
1510  enum smtp_result_code expect_code,
1511  int expect_more,
1512  const char *const expect_text){
1513  char *line_dup;
1514  struct smtp_command cmd;
1515  int rc;
1516 
1517  line_dup = smtp_strdup(line);
1518  assert(line_dup);
1519 
1520  rc = smtp_parse_cmd_line(line_dup, &cmd);
1521  assert(rc == expect_code);
1522  assert(cmd.code == expect_code);
1523  assert(cmd.more == expect_more);
1524  assert(strcmp(cmd.text, expect_text) == 0);
1525 
1526  free(line_dup);
1527 }
1528 
1532 static void
1536  0,
1537  "");
1540  0,
1541  "<5");
1542  smtp_unit_test_parse_cmd_line("bad text",
1544  0,
1545  "text");
1546  smtp_unit_test_parse_cmd_line("bad-text",
1548  1,
1549  "text");
1550  smtp_unit_test_parse_cmd_line("0x1 text",
1552  0,
1553  "text");
1554  smtp_unit_test_parse_cmd_line("-22 text",
1556  0,
1557  "text");
1558  smtp_unit_test_parse_cmd_line("220 ready",
1559  SMTP_READY,
1560  0,
1561  "ready");
1562 }
1563 
1571 static void
1573  const char *const expect,
1574  int expect_rc){
1575  char result[1000];
1576  int rc;
1577 
1580 
1581  setenv("TZ", "UTC", 1);
1582  rc = smtp_date_rfc_2822(result);
1583  assert(rc == expect_rc);
1584  if(expect_rc == 0){
1585  assert(strcmp(result, expect) == 0);
1586  }
1587 
1590 }
1591 
1595 static void
1597  smtp_unit_test_date_rfc_2822(0, "Thu, 01 Jan 1970 00:00:00 +0000", 0);
1598  smtp_unit_test_date_rfc_2822(60 * 60 * 24 * 2 + 5,
1599  "Sat, 03 Jan 1970 00:00:05 +0000",
1600  0);
1601 
1602  smtp_unit_test_date_rfc_2822(-1, NULL, -1);
1603 
1605  smtp_unit_test_date_rfc_2822(0, NULL, -1);
1607 
1609  smtp_unit_test_date_rfc_2822(0, NULL, -1);
1611 
1613  smtp_unit_test_date_rfc_2822(0, NULL, -1);
1615 
1617  smtp_unit_test_date_rfc_2822(0, NULL, -1);
1619 
1622  smtp_unit_test_date_rfc_2822(0, NULL, -1);
1624 }
1625 
1629 static void
1632  assert(smtp_address_validate_email("mail@example.com") == 0);
1633  assert(smtp_address_validate_email("īḑȋᵭ") == 0);
1634  assert(smtp_address_validate_email("<abc") == -1);
1635  assert(smtp_address_validate_email("abc>") == -1);
1636  assert(smtp_address_validate_email("\x7f") == -1);
1637  assert(smtp_address_validate_email("a b c") == -1);
1638 }
1639 
1643 static void
1646  assert(smtp_address_validate_name("John Doe") == 0);
1647  assert(smtp_address_validate_name("John O'Doe") == 0);
1648  assert(smtp_address_validate_name("īḑȋᵭ") == 0);
1649  assert(smtp_address_validate_name("a\nb\nc") == -1);
1650  assert(smtp_address_validate_name("\"abc") == -1);
1651  assert(smtp_address_validate_name("\x7f") == -1);
1652 }
1653 
1657 static void
1660  assert(smtp_attachment_validate_name("a b c") == 0);
1661  assert(smtp_attachment_validate_name("test.txt") == 0);
1662  assert(smtp_attachment_validate_name("īḑȋᵭ") == 0);
1663  assert(smtp_attachment_validate_name("a\nbc") == -1);
1664  assert(smtp_attachment_validate_name("\x7f") == -1);
1665  assert(smtp_attachment_validate_name("a\'bc") == -1);
1666  assert(smtp_attachment_validate_name("a\"bc") == -1);
1667 }
1668 
1672 static void
1675  assert(smtp_header_key_validate("") == -1);
1676  assert(smtp_header_key_validate("īḑȋᵭ") == -1);
1677  assert(smtp_header_key_validate("a b c") == -1);
1678  assert(smtp_header_key_validate("a\xff") == -1);
1679  assert(smtp_header_key_validate("a:b:c") == -1);
1680  assert(smtp_header_key_validate("a\nb\nc") == -1);
1681 }
1682 
1686 static void
1689  assert(smtp_header_value_validate("a\tb c") == 0);
1690  assert(smtp_header_value_validate("īḑȋᵭ") == 0);
1691  assert(smtp_header_value_validate("a\xff") == 0);
1692  assert(smtp_header_value_validate("a\nb\nc") == -1);
1693 }
1694 
1701 static void
1703  const char *const expect){
1704  const char *result;
1705 
1706  result = smtp_status_code_errstr(status_code);
1707  assert(strcmp(result, expect) == 0);
1708 }
1709 
1713 static void
1716  "Success");
1718  "Memory allocation failed");
1720  "Unknown error");
1722  "Unknown error");
1723 }
1724 
1733  FILE *fp;
1734 };
1735 
1741 
1751 static long
1753  void *buf,
1754  size_t count){
1755  struct smtp_test_getdelimfd_fp *getdelimfd_fp;
1756  size_t bytes_read;
1757 
1758  getdelimfd_fp = gdfd->user_data;
1759  bytes_read = fread(buf, sizeof(char), count, getdelimfd_fp->fp);
1760  if(g_smtp_test_getdelimfd_fp_fail){
1761  return -1;
1762  }
1763  return (long)bytes_read;
1764 }
1765 
1777 static void
1778 smtp_unit_test_str_getdelimfd(const char *const input_string,
1779  size_t nbytes,
1780  int delim,
1781  enum str_getdelim_retcode expect_rc,
1782  int null_fp,
1783  const char *expect_pieces, ...){
1784  const char *piece;
1785  enum str_getdelim_retcode rc;
1786  size_t bytes_written;
1787  struct str_getdelimfd gdfd;
1788  struct smtp_test_getdelimfd_fp getdelimfd_fp;
1789  struct smtp_str_list slist;
1790  FILE *fp;
1791  size_t piece_idx;
1792  va_list ap;
1793 
1794  memset(&slist, 0, sizeof(slist));
1795 
1796  bytes_written = smtp_file_put_contents(TMP_FILE_PATH,
1797  input_string,
1798  nbytes,
1799  0);
1800  assert(bytes_written == nbytes);
1801 
1802  memset(&getdelimfd_fp, 0, sizeof(getdelimfd_fp));
1803  fp = fopen(TMP_FILE_PATH, "r");
1804  assert(fp);
1805  getdelimfd_fp.fp = fp;
1806 
1807  memset(&gdfd, 0, sizeof(gdfd));
1808  gdfd.delim = delim;
1809  if(!null_fp){
1811  }
1812  gdfd.user_data = &getdelimfd_fp;
1813 
1814  do{
1815  rc = smtp_str_getdelimfd(&gdfd);
1816  if(expect_rc == STRING_GETDELIMFD_ERROR){
1817  assert(rc == expect_rc);
1818  smtp_str_list_free(&slist);
1819  return;
1820  }
1821  assert(rc != STRING_GETDELIMFD_ERROR);
1822  assert(smtp_str_list_append(&slist, gdfd.line, gdfd.line_len) == 0);
1823  } while (rc != STRING_GETDELIMFD_DONE);
1824  smtp_str_getdelimfd_free(&gdfd);
1825  assert(fclose(fp) == 0);
1826 
1827  piece_idx = 0;
1828  piece = expect_pieces;
1829  va_start(ap, expect_pieces);
1830  while (piece){
1831  assert(strcmp(piece, slist.slist[piece_idx]) == 0);
1832  piece_idx += 1;
1833  piece = va_arg(ap, const char *);
1834  }
1835  va_end(ap);
1836  assert(piece_idx == slist.n);
1837 
1838  smtp_str_list_free(&slist);
1839 }
1840 
1849 static void
1851  size_t copy_len,
1852  int expect_result){
1853  int result;
1854 
1855  result = smtp_str_getdelimfd_set_line_and_buf(gdfd, copy_len);
1856  assert(result == expect_result);
1857 }
1858 
1862 static void
1864  const char *s;
1865  struct str_getdelimfd gdfd;
1866  char test_str[] = "test";
1867  int i;
1868 
1869  s = "";
1871  strlen(s),
1872  '\n',
1874  0,
1875  "",
1876  NULL);
1877 
1878  s = "a";
1880  strlen(s),
1881  '\n',
1883  0,
1884  "a",
1885  NULL);
1886 
1887  s = "\n";
1889  strlen(s),
1890  '\n',
1892  0,
1893  "",
1894  "",
1895  NULL);
1896 
1897  s = "a\n";
1899  strlen(s),
1900  '\n',
1902  0,
1903  "a",
1904  "",
1905  NULL);
1906 
1907  s = "\na";
1909  strlen(s),
1910  '\n',
1912  0,
1913  "",
1914  "a",
1915  NULL);
1916 
1917  s = "test line 1";
1919  strlen(s),
1920  '\n',
1922  0,
1923  "test line 1",
1924  NULL);
1925 
1926  s = "test line 1\n";
1928  strlen(s),
1929  '\n',
1931  0,
1932  "test line 1",
1933  "",
1934  NULL);
1935 
1936  s = "test line 1\ntest line 2";
1938  strlen(s),
1939  '\n',
1941  0,
1942  "test line 1",
1943  "test line 2",
1944  NULL);
1945 
1946  s = "test line 1\ntest line 2\ntest line 3";
1948  strlen(s),
1949  '\n',
1951  0,
1952  "test line 1",
1953  "test line 2",
1954  "test line 3",
1955  NULL);
1956 
1957  /* smtp_str_getdelimfd_set_line_and_buf - 2 */
1959  s = "a";
1961  strlen(s),
1962  '\n',
1964  0,
1965  NULL);
1967 
1968  /* smtp_str_getdelimfd_set_line_and_buf - 2 */
1970  s = "a\na";
1972  strlen(s),
1973  '\n',
1975  0,
1976  NULL);
1978 
1979  /* realloc */
1981  s = "a";
1983  strlen(s),
1984  '\n',
1986  0,
1987  NULL);
1989 
1990  /* fread */
1991  g_smtp_test_getdelimfd_fp_fail = 1;
1992  s = "a";
1994  strlen(s),
1995  '\n',
1997  0,
1998  NULL);
1999  g_smtp_test_getdelimfd_fp_fail = 0;
2000 
2001  /* getdelimfd_read unset */
2003 
2004  /* Test unsigned wrapping. */
2006  s = "a";
2008  strlen(s),
2009  '\n',
2011  0,
2012  NULL);
2014 
2015  for(i = 0; i < 5; i++){
2017  s = "a";
2019  strlen(s),
2020  '\n',
2022  0,
2023  NULL);
2025  }
2026 
2027  memset(&gdfd, 0, sizeof(gdfd));
2028  gdfd._buf = test_str;
2033  smtp_unit_test_getdelimfd_set_line_and_buf(&gdfd, strlen(test_str), -1);
2035 }
2036 
2040 static void
2066 }
2067 
2081 static int
2082 smtp_test_config_load_from_file(const char *const config_path){
2083  char *config_data;
2084  char *config_data_new;
2085  size_t config_data_len;
2086  struct smtp_str_list line_list;
2087  char *line;
2088  int rc;
2089  size_t i;
2090  const char *key;
2091  const char *value;
2092 
2093  memset(&g_config, 0, sizeof(g_config));
2094 
2095  if((config_data = smtp_file_get_contents(config_path,
2096  &config_data_len)) == NULL){
2097  return -1;
2098  }
2099 
2100  /* add a null character at end of file data */
2101  if((config_data_new = realloc(config_data, config_data_len + 1)) == NULL){
2102  free(config_data);
2103  return -1;
2104  }
2105  config_data = config_data_new;
2106  config_data[config_data_len] = '\0';
2107 
2108  rc = smtp_str_split(config_data, config_data_len, "\n", 0, &line_list);
2109  assert(rc == 0);
2110  free(config_data);
2111 
2112  for(i = 0; i < line_list.n; i++){
2113  line = line_list.slist[i];
2114  if(line[0] == '#'){
2115  continue;
2116  }
2117  key = strtok(line, "=");
2118  if(key == NULL){
2119  continue;
2120  }
2121 
2122  value = strtok(NULL, "=");
2123  if(value == NULL){
2124  value = "";
2125  }
2126 
2127  if(strcmp(key, "server") == 0){
2128  smtp_strlcpy(g_config.server, value, sizeof(g_config.server));
2129  }
2130  else if(strcmp(key, "cafile") == 0){
2131  smtp_strlcpy(g_config.cafile, value, sizeof(g_config.cafile));
2132  }
2133  else if(strcmp(key, "port") == 0){
2134  smtp_strlcpy(g_config.port, value, sizeof(g_config.port));
2135  }
2136  else if(strcmp(key, "port_tls") == 0){
2137  smtp_strlcpy(g_config.port_tls, value, sizeof(g_config.port_tls));
2138  }
2139  else if(strcmp(key, "user") == 0){
2140  smtp_strlcpy(g_config.user, value, sizeof(g_config.user));
2141  }
2142  else if(strcmp(key, "pass") == 0){
2143  smtp_strlcpy(g_config.pass, value, sizeof(g_config.pass));
2144  }
2145  else if(strcmp(key, "email_from") == 0){
2147  }
2148  else if(strcmp(key, "email_to") == 0){
2149  smtp_strlcpy(g_config.email_to, value, sizeof(g_config.email_to));
2150  }
2151  else if(strcmp(key, "email_to_2") == 0){
2153  }
2154  else if(strcmp(key, "email_to_3") == 0){
2156  }
2157  }
2158  smtp_str_list_free(&line_list);
2159 
2160  return 0;
2161 }
2162 
2171 static void
2173  const char *const user,
2174  const char *const pass,
2175  const enum smtp_status_code expect_status){
2176  g_rc = smtp_auth(g_config.smtp, auth_method, user, pass);
2177  assert(g_rc == expect_status);
2178 }
2179 
2188 static void
2190  const char *const email,
2191  const char *const name,
2192  const enum smtp_status_code expect_status){
2193  g_rc = smtp_address_add(g_config.smtp, type, email, name);
2194  assert(g_rc == expect_status);
2195 }
2196 
2204 static void
2205 smtp_header_add_check(const char *const key,
2206  const char *const value,
2207  const enum smtp_status_code expect_status){
2208  g_rc = smtp_header_add(g_config.smtp, key, value);
2209  assert(g_rc == expect_status);
2210 }
2211 
2218 static void
2219 smtp_mail_check(const char *const body,
2220  const enum smtp_status_code expect_status){
2221  g_rc = smtp_mail(g_config.smtp, body);
2222  assert(g_rc == expect_status);
2223 }
2224 
2230 static void
2231 smtp_close_check(const enum smtp_status_code expect_status){
2233  assert(g_rc == expect_status);
2234 }
2235 
2243 static void
2246  g_config.port,
2250  &g_config.smtp);
2251  assert(g_rc == SMTP_STATUS_OK);
2252 
2256  SMTP_STATUS_OK);
2257 
2261  SMTP_STATUS_OK);
2262 
2266  SMTP_STATUS_OK);
2267 
2269  "test.txt",
2270  "test attachment",
2271  SIZE_MAX);
2272  assert(g_rc == SMTP_STATUS_OK);
2273 }
2274 
2278 static void
2281  g_config.port,
2285  &g_config.smtp);
2286  assert(g_rc == SMTP_STATUS_OK);
2287 
2289  assert(g_rc == SMTP_STATUS_OK);
2290 
2293  assert(g_rc == SMTP_STATUS_NOMEM);
2295 
2297 }
2298 
2313 static void
2315  enum smtp_connection_security connection_security,
2316  enum smtp_flag flags,
2317  enum smtp_authentication_method auth_method,
2318  const char *const cafile,
2319  const char *const subject,
2320  const char *const body){
2322  port,
2323  connection_security,
2324  flags,
2325  cafile,
2326  &g_config.smtp);
2327  assert(g_rc == SMTP_STATUS_OK);
2328 
2330 
2334  SMTP_STATUS_OK);
2335 
2339  SMTP_STATUS_OK);
2340 
2341  smtp_header_add_check("Subject", subject, SMTP_STATUS_OK);
2342 
2344 
2346 }
2347 
2355 static void
2356 smtp_func_test_connection_security(const char *const server_port,
2357  enum smtp_connection_security con_security,
2358  const char *const security_description){
2360  "SMTP Test: Connection Security %s",
2361  security_description);
2363  "Email sent with connection security: %s",
2364  security_description);
2365 
2366  smtp_func_test_send_email(server_port,
2367  con_security,
2371  g_config.subject,
2372  g_config.body);
2373 }
2374 
2379 static void
2383  "None");
2386  "STARTTLS");
2389  "TLS");
2390 }
2391 
2396 static void
2400  SMTP_DEBUG,
2402  g_config.cafile,
2403  "SMTP Test: cafile",
2404  g_config.cafile);
2405 }
2406 
2413 static void
2415  const char *const auth_description){
2417  "SMTP Test: AUTH %s",
2418  auth_description);
2420  "Email authenticated using %s",
2421  auth_description);
2422 
2426  auth_method,
2428  g_config.subject,
2429  g_config.body);
2430 }
2431 
2436 static void
2442 }
2443 
2452 static void
2453 smtp_func_test_attachment_path(const char *const name,
2454  const char *const path,
2455  enum smtp_status_code expect_rc){
2456  strcpy(g_config.subject, "SMTP Test: Attachment (file path)");
2457  strcpy(g_config.body, "This email should contain a pdf attachment");
2458 
2460  g_config.port,
2464  &g_config.smtp);
2465  assert(g_rc == SMTP_STATUS_OK);
2466 
2468  g_config.user,
2469  g_config.pass,
2470  SMTP_STATUS_OK);
2471 
2475  SMTP_STATUS_OK);
2476 
2480  SMTP_STATUS_OK);
2481 
2482  g_rc = smtp_attachment_add_path(g_config.smtp, name, path);
2483  assert(g_rc == expect_rc);
2484 
2485  smtp_header_add_check("Subject", g_config.subject, expect_rc);
2486 
2487  smtp_mail_check(g_config.body, expect_rc);
2488 
2489  smtp_close_check(expect_rc);
2490 }
2491 
2500 static void
2501 smtp_func_test_attachment_fp(const char *const name,
2502  const char *const path,
2503  enum smtp_status_code expect_rc){
2504  FILE *fp;
2505  int fp_rc;
2506 
2507  strcpy(g_config.subject, "SMTP Test: Attachment (fp)");
2508  strcpy(g_config.body, "This email should contain a pdf attachment");
2509 
2510  fp = fopen(path, "r");
2511  assert(fp != NULL);
2512 
2514  g_config.port,
2518  &g_config.smtp);
2519  assert(g_rc == SMTP_STATUS_OK);
2520 
2524  SMTP_STATUS_OK);
2525 
2529  SMTP_STATUS_OK);
2530 
2532  assert(g_rc == expect_rc);
2533 
2534  smtp_header_add_check("Subject", g_config.subject, expect_rc);
2535 
2536  smtp_mail_check(g_config.body, expect_rc);
2537 
2538  smtp_close_check(expect_rc);
2539 
2540  fp_rc = fclose(fp);
2541  assert(fp_rc == 0);
2542 }
2543 
2549 static void
2550 smtp_func_test_attachment_mem(size_t num_attachment){
2551  size_t i;
2552  char attachment_name[SMTP_MAX_ATTACHMENT_NAME_LEN];
2553  char attachment_data[100];
2554 
2556  "SMTP Test: Attachments (%u)",
2557  (unsigned)num_attachment);
2559  "You should have %u attachments in this email. "
2560  "Each attachment should contain the text "
2561  "\"Attachment# <number>\"",
2562  (unsigned)num_attachment);
2563 
2565  g_config.port,
2569  &g_config.smtp);
2570  assert(g_rc == SMTP_STATUS_OK);
2571 
2573  g_config.user,
2574  g_config.pass,
2575  SMTP_STATUS_OK);
2576 
2580  SMTP_STATUS_OK);
2581 
2585  SMTP_STATUS_OK);
2586 
2587  for(i = 0; i < num_attachment; i++){
2588  sprintf(attachment_name, "%u.txt", (unsigned)(i + 1));
2589  sprintf(attachment_data, "Attachment# %u", (unsigned)(i + 1));
2591  attachment_name,
2592  attachment_data,
2593  SIZE_MAX);
2594  assert(g_rc == SMTP_STATUS_OK);
2595  }
2596 
2598 
2600 
2602 }
2603 
2609 static void
2610 smtp_func_test_attachment_pdf(const size_t num_attachments){
2611  char attachment_name[SMTP_MAX_ATTACHMENT_NAME_LEN];
2612  size_t i;
2613 
2615  "SMTP Test: PDF Attachments (%u)",
2616  (unsigned)num_attachments);
2618  "You should have %u PDF attachments in this email. "
2619  "Each attachment should contain the text "
2620  "\"SMTP TEST PDF ATTACHMENT\"",
2621  (unsigned)num_attachments);
2623  g_config.port,
2627  &g_config.smtp);
2628  assert(g_rc == SMTP_STATUS_OK);
2630  g_config.user,
2631  g_config.pass,
2632  SMTP_STATUS_OK);
2636  SMTP_STATUS_OK);
2640  SMTP_STATUS_OK);
2641  for(i = 0; i < num_attachments; i++){
2642  sprintf(attachment_name, "test-%u.pdf", (unsigned)(i + 1));
2644  attachment_name,
2645  "test/test.pdf");
2646  assert(g_rc == SMTP_STATUS_OK);
2647  }
2651 }
2652 
2656 static void
2658  char *long_text;
2659 
2660  /* Send Large attachment attachment with repeated text. */
2662  g_config.port,
2666  &g_config.smtp);
2667  assert(g_rc == SMTP_STATUS_OK);
2668 
2670  g_config.user,
2671  g_config.pass,
2672  SMTP_STATUS_OK);
2673 
2677  SMTP_STATUS_OK);
2678 
2682  SMTP_STATUS_OK);
2683 
2684  long_text = smtp_str_repeat(STR_ALPHABET_LOWERCASE " ", 5000);
2685  assert(long_text);
2687  "alphabet-repeat.txt",
2688  long_text,
2689  SIZE_MAX);
2690  assert(g_rc == SMTP_STATUS_OK);
2691  free(long_text);
2692 
2693  smtp_header_add_check("Subject",
2694  "SMTP Test: Long Text Attachment",
2695  SMTP_STATUS_OK);
2696 
2697  smtp_mail_check("This email should contain long text attachment",
2698  SMTP_STATUS_OK);
2699 
2701 }
2702 
2706 static void
2708  /* Send one attachment using the mem interface. */
2710 
2711  /* Send 10 attachments in one email. */
2713 
2714  /* Send 10 PDF attachments in one email. */
2716 
2718 }
2719 
2723 static void
2725  /* Send a PDF test file using the path interface. */
2726  smtp_func_test_attachment_path("test.pdf",
2727  "test/test.pdf",
2728  SMTP_STATUS_OK);
2729 
2730  /* Try to send a file that does not exist. */
2731  smtp_func_test_attachment_path("noexist.txt",
2732  "test/noexist.txt",
2734 }
2735 
2739 static void
2741  smtp_func_test_attachment_fp("test.pdf",
2742  "test/test.pdf",
2743  SMTP_STATUS_OK);
2744 }
2745 
2749 static void
2754 }
2755 
2759 static void
2762  g_config.port,
2766  &g_config.smtp);
2767  assert(g_rc == SMTP_STATUS_OK);
2768 
2769  /* Multiple TO addresses. */
2772  smtp_header_add_check("Subject",
2773  "SMTP Test: Multiple TO Addresses",
2774  SMTP_STATUS_OK);
2778  SMTP_STATUS_OK);
2782  SMTP_STATUS_OK);
2786  SMTP_STATUS_OK);
2787  smtp_mail_check("This email should contain two TO recipients.",
2788  SMTP_STATUS_OK);
2789 
2790  /* One BCC address. */
2793  smtp_header_add_check("Subject",
2794  "SMTP Test: BCC Address",
2795  SMTP_STATUS_OK);
2799  SMTP_STATUS_OK);
2803  SMTP_STATUS_OK);
2804  smtp_mail_check("This email should contain one BCC recipient.",
2805  SMTP_STATUS_OK);
2806 
2807  /* One TO and one BCC address. */
2810  smtp_header_add_check("Subject",
2811  "SMTP Test: TO and BCC Addresses",
2812  SMTP_STATUS_OK);
2816  SMTP_STATUS_OK);
2820  SMTP_STATUS_OK);
2824  SMTP_STATUS_OK);
2825  smtp_mail_check("This email should contain one TO and one BCC recipient.",
2826  SMTP_STATUS_OK);
2827 
2828  /* One TO, CC, and BCC addresses. */
2831  smtp_header_add_check("Subject",
2832  "SMTP Test: TO, CC, and BCC Addresses",
2833  SMTP_STATUS_OK);
2837  SMTP_STATUS_OK);
2841  SMTP_STATUS_OK);
2845  SMTP_STATUS_OK);
2849  SMTP_STATUS_OK);
2850  smtp_mail_check("This email should contain one TO, CC, and BCC recipient.",
2851  SMTP_STATUS_OK);
2852 
2853  /* No FROM address. */
2856  smtp_header_add_check("Subject",
2857  "SMTP Test: No FROM address",
2858  SMTP_STATUS_OK);
2862  SMTP_STATUS_OK);
2863  smtp_mail_check("This email should not have a FROM address in the header.",
2866 
2867  /* FROM address contains UTF-8 characters. */
2870  smtp_header_add_check("Subject",
2871  "SMTP Test: From contains UTF-8 characters",
2872  SMTP_STATUS_OK);
2874  "smtp-cli€nt-t€st@somnisoft.com",
2876  SMTP_STATUS_OK);
2880  SMTP_STATUS_OK);
2884  smtp_mail_check("This email should contain a FROM address with UTF-8.",
2885  SMTP_STATUS_OK);
2886 
2888 }
2889 
2894 static void
2896  char *long_name;
2897 
2899  g_config.port,
2903  &g_config.smtp);
2904  assert(g_rc == SMTP_STATUS_OK);
2905 
2906  /* NULL From and Blank To Names */
2909  smtp_header_add_check("Subject",
2910  "SMTP Test: Null From Name and Blank To Name",
2911  SMTP_STATUS_OK);
2914  NULL,
2915  SMTP_STATUS_OK);
2918  "",
2919  SMTP_STATUS_OK);
2920  smtp_mail_check("This email should not have a name in From or To.",
2921  SMTP_STATUS_OK);
2922 
2923  /* Two To Names */
2926  smtp_header_add_check("Subject",
2927  "SMTP Test: Two To Names",
2928  SMTP_STATUS_OK);
2932  SMTP_STATUS_OK);
2935  "Email Name 1",
2936  SMTP_STATUS_OK);
2939  "Email Name 2",
2940  SMTP_STATUS_OK);
2941  smtp_mail_check("This email should have two addresses with different names.",
2942  SMTP_STATUS_OK);
2943 
2944  /* Three To Names */
2947  smtp_header_add_check("Subject",
2948  "SMTP Test: Three To Names",
2949  SMTP_STATUS_OK);
2953  SMTP_STATUS_OK);
2956  "Email Name 1",
2957  SMTP_STATUS_OK);
2960  "Email Name 2",
2961  SMTP_STATUS_OK);
2964  "Email Name 3",
2965  SMTP_STATUS_OK);
2966  smtp_mail_check("This email should have three addresses with different names.",
2967  SMTP_STATUS_OK);
2968 
2969  /* Long email name */
2970  long_name = smtp_str_repeat(STR_ALPHABET_LOWERCASE " ", 2);
2971  assert(long_name);
2974  smtp_header_add_check("Subject",
2975  "SMTP Test: Long Email Names",
2976  SMTP_STATUS_OK);
2979  long_name,
2980  SMTP_STATUS_OK);
2983  long_name,
2984  SMTP_STATUS_OK);
2985  smtp_mail_check("This email should have a long alphabet name.",
2986  SMTP_STATUS_OK);
2987  free(long_name);
2988 
2989  /* Very long email name */
2990  long_name = smtp_str_repeat(STR_ALPHABET_LOWERCASE " ", 100);
2991  assert(long_name);
2994  smtp_header_add_check("Subject",
2995  "SMTP Test: Very Long Email Names",
2996  SMTP_STATUS_OK);
2999  long_name,
3000  SMTP_STATUS_OK);
3003  long_name,
3004  SMTP_STATUS_OK);
3005  smtp_mail_check("This email should have a very long alphabet name "
3006  "repeated 100 times.",
3007  SMTP_STATUS_OK);
3008  free(long_name);
3009 
3011 }
3012 
3019 static void
3022  g_config.port,
3026  &g_config.smtp);
3027  assert(g_rc == SMTP_STATUS_OK);
3028 
3030 
3031  smtp_header_add_check("Subject",
3032  "SMTP Test: Custom Date",
3033  SMTP_STATUS_OK);
3034 
3035  smtp_header_add_check("Date",
3036  "Thu, 21 May 1998 05:33:29 -0700",
3037  SMTP_STATUS_OK);
3038 
3042  SMTP_STATUS_OK);
3043 
3047  SMTP_STATUS_OK);
3048 
3049  smtp_mail_check("This email should contain a custom date header.",
3050  SMTP_STATUS_OK);
3051 
3053 }
3054 
3060 static void
3063  g_config.port,
3067  &g_config.smtp);
3068  assert(g_rc == SMTP_STATUS_OK);
3069 
3071 
3072  smtp_header_add_check("Subject",
3073  "SMTP Test: Null Header (No Date)",
3074  SMTP_STATUS_OK);
3075 
3076  smtp_header_add_check("Date", NULL, SMTP_STATUS_OK);
3077 
3081  SMTP_STATUS_OK);
3082 
3086  SMTP_STATUS_OK);
3087 
3088  smtp_mail_check("This email should not contain a Date header.",
3089  SMTP_STATUS_OK);
3090 
3092 }
3093 
3097 static void
3099  char *long_text;
3100 
3102  g_config.port,
3106  &g_config.smtp);
3107  assert(g_rc == SMTP_STATUS_OK);
3108 
3110 
3111  long_text = smtp_str_repeat(STR_ALPHABET_LOWERCASE " ", 1000);
3112  assert(long_text);
3113 
3114  smtp_header_add_check("Subject", long_text, SMTP_STATUS_OK);
3115  smtp_header_add_check("Custom", long_text, SMTP_STATUS_OK);
3116 
3117  free(long_text);
3118 
3122  SMTP_STATUS_OK);
3123 
3127  SMTP_STATUS_OK);
3128 
3129  smtp_mail_check("This email should contain very long"
3130  " Subject and Custom headers.",
3131  SMTP_STATUS_OK);
3132 
3134 }
3135 
3139 static void
3144 }
3145 
3149 static void
3151  char *long_body;
3152 
3154  g_config.port,
3158  &g_config.smtp);
3159  assert(g_rc == SMTP_STATUS_OK);
3160 
3161  smtp_header_add_check("Subject",
3162  "SMTP Test: Very Long Email Body",
3163  SMTP_STATUS_OK);
3164 
3168  SMTP_STATUS_OK);
3169 
3173  SMTP_STATUS_OK);
3174 
3175  long_body = smtp_str_repeat(STR_ALPHABET_LOWERCASE " ", 5000);
3176  assert(long_body);
3177 
3178  smtp_mail_check(long_body, SMTP_STATUS_OK);
3179 
3180  free(long_body);
3181 
3183 }
3184 
3188 static void
3192  g_config.port,
3196  &g_config.smtp);
3197  assert(g_rc == SMTP_STATUS_OK);
3200 }
3201 
3205 static void
3208  g_config.port,
3212  &g_config.smtp);
3213  assert(g_rc == SMTP_STATUS_OK);
3214 
3216 
3217  smtp_header_add_check("Subject",
3218  "SMTP Test: No Debug Mode",
3219  SMTP_STATUS_OK);
3220 
3224  SMTP_STATUS_OK);
3225 
3229  SMTP_STATUS_OK);
3230 
3231  smtp_mail_check("This email sent with debug mode disabled.",
3232  SMTP_STATUS_OK);
3233 
3235 }
3236 
3240 static void
3242  const char *const html_body =
3243  "<html>\n"
3244  " <head><title>HTML Email Example</title></head>\n"
3245  " <body>\n"
3246  " <table style='border: 1px solid black; background-color: #a0a0a0'>\n"
3247  " <caption>smtp_connection_security</caption>\n"
3248  " <tr>\n"
3249  " <th>Code</th>\n"
3250  " <th>Description</th>\n"
3251  " </tr>\n"
3252  " <tr>\n"
3253  " <td>SMTP_SECURITY_STARTTLS</td>\n"
3254  " <td>Use STARTTLS</td>\n"
3255  " </tr>\n"
3256  " <tr>\n"
3257  " <td>SMTP_SECURITY_TLS</td>\n"
3258  " <td>Direct TLS connection</td>\n"
3259  " </tr>\n"
3260  " <tr>\n"
3261  " <td>SMTP_SECURITY_NONE</td>\n"
3262  " <td>No encryption</td>\n"
3263  " </tr>\n"
3264  " </table>\n"
3265  " </body>\n"
3266  "</html>";
3267 
3269  g_config.port,
3273  &g_config.smtp);
3274  assert(g_rc == SMTP_STATUS_OK);
3275 
3277 
3278  smtp_header_add_check("Subject",
3279  "SMTP Test: HTML Email (Content-Type: text/html)",
3280  SMTP_STATUS_OK);
3281 
3282  smtp_header_add_check("Content-Type", "text/html", SMTP_STATUS_OK);
3283 
3287  SMTP_STATUS_OK);
3288 
3292  SMTP_STATUS_OK);
3293 
3294  smtp_mail_check(html_body, SMTP_STATUS_OK);
3295 
3297 }
3298 
3302 static void
3304  const char *const html_body =
3305  "This is a multi-part message in MIME format.\r\n"
3306  "...\n"
3307  "..\n"
3308  ".\n"
3309  ".\r"
3310  ".\n"
3311  "\r\n"
3312  "--FEDCBA\r\n"
3313  "This is a multi-part message in MIME format.\r\n"
3314  "--ABCDEF\r\n"
3315  "Content-Type: text/plain; charset=\"utf-8\"\r\n"
3316  "Content-Transfer-Encoding: 8bit\r\n"
3317  "\r\n"
3318  "Plaintext section.\r\n"
3319  "\r\n"
3320  "--ABCDEF\r\n"
3321  "Content-Type: text/html; charset=\"utf-8\"\r\n"
3322  "Content-Transfer-Encoding: 8bit\r\n"
3323  "\r\n"
3324  "<html>\n"
3325  " <head><title>HTML/Plaintext Email</title></head>\n"
3326  " <body>\n"
3327  " <h1>HTML section</h1>\n"
3328  " <h2>Heading 2</h2>\n"
3329  " </body>\n"
3330  "</html>\n"
3331  "...\n"
3332  "..\n"
3333  ".\n"
3334  ".";
3335 
3337  g_config.port,
3341  &g_config.smtp);
3342  assert(g_rc == SMTP_STATUS_OK);
3343 
3345 
3346  smtp_header_add_check("Subject",
3347  "SMTP Test: HTML Email (with plaintext)",
3348  SMTP_STATUS_OK);
3349 
3350  smtp_header_add_check("Content-Type",
3351  "multipart/alternative; boundary=\"ABCDEF\"",
3352  SMTP_STATUS_OK);
3353 
3357  SMTP_STATUS_OK);
3358 
3362  SMTP_STATUS_OK);
3363 
3364  smtp_mail_check(html_body, SMTP_STATUS_OK);
3365 
3367 }
3368 
3372 static void
3376 }
3377 
3382 static void
3384  /* Send buffer to large in @ref smtp_write. */
3386  g_config.port,
3390  &g_config.smtp);
3391  assert(g_rc == SMTP_STATUS_OK);
3392  g_rc = smtp_write(g_config.smtp, "", (size_t)INT_MAX + 1);
3393  assert(g_rc == SMTP_STATUS_SEND);
3395 
3396  /* Memory allocation failure in smtp_puts_debug - the error gets ignored. */
3399  g_config.port,
3403  &g_config.smtp);
3405  assert(g_rc == SMTP_STATUS_OK);
3407 }
3408 
3412 static void
3414  /* Initial memory allocation failure for the SMTP client context. */
3417  g_config.port,
3421  &g_config.smtp);
3423  assert(g_rc == SMTP_STATUS_NOMEM);
3425 
3426  /* Invalid hostname should cause getaddrinfo() to fail. */
3427  g_rc = smtp_open(NULL,
3428  NULL,
3432  &g_config.smtp);
3433  assert(g_rc == SMTP_STATUS_CONNECT);
3435 
3436  /* socket() function failure. */
3439  g_config.port,
3443  &g_config.smtp);
3445  assert(g_rc == SMTP_STATUS_CONNECT);
3447 
3448  /* connect() function failure. */
3451  g_config.port,
3455  &g_config.smtp);
3457  assert(g_rc == SMTP_STATUS_CONNECT);
3459 
3460  /* SSL_CTX_new() failure. */
3463  g_config.port,
3467  &g_config.smtp);
3469  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3471 
3472  /* ERR_peek_error() failure. */
3475  g_config.port,
3479  &g_config.smtp);
3481  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3483 
3484  /* SSL_new() failure. */
3487  g_config.port,
3491  &g_config.smtp);
3493  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3495 
3496  /* BIO_new_socket() failure. */
3499  g_config.port,
3503  &g_config.smtp);
3505  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3507 
3508  /* SSL_connect() failure. */
3511  g_config.port,
3515  &g_config.smtp);
3517  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3519 
3520  /* SSL_do_handshake() failure. */
3523  g_config.port,
3527  &g_config.smtp);
3529  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3531 
3532  /*
3533  * Ensure self-signed certificate throws an error. This error will occur by
3534  * default since the test server uses a self-signed certificate.
3535  */
3537  g_config.port,
3539  SMTP_DEBUG,
3541  &g_config.smtp);
3542  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3544 
3545  /* SSL_CTX_load_verify_locations() failure. */
3547  g_config.port,
3549  SMTP_DEBUG,
3550  "test/config/file_does_not_exist",
3551  &g_config.smtp);
3552  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3554 
3555  /* SSL_get_peer_certificate() failure. */
3558  g_config.port,
3560  SMTP_DEBUG,
3561  g_config.cafile,
3562  &g_config.smtp);
3564  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3566 
3567  /* X509_check_host() failure. */
3570  g_config.port,
3572  SMTP_DEBUG,
3573  g_config.cafile,
3574  &g_config.smtp);
3576  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3578 
3579  /*
3580  * TLS failure in @ref smtp_initiate_handshake (1) when using direct
3581  * TLS connection.
3582  */
3585  g_config.port,
3589  &g_config.smtp);
3591  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3593 
3594  /* @ref smtp_initiate_handshake failure in (2). */
3597  g_config.port,
3601  &g_config.smtp);
3603  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3605 
3606  /* @ref smtp_initiate_handshake failure in (3). */
3609  g_config.port,
3613  &g_config.smtp);
3615  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3617 
3618  /* @ref smtp_initiate_handshake STARTTLS send failure in (4). */
3621  g_config.port,
3625  &g_config.smtp);
3627  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3629 
3630  /* @ref smtp_initiate_handshake failed response to STARTTLS in (4). */
3633  g_config.port,
3637  &g_config.smtp);
3639  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3641 
3642  /* @ref smtp_initiate_handshake second EHLO in (4). */
3645  g_config.port,
3649  &g_config.smtp);
3651  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3653 
3654  /* Failure in @ref BIO_should_retry. */
3659  g_config.port,
3663  &g_config.smtp);
3667  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3669 
3670  /* Failure in @ref SSL_Read but re-reading caused by @ref BIO_should_retry. */
3675  g_config.port,
3679  &g_config.smtp);
3683  assert(g_rc == SMTP_STATUS_OK);
3685 
3686  /* Test server prematurely ending the connection with no bytes to read. */
3690  g_config.port,
3694  &g_config.smtp);
3697  assert(g_rc == SMTP_STATUS_HANDSHAKE);
3699 }
3700 
3705 static void
3708  g_config.port,
3712  &g_config.smtp);
3713  assert(g_rc == SMTP_STATUS_OK);
3714 
3715  /* Invalid SMTP status code. */
3721 
3722  /* Invalid email address. */
3725  "<invalid>",
3728 
3729  /* Invalid email name. */
3733  "\"invalid\"",
3735 
3736  /* Wrap when trying to increase size of address list. */
3744 
3745  /* Memory allocation failed while trying to increase size of address list. */
3753 
3754  /* Failed to duplicate email string. */
3762 
3763  /* Failed to duplicate name string. */
3771 
3773 }
3774 
3779 static void
3781  FILE *fp;
3782  int fp_rc;
3783 
3785  g_config.port,
3789  &g_config.smtp);
3790  assert(g_rc == SMTP_STATUS_OK);
3791 
3792 
3793  /* Invalid SMTP status code. */
3796  "valid",
3797  "test",
3798  SIZE_MAX);
3799  assert(g_rc == SMTP_STATUS_PARAM);
3800 
3801 
3802  /* Invalid filename parameter. */
3805  "\"invalid\"",
3806  "test",
3807  SIZE_MAX);
3808  assert(g_rc == SMTP_STATUS_PARAM);
3809 
3810  /* Wrap when increasing the attachment list size. */
3814  "valid",
3815  "test",
3816  SIZE_MAX);
3817  assert(g_rc == SMTP_STATUS_NOMEM);
3819 
3820  /* Memory allocation failure while increasing the attachment list size. */
3824  "valid",
3825  "test",
3826  SIZE_MAX);
3827  assert(g_rc == SMTP_STATUS_NOMEM);
3829 
3830  /* Memory allocation failure while using smtp_strdup on file name. */
3834  "valid",
3835  "test",
3836  SIZE_MAX);
3837  assert(g_rc == SMTP_STATUS_NOMEM);
3839 
3840 
3841  /* Memory allocation failure while using smtp_base64_encode. */
3845  "valid",
3846  "test",
3847  SIZE_MAX);
3848  assert(g_rc == SMTP_STATUS_NOMEM);
3850 
3851  /* Memory allocation failure when splitting base64 lines into chunks. */
3855  "valid",
3856  "test",
3857  SIZE_MAX);
3858  assert(g_rc == SMTP_STATUS_NOMEM);
3860 
3861  /* Invalid SMTP status code. */
3863  g_rc = smtp_attachment_add_fp(g_config.smtp, "test", stdin);
3864  assert(g_rc == SMTP_STATUS_PARAM);
3865 
3866  /* @ref smtp_ffile_get_contents memory allocation failure. */
3869  g_rc = smtp_attachment_add_fp(g_config.smtp, "test", stdin);
3871  assert(g_rc == SMTP_STATUS_NOMEM);
3872 
3873  /* @ref smtp_ffile_get_contents fread error. */
3875  fp = fopen("COPYING", "r");
3876  assert(fp);
3878  g_rc = smtp_attachment_add_fp(g_config.smtp, "test", fp);
3880  assert(g_rc == SMTP_STATUS_FILE);
3881  fp_rc = fclose(fp);
3882  assert(fp_rc == 0);
3883 
3884  /* @ref smtp_file_get_contents memory allocation failure. */
3887  g_rc = smtp_attachment_add_path(g_config.smtp, "test", "COPYING");
3889  assert(g_rc == SMTP_STATUS_NOMEM);
3890 
3891  /* Invalid SMTP status code. */
3893  g_rc = smtp_attachment_add_path(g_config.smtp, "test", "test.txt");
3894  assert(g_rc == SMTP_STATUS_PARAM);
3895 
3897 }
3898 
3903 static void
3906  g_config.port,
3910  &g_config.smtp);
3911  assert(g_rc == SMTP_STATUS_OK);
3912 
3913  /* Invalid SMTP status code. */
3915  smtp_header_add_check("key", "value", SMTP_STATUS_NOMEM);
3916 
3917  /* Invalid header key. */
3919  smtp_header_add_check("invalid:", "value", SMTP_STATUS_PARAM);
3920 
3921  /* Invalid header value. */
3923  smtp_header_add_check("key", "invalid\n", SMTP_STATUS_PARAM);
3924 
3925  /* Wrap when increasing the header list size. */
3928  smtp_header_add_check("key", "value", SMTP_STATUS_NOMEM);
3930 
3931  /* Memory allocation failure while trying to increase header list size. */
3934  smtp_header_add_check("key", "value", SMTP_STATUS_NOMEM);
3936 
3937  /* Failed to strdup header key. */
3940  smtp_header_add_check("key", "value", SMTP_STATUS_NOMEM);
3942 
3943  /* Failed to strdup header value. */
3946  smtp_header_add_check("key", "value", SMTP_STATUS_NOMEM);
3948 
3950 }
3951 
3955 static void
3958  g_config.port,
3962  &g_config.smtp);
3963  assert(g_rc == SMTP_STATUS_OK);
3964 
3966  assert(g_rc == SMTP_STATUS_PARAM);
3967 
3969  assert(g_rc == SMTP_STATUS_PARAM);
3970 
3972  assert(g_rc == SMTP_STATUS_PARAM);
3973 
3975  assert(g_rc == SMTP_STATUS_OK);
3976 
3978 }
3979 
3983 static void
3985  /* Invalid SMTP client context. */
3990 
3991  /* Wrap in @ref smtp_mail_envelope_header size calculation. */
3999 
4000  /*
4001  * Memory allocation failure in the first call to
4002  * @ref smtp_mail_envelope_header.
4003  */
4009 
4010  /* Send failure in @ref smtp_mail_envelope_header. */
4018 
4019  /* Read failure in @ref smtp_mail_envelope_header. */
4027 
4028  /* Send failure in the second call to @ref smtp_mail_envelope_header. */
4036 
4037  /* Failed to send DATA command. */
4045 
4046  /* Failed to read response to DATA command. */
4054 
4055  /* Failed to generate date string in @ref smtp_date_rfc_2822. */
4061 
4062  /* Failed to add Date header to list using @ref smtp_header_add. */
4068 
4069  /* 1st wrap in @ref smtp_append_address_to_header */
4075 
4076  /* 2nd wrap in @ref smtp_append_address_to_header */
4082 
4083  /* 3rd wrap in @ref smtp_append_address_to_header */
4089 
4090  /*
4091  * Failed to add FROM address to header using
4092  * @ref smtp_append_address_to_header.
4093  */
4099 
4100  /*
4101  * Failed to add TO address to header using
4102  * @ref smtp_append_address_to_header.
4103  */
4109 
4110  /*
4111  * Failed to add CC address to header using
4112  * @ref smtp_append_address_to_header.
4113  */
4119 
4120  /* 1st wrap in @ref smtp_print_header. */
4126 
4127  /* 2nd wrap in @ref smtp_print_header. */
4133 
4134  /* Failed memory allocation in @ref smtp_print_header. */
4140 
4141  /* Failed @ref smtp_fold_whitespace in @ref smtp_print_header. */
4147 
4148  /* Failed @ref smtp_puts_terminate in @ref smtp_print_header. */
4156 
4157  /*
4158  * Failure in @ref smtp_print_mime_email ->
4159  * @ref smtp_print_mime_header_and_body ->
4160  * @ref smtp_str_replace.
4161  */
4167 
4168  /* Wrap in @ref smtp_print_mime_header_and_body size calculation. */
4174 
4175  /*
4176  * Memory allocation failure in @ref smtp_print_mime_email ->
4177  * @ref smtp_print_mime_header_and_body ->
4178  * malloc after @ref smtp_str_replace.
4179  */
4185 
4186  /*
4187  * Send failure in @ref smtp_print_mime_email ->
4188  * @ref smtp_print_mime_header_and_body ->
4189  * @ref smtp_puts.
4190  */
4198 
4199  /* 1st wrap in @ref smtp_print_mime_attachment. */
4205 
4206  /* 2nd wrap in @ref smtp_print_mime_attachment. */
4212 
4213  /* Memory allocation failure in @ref smtp_print_mime_attachment. */
4219 
4220  /* Send failure in @ref smtp_print_mime_attachment. */
4228 
4229  /* Send failure in @ref smtp_print_mime_end. */
4237 
4238  /* Failed to send end of DATA segment. */
4246 
4247  /* Invalid server response on DATA termination. */
4255 }
4256 
4260 static void
4262  /* Failed to send the QUIT command. */
4264  g_config.port,
4268  &g_config.smtp);
4269  assert(g_rc == SMTP_STATUS_OK);
4275 
4276  /* Failed to close the socket file descriptor. */
4278  g_config.port,
4282  &g_config.smtp);
4283  assert(g_rc == SMTP_STATUS_OK);
4287 
4288  /* Failed to send QUIT and close the socket file descriptor. */
4290  g_config.port,
4294  &g_config.smtp);
4295  assert(g_rc == SMTP_STATUS_OK);
4303 }
4304 
4309 static void
4311  smtp_test_sleep(15);
4312 
4313  /* Invalid SMTP status code. */
4317  g_config.user,
4318  g_config.pass,
4321 
4322  smtp_test_sleep(15);
4323 
4324  /* Invalid authentication method. */
4327  g_config.user,
4328  g_config.pass,
4331 
4332  smtp_test_sleep(15);
4333 
4334  /* PLAIN - Invalid credentials. */
4336  smtp_auth_check(SMTP_AUTH_PLAIN, "invalid", "invalid", SMTP_STATUS_AUTH);
4338 
4339  smtp_test_sleep(15);
4340 
4341  /* PLAIN - Wrap in 1st calculation for memory allocation in (1). */
4345  g_config.user,
4346  g_config.pass,
4350 
4351  smtp_test_sleep(15);
4352 
4353  /* PLAIN - Wrap in 2nd calculation for memory allocation in (1). */
4357  g_config.user,
4358  g_config.pass,
4362 
4363  smtp_test_sleep(15);
4364 
4365  /* PLAIN - Memory allocation failure in (1). */
4369  g_config.user,
4370  g_config.pass,
4374 
4375  smtp_test_sleep(15);
4376 
4377  /* PLAIN - @ref smtp_base64_encode failure in (2). */
4381  g_config.user,
4382  g_config.pass,
4386 
4387  smtp_test_sleep(15);
4388 
4389  /* PLAIN - Wrap in calculation for memory allocation in (3). */
4393  g_config.user,
4394  g_config.pass,
4398 
4399  smtp_test_sleep(15);
4400 
4401  /* PLAIN - Memory allocation failure in (3). */
4405  g_config.user,
4406  g_config.pass,
4410 
4411  smtp_test_sleep(15);
4412 
4413  /* PLAIN - @ref smtp_puts failure in (3). */
4418  g_config.user,
4419  g_config.pass,
4424 
4425  smtp_test_sleep(15);
4426 
4427  /* LOGIN - @ref smtp_base64_encode failure in (1). */
4431  g_config.user,
4432  g_config.pass,
4436 
4437  smtp_test_sleep(15);
4438 
4439  /* LOGIN - Wrap in calculation for memory allocation in (2). */
4443  g_config.user,
4444  g_config.pass,
4448 
4449  smtp_test_sleep(15);
4450 
4451  /* LOGIN - Memory allocation failure in (2). */
4455  g_config.user,
4456  g_config.pass,
4460 
4461  smtp_test_sleep(15);
4462 
4463  /* LOGIN - @ref smtp_puts send failure in (2). */
4468  g_config.user,
4469  g_config.pass,
4474 
4475  smtp_test_sleep(15);
4476 
4477  /* LOGIN - Response read error in (2). */
4482  g_config.user,
4483  g_config.pass,
4488 
4489  smtp_test_sleep(15);
4490 
4491  /* LOGIN - @ref smtp_base64_encode failure in (3). */
4495  g_config.user,
4496  g_config.pass,
4500 
4501  smtp_test_sleep(15);
4502 
4503  /* LOGIN - @ref smtp_puts_terminate failure in (3). */
4508  g_config.user,
4509  g_config.pass,
4514 
4515  smtp_test_sleep(15);
4516 
4517  /* LOGIN - @ref smtp_puts_terminate wrap in (3). */
4521  g_config.user,
4522  g_config.pass,
4526 
4527  smtp_test_sleep(15);
4528 
4529  /* LOGIN - @ref smtp_puts_terminate memory allocation failure in (3). */
4533  g_config.user,
4534  g_config.pass,
4538 
4539  smtp_test_sleep(15);
4540 
4541  /* LOGIN - Invalid credentials in (3). */
4544  "invalid",
4545  "invalid",
4548 
4549  smtp_test_sleep(15);
4550 
4551  /* CRAM-MD5 (1) @ref smtp_puts failure. */
4556  g_config.user,
4557  g_config.pass,
4562 
4563  smtp_test_sleep(15);
4564 
4565  /* CRAM-MD5 (1) Response read error. */
4570  g_config.user,
4571  g_config.pass,
4576 
4577  smtp_test_sleep(15);
4578 
4579  /* CRAM-MD5 (1) Response memory allocation error. */
4583  g_config.user,
4584  g_config.pass,
4588 
4589  smtp_test_sleep(15);
4590 
4591  /* CRAM-MD5 (1) Server response bad. */
4595  strcpy(g_smtp_test_err_recv_bytes, "535 authentication failed");
4597  g_config.user,
4598  g_config.pass,
4600  g_smtp_test_err_recv_bytes[0] = '\0';
4604 
4605  smtp_test_sleep(15);
4606 
4607  /* CRAM-MD5 (2) @ref smtp_base64_decode failure. */
4611  g_config.user,
4612  g_config.pass,
4616 
4617  smtp_test_sleep(15);
4618 
4619  /* CRAM-MD5 (3) @ref HMAC failure. */
4623  g_config.user,
4624  g_config.pass,
4628 
4629  smtp_test_sleep(15);
4630 
4631  /* CRAM-MD5 (4) @ref smtp_bin2hex failure. */
4635  g_config.user,
4636  g_config.pass,
4640 
4641  smtp_test_sleep(15);
4642 
4643  /* CRAM-MD5 (5) Wrap in 1st memory calculation. */
4647  g_config.user,
4648  g_config.pass,
4652 
4653  smtp_test_sleep(15);
4654 
4655  /* CRAM-MD5 (5) Wrap in 2nd memory calculation. */
4659  g_config.user,
4660  g_config.pass,
4664 
4665  smtp_test_sleep(15);
4666 
4667  /* CRAM-MD5 (5) Memory allocation failure. */
4671  g_config.user,
4672  g_config.pass,
4676 
4677  smtp_test_sleep(15);
4678 
4679  /* CRAM-MD5 (6) @ref smtp_base64_encode failure. */
4683  g_config.user,
4684  g_config.pass,
4688 
4689  smtp_test_sleep(15);
4690 
4691  /* CRAM-MD5 (7) @ref smtp_puts_terminate failure. */
4696  g_config.user,
4697  g_config.pass,
4702 
4703  smtp_test_sleep(15);
4704 
4705  /* CRAM-MD5 (7) Invalid credentials. */
4708  "invalid",
4709  "invalid",
4712 
4713  smtp_test_sleep(15);
4714 }
4715 
4719 static void
4722  g_config.port,
4726  &g_config.smtp);
4727  assert(g_rc == SMTP_STATUS_OK);
4728 
4732  SMTP_STATUS_OK);
4733 
4737 
4739 }
4740 
4744 static void
4756 }
4757 
4767 static void
4769  int rc;
4770 
4771  rc = smtp_test_config_load_from_file("test/config/postfix.txt");
4772  assert(rc == 0);
4773 
4775 
4776  smtp_test_sleep(60);
4777 
4790 }
4791 
4795 static void
4797  const char *const server = "smtpout.secureserver.net";
4798  const char *port;
4799  enum smtp_connection_security conn_security;
4800  struct smtp *smtp;
4801  unsigned int connection_i;
4802  unsigned int i;
4803 
4804  for(connection_i = 0; connection_i < 2; connection_i++){
4805  if(connection_i == 0){
4806  port = "25";
4807  conn_security = SMTP_SECURITY_STARTTLS;
4808  }
4809  else{
4810  port = "465";
4811  conn_security = SMTP_SECURITY_TLS;
4812  }
4813  for(i = 0; i < 4; i++){
4814  fprintf(stderr, "%s: %s: %u\n", server, port, i + 1);
4815  g_rc = smtp_open(server,
4816  port,
4817  conn_security,
4818  SMTP_DEBUG,
4819  NULL,
4820  &smtp);
4821  assert(g_rc == SMTP_STATUS_OK);
4822 
4823  g_rc = smtp_close(smtp);
4824  assert(g_rc == SMTP_STATUS_OK);
4825 
4826  smtp_test_sleep(1);
4827  }
4828  }
4829 }
4830 
4834 static void
4836  const char *const name = "test.pdf";
4837  const char *const path = "test/test.pdf";
4838 
4839  strcpy(g_config.subject, "SMTP Test: GMail Attachment (file path)");
4840  strcpy(g_config.body, "This email should contain a pdf attachment");
4841 
4843  g_config.port,
4845  SMTP_DEBUG,
4846  NULL,
4847  &g_config.smtp);
4848  assert(g_rc == SMTP_STATUS_OK);
4849 
4851  g_config.user,
4852  g_config.pass,
4853  SMTP_STATUS_OK);
4854 
4858  SMTP_STATUS_OK);
4859 
4863  SMTP_STATUS_OK);
4864 
4865  g_rc = smtp_attachment_add_path(g_config.smtp, name, path);
4866  assert(g_rc == SMTP_STATUS_OK);
4867 
4869 
4871 
4873 }
4874 
4881 static void
4883  int rc;
4884 
4885  rc = smtp_test_config_load_from_file("test/config/gmail.txt");
4886  assert(rc == 0);
4887 
4888  fprintf(stderr, "SMTP TEST: sending test email using gmail account");
4891  SMTP_DEBUG,
4894  "SMTP Test: gmail",
4895  "test email sent through gmail server");
4896 
4898 }
4899 
4903 static void
4908 }
4909 
4918 };
4919 
4923 struct smtp_test{
4927  enum smtp_test_flags flags;
4928 };
4929 
4942 int main(int argc, char *argv[]){
4943  struct smtp_test smtp_test;
4944  int c;
4945 
4946  memset(&smtp_test, 0, sizeof(smtp_test));
4947 
4948  while((c = getopt(argc, argv, "u")) != -1){
4949  switch(c){
4950  case 'u':
4951  smtp_test.flags |= SMTP_TEST_UNIT_TESTING_ONLY;
4952  break;
4953  default:
4954  return 1;
4955  }
4956  }
4957  argc -= optind;
4958  argv += optind;
4959 
4961 
4962  if(!(smtp_test.flags & SMTP_TEST_UNIT_TESTING_ONLY)){
4964  }
4965 
4966  return 0;
4967 }
4968 
SMTP_LINKAGE size_t smtp_strnlen_utf8(const char *s, size_t maxlen)
Definition: smtp.c:1138
static void smtp_func_test_all_cafile(void)
Definition: test.c:2397
int g_smtp_test_err_fclose_ctr
Definition: seams.c:65
#define TMP_FILE_PATH
Definition: test.c:33
enum smtp_status_code smtp_close(struct smtp *smtp)
Definition: smtp.c:3168
static void smtp_unit_test_all_str_getdelimfd(void)
Definition: test.c:1863
const char * smtp_status_code_errstr(enum smtp_status_code status_code)
Definition: smtp.c:3241
int g_smtp_test_err_ssl_read_ctr
Definition: seams.c:194
enum smtp_status_code smtp_status_code_set(struct smtp *const smtp, enum smtp_status_code new_status_code)
Definition: smtp.c:3231
static void smtp_unit_test_base64_encode(const char *const buf, size_t buflen, const char *const expect)
Definition: test.c:703
static char * smtp_str_repeat(const char *const s, size_t n)
Definition: test.c:294
enum smtp_status_code smtp_attachment_add_mem(struct smtp *const smtp, const char *const name, const void *const data, size_t datasz)
Definition: smtp.c:3462
size_t n
Definition: test.c:330
static void smtp_func_test_auth(enum smtp_authentication_method auth_method, const char *const auth_description)
Definition: test.c:2414
static void smtp_unit_test_all_date_rfc_2822(void)
Definition: test.c:1596
int g_smtp_test_err_err_peek_error_ctr
Definition: seams.c:60
static int smtp_str_split(const char *const s, size_t slen, const char *const delimiter, int limit, struct smtp_str_list *slist)
Definition: test.c:403
int g_smtp_test_err_recv_rc
Definition: seams.c:111
static void smtp_func_test_all_address(void)
Definition: test.c:2760
static void smtp_func_test_all_attachments_path(void)
Definition: test.c:2724
static long smtp_unit_test_getdelimfd_fp(struct str_getdelimfd *const gdfd, void *buf, size_t count)
Definition: test.c:1752
static void test_failure_attachment_add(void)
Definition: test.c:3780
enum smtp_result_code code
Definition: smtp.h:531
char cafile[SMTP_MAX_CAFILE_PATH]
Definition: test.c:159
static void smtp_func_test_attachment_mem(size_t num_attachment)
Definition: test.c:2550
SMTP_LINKAGE int smtp_parse_cmd_line(char *const line, struct smtp_command *const cmd)
Definition: smtp.c:1467
static void smtp_unit_test_all_chunk_split(void)
Definition: test.c:1366
SMTP_LINKAGE char * smtp_bin2hex(const unsigned char *const s, size_t slen)
Definition: smtp.c:1031
static void test_failure_header_add(void)
Definition: test.c:3904
static void test_failure_auth(void)
Definition: test.c:4310
static void smtp_func_test_connection_security(const char *const server_port, enum smtp_connection_security con_security, const char *const security_description)
Definition: test.c:2356
#define SMTP_MAX_SERVER_LEN
Definition: test.c:48
static void smtp_func_test_all_html(void)
Definition: test.c:3373
enum smtp_status_code smtp_header_add(struct smtp *const smtp, const char *const key, const char *const value)
Definition: smtp.c:3278
static void smtp_unit_test_all_smtp_address_validate_name(void)
Definition: test.c:1644
#define sprintf
Definition: seams.h:265
static void smtp_unit_test_all(void)
Definition: test.c:2041
#define SIZE_MAX
Definition: smtp.h:23
SMTP_LINKAGE void * smtp_reallocarray(void *ptr, size_t nmemb, size_t size)
Definition: smtp.c:622
char server[SMTP_MAX_SERVER_LEN]
Definition: test.c:154
static enum smtp_status_code g_rc
Definition: test.c:206
static void smtp_unit_test_stpcpy(const char *const init, const char *const s2, const char *const expect)
Definition: test.c:824
static void smtp_unit_test_all_smtp_header_key_validate(void)
Definition: test.c:1673
Test the smtp-client library.
char port_tls[SMTP_MAX_PORT_LEN]
Definition: test.c:169
enum smtp_status_code smtp_mail(struct smtp *const smtp, const char *const body)
Definition: smtp.c:3062
#define SMTP_TEST_DEFAULT_CONNECTION_SECURITY
Definition: test.c:79
SMTP_LINKAGE enum smtp_status_code smtp_write(struct smtp *const smtp, const char *const buf, size_t len)
Definition: smtp.c:1603
SMTP_LINKAGE char * smtp_file_get_contents(const char *const filename, size_t *bytes_read)
Definition: smtp.c:1439
static void smtp_unit_test_fold_whitespace(const char *const s, unsigned int maxlen, const char *const expect)
Definition: test.c:1253
static void smtp_func_test_all_body(void)
Definition: test.c:3150
SMTP_LINKAGE int smtp_header_key_validate(const char *const key)
Definition: smtp.c:2822
static void smtp_unit_test_date_rfc_2822(time_t t, const char *const expect, int expect_rc)
Definition: test.c:1572
static void smtp_unit_test_all_file_get_contents(void)
Definition: test.c:1457
int g_smtp_test_err_close_ctr
Definition: seams.c:49
enum smtp_status_code smtp_attachment_add_path(struct smtp *const smtp, const char *const name, const char *const path)
Definition: smtp.c:3416
#define realloc
Definition: seams.h:161
int g_smtp_test_err_ssl_ctx_new_ctr
Definition: seams.c:166
static void smtp_func_test_all_auth_methods(void)
Definition: test.c:2437
char port[SMTP_MAX_PORT_LEN]
Definition: test.c:164
static void test_failure_mail(void)
Definition: test.c:3984
static void smtp_mail_check(const char *const body, const enum smtp_status_code expect_status)
Definition: test.c:2219
static void smtp_unit_test_chunk_split(const char *const s, size_t chunklen, const char *const end, const char *const expect)
Definition: test.c:1346
static char * smtp_strndup(const char *s, size_t n)
Definition: test.c:269
char email_to_3[SMTP_MAX_EMAIL_LEN]
Definition: test.c:199
int g_smtp_test_err_hmac_ctr
Definition: seams.c:80
SMTP_LINKAGE void smtp_str_getdelimfd_free(struct str_getdelimfd *const gdfd)
Definition: smtp.c:489
int g_smtp_test_err_ssl_new_ctr
Definition: seams.c:189
size_t line_len
Definition: smtp.h:597
static void smtp_unit_test_smtp_status_code_errstr(enum smtp_status_code status_code, const char *const expect)
Definition: test.c:1702
static void smtp_close_check(const enum smtp_status_code expect_status)
Definition: test.c:2231
int more
Definition: smtp.h:539
int g_smtp_test_err_mktime_ctr
Definition: seams.c:96
char ** slist
Definition: test.c:335
smtp_connection_security
Definition: smtp.h:140
static size_t smtp_strlcpy(char *dest, const char *src, size_t destsz)
Definition: test.c:231
char user[SMTP_MAX_EMAIL_LEN]
Definition: test.c:174
#define SMTP_TEST_DEFAULT_TO_NAME
Definition: test.c:108
#define SMTP_MAX_CAFILE_PATH
Definition: test.c:53
#define SMTP_MAX_ATTACHMENT_NAME_LEN
Definition: test.c:73
int g_smtp_test_err_localtime_r_ctr
Definition: seams.c:86
int g_smtp_test_err_ssl_connect_ctr
Definition: seams.c:160
static void smtp_func_test_header_custom_date(void)
Definition: test.c:3020
struct smtp * smtp
Definition: test.c:135
static void smtp_unit_test_all_smtp_status_code_errstr(void)
Definition: test.c:1714
static void smtp_auth_check(const enum smtp_authentication_method auth_method, const char *const user, const char *const pass, const enum smtp_status_code expect_status)
Definition: test.c:2172
static struct smtp_test_config g_config
Definition: test.c:213
static void smtp_test_sleep(unsigned int seconds)
Definition: test.c:553
int g_smtp_test_strlen_custom_ret
Definition: seams.c:214
char pass[SMTP_MAX_PASS_LEN]
Definition: test.c:179
static void smtp_unit_test_strnlen_utf8(const char *s, size_t maxlen, size_t expect)
Definition: test.c:1063
char email_from[SMTP_MAX_EMAIL_LEN]
Definition: test.c:184
int g_smtp_test_err_ssl_get_peer_certificate_ctr
Definition: seams.c:178
static void smtp_unit_test_all_reallocarray(void)
Definition: test.c:895
int g_smtp_test_err_recv_ctr
Definition: seams.c:106
static void smtp_unit_test_all_strdup(void)
Definition: test.c:934
static void test_failure_timeout(void)
Definition: test.c:4720
static void smtp_unit_test_file_get_contents(const char *const s, size_t nbytes, const char *const expect)
Definition: test.c:1437
static void smtp_unit_test_all_base64_encode(void)
Definition: test.c:722
smtp_result_code
Definition: smtp.h:483
void smtp_header_clear_all(struct smtp *const smtp)
Definition: smtp.c:3332
SMTP_LINKAGE int smtp_address_validate_name(const char *const name)
Definition: smtp.c:2903
static void smtp_unit_test_all_base64_decode(void)
Definition: test.c:667
char * line
Definition: smtp.h:592
static void smtp_unit_test_all_stpcpy(void)
Definition: test.c:851
SMTP_LINKAGE int smtp_address_validate_email(const char *const email)
Definition: smtp.c:2878
static void smtp_func_test_server_gmail(void)
Definition: test.c:4882
static void smtp_unit_test_all_smtp_attachment_validate_name(void)
Definition: test.c:1658
int g_smtp_test_err_realloc_ctr
Definition: seams.c:101
int g_smtp_test_err_x509_check_host_ctr
Definition: seams.c:184
static size_t smtp_file_put_contents(const char *const filename, const void *const data, size_t datasz, int flags)
Definition: test.c:512
int g_smtp_test_err_ssl_write_ctr
Definition: seams.c:199
SMTP_LINKAGE char * smtp_base64_encode(const char *const buf, size_t buflen)
Definition: smtp.c:825
char * _buf
Definition: smtp.h:577
static void test_failure_close(void)
Definition: test.c:4261
int g_smtp_test_err_sprintf_ctr
Definition: seams.c:204
static void smtp_unit_test_reallocarray(void *ptr, size_t nmemb, size_t size, int expect_alloc)
Definition: test.c:875
int g_smtp_test_err_si_sub_size_t_ctr
Definition: seams.c:143
static void smtp_func_test_server_postfix(void)
Definition: test.c:4768
enum smtp_status_code smtp_status_code_clear(struct smtp *const smtp)
Definition: smtp.c:3222
static void smtp_str_list_free(struct smtp_str_list *const list)
Definition: test.c:374
void smtp_address_clear_all(struct smtp *const smtp)
Definition: smtp.c:3401
#define SMTP_TEST_DEFAULT_FLAGS
Definition: test.c:91
smtp_status_code
Definition: smtp.h:32
static void smtp_func_test_header_null_no_date(void)
Definition: test.c:3061
static void test_smtp_open_default(void)
Definition: test.c:2244
smtp_test_flags
Definition: test.c:4913
#define SMTP_TEST_DEFAULT_CAFILE
Definition: test.c:98
#define SMTP_TEST_SUBJECT_LEN
Definition: test.c:38
#define SMTP_MAX_PASS_LEN
Definition: test.c:68
#define SMTP_TEST_BODY_LEN
Definition: test.c:43
static int g_smtp_test_getdelimfd_fp_fail
Definition: test.c:1740
static void smtp_unit_test_all_fold_whitespace(void)
Definition: test.c:1272
static void smtp_unit_test_all_smtp_address_validate_email(void)
Definition: test.c:1630
int g_smtp_test_err_bio_should_retry_rc
Definition: seams.c:39
static void test_failure_open(void)
Definition: test.c:3413
int g_smtp_test_err_ferror_ctr
Definition: seams.c:70
static void smtp_unit_test_all_strnlen_utf8(void)
Definition: test.c:1076
smtp_authentication_method
Definition: smtp.h:170
SMTP_LINKAGE int smtp_date_rfc_2822(char *const date)
Definition: smtp.c:2236
SMTP_LINKAGE int smtp_str_has_nonascii_utf8(const char *const s)
Definition: smtp.c:1110
static void smtp_unit_test_si_size_t(int(*si_fp)(const size_t a, const size_t b, size_t *const result), size_t a, size_t b, size_t *result, size_t expect_result, int expect_wrap)
Definition: test.c:570
static void smtp_unit_test_strdup(const char *const s, const char *const expect)
Definition: test.c:916
static void smtp_unit_test_base64_decode(const char *const buf, const char *const expect_str, size_t expect_str_len)
Definition: test.c:646
#define SMTP_TEST_DEFAULT_CC_NAME
Definition: test.c:113
int g_smtp_test_err_gmtime_r_ctr
Definition: seams.c:75
char email_to[SMTP_MAX_EMAIL_LEN]
Definition: test.c:189
SMTP_LINKAGE size_t smtp_fold_whitespace_get_offset(const char *const s, unsigned int maxlen)
Definition: smtp.c:1179
size_t g_smtp_test_strlen_ret_value
Definition: seams.c:219
static void smtp_func_test_all_attachments(void)
Definition: test.c:2750
#define SMTP_MAX_PORT_LEN
Definition: test.c:58
int g_smtp_test_err_bio_new_socket_ctr
Definition: seams.c:28
static void smtp_func_test_all_headers(void)
Definition: test.c:3140
#define malloc
Definition: seams.h:145
enum smtp_status_code smtp_address_add(struct smtp *const smtp, enum smtp_address_type type, const char *const email, const char *const name)
Definition: smtp.c:3347
void * user_data
Definition: smtp.h:615
#define STR_ALPHABET_LOWERCASE
Definition: test.c:123
static void smtp_func_test_server_secureserver(void)
Definition: test.c:4796
static void smtp_func_test_send_email(const char *const port, enum smtp_connection_security connection_security, enum smtp_flag flags, enum smtp_authentication_method auth_method, const char *const cafile, const char *const subject, const char *const body)
Definition: test.c:2314
SMTP_LINKAGE size_t smtp_base64_decode(const char *const buf, unsigned char **decode)
Definition: smtp.c:984
#define SMTP_TEST_DEFAULT_AUTH_METHOD
Definition: test.c:85
static void smtp_func_test_all(void)
Definition: test.c:4904
SMTP_LINKAGE int smtp_si_sub_size_t(const size_t a, const size_t b, size_t *const result)
Definition: smtp.c:286
SMTP_LINKAGE size_t smtp_utf8_charlen(char c)
Definition: smtp.c:1078
static void smtp_unit_test_all_fold_whitespace_get_offset(void)
Definition: test.c:1137
static void smtp_func_test_all_status_code_get(void)
Definition: test.c:2279
static size_t smtp_ffile_put_contents(FILE *stream, const void *const data, size_t datasz)
Definition: test.c:474
static void smtp_unit_test_all_si(void)
Definition: test.c:591
int g_smtp_test_send_one_byte
Definition: seams.c:131
char g_smtp_test_err_recv_bytes[90]
Definition: seams.c:116
static void smtp_func_test_all_write(void)
Definition: test.c:3189
static void test_failure_misc(void)
Definition: test.c:3383
#define SMTP_MAX_EMAIL_LEN
Definition: test.c:63
int g_smtp_test_err_si_add_size_t_ctr
Definition: seams.c:137
int g_smtp_test_err_malloc_ctr
Definition: seams.c:91
#define strlen
Definition: seams.h:273
SMTP_LINKAGE int smtp_header_value_validate(const char *const value)
Definition: smtp.c:2852
static void smtp_func_test_gmail_attachment(void)
Definition: test.c:4835
Definition: smtp.c:150
static void smtp_func_test_all_attachments_mem(void)
Definition: test.c:2707
smtp_flag
Definition: smtp.h:198
SMTP_LINKAGE int smtp_si_mul_size_t(const size_t a, const size_t b, size_t *const result)
Definition: smtp.c:320
int g_smtp_test_time_custom_ret
Definition: seams.c:224
char subject[SMTP_TEST_SUBJECT_LEN]
Definition: test.c:140
static void smtp_func_test_all_attachments_fp(void)
Definition: test.c:2740
static void smtp_unit_test_all_smtp_str_has_nonascii_utf8(void)
Definition: test.c:1047
static int smtp_str_list_append(struct smtp_str_list *const slist, const char *const s, size_t n)
Definition: test.c:348
str_getdelim_retcode
Definition: smtp.h:551
enum smtp_status_code smtp_auth(struct smtp *const smtp, enum smtp_authentication_method auth_method, const char *const user, const char *const pass)
Definition: smtp.c:3026
static void smtp_func_test_html(void)
Definition: test.c:3241
SMTP_LINKAGE char * smtp_str_replace(const char *const search, const char *const replace, const char *const s)
Definition: smtp.c:679
int g_smtp_test_err_select_ctr
Definition: seams.c:121
#define SMTP_TEST_DEFAULT_BCC_NAME
Definition: test.c:118
SMTP_LINKAGE int smtp_attachment_validate_name(const char *const name)
Definition: smtp.c:2927
static void smtp_unit_test_all_bin2hex(void)
Definition: test.c:778
static void smtp_func_test_all_nodebug(void)
Definition: test.c:3206
static void smtp_address_add_check(const enum smtp_address_type type, const char *const email, const char *const name, const enum smtp_status_code expect_status)
Definition: test.c:2189
int g_smtp_test_err_connect_ctr
Definition: seams.c:54
static void smtp_unit_test_str_replace(const char *const search, const char *const replace, const char *const s, const char *const expect)
Definition: test.c:961
static void smtp_func_test_html_with_plaintext(void)
Definition: test.c:3303
int g_smtp_test_err_si_mul_size_t_ctr
Definition: seams.c:149
const char * text
Definition: smtp.h:544
static void smtp_unit_test_all_smtp_utf8_charlen(void)
Definition: test.c:1028
SMTP_LINKAGE char * smtp_stpcpy(char *s1, const char *s2)
Definition: smtp.c:599
SMTP_LINKAGE int smtp_si_add_size_t(const size_t a, const size_t b, size_t *const result)
Definition: smtp.c:252
static void smtp_func_test_attachment_pdf(const size_t num_attachments)
Definition: test.c:2610
static int smtp_test_config_load_from_file(const char *const config_path)
Definition: test.c:2082
static void smtp_unit_test_fold_whitespace_get_offset(const char *const s, unsigned int maxlen, size_t expect)
Definition: test.c:1124
int g_smtp_test_err_sprintf_rc
Definition: seams.c:209
#define fclose
Definition: seams.h:105
static void smtp_unit_test_getdelimfd_set_line_and_buf(struct str_getdelimfd *const gdfd, size_t copy_len, int expect_result)
Definition: test.c:1850
static void smtp_unit_test_bin2hex(const char *const s, size_t slen, const char *const expect)
Definition: test.c:759
SMTP_LINKAGE char * smtp_fold_whitespace(const char *const s, unsigned int maxlen)
Definition: smtp.c:1250
static void test_failure_status_code_set(void)
Definition: test.c:3956
SMTP_LINKAGE enum str_getdelim_retcode smtp_str_getdelimfd(struct str_getdelimfd *const gdfd)
Definition: smtp.c:523
static void smtp_func_test_header_long(void)
Definition: test.c:3098
enum smtp_status_code smtp_attachment_add_fp(struct smtp *const smtp, const char *const name, FILE *fp)
Definition: smtp.c:3439
enum smtp_status_code smtp_status_code_get(const struct smtp *const smtp)
Definition: smtp.c:3217
static void smtp_unit_test_parse_cmd_line(const char *const line, enum smtp_result_code expect_code, int expect_more, const char *const expect_text)
Definition: test.c:1509
static void smtp_func_test_attachment_path(const char *const name, const char *const path, enum smtp_status_code expect_rc)
Definition: test.c:2453
SMTP_LINKAGE int smtp_str_getdelimfd_set_line_and_buf(struct str_getdelimfd *const gdfd, size_t copy_len)
Definition: smtp.c:457
SMTP_LINKAGE char * smtp_chunk_split(const char *const s, size_t chunklen, const char *const end)
Definition: smtp.c:1312
static void smtp_func_test_all_names(void)
Definition: test.c:2895
SMTP_LINKAGE char * smtp_strdup(const char *s)
Definition: smtp.c:650
char email_to_2[SMTP_MAX_EMAIL_LEN]
Definition: test.c:194
int delim
Definition: smtp.h:620
static void smtp_func_test_attachment_long_text(void)
Definition: test.c:2657
int g_smtp_test_err_send_ctr
Definition: seams.c:126
int g_smtp_test_err_bio_should_retry_ctr
Definition: seams.c:34
static void smtp_unit_test_all_str_replace(void)
Definition: test.c:981
int g_smtp_test_err_ssl_do_handshake_ctr
Definition: seams.c:172
static void test_all_failure_modes(void)
Definition: test.c:4745
static void smtp_header_add_check(const char *const key, const char *const value, const enum smtp_status_code expect_status)
Definition: test.c:2205
int g_smtp_test_err_socket_ctr
Definition: seams.c:154
int main(int argc, char *argv[])
Definition: test.c:4942
#define SMTP_TEST_DEFAULT_FROM_NAME
Definition: test.c:103
enum smtp_status_code smtp_open(const char *const server, const char *const port, enum smtp_connection_security connection_security, enum smtp_flag flags, const char *const cafile, struct smtp **smtp)
Definition: smtp.c:2987
static void smtp_func_test_attachment_fp(const char *const name, const char *const path, enum smtp_status_code expect_rc)
Definition: test.c:2501
static void test_failure_address_add(void)
Definition: test.c:3706
static void smtp_func_test_all_connection_security(void)
Definition: test.c:2380
static void smtp_unit_test_all_parse_cmd_line(void)
Definition: test.c:1533
time_t g_smtp_test_time_ret_value
Definition: seams.c:229
static void smtp_unit_test_str_getdelimfd(const char *const input_string, size_t nbytes, int delim, enum str_getdelim_retcode expect_rc, int null_fp, const char *expect_pieces,...)
Definition: test.c:1778
long(* getdelimfd_read)(struct str_getdelimfd *const gdfd, void *buf, size_t count)
Definition: smtp.h:608
char body[SMTP_TEST_BODY_LEN]
Definition: test.c:145
smtp_address_type
Definition: smtp.h:105
enum smtp_test_flags flags
Definition: test.c:4927
static void smtp_unit_test_all_smtp_header_value_validate(void)
Definition: test.c:1687
int g_smtp_test_err_calloc_ctr
Definition: seams.c:44