sync with 0.7.4cvs35
authorPaul Mangan <paul@claws-mail.org>
Tue, 9 Apr 2002 15:21:52 +0000 (15:21 +0000)
committerPaul Mangan <paul@claws-mail.org>
Tue, 9 Apr 2002 15:21:52 +0000 (15:21 +0000)
12 files changed:
ChangeLog
ChangeLog.claws
ChangeLog.jp
configure.in
src/Makefile.am
src/imap.c
src/prefs_account.h
src/send.c
src/session.c
src/session.h
src/smtp.c
src/smtp.h

index 5ce59a3..6402086 100644 (file)
--- 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
index 300cd9e..0111a97 100644 (file)
@@ -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
index 6b152bf..bcf05a8 100644 (file)
@@ -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 ¥»¥Ã¥·¥ç¥ó¤¬³ÎΩ¤Ç¤­¤Ê¤¤¾ì¹ç·Ù¹ð
index c26dd7b..9c46aca 100644 (file)
@@ -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
index ce563ea..220e6c3 100644 (file)
@@ -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 \
index ee69bb0..2547370 100644 (file)
@@ -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));
        }
 }
 
index 6215fd9..aff4dda 100644 (file)
@@ -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;
index 645be80..94e234b 100644 (file)
@@ -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;
index bf4ae4f..391bb17 100644 (file)
@@ -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;
        }
index eaa7766..39b83c8 100644 (file)
@@ -31,7 +31,8 @@ typedef struct _Session       Session;
 
 typedef enum {
        SESSION_IMAP,
-       SESSION_NEWS
+       SESSION_NEWS,
+       SESSION_SMTP
 } SessionType;
 
 typedef enum {
index fdf5221..709faef 100644 (file)
@@ -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
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
 #include <glib.h>
 #include <stdio.h>
 #include <string.h>
 
+#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;
        }
 
index 03b5404..8e5707d 100644 (file)
@@ -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
 #ifndef __SMTP_H__
 #define __SMTP_H__
 
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
 #include <glib.h>
 
 #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
 #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__ */