X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Fcommon%2Fsmtp.c;h=346c63e5f4eae85ffcb431e99fc3023b00976fcc;hp=af730c3936c7d7c57e92a963ed62392d51958af8;hb=f69d8e55a0a3b1bf0075ea7bd7806b00e676153d;hpb=a66b687d916557ab899b3a322ca6b73c5999b1fb diff --git a/src/common/smtp.c b/src/common/smtp.c index af730c393..346c63e5f 100644 --- a/src/common/smtp.c +++ b/src/common/smtp.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2003 Hiroyuki Yamamoto + * Copyright (C) 1999-2004 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,7 +48,7 @@ static gint smtp_helo(SMTPSession *session); static gint smtp_rcpt(SMTPSession *session); static gint smtp_data(SMTPSession *session); static gint smtp_send_data(SMTPSession *session); -static gint smtp_rset(SMTPSession *session); +/* static gint smtp_rset(SMTPSession *session); */ static gint smtp_quit(SMTPSession *session); static gint smtp_eom(SMTPSession *session); @@ -61,12 +61,10 @@ Session *smtp_session_new(void) SMTPSession *session; session = g_new0(SMTPSession, 1); + + session_init(SESSION(session)); + SESSION(session)->type = SESSION_SMTP; - SESSION(session)->server = NULL; - SESSION(session)->port = 0; - SESSION(session)->sock = NULL; - SESSION(session)->state = SESSION_READY; - SESSION(session)->data = NULL; SESSION(session)->recv_msg = smtp_session_recv_msg; @@ -92,10 +90,15 @@ Session *smtp_session_new(void) session->send_data = NULL; session->send_data_len = 0; + session->max_message_size = -1; + session->avail_auth_type = 0; session->forced_auth_type = 0; session->auth_type = 0; + session->error_val = SM_OK; + session->error_msg = NULL; + return SESSION(session); } @@ -109,23 +112,36 @@ static void smtp_session_destroy(Session *session) g_free(smtp_session->from); g_free(smtp_session->send_data); + + g_free(smtp_session->error_msg); } static gint smtp_from(SMTPSession *session) { gchar buf[MSGBUFSIZE]; + gchar *mail_size = NULL; g_return_val_if_fail(session->from != NULL, SM_ERROR); session->state = SMTP_FROM; + + if (session->is_esmtp) + mail_size = g_strdup_printf(" SIZE=%d", session->send_data_len); + else + mail_size = g_strdup(""); + if (strchr(session->from, '<')) - g_snprintf(buf, sizeof(buf), "MAIL FROM: %s", session->from); + g_snprintf(buf, sizeof(buf), "MAIL FROM:%s%s", session->from, + mail_size); else - g_snprintf(buf, sizeof(buf), "MAIL FROM: <%s>", session->from); + g_snprintf(buf, sizeof(buf), "MAIL FROM:<%s>%s", session->from, + mail_size); + + g_free(mail_size); session_send_msg(SESSION(session), SESSION_MSG_NORMAL, buf); - log_print("SMTP> %s\n", buf); + log_print("%sSMTP> %s\n", (session->is_esmtp?"E":""), buf); return SM_OK; } @@ -177,15 +193,15 @@ static gint smtp_auth_recv(SMTPSession *session, const gchar *msg) case SMTPAUTH_CRAM_MD5: session->state = SMTP_AUTH_CRAM_MD5; - if (!strncmp(buf, "334 ", 4)) { + if (!strncmp(msg, "334 ", 4)) { gchar *response; gchar *response64; gchar *challenge; gint challengelen; guchar hexdigest[33]; - challenge = g_malloc(strlen(buf + 4) + 1); - challengelen = base64_decode(challenge, buf + 4, -1); + challenge = g_malloc(strlen(msg + 4) + 1); + challengelen = base64_decode(challenge, msg + 4, -1); challenge[challengelen] = '\0'; log_print("ESMTP< [Decoded: %s]\n", challenge); @@ -264,7 +280,7 @@ static gint smtp_ehlo_recv(SMTPSession *session, const gchar *msg) const gchar *p = msg; p += 3; if (*p == '-' || *p == ' ') p++; - if (g_strncasecmp(p, "AUTH", 4) == 0) { + if (g_ascii_strncasecmp(p, "AUTH", 4) == 0) { p += 5; if (strcasestr(p, "LOGIN")) session->avail_auth_type |= SMTPAUTH_LOGIN; @@ -273,6 +289,10 @@ static gint smtp_ehlo_recv(SMTPSession *session, const gchar *msg) if (strcasestr(p, "DIGEST-MD5")) session->avail_auth_type |= SMTPAUTH_DIGEST_MD5; } + if (g_ascii_strncasecmp(p, "SIZE", 4) == 0) { + p += 5; + session->max_message_size = atoi(p); + } return SM_OK; } else if ((msg[0] == '1' || msg[0] == '2' || msg[0] == '3') && (msg[3] == ' ' || msg[3] == '\0')) @@ -342,9 +362,9 @@ static gint smtp_rcpt(SMTPSession *session) to = (gchar *)session->cur_to->data; if (strchr(to, '<')) - g_snprintf(buf, sizeof(buf), "RCPT TO: %s", to); + g_snprintf(buf, sizeof(buf), "RCPT TO:%s", to); else - g_snprintf(buf, sizeof(buf), "RCPT TO: <%s>", to); + g_snprintf(buf, sizeof(buf), "RCPT TO:<%s>", to); session_send_msg(SESSION(session), SESSION_MSG_NORMAL, buf); log_print("SMTP> %s\n", buf); @@ -373,6 +393,7 @@ static gint smtp_send_data(SMTPSession *session) return SM_OK; } +#if 0 static gint smtp_rset(SMTPSession *session) { session->state = SMTP_RSET; @@ -382,6 +403,7 @@ static gint smtp_rset(SMTPSession *session) return SM_OK; } +#endif static gint smtp_quit(SMTPSession *session) { @@ -408,36 +430,76 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg) SMTPSession *smtp_session = SMTP_SESSION(session); gboolean cont = FALSE; - if (strlen(msg) < 4) + if (strlen(msg) < 4) { + log_warning(_("bad SMTP response\n")); return -1; + } - log_print("SMTP< %s\n", msg); + switch (smtp_session->state) { + case SMTP_EHLO: + case SMTP_STARTTLS: + case SMTP_AUTH: + case SMTP_AUTH_LOGIN_USER: + case SMTP_AUTH_LOGIN_PASS: + case SMTP_AUTH_CRAM_MD5: + log_print("ESMTP< %s\n", msg); + break; + default: + log_print("SMTP< %s\n", msg); + break; + } if (msg[0] == '5' && msg[1] == '0' && (msg[2] == '4' || msg[2] == '3' || msg[2] == '1')) { + log_warning(_("error occurred on SMTP session\n")); smtp_session->state = SMTP_ERROR; + smtp_session->error_val = SM_ERROR; + g_free(smtp_session->error_msg); + smtp_session->error_msg = g_strdup(msg); + return -1; + } + + if (!strncmp(msg, "535", 3)) { + log_warning(_("error occurred on authentication\n")); + smtp_session->state = SMTP_ERROR; + smtp_session->error_val = SM_AUTHFAIL; + g_free(smtp_session->error_msg); + smtp_session->error_msg = g_strdup(msg); return -1; } if (msg[0] != '1' && msg[0] != '2' && msg[0] != '3') { + log_warning(_("error occurred on SMTP session\n")); smtp_session->state = SMTP_ERROR; + smtp_session->error_val = SM_ERROR; + g_free(smtp_session->error_msg); + smtp_session->error_msg = g_strdup(msg); return -1; } if (msg[3] == '-') cont = TRUE; else if (msg[3] != ' ' && msg[3] != '\0') { + log_warning(_("bad SMTP response\n")); smtp_session->state = SMTP_ERROR; + smtp_session->error_val = SM_UNRECOVERABLE; return -1; } + /* ignore all multiline responses except for EHLO */ + if (cont && smtp_session->state != SMTP_EHLO) + return session_recv_msg(session); + switch (smtp_session->state) { case SMTP_READY: + if (strstr(msg, "ESMTP")) + smtp_session->is_esmtp = TRUE; case SMTP_CONNECTED: #if USE_OPENSSL - if (smtp_session->user || session->ssl_type != SSL_NONE) + if (smtp_session->user || session->ssl_type != SSL_NONE || + smtp_session->is_esmtp) #else - if (smtp_session->user) + if (smtp_session->user || smtp_session->is_esmtp) #endif smtp_ehlo(smtp_session); else @@ -450,6 +512,17 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg) smtp_ehlo_recv(smtp_session, msg); if (cont == TRUE) break; + if (smtp_session->max_message_size > 0 + && smtp_session->max_message_size < + smtp_session->send_data_len) { + log_warning(_("Message is too big " + "(Maximum size is %s)\n"), + to_human_readable( + (off_t)(smtp_session->max_message_size))); + smtp_session->state = SMTP_ERROR; + smtp_session->error_val = SM_ERROR; + return -1; + } #if USE_OPENSSL if (session->ssl_type == SSL_STARTTLS && smtp_session->tls_init_done == FALSE) { @@ -465,8 +538,12 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg) break; case SMTP_STARTTLS: #if USE_OPENSSL - if (session_start_tls(session) < 0) + if (session_start_tls(session) < 0) { + log_warning(_("can't start TLS session\n")); + smtp_session->state = SMTP_ERROR; + smtp_session->error_val = SM_ERROR; return -1; + } smtp_session->tls_init_done = TRUE; smtp_ehlo(smtp_session); #endif @@ -502,11 +579,13 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg) break; case SMTP_ERROR: default: + log_warning(_("error occurred on SMTP session\n")); + smtp_session->error_val = SM_ERROR; return -1; } if (cont) - return 1; + return session_recv_msg(session); return 0; }