59#if LWIP_TCP && LWIP_CALLBACK_API
72#define SMTP_POLL_INTERVAL 4
75#define SMTP_TIMEOUT_DATABLOCK ( 3 * 60 * SMTP_POLL_INTERVAL / 2)
78#define SMTP_TIMEOUT_DATATERM (10 * 60 * SMTP_POLL_INTERVAL / 2)
83#define SMTP_TIMEOUT ( 2 * 60 * SMTP_POLL_INTERVAL / 2)
86#define SMTP_DEBUG_TRACE (SMTP_DEBUG | LWIP_DBG_TRACE)
87#define SMTP_DEBUG_STATE (SMTP_DEBUG | LWIP_DBG_STATE)
88#define SMTP_DEBUG_WARN (SMTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
89#define SMTP_DEBUG_WARN_STATE (SMTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
90#define SMTP_DEBUG_SERIOUS (SMTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
93#define SMTP_RX_BUF_LEN 255
94#define SMTP_TX_BUF_LEN 255
95#define SMTP_CRLF "\r\n"
96#define SMTP_CRLF_LEN 2
98#define SMTP_RESP_220 "220"
99#define SMTP_RESP_235 "235"
100#define SMTP_RESP_250 "250"
101#define SMTP_RESP_334 "334"
102#define SMTP_RESP_354 "354"
103#define SMTP_RESP_LOGIN_UNAME "VXNlcm5hbWU6"
104#define SMTP_RESP_LOGIN_PASS "UGFzc3dvcmQ6"
106#define SMTP_KEYWORD_AUTH_SP "AUTH "
107#define SMTP_KEYWORD_AUTH_EQ "AUTH="
108#define SMTP_KEYWORD_AUTH_LEN 5
109#define SMTP_AUTH_PARAM_PLAIN "PLAIN"
110#define SMTP_AUTH_PARAM_LOGIN "LOGIN"
112#define SMTP_CMD_EHLO_1 "EHLO ["
113#define SMTP_CMD_EHLO_1_LEN 6
114#define SMTP_CMD_EHLO_2 "]\r\n"
115#define SMTP_CMD_EHLO_2_LEN 3
116#define SMTP_CMD_AUTHPLAIN_1 "AUTH PLAIN "
117#define SMTP_CMD_AUTHPLAIN_1_LEN 11
118#define SMTP_CMD_AUTHPLAIN_2 "\r\n"
119#define SMTP_CMD_AUTHPLAIN_2_LEN 2
120#define SMTP_CMD_AUTHLOGIN "AUTH LOGIN\r\n"
121#define SMTP_CMD_AUTHLOGIN_LEN 12
122#define SMTP_CMD_MAIL_1 "MAIL FROM: <"
123#define SMTP_CMD_MAIL_1_LEN 12
124#define SMTP_CMD_MAIL_2 ">\r\n"
125#define SMTP_CMD_MAIL_2_LEN 3
126#define SMTP_CMD_RCPT_1 "RCPT TO: <"
127#define SMTP_CMD_RCPT_1_LEN 10
128#define SMTP_CMD_RCPT_2 ">\r\n"
129#define SMTP_CMD_RCPT_2_LEN 3
130#define SMTP_CMD_DATA "DATA\r\n"
131#define SMTP_CMD_DATA_LEN 6
132#define SMTP_CMD_HEADER_1 "From: <"
133#define SMTP_CMD_HEADER_1_LEN 7
134#define SMTP_CMD_HEADER_2 ">\r\nTo: <"
135#define SMTP_CMD_HEADER_2_LEN 8
136#define SMTP_CMD_HEADER_3 ">\r\nSubject: "
137#define SMTP_CMD_HEADER_3_LEN 12
138#define SMTP_CMD_HEADER_4 "\r\n\r\n"
139#define SMTP_CMD_HEADER_4_LEN 4
140#define SMTP_CMD_BODY_FINISHED "\r\n.\r\n"
141#define SMTP_CMD_BODY_FINISHED_LEN 5
142#define SMTP_CMD_QUIT "QUIT\r\n"
143#define SMTP_CMD_QUIT_LEN 6
145#if defined(SMTP_STAT_TX_BUF_MAX) && SMTP_STAT_TX_BUF_MAX
146#define SMTP_TX_BUF_MAX(len) LWIP_MACRO(if((len) > smtp_tx_buf_len_max) smtp_tx_buf_len_max = (len);)
148#define SMTP_TX_BUF_MAX(len)
151#if SMTP_COPY_AUTHDATA
152#define SMTP_USERNAME(session) (session)->username
153#define SMTP_PASS(session) (session)->pass
154#define SMTP_AUTH_PLAIN_DATA(session) (session)->auth_plain
155#define SMTP_AUTH_PLAIN_LEN(session) (session)->auth_plain_len
157#define SMTP_USERNAME(session) smtp_username
158#define SMTP_PASS(session) smtp_pass
159#define SMTP_AUTH_PLAIN_DATA(session) smtp_auth_plain
160#define SMTP_AUTH_PLAIN_LEN(session) smtp_auth_plain_len
164#ifndef SMTP_BODYDH_MALLOC
165#define SMTP_BODYDH_MALLOC(size) mem_malloc(size)
166#define SMTP_BODYDH_FREE(ptr) mem_free(ptr)
170#define BDHALLDATASENT 2
171#define BDHSOMEDATASENT 1
173enum bdh_handler_state {
180enum smtp_session_state {
184 SMTP_AUTH_LOGIN_UNAME,
185 SMTP_AUTH_LOGIN_PASS,
197static const char *smtp_state_str[] = {
201 "SMTP_AUTH_LOGIN_UNAME",
202 "SMTP_AUTH_LOGIN_PASS",
212static const char *smtp_result_strs[] = {
214 "SMTP_RESULT_ERR_UNKNOWN",
215 "SMTP_RESULT_ERR_CONNECT",
216 "SMTP_RESULT_ERR_HOSTNAME",
217 "SMTP_RESULT_ERR_CLOSED",
218 "SMTP_RESULT_ERR_TIMEOUT",
219 "SMTP_RESULT_ERR_SVR_RESP",
220 "SMTP_RESULT_ERR_MEM"
225struct smtp_bodydh_state {
226 smtp_bodycback_fn callback_fn;
228 struct smtp_bodydh exposed;
235 enum smtp_session_state
state;
239 char tx_buf[SMTP_TX_BUF_LEN + 1];
263#if SMTP_COPY_AUTHDATA
271 size_t auth_plain_len;
274 struct smtp_bodydh_state *bodydh;
282#if LWIP_ALTCP && LWIP_ALTCP_TLS
284static struct altcp_tls_config *smtp_server_tls_config;
287static char *smtp_username;
289static char *smtp_pass;
293static size_t smtp_auth_plain_len;
296static err_t smtp_verify(
const char *
data,
size_t data_len,
u8_t linebreaks_allowed);
306#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN
307static size_t smtp_base64_encode(
char*
target,
size_t target_len,
const char*
source,
size_t source_len);
309static enum smtp_session_state smtp_prepare_mail(
struct smtp_session *
s,
u16_t *tx_buf_len);
310static void smtp_send_body(
struct smtp_session *
s,
struct altcp_pcb *pcb);
313static void smtp_send_body_data_handler(
struct smtp_session *
s,
struct altcp_pcb *pcb);
320smtp_result_str(
u8_t smtp_result)
325 return smtp_result_strs[smtp_result];
333smtp_pbuf_str(
struct pbuf*
p)
335 if ((
p ==
NULL) || (
p->len == 0)) {
338 ((
char*)
p->payload)[
p->len] = 0;
339 return (
const char*)
p->payload;
365 smtp_server[
len] = 0;
378 smtp_server_port =
port;
381#if LWIP_ALTCP && LWIP_ALTCP_TLS
388smtp_set_tls_config(
struct altcp_tls_config *tls_config)
391 smtp_server_tls_config = tls_config;
404 size_t uname_len = 0;
409 memset(smtp_auth_plain, 0xfa, 64);
413 LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, (
"Username is too long, %d instead of %d\n",
419#if SMTP_SUPPORT_AUTH_LOGIN || SMTP_SUPPORT_AUTH_PLAIN
422 LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, (
"Password is too long, %d instead of %d\n",
427 LWIP_DEBUGF(SMTP_DEBUG_WARN, (
"Password not supported as no authentication methods are activated\n"));
430 *smtp_auth_plain = 0;
432 smtp_username = smtp_auth_plain + 1;
436 smtp_pass = smtp_auth_plain + uname_len + 2;
439 smtp_auth_plain_len = uname_len + pass_len + 2;
445static void smtp_free_struct(
struct smtp_session *
s)
447 if (
s->bodydh !=
NULL) {
448 SMTP_BODYDH_FREE(
s->bodydh);
453#define smtp_free_struct(x) SMTP_STATE_FREE(x)
457smtp_setup_pcb(
struct smtp_session *
s,
const ip_addr_t* remote_ip)
462#if LWIP_ALTCP && LWIP_ALTCP_TLS
463 if (smtp_server_tls_config) {
464 pcb = altcp_tls_new(smtp_server_tls_config,
IP_GET_TYPE(remote_ip));
474 altcp_poll(pcb, smtp_tcp_poll, SMTP_POLL_INTERVAL);
484smtp_send_mail_alloced(
struct smtp_session *
s)
497 if (smtp_verify(
s->to,
s->to_len, 0) !=
ERR_OK) {
501 if (smtp_verify(
s->from,
s->from_len, 0) !=
ERR_OK) {
505 if (smtp_verify(
s->subject,
s->subject_len, 0) !=
ERR_OK) {
510 if (
s->bodydh ==
NULL)
513 if (smtp_verify(
s->body,
s->body_len, 0) !=
ERR_OK) {
520#if SMTP_COPY_AUTHDATA
522 MEMCPY(
s->auth_plain + 1, smtp_auth_plain + 1, smtp_auth_plain_len - 1);
523 s->auth_plain_len = smtp_auth_plain_len;
525 s->username =
s->auth_plain;
526 s->pass =
s->auth_plain;
527 if (smtp_username !=
NULL) {
528 s->username += smtp_username - smtp_auth_plain;
530 if (smtp_pass !=
NULL) {
531 s->pass += smtp_pass - smtp_auth_plain;
535 s->state = SMTP_NULL;
536 s->timer = SMTP_TIMEOUT;
539 err = dns_gethostbyname(smtp_server, &
addr, smtp_dns_found,
s);
544 pcb = smtp_setup_pcb(
s, &
addr);
551 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"tcp_connect failed: %d\n", (
int)
err));
552 goto deallocate_and_leave;
555 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"dns_gethostbyname failed: %d\n", (
int)
err));
556 goto deallocate_and_leave;
588 struct smtp_session*
s;
590 size_t to_len =
strlen(to);
591 size_t subject_len =
strlen(subject);
593 size_t mem_len =
sizeof(
struct smtp_session);
594 char *sfrom, *sto, *ssubject, *sbody;
598 mem_len += from_len + to_len + subject_len + body_len + 4;
599 if (mem_len > 0xffff) {
611 s->from = sfrom = (
char*)
s +
sizeof(
struct smtp_session);
612 s->from_len = (
u16_t)from_len;
613 s->to = sto = sfrom + from_len + 1;
614 s->to_len = (
u16_t)to_len;
615 s->subject = ssubject = sto + to_len + 1;
616 s->subject_len = (
u16_t)subject_len;
617 s->body = sbody = ssubject + subject_len + 1;
618 s->body_len = (
u16_t)body_len;
622 MEMCPY(sto, to, to_len + 1);
623 MEMCPY(ssubject, subject, subject_len + 1);
626 s->callback_fn = callback_fn;
627 s->callback_arg = callback_arg;
630 return smtp_send_mail_alloced(
s);
643 struct smtp_session*
s;
652 memset(
s, 0,
sizeof(
struct smtp_session));
662 s->subject = subject;
670 s->callback_fn = callback_fn;
671 s->callback_arg = callback_arg;
673 return smtp_send_mail_alloced(
s);
721smtp_verify(
const char *
data,
size_t data_len,
u8_t linebreaks_allowed)
724 u8_t last_was_cr = 0;
725 for (
i = 0;
i < data_len;
i++) {
728 LWIP_DEBUGF(SMTP_DEBUG_WARN, (
"smtp_verify: no 8-bit data supported: %s\n",
data));
732 if (!linebreaks_allowed) {
733 LWIP_DEBUGF(SMTP_DEBUG_WARN, (
"smtp_verify: found CR where no linebreaks allowed: %s\n",
data));
737 LWIP_DEBUGF(SMTP_DEBUG_WARN, (
"smtp_verify: found double CR: %s\n",
data));
744 LWIP_DEBUGF(SMTP_DEBUG_WARN, (
"smtp_verify: found LF without CR before: %s\n",
data));
760 void *
arg =
s->callback_arg;
798 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"smtp_tcp_err: connection reset by remote host\n"));
808 struct smtp_session *
s = (
struct smtp_session*)
arg;
835 smtp_process(
arg, pcb,
p);
837 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"smtp_tcp_recv: connection closed by remote host\n"));
849 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_connected: Waiting for 220\n"));
865 struct smtp_session *
s = (
struct smtp_session*)
arg;
872 if (ipaddr !=
NULL) {
873 pcb = smtp_setup_pcb(
s, ipaddr);
875 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_dns_found: hostname resolved, connecting\n"));
880 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"tcp_connect failed: %d\n", (
int)
err));
883 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_dns_found: failed to allocate tcp pcb\n"));
888 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"smtp_dns_found: failed to resolve hostname: %s\n",
898#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN
901static const char base64_table[] = {
902 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
903 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
904 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
905 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
906 'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
907 'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
908 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
914smtp_base64_encode(
char*
target,
size_t target_len,
const char*
source,
size_t source_len)
918 size_t target_idx = 0;
919 size_t longer = (source_len % 3) ? (3 - (source_len % 3)) : 0;
920 size_t source_len_b64 = source_len + longer;
921 size_t len = (((source_len_b64) * 4) / 3);
928 for (
i = 0;
i < source_len_b64;
i++) {
930 for (
j = 7;
j >= 0;
j--,
x--) {
931 if ((
b & (1 <<
j)) != 0) {
955smtp_is_response(
struct smtp_session *
s)
970 if ((
num <= 0) || (
num >= 1000)) {
987smtp_is_response_finished(
struct smtp_session *
s)
1003 if (
offset > 0xFFFF - 4) {
1008 if (
crlf == 0xFFFF) {
1021 }
else if (
sp ==
' ') {
1030static enum smtp_session_state
1031smtp_prepare_helo(
struct smtp_session *
s,
u16_t *tx_buf_len,
struct altcp_pcb *pcb)
1037 LWIP_ASSERT(
"string too long", ipa_len <= (SMTP_TX_BUF_LEN-SMTP_CMD_EHLO_1_LEN-SMTP_CMD_EHLO_2_LEN));
1039 *tx_buf_len = (
u16_t)(SMTP_CMD_EHLO_1_LEN + (
u16_t)ipa_len + SMTP_CMD_EHLO_2_LEN);
1040 LWIP_ASSERT(
"tx_buf overflow detected", *tx_buf_len <= SMTP_TX_BUF_LEN);
1042 SMEMCPY(
s->tx_buf, SMTP_CMD_EHLO_1, SMTP_CMD_EHLO_1_LEN);
1043 MEMCPY(&
s->tx_buf[SMTP_CMD_EHLO_1_LEN], ipa, ipa_len);
1044 SMEMCPY(&
s->tx_buf[SMTP_CMD_EHLO_1_LEN + ipa_len], SMTP_CMD_EHLO_2, SMTP_CMD_EHLO_2_LEN);
1048#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN
1053static enum smtp_session_state
1054smtp_prepare_auth_or_mail(
struct smtp_session *
s,
u16_t *tx_buf_len)
1058 if (auth == 0xFFFF) {
1061 if (auth != 0xFFFF) {
1063 if ((
crlf != 0xFFFF) && (
crlf > auth)) {
1067 char *sep =
s->tx_buf + SMTP_KEYWORD_AUTH_LEN;
1068 s->tx_buf[copied] = 0;
1069#if SMTP_SUPPORT_AUTH_PLAIN
1071 if (
strstr(sep, SMTP_AUTH_PARAM_PLAIN) !=
NULL) {
1074 SMEMCPY(
s->tx_buf, SMTP_CMD_AUTHPLAIN_1, SMTP_CMD_AUTHPLAIN_1_LEN);
1077 auth_len = smtp_base64_encode(&
s->tx_buf[SMTP_CMD_AUTHPLAIN_1_LEN],
1078 SMTP_TX_BUF_LEN - SMTP_CMD_AUTHPLAIN_1_LEN, SMTP_AUTH_PLAIN_DATA(
s),
1079 SMTP_AUTH_PLAIN_LEN(
s));
1080 LWIP_ASSERT(
"string too long", auth_len <= (SMTP_TX_BUF_LEN-SMTP_CMD_AUTHPLAIN_1_LEN-SMTP_CMD_AUTHPLAIN_2_LEN));
1081 *tx_buf_len = (
u16_t)(SMTP_CMD_AUTHPLAIN_1_LEN + SMTP_CMD_AUTHPLAIN_2_LEN + (
u16_t)auth_len);
1082 SMEMCPY(&
s->tx_buf[SMTP_CMD_AUTHPLAIN_1_LEN + auth_len], SMTP_CMD_AUTHPLAIN_2,
1083 SMTP_CMD_AUTHPLAIN_2_LEN);
1084 return SMTP_AUTH_PLAIN;
1088#if SMTP_SUPPORT_AUTH_LOGIN
1089 if (
strstr(sep, SMTP_AUTH_PARAM_LOGIN) !=
NULL) {
1091 *tx_buf_len = SMTP_CMD_AUTHLOGIN_LEN;
1092 SMEMCPY(
s->tx_buf, SMTP_CMD_AUTHLOGIN, SMTP_CMD_AUTHLOGIN_LEN);
1093 return SMTP_AUTH_LOGIN_UNAME;
1101 return smtp_prepare_mail(
s, tx_buf_len);
1105#if SMTP_SUPPORT_AUTH_LOGIN
1107static enum smtp_session_state
1108smtp_prepare_auth_login_uname(
struct smtp_session *
s,
u16_t *tx_buf_len)
1110 size_t base64_len = smtp_base64_encode(
s->tx_buf, SMTP_TX_BUF_LEN,
1111 SMTP_USERNAME(
s),
strlen(SMTP_USERNAME(
s)));
1113 LWIP_ASSERT(
"string too long", base64_len <= 0xffff);
1114 LWIP_ASSERT(
"tx_buf overflow detected", base64_len <= SMTP_TX_BUF_LEN - SMTP_CRLF_LEN);
1115 *tx_buf_len = (
u16_t)(base64_len + SMTP_CRLF_LEN);
1117 SMEMCPY(&
s->tx_buf[base64_len], SMTP_CRLF, SMTP_CRLF_LEN);
1118 s->tx_buf[*tx_buf_len] = 0;
1119 return SMTP_AUTH_LOGIN_PASS;
1123static enum smtp_session_state
1124smtp_prepare_auth_login_pass(
struct smtp_session *
s,
u16_t *tx_buf_len)
1126 size_t base64_len = smtp_base64_encode(
s->tx_buf, SMTP_TX_BUF_LEN,
1127 SMTP_PASS(
s),
strlen(SMTP_PASS(
s)));
1129 LWIP_ASSERT(
"string too long", base64_len <= 0xffff);
1130 LWIP_ASSERT(
"tx_buf overflow detected", base64_len <= SMTP_TX_BUF_LEN - SMTP_CRLF_LEN);
1131 *tx_buf_len = (
u16_t)(base64_len + SMTP_CRLF_LEN);
1133 SMEMCPY(&
s->tx_buf[base64_len], SMTP_CRLF, SMTP_CRLF_LEN);
1134 s->tx_buf[*tx_buf_len] = 0;
1135 return SMTP_AUTH_LOGIN;
1140static enum smtp_session_state
1141smtp_prepare_mail(
struct smtp_session *
s,
u16_t *tx_buf_len)
1144 LWIP_ASSERT(
"tx_buf overflow detected",
s->from_len <= (SMTP_TX_BUF_LEN - SMTP_CMD_MAIL_1_LEN - SMTP_CMD_MAIL_2_LEN));
1145 *tx_buf_len = (
u16_t)(SMTP_CMD_MAIL_1_LEN + SMTP_CMD_MAIL_2_LEN +
s->from_len);
1149 target += SMTP_CMD_MAIL_1_LEN;
1157static enum smtp_session_state
1158smtp_prepare_rcpt(
struct smtp_session *
s,
u16_t *tx_buf_len)
1161 LWIP_ASSERT(
"tx_buf overflow detected",
s->to_len <= (SMTP_TX_BUF_LEN - SMTP_CMD_RCPT_1_LEN - SMTP_CMD_RCPT_2_LEN));
1162 *tx_buf_len = (
u16_t)(SMTP_CMD_RCPT_1_LEN + SMTP_CMD_RCPT_2_LEN +
s->to_len);
1166 target += SMTP_CMD_RCPT_1_LEN;
1174static enum smtp_session_state
1175smtp_prepare_header(
struct smtp_session *
s,
u16_t *tx_buf_len)
1178 int len = SMTP_CMD_HEADER_1_LEN + SMTP_CMD_HEADER_2_LEN +
1179 SMTP_CMD_HEADER_3_LEN + SMTP_CMD_HEADER_4_LEN +
s->from_len +
s->to_len +
1186 target += SMTP_CMD_HEADER_1_LEN;
1190 target += SMTP_CMD_HEADER_2_LEN;
1194 target += SMTP_CMD_HEADER_3_LEN;
1203static enum smtp_session_state
1204smtp_prepare_quit(
struct smtp_session *
s,
u16_t *tx_buf_len)
1206 *tx_buf_len = SMTP_CMD_QUIT_LEN;
1207 s->tx_buf[*tx_buf_len] = 0;
1208 SMEMCPY(
s->tx_buf, SMTP_CMD_QUIT, SMTP_CMD_QUIT_LEN);
1209 LWIP_ASSERT(
"tx_buf overflow detected", *tx_buf_len <= SMTP_TX_BUF_LEN);
1215smtp_send_body(
struct smtp_session *
s,
struct altcp_pcb *pcb)
1219 if (
s->state == SMTP_BODY) {
1222 smtp_send_body_data_handler(
s, pcb);
1229 if (send_len > snd_buf) {
1236 s->timer = SMTP_TIMEOUT_DATABLOCK;
1237 s->body_sent = (
u16_t)(
s->body_sent + send_len);
1238 if (
s->body_sent <
s->body_len) {
1239 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_send_body: %d of %d bytes written\n",
1240 s->body_sent,
s->body_len));
1246 if (
s->body_sent ==
s->body_len) {
1248 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_send_body: body completely written (%d bytes), appending end-of-body\n",
1250 err =
altcp_write(pcb, SMTP_CMD_BODY_FINISHED, SMTP_CMD_BODY_FINISHED_LEN, 0);
1252 s->timer = SMTP_TIMEOUT_DATATERM;
1253 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_send_body: end-of-body written, changing state to %s\n",
1254 smtp_state_str[SMTP_QUIT]));
1256 s->state = SMTP_QUIT;
1267 struct smtp_session*
s = (
struct smtp_session*)
arg;
1268 u16_t response_code = 0;
1269 u16_t tx_buf_len = 0;
1270 enum smtp_session_state next_state;
1275 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"Received %d bytes after closing: %s\n",
1276 p->tot_len, smtp_pbuf_str(
p)));
1282 next_state =
s->state;
1293 if (
s->timer == 0) {
1294 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"smtp_process: connection timed out, closing\n"));
1298 if (
s->state == SMTP_BODY) {
1299 smtp_send_body(
s, pcb);
1303 response_code = smtp_is_response(
s);
1304 if (response_code) {
1305 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_process: received response code: %d\n", response_code));
1306 if (smtp_is_response_finished(
s) !=
ERR_OK) {
1307 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_process: partly received response code: %d\n", response_code));
1313 LWIP_DEBUGF(SMTP_DEBUG_WARN, (
"smtp_process: unknown data received (%s)\n",
1314 smtp_pbuf_str(
s->p)));
1325 if (response_code == 220) {
1327 next_state = smtp_prepare_helo(
s, &tx_buf_len, pcb);
1332 if (response_code == 250) {
1333#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN
1335 next_state = smtp_prepare_auth_or_mail(
s, &tx_buf_len);
1338 case(SMTP_AUTH_LOGIN):
1339 case(SMTP_AUTH_PLAIN):
1341 if (response_code == 235) {
1344 next_state = smtp_prepare_mail(
s, &tx_buf_len);
1347#if SMTP_SUPPORT_AUTH_LOGIN
1348 case(SMTP_AUTH_LOGIN_UNAME):
1350 if (response_code == 334) {
1351 if (
pbuf_strstr(
s->p, SMTP_RESP_LOGIN_UNAME) != 0xFFFF) {
1353 next_state = smtp_prepare_auth_login_uname(
s, &tx_buf_len);
1357 case(SMTP_AUTH_LOGIN_PASS):
1359 if (response_code == 334) {
1360 if (
pbuf_strstr(
s->p, SMTP_RESP_LOGIN_PASS) != 0xFFFF) {
1362 next_state = smtp_prepare_auth_login_pass(
s, &tx_buf_len);
1369 if (response_code == 250) {
1371 next_state = smtp_prepare_rcpt(
s, &tx_buf_len);
1376 if (response_code == 250) {
1378 SMEMCPY(
s->tx_buf, SMTP_CMD_DATA, SMTP_CMD_DATA_LEN);
1379 tx_buf_len = SMTP_CMD_DATA_LEN;
1380 next_state = SMTP_DATA;
1385 if (response_code == 354) {
1387 next_state = smtp_prepare_header(
s, &tx_buf_len);
1395 if (response_code == 250) {
1397 next_state = smtp_prepare_quit(
s, &tx_buf_len);
1404 LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, (
"Invalid state: %d/%s\n", (
int)
s->state,
1405 smtp_state_str[
s->state]));
1408 if (
s->state == next_state) {
1409 LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, (
"smtp_process[%s]: unexpected response_code, closing: %d (%s)\n",
1410 smtp_state_str[
s->state], response_code, smtp_pbuf_str(
s->p)));
1415 if (tx_buf_len > 0) {
1416 SMTP_TX_BUF_MAX(tx_buf_len);
1418 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_process[%s]: received command %d (%s)\n",
1419 smtp_state_str[
s->state], response_code, smtp_pbuf_str(
s->p)));
1420 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_process[%s]: sent %"U16_F" bytes: \"%s\"\n",
1421 smtp_state_str[
s->state], tx_buf_len,
s->tx_buf));
1422 s->timer = SMTP_TIMEOUT;
1425 LWIP_DEBUGF(SMTP_DEBUG_STATE, (
"smtp_process: changing state from %s to %s\n",
1426 smtp_state_str[
s->state], smtp_state_str[next_state]));
1427 s->state = next_state;
1428 if (next_state == SMTP_BODY) {
1430 smtp_send_body(
s, pcb);
1431 }
else if (next_state == SMTP_CLOSED) {
1458 return BDHSOMEDATASENT;
1460 return BDHALLDATASENT;
1468smtp_send_mail_bodycback(
const char *
from,
const char* to,
const char* subject,
1469 smtp_bodycback_fn bodycback_fn,
smtp_result_fn callback_fn,
void* callback_arg)
1471 struct smtp_session*
s;
1480 memset(
s, 0,
sizeof(
struct smtp_session));
1481 s->bodydh = (
struct smtp_bodydh_state*)SMTP_BODYDH_MALLOC(
sizeof(
struct smtp_bodydh_state));
1482 if (
s->bodydh ==
NULL) {
1486 memset(
s->bodydh, 0,
sizeof(
struct smtp_bodydh_state));
1496 s->subject = subject;
1501 s->callback_fn = callback_fn;
1502 s->callback_arg = callback_arg;
1503 s->bodydh->callback_fn = bodycback_fn;
1504 s->bodydh->state = BDH_SENDING;
1506 return smtp_send_mail_alloced(
s);
1510smtp_send_body_data_handler(
struct smtp_session *
s,
struct altcp_pcb *pcb)
1512 struct smtp_bodydh_state *bdh;
1520 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_send_body_data_handler: resume\n"));
1521 if((
res = smtp_send_bodyh_data(pcb, (
const char **)&
s->body, &
s->body_len))
1522 != BDHALLDATASENT) {
1523 s->body_sent =
s->body_len - 1;
1529 if (bdh->state == BDH_SENDING) {
1530 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_send_body_data_handler: run\n"));
1533 bdh->exposed.length = 0;
1534 if (bdh->callback_fn(
s->callback_arg, &bdh->exposed) == BDH_DONE) {
1535 bdh->state = BDH_STOP;
1537 s->body = bdh->exposed.buffer;
1538 s->body_len = bdh->exposed.length;
1539 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_send_body_data_handler: trying to send %u bytes\n", (
unsigned int)
s->body_len));
1540 }
while (
s->body_len &&
1541 ((
res = smtp_send_bodyh_data(pcb, (
const char **)&
s->body, &
s->body_len)) == BDHALLDATASENT)
1542 && (bdh->state != BDH_STOP));
1544 if ((bdh->state != BDH_SENDING) && (
ret != BDHSOMEDATASENT)) {
1545 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_send_body_data_handler: stop\n"));
1546 s->body_sent =
s->body_len;
1548 LWIP_DEBUGF(SMTP_DEBUG_TRACE, (
"smtp_send_body_data_handler: pause\n"));
1549 s->body_sent =
s->body_len - 1;
char * strstr(char *String1, char *String2)
ACPI_SIZE strlen(const char *String)
#define altcp_get_ip(pcb, local)
#define altcp_tcp_new_ip_type
#define LWIP_ARRAYSIZE(x)
static const WCHAR crlf[]
#define LWIP_DEBUGF(debug, message)
#define LWIP_ASSERT(message, assertion)
GLint GLint GLint GLint GLint x
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLboolean GLboolean GLboolean b
GLenum const GLvoid * addr
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
#define LWIP_UNUSED_ARG(x)
#define LWIP_ASSERT_CORE_LOCKED()
#define SMEMCPY(dst, src, len)
u16_t pbuf_memfind(const struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
u8_t pbuf_get_at(const struct pbuf *p, u16_t offset)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
u8_t pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define SMTP_MAX_PASS_LEN
#define SMTP_STATE_MALLOC(size)
#define SMTP_MAX_SERVERNAME_LEN
#define SMTP_MAX_USERNAME_LEN
#define SMTP_STATE_FREE(ptr)
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
#define ipaddr_aton(cp, addr)
#define IP_GET_TYPE(ipaddr)
#define ipaddr_ntoa(ipaddr)
static const int digits[]
#define MEMCPY(DST, SRC, BYTES)
struct task_struct * current
u16_t pbuf_strstr(const struct pbuf *p, const char *substr)
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
err_t smtp_send_mail_static(const char *from, const char *to, const char *subject, const char *body, smtp_result_fn callback_fn, void *callback_arg)
err_t smtp_set_server_addr(const char *server)
#define SMTP_RESULT_ERR_CLOSED
void smtp_set_server_port(u16_t port)
#define SMTP_RESULT_ERR_HOSTNAME
err_t smtp_set_auth(const char *username, const char *pass)
#define SMTP_RESULT_ERR_CONNECT
#define SMTP_RESULT_ERR_MEM
#define SMTP_DEFAULT_PORT
void(* smtp_result_fn)(void *arg, u8_t smtp_result, u16_t srv_err, err_t err)
#define SMTP_RESULT_ERR_UNKNOWN
void smtp_send_mail_int(void *arg)
#define SMTP_RESULT_ERR_TIMEOUT
#define SMTP_RESULT_ERR_SVR_RESP
err_t smtp_send_mail(const char *from, const char *to, const char *subject, const char *body, smtp_result_fn callback_fn, void *callback_arg)
smtp_result_fn callback_fn
static rfbScreenInfoPtr server
static GLenum _GLUfuncptr fn