talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

smtp.c (15772B)


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