25 #if defined(_WIN32) || defined(WIN32) 26 # define SMTP_IS_WINDOWS 29 #ifdef SMTP_IS_WINDOWS 30 # include <winsock2.h> 31 # include <ws2tcpip.h> 33 # include <netinet/in.h> 34 # include <sys/select.h> 35 # include <sys/socket.h> 49 # include <openssl/bio.h> 50 # include <openssl/err.h> 51 # include <openssl/ssl.h> 52 # include <openssl/x509.h> 53 # include <openssl/x509v3.h> 59 #define SMTP_INTERNAL_DEFINE 74 # define SMTP_LINKAGE extern 75 # include "../test/seams.h" 81 # define SMTP_LINKAGE static 88 #define SMTP_GETDELIM_READ_SZ 1000 254 size_t *
const result){
288 size_t *
const result){
322 size_t *
const result){
354 struct timeval timeout;
358 FD_SET(smtp->
sock, &readfds);
361 sel_rc =
select(smtp->
sock + 1, &readfds, NULL, NULL, &timeout);
407 bytes_read =
recv(smtp->
sock, buf, count, 0);
434 size_t *
const delim_pos){
438 for(i = 0; i < buf_len; i++){
460 size_t nbytes_to_shift;
471 (gdfd->
line =
calloc(1, copy_len_inc)) == NULL){
474 memcpy(gdfd->
line, gdfd->
_buf, copy_len);
476 memmove(gdfd->
_buf, gdfd->
_buf + copy_len_inc, nbytes_to_shift);
528 size_t buf_sz_remaining;
546 }
else if(bytes_read == 0){
567 gdfd->
_buf = buf_new;
568 gdfd->
_bufsz = buf_sz_new;
606 }
while(s2[i++] !=
'\0');
633 alloc =
realloc(ptr, size_mul);
660 else if((dup =
malloc(dup_len)) != NULL){
661 memcpy(dup, s, dup_len);
680 const char *
const replace,
681 const char *
const s){
684 size_t replace_len_inc;
692 size_t snew_sz_plus_slen;
693 size_t snew_replace_len_inc;
697 search_len =
strlen(search);
698 replace_len =
strlen(replace);
713 else if(search_len < 1){
725 if(strncmp(&s[s_idx], search, search_len) == 0){
730 if(snew_replace_len_inc >= snew_sz){
734 (stmp =
realloc(snew, snew_sz)) == NULL){
740 memcpy(&snew[snew_len], replace, replace_len);
741 snew_len += replace_len;
745 if(snew_len_inc >= snew_sz){
749 (stmp =
realloc(snew, snew_sz)) == NULL){
755 snew[snew_len] = s[s_idx];
757 snew_len = snew_len_inc;
760 snew[snew_len] =
'\0';
773 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
774 'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
775 'U',
'V',
'W',
'X',
'Y',
'Z',
776 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
777 'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
778 'u',
'v',
'w',
'x',
'y',
'z',
779 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
795 unsigned char inb[3] = {0};
796 unsigned char in_idx[4] = {0};
797 char outb[5] = {
'=',
'=',
'=',
'=',
'\0'};
800 memcpy(inb, buf, buf_block_sz);
802 in_idx[0] = ((inb[0] >> 2)) & 0x3F;
803 in_idx[1] = ((inb[0] << 4) | ((inb[1] >> 4) & 0xF)) & 0x3F;
804 in_idx[2] = ((inb[1] << 2) | ((inb[2] >> 6) & 0x3)) & 0x3F;
805 in_idx[3] = ((inb[2] )) & 0x3F;
806 for(i = 0; i < 4; i++){
807 if(i < buf_block_sz + 1){
831 size_t remaining_block_sz;
847 b64_sz = (4 * buflen / 3) + 1 + 2 + 1;
848 if((b64 =
calloc(1, b64_sz)) == NULL){
858 remaining_block_sz = buflen;
859 while(remaining_block_sz > 0){
860 if(remaining_block_sz >= 3){
864 buf_block_sz = remaining_block_sz;
876 remaining_block_sz -= buf_block_sz;
895 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
896 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
897 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
898 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
903 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
904 -1, -1, -1, -1, -1, -1, -1,
905 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
906 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
907 20, 21, 22, 23, 24, 25,
908 -1, -1, -1, -1, -1, -1,
909 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
910 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
911 46, 47, 48, 49, 50, 51,
925 unsigned char *
const decode){
926 size_t decode_block_len;
928 signed char decode_table[4];
929 unsigned char outb[3];
931 decode_block_len = 0;
932 for(i = 0; i < 4; i++){
938 if(decode_table[i] < 0){
943 outb[0] = ((decode_table[0] << 2) & 0xFC) | ((decode_table[1] >> 4) & 0x03);
944 outb[1] = ((decode_table[1] << 4) & 0xF0) | ((decode_table[2] >> 2) & 0x0F);
945 outb[2] = ((decode_table[2] << 6) & 0xC0) | ((decode_table[3] ) & 0x3F);
948 decode_block_len += 1;
955 decode_block_len += 1;
963 decode_block_len += 1;
966 return decode_block_len;
985 unsigned char **decode){
989 unsigned char *b64_decode;
991 size_t decode_block_len;
996 if(buf_len % 4 != 0){
1001 (b64_decode =
calloc(1, buf_len_inc)) == NULL){
1006 for(buf_i = 0; buf_i < buf_len; buf_i += 4){
1008 (
const unsigned char*)&buf[buf_i],
1009 &b64_decode[decode_len]);
1010 if(decode_block_len == 0){
1014 decode_len += decode_block_len;
1016 *decode = b64_decode;
1045 if((snew =
malloc(alloc_sz)) == NULL){
1050 for(i = 0; i < slen; i++){
1052 rc =
sprintf(&snew[j],
"%02x", hex);
1053 if(rc < 0 || (
size_t)rc >= 3){
1081 uc = (
unsigned char)c;
1082 if((uc & 0x80) == 0){
1085 else if((uc & 0xE0) == 0xC0){
1088 else if((uc & 0xF0) == 0xE0){
1091 else if((uc & 0xF8) == 0xF0){
1114 for(i = 0; s[i]; i++){
1144 for(i = 0; *s && i < maxlen; i += utf8_len){
1150 for(utf8_i = 0; utf8_i < utf8_len; utf8_i++){
1180 unsigned int maxlen){
1187 while(s[i] ==
' ' || s[i] ==
'\t'){
1192 if(s[i] ==
' ' || s[i] ==
'\t'){
1195 }
while(s[i] ==
' ' || s[i] ==
'\t');
1197 if(i < maxlen || !offset_i){
1207 if(!offset_i || i < maxlen){
1218 #define SMTP_LINE_MAX 78 1251 unsigned int maxlen){
1252 const char *
const SMTP_LINE_FOLD_STR =
"\r\n ";
1265 end_slen =
strlen(SMTP_LINE_FOLD_STR);
1279 (buf_new =
realloc(buf, bufsz)) == NULL){
1284 memcpy(&buf[buf_i], &s[s_i], ws_offset);
1285 buf[buf_i + ws_offset] =
'\0';
1287 if(s[s_i + ws_offset] ==
'\0'){
1292 strcat(&buf[buf_i], SMTP_LINE_FOLD_STR);
1296 s_i += ws_offset + 1;
1314 const char *
const end){
1324 size_t body_copy_len;
1346 (snew =
calloc(1, snewlen)) == NULL){
1352 for(chunk_i = 0; chunk_i < bodylen / chunklen + 1; chunk_i++){
1358 memcpy(&snew[snew_i], &s[body_i], body_copy_len);
1359 snew_i += body_copy_len;
1360 if(s[body_i] ==
'\0'){
1363 body_i += body_copy_len;
1366 memcpy(&snew[snew_i], end, endlen);
1387 size_t *bytes_read){
1392 size_t bytes_read_loop;
1393 const size_t BUFSZ_INCREMENT = 512;
1404 (new_buf =
realloc(read_buf, bufsz_inc)) == NULL){
1411 bytes_read_loop = fread(&read_buf[bufsz - BUFSZ_INCREMENT],
1416 *bytes_read += bytes_read_loop;
1422 }
while(!feof(stream));
1440 size_t *bytes_read){
1444 if((fp = fopen(filename,
"rb")) == NULL){
1472 unsigned long int ulcode;
1482 cmd->
text = &line[4];
1484 memcpy(code_str, line, 3);
1486 ulcode = strtoul(code_str, &ep, 10);
1513 const char *
const prefix,
1514 const char *
const str){
1524 for(i = 0; sdup[i]; i++){
1525 if(sdup[i] ==
'\r' || sdup[i] ==
'\n'){
1530 if(fprintf(stderr,
"[smtp %s]: %s\n", prefix, sdup) < 0){
1549 if(errno == ENOMEM){
1604 const char *
const buf,
1606 size_t bytes_to_send;
1608 const char *buf_offset;
1609 int ssl_bytes_to_send;
1613 bytes_to_send = len;
1615 while(bytes_to_send){
1616 if(bytes_to_send > INT_MAX){
1623 ssl_bytes_to_send = (int)bytes_to_send;
1624 bytes_sent =
SSL_write(smtp->
tls, buf_offset, ssl_bytes_to_send);
1625 if(bytes_sent <= 0){
1631 (void)ssl_bytes_to_send;
1635 bytes_sent =
send(smtp->
sock, buf_offset, bytes_to_send, 0);
1640 bytes_to_send -= (size_t)bytes_sent;
1641 buf_offset += bytes_sent;
1656 const char *
const s){
1670 const char *
const s){
1679 (line =
malloc(allocsz)) == NULL){
1704 const char *
const server,
1705 const char *
const port){
1706 struct addrinfo hints;
1707 struct addrinfo *res0;
1708 struct addrinfo *res;
1714 #ifdef SMTP_IS_WINDOWS 1717 if(WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0){
1722 memset(&hints, 0,
sizeof(hints));
1723 hints.ai_family = AF_UNSPEC;
1724 hints.ai_socktype = SOCK_STREAM;
1726 hints.ai_protocol = IPPROTO_TCP;
1728 if(getaddrinfo(server, port, &hints, &res0) != 0){
1732 for(res = res0; res; res = res->ai_next){
1733 smtp->
sock =
socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1738 if(
connect(smtp->
sock, res->ai_addr, res->ai_addrlen) < 0){
1739 #ifdef SMTP_IS_WINDOWS 1740 closesocket(smtp->
sock);
1771 const char *
const server){
1772 X509 *X509_cert_peer;
1777 SSL_load_error_strings();
1778 ERR_load_BIO_strings();
1779 OpenSSL_add_all_algorithms();
1786 SSL_CTX_set_options(smtp->
tls_ctx,
1791 SSL_CTX_set_mode(smtp->
tls_ctx, SSL_MODE_AUTO_RETRY);
1793 SSL_CTX_set_verify(smtp->
tls_ctx, SSL_VERIFY_PEER, NULL);
1801 if(SSL_CTX_load_verify_locations(smtp->
tls_ctx, smtp->
cafile, NULL) != 1){
1807 X509_STORE_set_default_paths(SSL_CTX_get_cert_store(smtp->
tls_ctx));
1821 SSL_free(smtp->
tls);
1826 SSL_set_connect_state(smtp->
tls);
1829 SSL_free(smtp->
tls);
1835 SSL_free(smtp->
tls);
1843 SSL_free(smtp->
tls);
1848 SSL_free(smtp->
tls);
1851 X509_free(X509_cert_peer);
1894 const char *
const user,
1895 const char *
const pass){
1901 size_t login_b64_len;
1911 (login_str =
malloc(login_len)) == NULL){
1914 login_str[0] =
'\0';
1915 memcpy(&login_str[1], user, user_len);
1916 login_str[1 + user_len] =
'\0';
1917 memcpy(&login_str[1 + user_len + 1], pass, pass_len);
1922 if(login_b64 == NULL){
1927 login_b64_len =
strlen(login_b64);
1929 (login_send =
malloc(login_b64_len)) == NULL){
1967 const char *
const user,
1968 const char *
const pass){
1971 size_t b64_user_len;
1981 b64_user_len =
strlen(b64_user);
1983 (login_str =
malloc(b64_user_len)) == NULL){
2038 const char *
const user,
2039 const char *
const pass){
2041 unsigned char *challenge_decoded;
2042 size_t challenge_decoded_len;
2045 unsigned char hmac[EVP_MAX_MD_SIZE];
2046 unsigned int hmac_len;
2047 unsigned char *hmac_ret;
2048 char *challenge_hex;
2050 size_t challenge_hex_len;
2053 size_t auth_concat_len;
2069 &challenge_decoded);
2070 if(challenge_decoded_len ==
SIZE_MAX){
2076 key_len = (int)
strlen(pass);
2077 hmac_ret =
HMAC(EVP_md5(),
2081 challenge_decoded_len,
2084 free(challenge_decoded);
2085 if(hmac_ret == NULL){
2091 if(challenge_hex == NULL){
2097 challenge_hex_len =
strlen(challenge_hex);
2101 (auth_concat =
malloc(auth_concat_len)) == NULL){
2102 free(challenge_hex);
2108 free(challenge_hex);
2113 if(b64_auth == NULL){
2162 const char *
const server,
2166 (void)connection_security;
2222 #define SMTP_DATE_MAX_SZ (32 + 15) 2243 double diff_local_utc;
2246 const char weekday_abbreviation[7][4] = {
2247 "Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat" 2250 const char month_abbreviation[12][4] = {
2251 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
2252 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" 2255 if((t =
time(NULL)) == (time_t)(-1)){
2259 #ifdef SMTP_IS_WINDOWS 2260 if(localtime_s(&tm_local, &t) ||
2261 gmtime_s(&tm_utc, &t)){
2266 # ifdef SMTP_TIME_NO_REENTRANT 2270 if((tm = localtime(&t)) == NULL){
2273 memcpy(&tm_local, tm,
sizeof(tm_local));
2276 if((tm = gmtime(&t)) == NULL){
2279 memcpy(&tm_utc, tm,
sizeof(tm_utc));
2288 if((t_local =
mktime(&tm_local)) == (time_t)(-1)){
2292 if((t_utc =
mktime(&tm_utc)) == (time_t)(-1)){
2301 diff_local_utc = difftime(t_local, t_utc);
2302 offset_utc = (long)diff_local_utc;
2303 offset_utc = offset_utc / 60 / 60 * 100;
2306 "%s, %02d %s %d %02d:%02d:%02d %0+5ld",
2307 weekday_abbreviation[tm_local.tm_wday],
2309 month_abbreviation[tm_local.tm_mon],
2310 tm_local.tm_year + 1900,
2334 const void *
const v2){
2340 return strcmp(key, header2->
key);
2353 const char *
const key){
2370 #define SMTP_MIME_BOUNDARY_LEN 15 2390 seed = (
unsigned int)
time(NULL);
2393 strcpy(boundary,
"mime");
2396 boundary[i] = rand() % 26 +
'A';
2398 boundary[SMTP_MIME_BOUNDARY_LEN - 1] =
'\0';
2412 const char *
const boundary,
2413 const char *
const body_dd){
2415 const size_t MIME_TEXT_BUFSZ = 1000;
2416 size_t data_double_dot_len;
2417 char *data_header_and_body;
2420 data_double_dot_len =
strlen(body_dd);
2423 &data_double_dot_len) ||
2424 (data_header_and_body =
malloc(data_double_dot_len)) == NULL){
2429 "MIME-Version: 1.0\r\n" 2430 "Content-Type: multipart/mixed; boundary=");
2436 "Multipart MIME message.\r\n" 2442 "Content-Type: text/plain; charset=\"UTF-8\"\r\n" 2451 free(data_header_and_body);
2465 const char *
const boundary,
2468 const size_t MIME_TEXT_BUFSZ = 1000;
2470 size_t b64_data_len;
2472 char *mime_attach_text;
2484 (mime_attach_text =
malloc(bufsz)) == NULL){
2494 "Content-Type: application/octet-stream\r\n" 2495 "Content-Disposition: attachment; filename=\"");
2500 "Content-Transfer-Encoding: base64\r\n" 2508 free(mime_attach_text);
2522 const char *
const boundary){
2544 const char *
const body_dd){
2577 const char *
const body_dd){
2590 const char *
const body){
2591 char *body_double_dot;
2608 free(body_double_dot);
2629 char *header_concat;
2633 if(header->
value == NULL){
2643 (header_concat =
malloc(concat_len)) == NULL){
2651 free(header_concat);
2652 if(header_fmt == NULL){
2676 const char *
const key){
2678 size_t num_address_in_header;
2679 size_t header_value_sz;
2685 char *header_value_new;
2688 num_address_in_header = 0;
2689 header_value_sz = 0;
2690 header_value = NULL;
2694 if(address->
type == address_type){
2708 (header_value_new =
realloc(header_value,
2709 header_value_sz)) == NULL){
2713 header_value = header_value_new;
2714 concat = header_value + concat_len;
2715 if(num_address_in_header > 0){
2727 num_address_in_header += 1;
2728 concat_len = (size_t)(concat - header_value);
2753 const char *
const header,
2755 const char *
const SMTPUTF8 =
" SMTPUTF8";
2756 const size_t SMTPUTF8_LEN =
strlen(SMTPUTF8);
2759 char *envelope_address;
2761 const char *smtputf8_opt;
2767 (envelope_address =
malloc(bufsz)) == NULL){
2773 smtputf8_opt = SMTPUTF8;
2783 free(envelope_address);
2809 return strcmp(header1->
key, header2->
key);
2832 for(i = 0; i < keylen; i++){
2833 uc = (
unsigned char)key[i];
2834 if(uc <= ' ' || uc > 126 || uc ==
':'){
2856 for(i = 0; value[i]; i++){
2857 uc = (
unsigned char)value[i];
2858 if((uc < ' ' || uc > 126) &&
2882 for(i = 0; email[i]; i++){
2883 uc = (
unsigned char)email[i];
2884 if(uc <=
' ' || uc == 127 ||
2885 uc ==
'<' || uc ==
'>'){
2907 for(i = 0; name[i]; i++){
2908 uc = (
unsigned char)name[i];
2909 if(uc <
' ' || uc == 127 || uc ==
'\"'){
2931 for(i = 0; name[i]; i++){
2932 uc = (
unsigned char)name[i];
2933 if(uc <
' ' || uc == 127 ||
2934 uc ==
'\'' || uc ==
'\"'){
2945 #define SMTP_FLAG_INVALID_MEMORY (enum smtp_flag)(0xFFFFFFFF) 2988 const char *
const port,
2991 const char *
const cafile,
2995 if((snew =
calloc(1,
sizeof(**smtp))) == NULL){
3008 #ifndef SMTP_IS_WINDOWS 3009 signal(SIGPIPE, SIG_IGN);
3028 const char *
const user,
3029 const char *
const pass){
3063 const char *
const body){
3177 if(smtp->
sock != -1){
3187 SSL_free(smtp->
tls);
3192 #ifdef SMTP_IS_WINDOWS 3193 closesocket(smtp->
sock);
3242 const char *
const status_code_err_str[] = {
3246 "Memory allocation failed",
3248 "Failed to connect to the mail server",
3250 "Failed to handshake or negotiate a TLS connection with the server",
3252 "Failed to authenticate with the given credentials",
3254 "Failed to send bytes to the server",
3256 "Failed to receive bytes from the server",
3258 "Failed to properly close a connection",
3260 "SMTP server sent back an unexpected status code",
3262 "Invalid parameter",
3264 "Failed to read or open a local file",
3266 "Failed to get the local date and time",
3274 return status_code_err_str[status_code];
3279 const char *
const key,
3280 const char *
const value){
3283 size_t num_headers_inc;
3312 new_header->
value = NULL;
3314 if(new_header->
key == NULL ||
3315 (new_header->
value == NULL && value)){
3316 free(new_header->
key);
3317 free(new_header->
value);
3339 free(header->
value);
3349 const char *
const email,
3350 const char *
const name){
3353 size_t num_address_inc;
3373 sizeof(*new_address_list));
3374 if(new_address_list == NULL){
3377 new_address = &new_address_list[smtp->
num_address];
3387 new_address->
name = NULL;
3389 if(new_address->
email == NULL ||
3390 (new_address->
name == NULL && name)){
3391 free(new_address->
email);
3392 free(new_address->
name);
3407 free(address->
email);
3408 free(address->
name);
3417 const char *
const name,
3418 const char *
const path){
3428 if(errno == ENOMEM){
3440 const char *
const name,
3451 if(errno == ENOMEM){
3463 const char *
const name,
3464 const void *
const data,
3466 size_t num_attachment_inc;
3487 sizeof(*new_attachment_list))) == NULL){
3495 if(new_attachment->
name == NULL || b64_encode == NULL){
3496 free(new_attachment->
name);
3505 if(new_attachment->
b64_data == NULL){
3506 free(new_attachment->
name);
3521 free(attachment->
name);
SMTP_LINKAGE size_t smtp_strnlen_utf8(const char *s, size_t maxlen)
static enum smtp_status_code smtp_print_nomime_email(struct smtp *const smtp, const char *const body_dd)
#define SMTP_GETDELIM_READ_SZ
enum smtp_status_code smtp_status_code_clear(struct smtp *const smtp)
enum smtp_address_type type
struct smtp_address * address_list
static enum str_getdelim_retcode smtp_getline(struct smtp *const smtp)
static size_t smtp_base64_decode_block(const unsigned char *const buf, unsigned char *const decode)
enum smtp_status_code smtp_close(struct smtp *smtp)
enum smtp_status_code smtp_address_add(struct smtp *const smtp, enum smtp_address_type type, const char *const email, const char *const name)
enum smtp_result_code code
SMTP_LINKAGE int smtp_parse_cmd_line(char *const line, struct smtp_command *const cmd)
SMTP_LINKAGE char * smtp_bin2hex(const unsigned char *const s, size_t slen)
static int smtp_auth_cram_md5(struct smtp *const smtp, const char *const user, const char *const pass)
#define SMTP_FLAG_INVALID_MEMORY
struct str_getdelimfd gdfd
#define SMTP_MIME_BOUNDARY_LEN
enum smtp_status_code smtp_attachment_add_fp(struct smtp *const smtp, const char *const name, FILE *fp)
void smtp_address_clear_all(struct smtp *const smtp)
enum smtp_status_code smtp_status_code_get(const struct smtp *const smtp)
SMTP_LINKAGE void * smtp_reallocarray(void *ptr, size_t nmemb, size_t size)
static int smtp_header_exists(const struct smtp *const smtp, const char *const key)
SMTP_LINKAGE enum smtp_status_code smtp_write(struct smtp *const smtp, const char *const buf, size_t len)
SMTP_LINKAGE char * smtp_file_get_contents(const char *const filename, size_t *bytes_read)
static long smtp_str_getdelimfd_read(struct str_getdelimfd *const gdfd, void *buf, size_t count)
SMTP_LINKAGE char * smtp_ffile_get_contents(FILE *stream, size_t *bytes_read)
SMTP_LINKAGE int smtp_header_key_validate(const char *const key)
static enum smtp_status_code smtp_print_header(struct smtp *const smtp, const struct smtp_header *const header)
struct smtp_attachment * attachment_list
SMTP_LINKAGE void smtp_str_getdelimfd_free(struct str_getdelimfd *const gdfd)
static enum smtp_status_code smtp_puts(struct smtp *const smtp, const char *const s)
enum smtp_status_code smtp_attachment_add_path(struct smtp *const smtp, const char *const name, const char *const path)
static int smtp_read_and_parse_code(struct smtp *const smtp)
static enum smtp_status_code smtp_mail_envelope_header(struct smtp *const smtp, const char *const header, const struct smtp_address *const address)
static struct smtp g_smtp_error
static void smtp_base64_encode_block(const char *const buf, size_t buf_block_sz, char *const b64)
static int smtp_str_getdelimfd_search_delim(const char *const buf, size_t buf_len, int delim, size_t *const delim_pos)
SMTP_LINKAGE int smtp_address_validate_name(const char *const name)
static enum smtp_status_code smtp_print_mime_attachment(struct smtp *const smtp, const char *const boundary, const struct smtp_attachment *const attachment)
SMTP_LINKAGE int smtp_address_validate_email(const char *const email)
static int smtp_connect(struct smtp *const smtp, const char *const server, const char *const port)
#define SSL_get_peer_certificate
SMTP_LINKAGE char * smtp_base64_encode(const char *const buf, size_t buflen)
void smtp_header_clear_all(struct smtp *const smtp)
int g_smtp_test_err_si_sub_size_t_ctr
static enum smtp_status_code smtp_print_mime_header_and_body(struct smtp *const smtp, const char *const boundary, const char *const body_dd)
static enum smtp_status_code smtp_initiate_handshake(struct smtp *const smtp, const char *const server, enum smtp_connection_security connection_security)
enum smtp_status_code smtp_mail(struct smtp *const smtp, const char *const body)
static void smtp_gen_mime_boundary(char *const boundary)
struct smtp_header * header_list
enum smtp_status_code smtp_attachment_add_mem(struct smtp *const smtp, const char *const name, const void *const data, size_t datasz)
static enum smtp_status_code smtp_append_address_to_header(struct smtp *const smtp, enum smtp_address_type address_type, const char *const key)
smtp_authentication_method
SMTP_LINKAGE int smtp_date_rfc_2822(char *const date)
static int smtp_auth_plain(struct smtp *const smtp, const char *const user, const char *const pass)
SMTP_LINKAGE int smtp_str_has_nonascii_utf8(const char *const s)
SMTP_LINKAGE size_t smtp_fold_whitespace_get_offset(const char *const s, unsigned int maxlen)
static void smtp_set_read_timeout(struct smtp *const smtp, long seconds)
static enum smtp_status_code smtp_print_mime_end(struct smtp *const smtp, const char *const boundary)
void smtp_attachment_clear_all(struct smtp *const smtp)
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)
static int smtp_auth_login(struct smtp *const smtp, const char *const user, const char *const pass)
SMTP_LINKAGE size_t smtp_base64_decode(const char *const buf, unsigned char **decode)
SMTP_LINKAGE int smtp_si_sub_size_t(const size_t a, const size_t b, size_t *const result)
SMTP_LINKAGE size_t smtp_utf8_charlen(char c)
enum smtp_status_code smtp_header_add(struct smtp *const smtp, const char *const key, const char *const value)
static enum smtp_status_code smtp_print_mime_email(struct smtp *const smtp, const char *const body_dd)
static int smtp_header_cmp_key(const void *const v1, const void *const v2)
static int smtp_tls_init(struct smtp *const smtp, const char *const server)
static enum smtp_status_code smtp_print_email(struct smtp *const smtp, const char *const body)
enum smtp_status_code smtp_status_code_set(struct smtp *const smtp, enum smtp_status_code status_code)
int g_smtp_test_err_si_add_size_t_ctr
enum smtp_status_code status_code
SMTP_LINKAGE int smtp_header_value_validate(const char *const value)
enum smtp_status_code smtp_auth(struct smtp *const smtp, enum smtp_authentication_method auth_method, const char *const user, const char *const pass)
SMTP_LINKAGE int smtp_si_mul_size_t(const size_t a, const size_t b, size_t *const result)
SMTP_LINKAGE char * smtp_str_replace(const char *const search, const char *const replace, const char *const s)
SMTP_LINKAGE int smtp_attachment_validate_name(const char *const name)
static enum smtp_status_code smtp_str_getdelimfd_read_timeout(struct smtp *const smtp)
int g_smtp_test_err_si_mul_size_t_ctr
int smtp_test_seam_dec_err_ctr(int *const test_err_ctr)
SMTP_LINKAGE char * smtp_stpcpy(char *s1, const char *s2)
SMTP_LINKAGE int smtp_si_add_size_t(const size_t a, const size_t b, size_t *const result)
static signed char g_base64_decode_table[]
static char g_base64_encode_table[]
SMTP_LINKAGE char * smtp_fold_whitespace(const char *const s, unsigned int maxlen)
static int smtp_header_cmp(const void *v1, const void *v2)
SMTP_LINKAGE enum str_getdelim_retcode smtp_str_getdelimfd(struct str_getdelimfd *const gdfd)
const char * smtp_status_code_errstr(enum smtp_status_code status_code)
static void smtp_puts_dbg(struct smtp *const smtp, const char *const prefix, const char *const str)
SMTP_LINKAGE int smtp_str_getdelimfd_set_line_and_buf(struct str_getdelimfd *const gdfd, size_t copy_len)
SMTP_LINKAGE char * smtp_chunk_split(const char *const s, size_t chunklen, const char *const end)
SMTP_LINKAGE char * smtp_strdup(const char *s)
static enum smtp_status_code smtp_puts_terminate(struct smtp *const smtp, const char *const s)
static enum smtp_status_code smtp_ehlo(struct smtp *const smtp)
static enum str_getdelim_retcode smtp_str_getdelimfd_throw_error(struct str_getdelimfd *const gdfd)
long(* getdelimfd_read)(struct str_getdelimfd *const gdfd, void *buf, size_t count)