1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #include "claws-features.h"
23 #endif
24
25 #include <glib.h>
26 #ifdef ENABLE_NLS
27 #include <glib/gi18n.h>
28 #else
29 #define _(a) (a)
30 #define N_(a) (a)
31 #endif
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "smtp.h"
36 #include "md5.h"
37 #include "utils.h"
38 #include "log.h"
39
40 static void smtp_session_destroy(Session *session);
41
42 static gint smtp_auth(SMTPSession *session);
43 #ifdef USE_GNUTLS
44 static gint smtp_starttls(SMTPSession *session);
45 #endif
46 static gint smtp_auth_cram_md5(SMTPSession *session);
47 static gint smtp_auth_login(SMTPSession *session);
48 static gint smtp_auth_plain(SMTPSession *session);
49 static gint smtp_auth_oauth2(SMTPSession *session);
50
51 static gint smtp_ehlo(SMTPSession *session);
52 static gint smtp_ehlo_recv(SMTPSession *session, const gchar *msg);
53
54 static gint smtp_helo(SMTPSession *session);
55 static gint smtp_rcpt(SMTPSession *session);
56 static gint smtp_data(SMTPSession *session);
57 static gint smtp_send_data(SMTPSession *session);
58 static gint smtp_make_ready(SMTPSession *session);
59 static gint smtp_eom(SMTPSession *session);
60
61 static gint smtp_session_recv_msg(Session *session, const gchar *msg);
62 static gint smtp_session_send_data_finished(Session *session, guint len);
63
64
smtp_session_new(void * prefs_account)65 Session *smtp_session_new(void *prefs_account)
66 {
67 SMTPSession *session;
68
69 session = g_new0(SMTPSession, 1);
70
71 session_init(SESSION(session), prefs_account, TRUE);
72
73 SESSION(session)->type = SESSION_SMTP;
74
75 SESSION(session)->recv_msg = smtp_session_recv_msg;
76
77 SESSION(session)->recv_data_finished = NULL;
78 SESSION(session)->send_data_finished = smtp_session_send_data_finished;
79
80 SESSION(session)->destroy = smtp_session_destroy;
81
82 session->state = SMTP_READY;
83
84 #ifdef USE_GNUTLS
85 session->tls_init_done = FALSE;
86 #endif
87
88 session->hostname = NULL;
89 session->user = NULL;
90 session->pass = NULL;
91
92 session->from = NULL;
93 session->to_list = NULL;
94 session->cur_to = NULL;
95
96 session->send_data = NULL;
97 session->send_data_len = 0;
98
99 session->max_message_size = -1;
100
101 session->avail_auth_type = 0;
102 session->forced_auth_type = 0;
103 session->auth_type = 0;
104 session->esmtp_flags = 0;
105
106 session->error_val = SM_OK;
107 session->error_msg = NULL;
108
109 return SESSION(session);
110 }
111
smtp_session_destroy(Session * session)112 static void smtp_session_destroy(Session *session)
113 {
114 SMTPSession *smtp_session = SMTP_SESSION(session);
115
116 g_free(smtp_session->hostname);
117 g_free(smtp_session->user);
118 g_free(smtp_session->pass);
119 g_free(smtp_session->from);
120
121 g_free(smtp_session->send_data);
122
123 g_free(smtp_session->error_msg);
124 }
125
smtp_from(SMTPSession * session)126 gint smtp_from(SMTPSession *session)
127 {
128 gchar buf[MESSAGEBUFSIZE];
129 gchar *mail_size = NULL;
130
131 cm_return_val_if_fail(session->from != NULL, SM_ERROR);
132
133 session->state = SMTP_FROM;
134
135 if (session->is_esmtp && (session->esmtp_flags & ESMTP_SIZE)!=0)
136 mail_size = g_strdup_printf(" SIZE=%d", session->send_data_len);
137 else
138 mail_size = g_strdup("");
139
140
141 if (strchr(session->from, '<'))
142 g_snprintf(buf, sizeof(buf), "MAIL FROM:%s%s", session->from,
143 mail_size);
144 else
145 g_snprintf(buf, sizeof(buf), "MAIL FROM:<%s>%s", session->from,
146 mail_size);
147
148 g_free(mail_size);
149
150 if (session_send_msg(SESSION(session), buf) < 0)
151 return SM_ERROR;
152 log_print(LOG_PROTOCOL, "%sSMTP> %s\n", (session->is_esmtp?"E":""), buf);
153
154 return SM_OK;
155 }
156
smtp_auth(SMTPSession * session)157 static gint smtp_auth(SMTPSession *session)
158 {
159
160 cm_return_val_if_fail(session->user != NULL, SM_ERROR);
161
162 session->state = SMTP_AUTH;
163
164 if ((session->forced_auth_type == SMTPAUTH_CRAM_MD5
165 || session->forced_auth_type == 0)
166 &&
167 (session->avail_auth_type & SMTPAUTH_CRAM_MD5) != 0)
168 smtp_auth_cram_md5(session);
169 else if ((session->forced_auth_type == SMTPAUTH_LOGIN
170 || session->forced_auth_type == 0)
171 &&
172 (session->avail_auth_type & SMTPAUTH_LOGIN) != 0)
173 smtp_auth_login(session);
174 else if ((session->forced_auth_type == SMTPAUTH_PLAIN
175 || session->forced_auth_type == 0)
176 &&
177 (session->avail_auth_type & SMTPAUTH_PLAIN) != 0)
178 smtp_auth_plain(session);
179 else if ((session->forced_auth_type == SMTPAUTH_OAUTH2
180 || session->forced_auth_type == 0)
181 &&
182 (session->avail_auth_type & SMTPAUTH_OAUTH2) != 0)
183 smtp_auth_oauth2(session);
184 else if (session->forced_auth_type == 0) {
185 log_warning(LOG_PROTOCOL, _("No SMTP AUTH method available\n"));
186 return SM_AUTHFAIL;
187 } else {
188 log_warning(LOG_PROTOCOL, _("Selected SMTP AUTH method not available\n"));
189 return SM_AUTHFAIL;
190 }
191
192 return SM_OK;
193 }
194
smtp_auth_recv(SMTPSession * session,const gchar * msg)195 static gint smtp_auth_recv(SMTPSession *session, const gchar *msg)
196 {
197 gchar buf[MESSAGEBUFSIZE], *tmp;
198
199 switch (session->auth_type) {
200 case SMTPAUTH_LOGIN:
201 session->state = SMTP_AUTH_LOGIN_USER;
202
203 if (!strncmp(msg, "334 ", 4)) {
204 tmp = g_base64_encode(session->user, strlen(session->user));
205
206 if (session_send_msg(SESSION(session), tmp) < 0) {
207 g_free(tmp);
208 return SM_ERROR;
209 }
210 g_free(tmp);
211 log_print(LOG_PROTOCOL, "ESMTP> [USERID]\n");
212 } else {
213 /* Server rejects AUTH */
214 if (session_send_msg(SESSION(session), "*") < 0)
215 return SM_ERROR;
216 log_print(LOG_PROTOCOL, "ESMTP> *\n");
217 }
218 break;
219 case SMTPAUTH_CRAM_MD5:
220 session->state = SMTP_AUTH_CRAM_MD5;
221
222 if (!strncmp(msg, "334 ", 4)) {
223 gchar *response;
224 gchar *response64;
225 gchar *challenge;
226 gsize challengelen;
227 guchar hexdigest[33];
228
229 challenge = g_base64_decode_zero(msg + 4, &challengelen);
230 log_print(LOG_PROTOCOL, "ESMTP< [Decoded: %s]\n", challenge);
231
232 g_snprintf(buf, sizeof(buf), "%s", session->pass);
233 md5_hex_hmac(hexdigest, challenge, challengelen,
234 buf, strlen(session->pass));
235 g_free(challenge);
236
237 response = g_strdup_printf
238 ("%s %s", session->user, hexdigest);
239 log_print(LOG_PROTOCOL, "ESMTP> [Encoded: %s]\n", response);
240
241 response64 = g_base64_encode(response, strlen(response));
242 g_free(response);
243
244 if (session_send_msg(SESSION(session), response64) < 0) {
245 g_free(response64);
246 return SM_ERROR;
247 }
248 log_print(LOG_PROTOCOL, "ESMTP> %s\n", response64);
249 g_free(response64);
250 } else {
251 /* Server rejects AUTH */
252 if (session_send_msg(SESSION(session), "*") < 0)
253 return SM_ERROR;
254 log_print(LOG_PROTOCOL, "ESMTP> *\n");
255 }
256 break;
257 case SMTPAUTH_DIGEST_MD5:
258 default:
259 /* stop smtp_auth when no correct authtype */
260 if (session_send_msg(SESSION(session), "*") < 0)
261 return SM_ERROR;
262 log_print(LOG_PROTOCOL, "ESMTP> *\n");
263 break;
264 }
265
266 return SM_OK;
267 }
268
smtp_auth_login_user_recv(SMTPSession * session,const gchar * msg)269 static gint smtp_auth_login_user_recv(SMTPSession *session, const gchar *msg)
270 {
271 gchar *tmp;
272
273 session->state = SMTP_AUTH_LOGIN_PASS;
274
275 if (!strncmp(msg, "334 ", 4)) {
276 tmp = g_base64_encode(session->pass, strlen(session->pass));
277 } else {
278 /* Server rejects AUTH */
279 tmp = g_strdup("*");
280 }
281
282 if (session_send_msg(SESSION(session), tmp) < 0) {
283 g_free(tmp);
284 return SM_ERROR;
285 }
286 g_free(tmp);
287
288 log_print(LOG_PROTOCOL, "ESMTP> [PASSWORD]\n");
289
290 return SM_OK;
291 }
292
smtp_ehlo(SMTPSession * session)293 static gint smtp_ehlo(SMTPSession *session)
294 {
295 gchar buf[MESSAGEBUFSIZE];
296
297 session->state = SMTP_EHLO;
298
299 session->avail_auth_type = 0;
300
301 g_snprintf(buf, sizeof(buf), "EHLO %s",
302 session->hostname ? session->hostname : get_domain_name());
303 if (session_send_msg(SESSION(session), buf) < 0)
304 return SM_ERROR;
305 log_print(LOG_PROTOCOL, "ESMTP> %s\n", buf);
306
307 return SM_OK;
308 }
309
smtp_ehlo_recv(SMTPSession * session,const gchar * msg)310 static gint smtp_ehlo_recv(SMTPSession *session, const gchar *msg)
311 {
312 if (strncmp(msg, "250", 3) == 0) {
313 const gchar *p = msg;
314 p += 3;
315 if (*p == '-' || *p == ' ') p++;
316 if (g_ascii_strncasecmp(p, "AUTH", 4) == 0) {
317 p += 5;
318 if (strcasestr(p, "PLAIN"))
319 session->avail_auth_type |= SMTPAUTH_PLAIN;
320 if (strcasestr(p, "LOGIN"))
321 session->avail_auth_type |= SMTPAUTH_LOGIN;
322 if (strcasestr(p, "CRAM-MD5"))
323 session->avail_auth_type |= SMTPAUTH_CRAM_MD5;
324 if (strcasestr(p, "DIGEST-MD5"))
325 session->avail_auth_type |= SMTPAUTH_DIGEST_MD5;
326 if (strcasestr(p, "XOAUTH2"))
327 session->avail_auth_type |= SMTPAUTH_OAUTH2;
328 }
329 if (g_ascii_strncasecmp(p, "SIZE", 4) == 0) {
330 p += 5;
331 session->max_message_size = atoi(p);
332 session->esmtp_flags |= ESMTP_SIZE;
333 }
334 if (g_ascii_strncasecmp(p, "STARTTLS", 8) == 0) {
335 p += 9;
336 session->avail_auth_type |= SMTPAUTH_TLS_AVAILABLE;
337 }
338 return SM_OK;
339 } else if ((msg[0] == '1' || msg[0] == '2' || msg[0] == '3') &&
340 (msg[3] == ' ' || msg[3] == '\0'))
341 return SM_OK;
342 else if (msg[0] == '5' && msg[1] == '0' &&
343 (msg[2] == '4' || msg[2] == '3' || msg[2] == '1'))
344 return SM_ERROR;
345
346 return SM_ERROR;
347 }
348
349 #ifdef USE_GNUTLS
smtp_starttls(SMTPSession * session)350 static gint smtp_starttls(SMTPSession *session)
351 {
352 session->state = SMTP_STARTTLS;
353
354 if (session_send_msg(SESSION(session), "STARTTLS") < 0)
355 return SM_ERROR;
356 log_print(LOG_PROTOCOL, "ESMTP> STARTTLS\n");
357
358 return SM_OK;
359 }
360 #endif
361
smtp_auth_cram_md5(SMTPSession * session)362 static gint smtp_auth_cram_md5(SMTPSession *session)
363 {
364 session->state = SMTP_AUTH;
365 session->auth_type = SMTPAUTH_CRAM_MD5;
366
367 if (session_send_msg(SESSION(session), "AUTH CRAM-MD5") < 0)
368 return SM_ERROR;
369 log_print(LOG_PROTOCOL, "ESMTP> AUTH CRAM-MD5\n");
370
371 return SM_OK;
372 }
373
smtp_auth_plain(SMTPSession * session)374 static gint smtp_auth_plain(SMTPSession *session)
375 {
376 gchar buf[MESSAGEBUFSIZE], *b64buf, *out;
377 gint len;
378
379 session->state = SMTP_AUTH_PLAIN;
380 session->auth_type = SMTPAUTH_PLAIN;
381
382 memset(buf, 0, sizeof buf);
383
384 /* "\0user\0password" */
385 len = sprintf(buf, "%c%s%c%s", '\0', session->user, '\0', session->pass);
386 b64buf = g_base64_encode(buf, len);
387 out = g_strconcat("AUTH PLAIN ", b64buf, NULL);
388 g_free(b64buf);
389
390 if (session_send_msg(SESSION(session), out) < 0) {
391 g_free(out);
392 return SM_ERROR;
393 }
394
395 g_free(out);
396
397 log_print(LOG_PROTOCOL, "ESMTP> [AUTH PLAIN]\n");
398
399 return SM_OK;
400 }
401
402
smtp_auth_oauth2(SMTPSession * session)403 static gint smtp_auth_oauth2(SMTPSession *session)
404 {
405 gchar buf[MESSAGEBUFSIZE], *b64buf, *out;
406 gint len;
407
408 session->state = SMTP_AUTH_OAUTH2;
409 session->auth_type = SMTPAUTH_OAUTH2;
410
411 memset(buf, 0, sizeof buf);
412
413 /* "user=" {User} "^Aauth=Bearer " {Access Token} "^A^A"*/
414 /* session->pass contains the OAUTH2 Access Token*/
415 len = sprintf(buf, "user=%s\1auth=Bearer %s\1\1", session->user, session->pass);
416 b64buf = g_base64_encode(buf, len);
417 out = g_strconcat("AUTH XOAUTH2 ", b64buf, NULL);
418 g_free(b64buf);
419
420 if (session_send_msg(SESSION(session), out) < 0) {
421 g_free(out);
422 return SM_ERROR;
423 }
424
425 g_free(out);
426
427 log_print(LOG_PROTOCOL, "ESMTP> [AUTH XOAUTH2]\n");
428
429 return SM_OK;
430 }
431
smtp_auth_login(SMTPSession * session)432 static gint smtp_auth_login(SMTPSession *session)
433 {
434 session->state = SMTP_AUTH;
435 session->auth_type = SMTPAUTH_LOGIN;
436
437 if (session_send_msg(SESSION(session), "AUTH LOGIN") < 0)
438 return SM_ERROR;
439 log_print(LOG_PROTOCOL, "ESMTP> AUTH LOGIN\n");
440
441 return SM_OK;
442 }
443
smtp_helo(SMTPSession * session)444 static gint smtp_helo(SMTPSession *session)
445 {
446 gchar buf[MESSAGEBUFSIZE];
447
448 session->state = SMTP_HELO;
449
450 g_snprintf(buf, sizeof(buf), "HELO %s",
451 session->hostname ? session->hostname : get_domain_name());
452 if (session_send_msg(SESSION(session), buf) < 0)
453 return SM_ERROR;
454 log_print(LOG_PROTOCOL, "SMTP> %s\n", buf);
455
456 return SM_OK;
457 }
458
smtp_rcpt(SMTPSession * session)459 static gint smtp_rcpt(SMTPSession *session)
460 {
461 gchar buf[MESSAGEBUFSIZE];
462 gchar *to;
463
464 cm_return_val_if_fail(session->cur_to != NULL, SM_ERROR);
465
466 session->state = SMTP_RCPT;
467
468 to = (gchar *)session->cur_to->data;
469
470 if (strchr(to, '<'))
471 g_snprintf(buf, sizeof(buf), "RCPT TO:%s", to);
472 else
473 g_snprintf(buf, sizeof(buf), "RCPT TO:<%s>", to);
474 if (session_send_msg(SESSION(session), buf) < 0)
475 return SM_ERROR;
476 log_print(LOG_PROTOCOL, "SMTP> %s\n", buf);
477
478 session->cur_to = session->cur_to->next;
479
480 return SM_OK;
481 }
482
smtp_data(SMTPSession * session)483 static gint smtp_data(SMTPSession *session)
484 {
485 session->state = SMTP_DATA;
486
487 if (session_send_msg(SESSION(session), "DATA") < 0)
488 return SM_ERROR;
489 log_print(LOG_PROTOCOL, "SMTP> DATA\n");
490
491 return SM_OK;
492 }
493
smtp_send_data(SMTPSession * session)494 static gint smtp_send_data(SMTPSession *session)
495 {
496 session->state = SMTP_SEND_DATA;
497
498 session_send_data(SESSION(session), session->send_data,
499 session->send_data_len);
500
501 return SM_OK;
502 }
503
smtp_make_ready(SMTPSession * session)504 static gint smtp_make_ready(SMTPSession *session)
505 {
506 session->state = SMTP_MAIL_SENT_OK;
507
508 return SM_OK;
509 }
510
smtp_quit(SMTPSession * session)511 gint smtp_quit(SMTPSession *session)
512 {
513 session->state = SMTP_QUIT;
514
515 session_send_msg(SESSION(session), "QUIT");
516 log_print(LOG_PROTOCOL, "SMTP> QUIT\n");
517
518 return SM_OK;
519 }
520
smtp_eom(SMTPSession * session)521 static gint smtp_eom(SMTPSession *session)
522 {
523 session->state = SMTP_EOM;
524
525 if (session_send_msg(SESSION(session), ".") < 0)
526 return SM_ERROR;
527 log_print(LOG_PROTOCOL, "SMTP> . (EOM)\n");
528
529 return SM_OK;
530 }
531
smtp_session_recv_msg(Session * session,const gchar * msg)532 static gint smtp_session_recv_msg(Session *session, const gchar *msg)
533 {
534 SMTPSession *smtp_session = SMTP_SESSION(session);
535 gboolean cont = FALSE;
536 gint ret = 0;
537
538 if (strlen(msg) < 4) {
539 log_warning(LOG_PROTOCOL, _("bad SMTP response\n"));
540 return -1;
541 }
542
543 switch (smtp_session->state) {
544 case SMTP_EHLO:
545 case SMTP_STARTTLS:
546 case SMTP_AUTH:
547 case SMTP_AUTH_PLAIN:
548 case SMTP_AUTH_LOGIN_USER:
549 case SMTP_AUTH_LOGIN_PASS:
550 case SMTP_AUTH_OAUTH2:
551 case SMTP_AUTH_CRAM_MD5:
552 log_print(LOG_PROTOCOL, "ESMTP< %s\n", msg);
553 break;
554 default:
555 log_print(LOG_PROTOCOL, "SMTP< %s\n", msg);
556 break;
557 }
558
559 /* ignore all multiline responses except for EHLO */
560 if (msg[3] == '-' && smtp_session->state != SMTP_EHLO)
561 return session_recv_msg(session);
562
563 if (msg[0] == '5' && msg[1] == '0' &&
564 (msg[2] == '4' || msg[2] == '3' || msg[2] == '1')) {
565 log_warning(LOG_PROTOCOL, _("error occurred on SMTP session\n"));
566 smtp_session->state = SMTP_ERROR;
567 smtp_session->error_val = SM_ERROR;
568 g_free(smtp_session->error_msg);
569 smtp_session->error_msg = g_strdup(msg);
570 return -1;
571 }
572
573 if (!strncmp(msg, "535", 3)) {
574 log_warning(LOG_PROTOCOL, _("error occurred on authentication\n"));
575 smtp_session->state = SMTP_ERROR;
576 smtp_session->error_val = SM_AUTHFAIL;
577 g_free(smtp_session->error_msg);
578 smtp_session->error_msg = g_strdup(msg);
579 return -1;
580 }
581
582 if (msg[0] != '1' && msg[0] != '2' && msg[0] != '3') {
583 log_warning(LOG_PROTOCOL, _("error occurred on SMTP session\n"));
584 smtp_session->state = SMTP_ERROR;
585 smtp_session->error_val = SM_ERROR;
586 g_free(smtp_session->error_msg);
587 smtp_session->error_msg = g_strdup(msg);
588 return -1;
589 }
590
591 if (msg[3] == '-')
592 cont = TRUE;
593 else if (msg[3] != ' ' && msg[3] != '\0') {
594 log_warning(LOG_PROTOCOL, _("bad SMTP response\n"));
595 smtp_session->state = SMTP_ERROR;
596 smtp_session->error_val = SM_UNRECOVERABLE;
597 return -1;
598 }
599
600 switch (smtp_session->state) {
601 case SMTP_READY:
602 if (strstr(msg, "ESMTP"))
603 smtp_session->is_esmtp = TRUE;
604 #ifdef USE_GNUTLS
605 if (smtp_session->user || session->ssl_type != SSL_NONE ||
606 smtp_session->is_esmtp)
607 #else
608 if (smtp_session->user || smtp_session->is_esmtp)
609 #endif
610 ret = smtp_ehlo(smtp_session);
611 else
612 ret = smtp_helo(smtp_session);
613 break;
614 case SMTP_HELO:
615 ret = smtp_from(smtp_session);
616 break;
617 case SMTP_EHLO:
618 ret = smtp_ehlo_recv(smtp_session, msg);
619 if (cont == TRUE)
620 break;
621 if (smtp_session->max_message_size > 0
622 && smtp_session->max_message_size <
623 smtp_session->send_data_len) {
624 log_warning(LOG_PROTOCOL, _("Message is too big "
625 "(Maximum size is %s)\n"),
626 to_human_readable(
627 (goffset)(smtp_session->max_message_size)));
628 smtp_session->state = SMTP_ERROR;
629 smtp_session->error_val = SM_ERROR;
630 return -1;
631 }
632 #ifdef USE_GNUTLS
633 if (session->ssl_type == SSL_STARTTLS &&
634 smtp_session->tls_init_done == FALSE) {
635 ret = smtp_starttls(smtp_session);
636 break;
637 }
638 #endif
639 if (smtp_session->user) {
640 if (smtp_auth(smtp_session) != SM_OK) {
641 #ifdef USE_GNUTLS
642 if (session->ssl_type == SSL_NONE
643 && smtp_session->tls_init_done == FALSE
644 && (smtp_session->avail_auth_type & SMTPAUTH_TLS_AVAILABLE))
645 ret = smtp_starttls(smtp_session);
646 else
647 #endif
648 ret = smtp_from(smtp_session);
649 }
650 } else
651 ret = smtp_from(smtp_session);
652 break;
653 case SMTP_STARTTLS:
654 #ifdef USE_GNUTLS
655 if (session_start_tls(session) < 0) {
656 log_warning(LOG_PROTOCOL, _("couldn't start STARTTLS session\n"));
657 smtp_session->state = SMTP_ERROR;
658 smtp_session->error_val = SM_ERROR;
659 return -1;
660 }
661 smtp_session->tls_init_done = TRUE;
662 ret = smtp_ehlo(smtp_session);
663 #endif
664 break;
665 case SMTP_AUTH:
666 ret = smtp_auth_recv(smtp_session, msg);
667 break;
668 case SMTP_AUTH_LOGIN_USER:
669 ret = smtp_auth_login_user_recv(smtp_session, msg);
670 break;
671 case SMTP_AUTH_PLAIN:
672 case SMTP_AUTH_LOGIN_PASS:
673 case SMTP_AUTH_OAUTH2:
674 case SMTP_AUTH_CRAM_MD5:
675 ret = smtp_from(smtp_session);
676 break;
677 case SMTP_FROM:
678 if (smtp_session->cur_to)
679 ret = smtp_rcpt(smtp_session);
680 break;
681 case SMTP_RCPT:
682 if (smtp_session->cur_to)
683 ret = smtp_rcpt(smtp_session);
684 else
685 ret = smtp_data(smtp_session);
686 break;
687 case SMTP_DATA:
688 ret = smtp_send_data(smtp_session);
689 break;
690 case SMTP_EOM:
691 smtp_make_ready(smtp_session);
692 break;
693 case SMTP_QUIT:
694 session_disconnect(session);
695 break;
696 case SMTP_ERROR:
697 default:
698 log_warning(LOG_PROTOCOL, _("error occurred on SMTP session\n"));
699 smtp_session->error_val = SM_ERROR;
700 return -1;
701 }
702
703 if (cont && ret == SM_OK)
704 return session_recv_msg(session);
705
706 if (ret != SM_OK)
707 smtp_session->error_val = SM_ERROR;
708
709 return ret == SM_OK ? 0 : -1;
710 }
711
smtp_session_send_data_finished(Session * session,guint len)712 static gint smtp_session_send_data_finished(Session *session, guint len)
713 {
714 return smtp_eom(SMTP_SESSION(session));
715 }
716