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