From: Paul Mangan Date: Tue, 9 Apr 2002 15:21:52 +0000 (+0000) Subject: sync with 0.7.4cvs35 X-Git-Tag: rel_0_7_5~46 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=cb25b493529312c993792f008fb7b33f231f8ced sync with 0.7.4cvs35 --- diff --git a/ChangeLog b/ChangeLog index 5ce59a302..64020867c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2002-04-09 + + * src/prefs_account.c + src/smtp.[ch]: fixed a bug that didn't complie with OpenSSL enabled. + +2002-04-09 + + * src/smtp.[ch] + src/send.c + src/session.[ch]: first reorganization of SMTP protocol handling. + SMTPSession: new class which is a sub class of Session. + smtp_session_new(): moved send_smtp_open() into this function. + smtp_from(): moved SMTP AUTH calls into smtp_auth(). + smtp_auth(): use server response for SMTP AUTH method. + smtp_ehlo(): read server response and set auth type flags. + smtp_helo(): separated EHLO command. + smtp_ok(): return the last server response if the buffer is + specified. + * src/esmtp.[ch]: merged into smtp.[ch]. + * src/imap.c: imap_session_destroy_all(): use session_destroy(). + 2002-04-08 * src/imap.c: imap_open(): show warning message if IMAP4 session diff --git a/ChangeLog.claws b/ChangeLog.claws index 300cd9edc..0111a97fc 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,8 @@ +2002-04-09 [paul] 0.7.4claws74 + + * sync with 0.7.4cvs35 + see ChangeLog entries 2002-04-09 + 2002-04-08 [paul] 0.7.4claws73 * sync with 0.7.4cvs33 diff --git a/ChangeLog.jp b/ChangeLog.jp index 6b152bfa1..bcf05a82f 100644 --- a/ChangeLog.jp +++ b/ChangeLog.jp @@ -1,3 +1,24 @@ +2002-04-09 + + * src/prefs_account.c + src/smtp.[ch]: OpenSSL Í­¸ú»þ¤Ë¥³¥ó¥Ñ¥¤¥ë¤Ç¤­¤Ê¤¤¥Ð¥°¤ò½¤Àµ¡£ + +2002-04-09 + + * src/smtp.[ch] + src/send.c + src/session.[ch]: SMTP ¥×¥í¥È¥³¥ë½èÍý¤ÎºÇ½é¤ÎºÆ¹½À®¡£ + SMTPSession: ¿·µ¬¥¯¥é¥¹¡£ Session ¤Î¥µ¥Ö¥¯¥é¥¹¡£ + smtp_session_new(): send_smtp_open() ¤ò¤³¤Î´Ø¿ô¤Ë°ÜÆ°¡£ + smtp_from(): SMTP AUTH ¤Î¸Æ¤Ó½Ð¤·¤ò smtp_auth() ¤Ë°ÜÆ°¡£ + smtp_auth(): SMTP AUTH ¥á¥½¥Ã¥É¤Ë¥µ¡¼¥Ð¤Î±þÅú¤ò»ÈÍÑ¡£ + smtp_ehlo(): ¥µ¡¼¥Ð¤Î±þÅú¤òÆɤߡ¢Ç§¾Ú¥¿¥¤¥×¤Î¥Õ¥é¥°¤ò¥»¥Ã¥È¡£ + smtp_helo(): EHLO ¥³¥Þ¥ó¥É¤òʬΥ¡£ + smtp_ok(): ¥Ð¥Ã¥Õ¥¡¤¬»ØÄꤵ¤ì¤Æ¤¤¤ì¤ÐºÇ¸å¤Î¥µ¡¼¥Ð¤Î±þÅú¤òÊÖ¤¹ + ¤è¤¦¤Ë¤·¤¿¡£ + * src/esmtp.[ch]: smtp.[ch] ¤Ë¥Þ¡¼¥¸¡£ + * src/imap.c: imap_session_destroy_all(): session_destroy() ¤ò»ÈÍÑ¡£ + 2002-04-08 * src/imap.c: imap_open(): IMAP4 ¥»¥Ã¥·¥ç¥ó¤¬³ÎΩ¤Ç¤­¤Ê¤¤¾ì¹ç·Ù¹ð diff --git a/configure.in b/configure.in index c26dd7b7e..9c46acac8 100644 --- a/configure.in +++ b/configure.in @@ -8,7 +8,7 @@ MINOR_VERSION=7 MICRO_VERSION=4 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=claws73 +EXTRA_VERSION=claws74 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION dnl set $target diff --git a/src/Makefile.am b/src/Makefile.am index ce563ea1b..220e6c31b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,7 +94,6 @@ sylpheed_SOURCES = \ automaton.c automaton.h \ session.c session.h \ smtp.c smtp.h \ - esmtp.c esmtp.h \ pop.c pop.h \ mh.c mh.h \ mbox.c mbox.h \ diff --git a/src/imap.c b/src/imap.c index ee69bb0b3..254737077 100644 --- a/src/imap.c +++ b/src/imap.c @@ -463,7 +463,7 @@ void imap_session_destroy_all(void) IMAPSession *session = (IMAPSession *)session_list->data; imap_cmd_logout(SESSION(session)->sock); - imap_session_destroy(session); + session_destroy(SESSION(session)); } } diff --git a/src/prefs_account.h b/src/prefs_account.h index 6215fd9aa..aff4dda8e 100644 --- a/src/prefs_account.h +++ b/src/prefs_account.h @@ -29,6 +29,7 @@ typedef struct _PrefsAccount PrefsAccount; #include "folder.h" +#include "smtp.h" #ifdef USE_GPGME # include "rfc2015.h" @@ -60,14 +61,6 @@ typedef enum { } SignKeyType; #endif /* USE_GPGME */ -#if USE_SSL -typedef enum { - SSL_SMTP_NONE, - SSL_SMTP_TUNNEL, - SSL_SMTP_STARTTLS -} SSLSMTPType; -#endif /* USE_SSL */ - struct _PrefsAccount { gchar *account_name; diff --git a/src/send.c b/src/send.c index 645be80ba..94e234b12 100644 --- a/src/send.c +++ b/src/send.c @@ -39,7 +39,6 @@ #include "socket.h" #include "ssl.h" #include "smtp.h" -#include "esmtp.h" #include "prefs_common.h" #include "prefs_account.h" #include "account.h" @@ -61,14 +60,6 @@ struct _SendProgressDialog gboolean cancelled; }; -#if USE_SSL -static SockInfo *send_smtp_open (const gchar *server, gushort port, - const gchar *domain, gboolean use_smtp_auth, - SSLSMTPType ssl_type); -#else -static SockInfo *send_smtp_open (const gchar *server, gushort port, - const gchar *domain, gboolean use_smtp_auth); -#endif static gint send_message_data (SendProgressDialog *dialog, SockInfo *sock, FILE *fp, gint size); @@ -257,7 +248,8 @@ gint send_message_local(const gchar *command, FILE *fp) #define EXIT_IF_CANCELLED() \ { \ if (dialog->cancelled) { \ - sock_close(smtp_sock); \ + if (session) \ + session_destroy(session); \ send_progress_dialog_destroy(dialog); \ return -1; \ } \ @@ -268,7 +260,8 @@ gint send_message_local(const gchar *command, FILE *fp) EXIT_IF_CANCELLED(); \ if (!(f)) { \ log_warning("Error occurred while %s\n", s); \ - sock_close(smtp_sock); \ + if (session) \ + session_destroy(session); \ send_progress_dialog_destroy(dialog); \ return -1; \ } \ @@ -282,7 +275,7 @@ gint send_message_local(const gchar *command, FILE *fp) if ((ok = (f)) != SM_OK) { \ log_warning("Error occurred while %s\n", s); \ if (ok == SM_AUTHFAIL) { \ - log_warning("SMTP AUTH failed\n"); \ + log_warning(_("SMTP AUTH failed\n")); \ if (ac_prefs->tmp_pass) { \ g_free(ac_prefs->tmp_pass); \ ac_prefs->tmp_pass = NULL; \ @@ -292,9 +285,9 @@ gint send_message_local(const gchar *command, FILE *fp) ac_prefs->tmp_smtp_pass = NULL; \ } \ } \ - if (smtp_quit(smtp_sock) != SM_OK) \ - log_warning("Error occurred while sending QUIT\n"); \ - sock_close(smtp_sock); \ + if (smtp_quit(session->sock) != SM_OK) \ + log_warning(_("Error occurred while sending QUIT\n")); \ + session_destroy(session); \ send_progress_dialog_destroy(dialog); \ return -1; \ } \ @@ -303,8 +296,8 @@ gint send_message_local(const gchar *command, FILE *fp) gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp) { - SockInfo *smtp_sock = NULL; SendProgressDialog *dialog; + Session *session = NULL; GtkCList *clist; const gchar *text[3]; gchar buf[BUFFSIZE]; @@ -376,14 +369,14 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, GTK_EVENTS_FLUSH(); #if USE_SSL - SEND_EXIT_IF_ERROR((smtp_sock = send_smtp_open + SEND_EXIT_IF_ERROR((session = smtp_session_new (ac_prefs->smtp_server, port, domain, - ac_prefs->use_smtp_auth, ac_prefs->ssl_smtp)), + user, pass, ac_prefs->ssl_smtp)), "connecting to server"); #else - SEND_EXIT_IF_ERROR((smtp_sock = send_smtp_open + SEND_EXIT_IF_ERROR((session = smtp_session_new (ac_prefs->smtp_server, port, domain, - ac_prefs->use_smtp_auth)), + user, pass)), "connecting to server"); #endif @@ -392,33 +385,33 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, GTK_EVENTS_FLUSH(); SEND_EXIT_IF_NOTOK - (smtp_from(smtp_sock, ac_prefs->address, user, pass, - ac_prefs->use_smtp_auth), + (smtp_from(SMTP_SESSION(session), ac_prefs->address), "sending MAIL FROM"); progress_dialog_set_label(dialog->dialog, _("Sending RCPT TO...")); GTK_EVENTS_FLUSH(); for (cur = to_list; cur != NULL; cur = cur->next) - SEND_EXIT_IF_NOTOK(smtp_rcpt(smtp_sock, (gchar *)cur->data), + SEND_EXIT_IF_NOTOK(smtp_rcpt(session->sock, (gchar *)cur->data), "sending RCPT TO"); progress_dialog_set_label(dialog->dialog, _("Sending DATA...")); GTK_EVENTS_FLUSH(); - SEND_EXIT_IF_NOTOK(smtp_data(smtp_sock), "sending DATA"); + SEND_EXIT_IF_NOTOK(smtp_data(session->sock), "sending DATA"); /* send main part */ - SEND_EXIT_IF_ERROR(send_message_data(dialog, smtp_sock, fp, size) == 0, - "sending data"); + SEND_EXIT_IF_ERROR + (send_message_data(dialog, session->sock, fp, size) == 0, + "sending data"); progress_dialog_set_label(dialog->dialog, _("Quitting...")); GTK_EVENTS_FLUSH(); - SEND_EXIT_IF_NOTOK(smtp_eom(smtp_sock), "terminating data"); - SEND_EXIT_IF_NOTOK(smtp_quit(smtp_sock), "sending QUIT"); + SEND_EXIT_IF_NOTOK(smtp_eom(session->sock), "terminating data"); + SEND_EXIT_IF_NOTOK(smtp_quit(session->sock), "sending QUIT"); - sock_close(smtp_sock); + session_destroy(session); send_progress_dialog_destroy(dialog); return 0; @@ -523,80 +516,6 @@ static gint send_message_data(SendProgressDialog *dialog, SockInfo *sock, #undef SEND_EXIT_IF_ERROR #undef SEND_DIALOG_UPDATE -#if USE_SSL -static SockInfo *send_smtp_open(const gchar *server, gushort port, - const gchar *domain, gboolean use_smtp_auth, - SSLSMTPType ssl_type) -#else -static SockInfo *send_smtp_open(const gchar *server, gushort port, - const gchar *domain, gboolean use_smtp_auth) -#endif -{ - SockInfo *sock; - gint val; - - g_return_val_if_fail(server != NULL, NULL); - - if ((sock = sock_connect(server, port)) == NULL) { - log_warning(_("Can't connect to SMTP server: %s:%d\n"), - server, port); - return NULL; - } - -#if USE_SSL - if (ssl_type == SSL_SMTP_TUNNEL && !ssl_init_socket(sock)) { - log_warning(_("SSL connection failed")); - sock_close(sock); - return NULL; - } -#endif - - if (smtp_ok(sock) != SM_OK) { - log_warning(_("Error occurred while connecting to %s:%d\n"), - server, port); - sock_close(sock); - return NULL; - } - -#if USE_SSL - val = smtp_helo(sock, domain ? domain : get_domain_name(), - use_smtp_auth || ssl_type == SSL_SMTP_STARTTLS); -#else - val = smtp_helo(sock, domain ? domain : get_domain_name(), - use_smtp_auth); -#endif - - if (val != SM_OK) { - log_warning(_("Error occurred while sending HELO\n")); - sock_close(sock); - return NULL; - } - -#if USE_SSL - if (ssl_type == SSL_SMTP_STARTTLS) { - val = esmtp_starttls(sock); - if (val != SM_OK) { - log_warning(_("Error occurred while sending STARTTLS\n")); - sock_close(sock); - return NULL; - } - if (!ssl_init_socket_with_method(sock, SSL_METHOD_TLSv1)) { - sock_close(sock); - return NULL; - } - val = esmtp_ehlo(sock, domain ? domain : get_domain_name()); - if (val != SM_OK) { - log_warning(_("Error occurred while sending EHLO\n")); - sock_close(sock); - return NULL; - } - } -#endif - - return sock; -} - - static SendProgressDialog *send_progress_dialog_create(void) { SendProgressDialog *dialog; diff --git a/src/session.c b/src/session.c index bf4ae4fdc..391bb173e 100644 --- a/src/session.c +++ b/src/session.c @@ -22,6 +22,7 @@ #include "session.h" #include "imap.h" #include "news.h" +#include "smtp.h" void session_destroy(Session *session) { @@ -34,6 +35,9 @@ void session_destroy(Session *session) case SESSION_NEWS: news_session_destroy(NNTP_SESSION(session)); break; + case SESSION_SMTP: + smtp_session_destroy(SMTP_SESSION(session)); + break; default: break; } diff --git a/src/session.h b/src/session.h index eaa776624..39b83c880 100644 --- a/src/session.h +++ b/src/session.h @@ -31,7 +31,8 @@ typedef struct _Session Session; typedef enum { SESSION_IMAP, - SESSION_NEWS + SESSION_NEWS, + SESSION_SMTP } SessionType; typedef enum { diff --git a/src/smtp.c b/src/smtp.c index fdf52218e..709faef53 100644 --- a/src/smtp.c +++ b/src/smtp.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * Copyright (C) 1999-2002 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 @@ -17,54 +17,142 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include +#include "intl.h" #include "smtp.h" -#include "esmtp.h" #include "socket.h" +#include "md5.h" +#include "base64.h" #include "utils.h" -#define MSGBUFSIZE 8192 - static gint verbose = 1; -static gchar smtp_response[MSGBUFSIZE]; -gint smtp_helo(SockInfo *sock, const gchar *hostname, gboolean esmtp) +static gint smtp_starttls(SockInfo *sock); +static gint smtp_auth_cram_md5(SockInfo *sock, gchar *buf, gint len); +static gint smtp_auth_login(SockInfo *sock, gchar *buf, gint len); +static gint smtp_ok(SockInfo *sock, gchar *buf, gint len); + +#if USE_SSL +Session *smtp_session_new(const gchar *server, gushort port, + const gchar *domain, + const gchar *user, const gchar *pass, + SSLSMTPType ssl_type) +#else +Session *smtp_session_new(const gchar *server, gushort port, + const gchar *domain, + const gchar *user, const gchar *pass) +#endif { - if (esmtp) - return esmtp_ehlo(sock, hostname); - else { - sock_printf(sock, "HELO %s\r\n", hostname); - if (verbose) - log_print("SMTP> HELO %s\n", hostname); + SMTPSession *session; + SockInfo *sock; + gboolean use_esmtp; + SMTPAuthType avail_auth_type = 0; + gint val; + + g_return_val_if_fail(server != NULL, NULL); + +#if USE_SSL + use_esmtp = user != NULL || ssl_type == SSL_SMTP_STARTTLS; +#else + use_esmtp = user != NULL; +#endif + + if ((sock = sock_connect(server, port)) == NULL) { + log_warning(_("Can't connect to SMTP server: %s:%d\n"), + server, port); + return NULL; + } + +#if USE_SSL + if (ssl_type == SSL_SMTP_TUNNEL && !ssl_init_socket(sock)) { + log_warning(_("SSL connection failed")); + sock_close(sock); + return NULL; + } +#endif - return smtp_ok(sock); + if (smtp_ok(sock, NULL, 0) != SM_OK) { + log_warning(_("Error occurred while connecting to %s:%d\n"), + server, port); + sock_close(sock); + return NULL; } + + if (!domain) + domain = get_domain_name(); + + if (use_esmtp) + val = smtp_ehlo(sock, domain, &avail_auth_type); + else + val = smtp_helo(sock, domain); + if (val != SM_OK) { + log_warning(_("Error occurred while sending HELO\n")); + sock_close(sock); + return NULL; + } + +#if USE_SSL + if (ssl_type == SSL_SMTP_STARTTLS) { + val = smtp_starttls(sock); + if (val != SM_OK) { + log_warning(_("Error occurred while sending STARTTLS\n")); + sock_close(sock); + return NULL; + } + if (!ssl_init_socket_with_method(sock, SSL_METHOD_TLSv1)) { + sock_close(sock); + return NULL; + } + val = smtp_ehlo(sock, domain, &avail_auth_type); + if (val != SM_OK) { + log_warning(_("Error occurred while sending EHLO\n")); + sock_close(sock); + return NULL; + } + } +#endif + + session = g_new(SMTPSession, 1); + SESSION(session)->type = SESSION_SMTP; + SESSION(session)->server = g_strdup(server); + SESSION(session)->sock = sock; + SESSION(session)->connected = TRUE; + SESSION(session)->phase = SESSION_READY; + SESSION(session)->last_access_time = 0; + SESSION(session)->data = NULL; + session->avail_auth_type = avail_auth_type; + session->user = user ? g_strdup(user) : NULL; + session->pass = pass ? g_strdup(pass) : + user ? g_strdup("") : NULL; + + return SESSION(session); +} + +void smtp_session_destroy(SMTPSession *session) +{ + sock_close(SESSION(session)->sock); + SESSION(session)->sock = NULL; + + g_free(session->user); + g_free(session->pass); } -gint smtp_from(SockInfo *sock, const gchar *from, - const gchar *userid, const gchar *passwd, - gboolean use_smtp_auth) +gint smtp_from(SMTPSession *session, const gchar *from) { gchar buf[MSGBUFSIZE]; - SMTPAuthType authtype; - - if (use_smtp_auth) { - /* exist AUTH-Type CRAM_MD5 */ - if (!smtp_auth_methods[SMTPAUTH_CRAM_MD5] - || esmtp_auth_cram_md5(sock) == SM_ERROR) { - /* exist AUTH-Type LOGIN */ - if (!smtp_auth_methods[SMTPAUTH_LOGIN] - || esmtp_auth_login(sock) == SM_ERROR) - return SM_ERROR; - else - authtype = SMTPAUTH_LOGIN; - } else - authtype = SMTPAUTH_CRAM_MD5; - - if (esmtp_auth(sock, authtype, userid, passwd) != SM_OK) + + g_return_val_if_fail(session != NULL, SM_ERROR); + g_return_val_if_fail(from != NULL, SM_ERROR); + + if (session->user) { + if (smtp_auth(session) != SM_OK) return SM_AUTHFAIL; } @@ -73,11 +161,183 @@ gint smtp_from(SockInfo *sock, const gchar *from, else g_snprintf(buf, sizeof(buf), "MAIL FROM: <%s>", from); - sock_printf(sock, "%s\r\n", buf); + sock_printf(SESSION(session)->sock, "%s\r\n", buf); if (verbose) log_print("SMTP> %s\n", buf); - return smtp_ok(sock); + return smtp_ok(SESSION(session)->sock, NULL, 0); +} + +gint smtp_auth(SMTPSession *session) +{ + gchar buf[MSGBUFSIZE]; + SMTPAuthType authtype = 0; + guchar hexdigest[33]; + gchar *challenge, *response, *response64; + gint challengelen; + SockInfo *sock; + + g_return_val_if_fail(session != NULL, SM_ERROR); + g_return_val_if_fail(session->user != NULL, SM_ERROR); + + sock = SESSION(session)->sock; + + if ((session->avail_auth_type & SMTPAUTH_CRAM_MD5) != 0 && + smtp_auth_cram_md5(sock, buf, sizeof(buf)) == SM_OK) + authtype = SMTPAUTH_CRAM_MD5; + else if ((session->avail_auth_type & SMTPAUTH_LOGIN) != 0 && + smtp_auth_login(sock, buf, sizeof(buf)) == SM_OK) + authtype = SMTPAUTH_LOGIN; + else { + log_warning(_("SMTP AUTH not available\n")); + return SM_AUTHFAIL; + } + + switch (authtype) { + case SMTPAUTH_LOGIN: + if (!strncmp(buf, "334 ", 4)) + to64frombits(buf, session->user, strlen(session->user)); + else + /* Server rejects AUTH */ + g_snprintf(buf, sizeof(buf), "*"); + + sock_printf(sock, "%s\r\n", buf); + if (verbose) log_print("ESMTP> [USERID]\n"); + + smtp_ok(sock, buf, sizeof(buf)); + + if (!strncmp(buf, "334 ", 4)) + to64frombits(buf, session->pass, strlen(session->pass)); + else + /* Server rejects AUTH */ + g_snprintf(buf, sizeof(buf), "*"); + + sock_printf(sock, "%s\r\n", buf); + if (verbose) log_print("ESMTP> [PASSWORD]\n"); + break; + case SMTPAUTH_CRAM_MD5: + if (!strncmp(buf, "334 ", 4)) { + challenge = g_malloc(strlen(buf + 4) + 1); + challengelen = from64tobits(challenge, buf + 4); + challenge[challengelen] = '\0'; + if (verbose) + log_print("ESMTP< [Decoded: %s]\n", challenge); + + g_snprintf(buf, sizeof(buf), "%s", session->pass); + md5_hex_hmac(hexdigest, challenge, challengelen, + buf, strlen(session->pass)); + g_free(challenge); + + response = g_strdup_printf + ("%s %s", session->user, hexdigest); + if (verbose) + log_print("ESMTP> [Encoded: %s]\n", response); + + response64 = g_malloc((strlen(response) + 3) * 2 + 1); + to64frombits(response64, response, strlen(response)); + g_free(response); + + sock_printf(sock, "%s\r\n", response64); + if (verbose) log_print("ESMTP> %s\n", response64); + g_free(response64); + } else { + /* Server rejects AUTH */ + g_snprintf(buf, sizeof(buf), "*"); + sock_printf(sock, "%s\r\n", buf); + if (verbose) + log_print("ESMTP> %s\n", buf); + } + break; + case SMTPAUTH_DIGEST_MD5: + default: + /* stop smtp_auth when no correct authtype */ + g_snprintf(buf, sizeof(buf), "*"); + sock_printf(sock, "%s\r\n", buf); + if (verbose) log_print("ESMTP> %s\n", buf); + break; + } + + return smtp_ok(sock, NULL, 0); +} + +gint smtp_ehlo(SockInfo *sock, const gchar *hostname, + SMTPAuthType *avail_auth_type) +{ + gchar buf[MSGBUFSIZE]; + + *avail_auth_type = 0; + + sock_printf(sock, "EHLO %s\r\n", hostname); + if (verbose) + log_print("ESMTP> EHLO %s\n", hostname); + + while ((sock_gets(sock, buf, sizeof(buf) - 1)) != -1) { + if (strlen(buf) < 4) + return SM_ERROR; + strretchomp(buf); + + if (verbose) + log_print("ESMTP< %s\n", buf); + + if (strncmp(buf, "250-", 4) == 0) { + gchar *p = buf; + p += 4; + if (g_strncasecmp(p, "AUTH ", 5) == 0) { + p += 5; + if (strcasestr(p, "LOGIN")) + *avail_auth_type |= SMTPAUTH_LOGIN; + if (strcasestr(p, "CRAM-MD5")) + *avail_auth_type |= SMTPAUTH_CRAM_MD5; + if (strcasestr(p, "DIGEST-MD5")) + *avail_auth_type |= SMTPAUTH_DIGEST_MD5; + } + } else if ((buf[0] == '1' || buf[0] == '2' || buf[0] == '3') && + (buf[3] == ' ' || buf[3] == '\0')) + return SM_OK; + else if (buf[3] != '-') + return SM_ERROR; + else if (buf[0] == '5' && buf[1] == '0' && + (buf[2] == '4' || buf[2] == '3' || buf[2] == '1')) + return SM_ERROR; + } + + return SM_UNRECOVERABLE; +} + +static gint smtp_starttls(SockInfo *sock) +{ + sock_printf(sock, "STARTTLS\r\n"); + if (verbose) + log_print("ESMTP> STARTTLS\n"); + + return smtp_ok(sock, NULL, 0); +} + +static gint smtp_auth_cram_md5(SockInfo *sock, gchar *buf, gint len) +{ + sock_printf(sock, "AUTH CRAM-MD5\r\n"); + if (verbose) + log_print("ESMTP> AUTH CRAM-MD5\n"); + + return smtp_ok(sock, buf, len); +} + +static gint smtp_auth_login(SockInfo *sock, gchar *buf, gint len) +{ + sock_printf(sock, "AUTH LOGIN\r\n"); + if (verbose) + log_print("ESMTP> AUTH LOGIN\n"); + + return smtp_ok(sock, buf, len); +} + +gint smtp_helo(SockInfo *sock, const gchar *hostname) +{ + sock_printf(sock, "HELO %s\r\n", hostname); + if (verbose) + log_print("SMTP> HELO %s\n", hostname); + + return smtp_ok(sock, NULL, 0); } gint smtp_rcpt(SockInfo *sock, const gchar *to) @@ -93,7 +353,7 @@ gint smtp_rcpt(SockInfo *sock, const gchar *to) if (verbose) log_print("SMTP> %s\n", buf); - return smtp_ok(sock); + return smtp_ok(sock, NULL, 0); } gint smtp_data(SockInfo *sock) @@ -102,7 +362,7 @@ gint smtp_data(SockInfo *sock) if (verbose) log_print("SMTP> DATA\n"); - return smtp_ok(sock); + return smtp_ok(sock, NULL, 0); } gint smtp_rset(SockInfo *sock) @@ -111,7 +371,7 @@ gint smtp_rset(SockInfo *sock) if (verbose) log_print("SMTP> RSET\n"); - return smtp_ok(sock); + return smtp_ok(sock, NULL, 0); } gint smtp_quit(SockInfo *sock) @@ -120,7 +380,7 @@ gint smtp_quit(SockInfo *sock) if (verbose) log_print("SMTP> QUIT\n"); - return smtp_ok(sock); + return smtp_ok(sock, NULL, 0); } gint smtp_eom(SockInfo *sock) @@ -129,31 +389,33 @@ gint smtp_eom(SockInfo *sock) if (verbose) log_print("SMTP> . (EOM)\n"); - return smtp_ok(sock); + return smtp_ok(sock, NULL, 0); } -gint smtp_ok(SockInfo *sock) +static gint smtp_ok(SockInfo *sock, gchar *buf, gint len) { - while ((sock_gets(sock, smtp_response, sizeof(smtp_response) - 1)) - != -1) { - if (strlen(smtp_response) < 4) + gchar tmpbuf[MSGBUFSIZE]; + + if (!buf) { + buf = tmpbuf; + len = sizeof(tmpbuf); + } + + while ((sock_gets(sock, buf, len - 1)) != -1) { + if (strlen(buf) < 4) return SM_ERROR; - strretchomp(smtp_response); + strretchomp(buf); if (verbose) - log_print("SMTP< %s\n", smtp_response); + log_print("SMTP< %s\n", buf); - if ((smtp_response[0] == '1' || smtp_response[0] == '2' || - smtp_response[0] == '3') && - (smtp_response[3] == ' ' || smtp_response[3] == '\0')) + if ((buf[0] == '1' || buf[0] == '2' || buf[0] == '3') && + (buf[3] == ' ' || buf[3] == '\0')) return SM_OK; - else if (smtp_response[3] != '-') + else if (buf[3] != '-') return SM_ERROR; - else if (smtp_response[0] == '5' && - smtp_response[1] == '0' && - (smtp_response[2] == '4' || - smtp_response[2] == '3' || - smtp_response[2] == '1')) + else if (buf[0] == '5' && buf[1] == '0' && + (buf[2] == '4' || buf[2] == '3' || buf[2] == '1')) return SM_ERROR; } diff --git a/src/smtp.h b/src/smtp.h index 03b5404e2..8e5707dff 100644 --- a/src/smtp.h +++ b/src/smtp.h @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * Copyright (C) 1999-2002 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 @@ -20,11 +20,23 @@ #ifndef __SMTP_H__ #define __SMTP_H__ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include "socket.h" +#if USE_SSL +# include "ssl.h" +#endif +#include "session.h" + +typedef struct _SMTPSession SMTPSession; + +#define SMTP_SESSION(obj) ((SMTPSession *)obj) -#define SMTPBUFSIZE 256 +#define MSGBUFSIZE 8192 #define SM_OK 0 #define SM_ERROR 128 @@ -35,14 +47,62 @@ #define ESMTP_SIZE 0x02 #define ESMTP_ETRN 0x04 -gint smtp_helo(SockInfo *sock, const gchar *hostname, gboolean esmtp); -gint smtp_from(SockInfo *sock, const gchar *from, const gchar *userid, - const gchar *passwd, gboolean use_smtp_auth); -gint smtp_rcpt(SockInfo *sock, const gchar *to); -gint smtp_data(SockInfo *sock); -gint smtp_rset(SockInfo *sock); -gint smtp_quit(SockInfo *sock); -gint smtp_eom(SockInfo *sock); -gint smtp_ok(SockInfo *sock); +#if USE_SSL +typedef enum +{ + SSL_SMTP_NONE, + SSL_SMTP_TUNNEL, + SSL_SMTP_STARTTLS +} SSLSMTPType; +#endif + +typedef enum +{ + SMTPAUTH_LOGIN = 1 << 0, + SMTPAUTH_CRAM_MD5 = 1 << 1, + SMTPAUTH_DIGEST_MD5 = 1 << 2 +} SMTPAuthType; + +struct _SMTPSession +{ + Session session; + + SMTPAuthType avail_auth_type; + gchar *user; + gchar *pass; +}; + +#if USE_SSL +Session *smtp_session_new (const gchar *server, + gushort port, + const gchar *domain, + const gchar *user, + const gchar *pass, + SSLSMTPType ssl_type); +#else +Session *smtp_session_new (const gchar *server, + gushort port, + const gchar *domain, + const gchar *user, + const gchar *pass); +#endif +void smtp_session_destroy (SMTPSession *session); + +gint smtp_from (SMTPSession *session, + const gchar *from); +gint smtp_auth (SMTPSession *session); + +gint smtp_ehlo (SockInfo *sock, + const gchar *hostname, + SMTPAuthType *avail_auth_type); + +gint smtp_helo (SockInfo *sock, + const gchar *hostname); +gint smtp_rcpt (SockInfo *sock, + const gchar *to); +gint smtp_data (SockInfo *sock); +gint smtp_rset (SockInfo *sock); +gint smtp_quit (SockInfo *sock); +gint smtp_eom (SockInfo *sock); #endif /* __SMTP_H__ */