2005-04-30 [colin] 1.9.6cvs47
authorColin Leroy <colin@colino.net>
Sat, 30 Apr 2005 16:47:40 +0000 (16:47 +0000)
committerColin Leroy <colin@colino.net>
Sat, 30 Apr 2005 16:47:40 +0000 (16:47 +0000)
* src/prefs_account.h
* src/procmsg.c
* src/send_message.c
* src/common/smtp.c
* src/common/smtp.h
Try to batch sending mails (per account) instead of
reconnecting to server every time.

ChangeLog-gtk2.claws
PATCHSETS
configure.ac
src/common/smtp.c
src/common/smtp.h
src/prefs_account.h
src/procmsg.c
src/send_message.c

index 1c84f2850266b0819585af34efa1b56bc6117796..f74cbdb1b07b504d7d3c9ca4719167335ced5aa6 100644 (file)
@@ -1,3 +1,13 @@
+2005-04-30 [colin]     1.9.6cvs47
+
+       * src/prefs_account.h
+       * src/procmsg.c
+       * src/send_message.c
+       * src/common/smtp.c
+       * src/common/smtp.h
+               Try to batch sending mails (per account) instead of
+               reconnecting to server every time.
+
 2005-04-29 [colin]     1.9.6cvs46
 
        * src/messageview.c
index 4b62689cd9344446c7c64d7a96018626baae08b1..a0625770a911022d798c1512f8f55b678302f347 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.5.2.4 -r 1.5.2.5 src/setup.c; cvs diff -u -r 1.5.2.3 -r 1.5.2.4 src/statusbar.c; cvs diff -u -r 1.3 -r 1.4 src/statusbar.h; cvs diff -u -r 1.96.2.52 -r 1.96.2.53 src/textview.c; cvs diff -u -r 1.5.2.11 -r 1.5.2.12 src/gtk/gtkutils.c; cvs diff -u -r 1.4.2.9 -r 1.4.2.10 src/gtk/gtkutils.h; ) > 1.9.6cvs44.patchset
 ( cvs diff -u -r 1.1.2.500 -r 1.1.2.501 ChangeLog-gtk2.claws; cvs diff -u -r 1.5.2.5 -r 1.5.2.6 src/setup.c; ) > 1.9.6cvs45.patchset
 ( cvs diff -u -r 1.94.2.50 -r 1.94.2.51 src/messageview.c; cvs diff -u -r 1.204.2.35 -r 1.204.2.36 src/prefs_common.c; cvs diff -u -r 1.103.2.14 -r 1.103.2.15 src/prefs_common.h; cvs diff -u -r 1.59.2.15 -r 1.59.2.16 src/prefs_filtering.c; ) > 1.9.6cvs46.patchset
+( cvs diff -u -r 1.49.2.10 -r 1.49.2.11 src/prefs_account.h; cvs diff -u -r 1.150.2.22 -r 1.150.2.23 src/procmsg.c; cvs diff -u -r 1.17.2.8 -r 1.17.2.9 src/send_message.c; cvs diff -u -r 1.11.2.9 -r 1.11.2.10 src/common/smtp.c; cvs diff -u -r 1.6.2.5 -r 1.6.2.6 src/common/smtp.h; ) > 1.9.6cvs47.patchset
index dbcc6db56c1b23ada2d53c718df02c64dddba880..377b3c41be10210a3224bbfbda2193e57b219d85 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=6
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=46
+EXTRA_VERSION=47
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 23087b5f0ae3cc68b0d00dcb3bfd12e0b8bddb72..a28ef13eec2be1cbc5f70c45100446da664b4977 100644 (file)
@@ -34,7 +34,7 @@
 
 static void smtp_session_destroy(Session *session);
 
-static gint smtp_from(SMTPSession *session);
+gint smtp_from(SMTPSession *session);
 
 static gint smtp_auth(SMTPSession *session);
 static gint smtp_starttls(SMTPSession *session);
@@ -49,8 +49,8 @@ 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_quit(SMTPSession *session);
+static gint smtp_make_ready(SMTPSession *session);
+gint smtp_quit(SMTPSession *session);
 static gint smtp_eom(SMTPSession *session);
 
 static gint smtp_session_recv_msg(Session *session, const gchar *msg);
@@ -118,7 +118,7 @@ static void smtp_session_destroy(Session *session)
        g_free(smtp_session->error_msg);
 }
 
-static gint smtp_from(SMTPSession *session)
+gint smtp_from(SMTPSession *session)
 {
        gchar buf[MSGBUFSIZE];
        gchar *mail_size = NULL;
@@ -466,7 +466,14 @@ static gint smtp_rset(SMTPSession *session)
 }
 #endif
 
-static gint smtp_quit(SMTPSession *session)
+static gint smtp_make_ready(SMTPSession *session)
+{
+       session->state = SMTP_MAIL_SENT_OK;
+
+       return SM_OK;
+}
+
+gint smtp_quit(SMTPSession *session)
 {
        session->state = SMTP_QUIT;
 
@@ -635,7 +642,7 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg)
                smtp_send_data(smtp_session);
                break;
        case SMTP_EOM:
-               smtp_quit(smtp_session);
+               smtp_make_ready(smtp_session);
                break;
        case SMTP_QUIT:
                session_disconnect(session);
index 642919c589fbe6b49f6bf372551fb2a823713b53..e30deae19a6834e43b51b3b7178720cd486aac17 100644 (file)
@@ -79,6 +79,7 @@ typedef enum
        SMTP_QUIT,
        SMTP_ERROR,
        SMTP_DISCONNECTED,
+       SMTP_MAIL_SENT_OK,
 
        N_SMTP_PHASE
 } SMTPState;
@@ -115,6 +116,8 @@ struct _SMTPSession
        gchar *error_msg;
        gboolean is_esmtp;
        ESMTPFlag esmtp_flags;
+       
+       void *dialog;
 };
 
 Session *smtp_session_new      (void);
index faee0bd09d0d3bb791ff5c4d939e53f3ad61d57d..79c9327099a74703b92d31451644f8ca3d6c40d2 100644 (file)
@@ -177,6 +177,7 @@ struct _PrefsAccount
 
        Folder *folder;
        GHashTable *privacy_prefs;
+       SMTPSession *session;
 };
 
 void prefs_account_init                        (void);
index a77a50066d2ac718fd475c7d2ecc07f21eb290a9..18f3719646f36d99cfdcf94a5aa43c7f44df0b57 100644 (file)
 #include "msgcache.h"
 #include "partial_download.h"
 
+static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_session);
+
+enum
+{
+       Q_SENDER           = 0,
+       Q_SMTPSERVER       = 1,
+       Q_RECIPIENTS       = 2,
+       Q_NEWSGROUPS       = 3,
+       Q_MAIL_ACCOUNT_ID  = 4,
+       Q_NEWS_ACCOUNT_ID  = 5,
+       Q_SAVE_COPY_FOLDER = 6,
+       Q_REPLY_MESSAGE_ID = 7,
+       Q_FWD_MESSAGE_ID   = 8,
+       Q_PRIVACY_SYSTEM   = 9,
+       Q_ENCRYPT          = 10,
+       Q_ENCRYPT_DATA     = 11,
+};
+
 GHashTable *procmsg_msg_hash_table_create(GSList *mlist)
 {
        GHashTable *msg_table;
@@ -638,6 +656,134 @@ void procmsg_empty_all_trash(void)
        }
 }
 
+static PrefsAccount *procmsg_get_account_from_file(const gchar *file)
+{
+       PrefsAccount *mailac = NULL;
+       FILE *fp;
+       int hnum;
+       gchar buf[BUFFSIZE];
+       
+       g_return_val_if_fail(file != NULL, NULL);
+
+       if ((fp = fopen(file, "rb")) == NULL) {
+               FILE_OP_ERROR(file, "fopen");
+               return NULL;
+       }
+       static HeaderEntry qentry[] = {{"S:",    NULL, FALSE},
+                                      {"SSV:",  NULL, FALSE},
+                                      {"R:",    NULL, FALSE},
+                                      {"NG:",   NULL, FALSE},
+                                      {"MAID:", NULL, FALSE},
+                                      {"NAID:", NULL, FALSE},
+                                      {"SCF:",  NULL, FALSE},
+                                      {"RMID:", NULL, FALSE},
+                                      {"FMID:", NULL, FALSE},
+                                      {"X-Sylpheed-Privacy-System:", NULL, FALSE},
+                                      {"X-Sylpheed-Encrypt:", NULL, FALSE},
+                                      {"X-Sylpheed-Encrypt-Data:", NULL, FALSE},
+                                      {NULL,    NULL, FALSE}};
+
+       while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
+              != -1) {
+               gchar *p = buf + strlen(qentry[hnum].name);
+
+               if (hnum == Q_MAIL_ACCOUNT_ID) {
+                       mailac = account_find_from_id(atoi(p));
+                       break;
+               }
+       }
+       fclose(fp);
+       return mailac;
+}
+
+static GSList *procmsg_list_sort_by_account(FolderItem *queue, GSList *list)
+{
+       GSList *result = NULL;
+       GSList *orig = NULL;
+       PrefsAccount *last_account = NULL;
+       MsgInfo *msg = NULL;
+       GSList *cur = NULL;
+       gboolean nothing_to_sort = TRUE;
+
+       if (!list)
+               return NULL;
+
+       orig = g_slist_copy(list);
+       
+       msg = (MsgInfo *)orig->data;
+       
+       for (cur = orig; cur; cur = cur->next)
+               debug_print("sort before %s\n", ((MsgInfo *)cur->data)->from);
+       
+       debug_print("\n");
+
+parse_again:   
+       nothing_to_sort = TRUE;
+       cur = orig;
+       while (cur) {
+               gchar *file;
+               msg = (MsgInfo *)cur->data;
+               file = folder_item_fetch_msg(queue, msg->msgnum);
+               PrefsAccount *ac = procmsg_get_account_from_file(file);
+               g_free(file);
+
+               if (last_account == NULL || (ac != NULL && ac == last_account)) {
+                       result = g_slist_append(result, msg);
+                       orig = g_slist_remove(orig, msg);
+                       last_account = ac;
+                       nothing_to_sort = FALSE;
+                       goto parse_again;
+               }
+               cur = cur->next;
+       }
+       
+       if (orig || g_slist_length(orig)) {
+               if (!last_account && nothing_to_sort) {
+                       /* can't find an account for the rest of the list */
+                       cur = orig;
+                       while (cur) {
+                               result = g_slist_append(result, cur->data);
+                               cur = cur->next;
+                       }
+               } else {
+                       last_account = NULL;
+                       goto parse_again;
+               }
+       }
+       
+       g_slist_free(orig);
+       
+       for (cur = result; cur; cur = cur->next)
+               debug_print("sort after  %s\n", ((MsgInfo *)cur->data)->from);
+
+       debug_print("\n");
+
+       return result;
+}
+
+static gboolean procmsg_is_last_for_account(FolderItem *queue, MsgInfo *msginfo, GSList *elem)
+{
+       gchar *file = folder_item_fetch_msg(queue, msginfo->msgnum);
+       PrefsAccount *ac = procmsg_get_account_from_file(file);
+       GSList *cur = elem;
+       g_free(file);
+       for (cur = elem; cur; cur = cur->next) {
+               MsgInfo *cur_msginfo = (MsgInfo *)cur->data;
+               PrefsAccount *cur_ac = NULL;
+               file = folder_item_fetch_msg(queue, cur_msginfo->msgnum);
+               
+               if (cur_msginfo != msginfo && !MSG_IS_LOCKED(cur_msginfo->flags)) {
+                       if (procmsg_get_account_from_file(file) == ac) {
+                               g_free(file);
+                               return FALSE;
+                       }
+               }
+               
+               g_free(file);
+       }
+       return TRUE;
+}
+
 /*!
  *\brief       Send messages in queue
  *
@@ -651,6 +797,7 @@ gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs)
 {
        gint sent = 0, err = 0;
        GSList *list, *elem;
+       GSList *sorted_list = NULL;
 
        if (!queue)
                queue = folder_get_default_queue();
@@ -659,15 +806,19 @@ gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs)
        folder_item_scan(queue);
        list = folder_item_get_msg_list(queue);
 
-       for (elem = list; elem != NULL; elem = elem->next) {
+       /* sort the list per sender account; this helps reusing the same SMTP server */
+       sorted_list = procmsg_list_sort_by_account(queue, list);
+       
+       for (elem = sorted_list; elem != NULL; elem = elem->next) {
                gchar *file;
                MsgInfo *msginfo;
-               
+                       
                msginfo = (MsgInfo *)(elem->data);
                if (!MSG_IS_LOCKED(msginfo->flags)) {
                        file = folder_item_fetch_msg(queue, msginfo->msgnum);
                        if (file) {
-                               if (procmsg_send_message_queue(file) < 0) {
+                               if (procmsg_send_message_queue_full(file, 
+                                               !procmsg_is_last_for_account(queue, msginfo, elem)) < 0) {
                                        g_warning("Sending queued message %d failed.\n", 
                                                  msginfo->msgnum);
                                        err++;
@@ -694,6 +845,8 @@ gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs)
                procmsg_msginfo_free(msginfo);
        }
 
+       g_slist_free(sorted_list);
+
        return (err != 0 ? -err : sent);
 }
 
@@ -1046,23 +1199,7 @@ gint procmsg_cmp_msgnum_for_sort(gconstpointer a, gconstpointer b)
        return msginfo1->msgnum - msginfo2->msgnum;
 }
 
-enum
-{
-       Q_SENDER           = 0,
-       Q_SMTPSERVER       = 1,
-       Q_RECIPIENTS       = 2,
-       Q_NEWSGROUPS       = 3,
-       Q_MAIL_ACCOUNT_ID  = 4,
-       Q_NEWS_ACCOUNT_ID  = 5,
-       Q_SAVE_COPY_FOLDER = 6,
-       Q_REPLY_MESSAGE_ID = 7,
-       Q_FWD_MESSAGE_ID   = 8,
-       Q_PRIVACY_SYSTEM   = 9,
-       Q_ENCRYPT          = 10,
-       Q_ENCRYPT_DATA     = 11,
-};
-
-gint procmsg_send_message_queue(const gchar *file)
+static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_session)
 {
        static HeaderEntry qentry[] = {{"S:",    NULL, FALSE},
                                       {"SSV:",  NULL, FALSE},
@@ -1229,7 +1366,7 @@ gint procmsg_send_message_queue(const gchar *file)
                        }
 
                        if (mailac)
-                               mailval = send_message_smtp(mailac, to_list, fp);
+                               mailval = send_message_smtp_full(mailac, to_list, fp, keep_session);
                        else {
                                PrefsAccount tmp_ac;
 
@@ -1370,6 +1507,11 @@ gint procmsg_send_message_queue(const gchar *file)
        return (newsval != 0 ? newsval : mailval);
 }
 
+gint procmsg_send_message_queue(const gchar *file)
+{
+       return procmsg_send_message_queue_full(file, FALSE);
+}
+
 static void update_folder_msg_counts(FolderItem *item, MsgInfo *msginfo, MsgPermFlags old_flags)
 {
        MsgPermFlags new_flags = msginfo->flags.perm_flags;
index 4f8cca88c2868f27c16562e4af47147659004622..5681567376c501778b93dd69577a186eddb34016 100644 (file)
@@ -59,13 +59,6 @@ struct _SendProgressDialog
        Session *session;
        gboolean cancelled;
 };
-#if 0
-static gint send_message_local         (const gchar            *command,
-                                        FILE                   *fp);
-static gint send_message_smtp          (PrefsAccount           *ac_prefs,
-                                        GSList                 *to_list,
-                                        FILE                   *fp);
-#endif
 
 static gint send_recv_message          (Session                *session,
                                         const gchar            *msg,
@@ -122,125 +115,6 @@ enum
        Q_ACCOUNT_ID = 3
 };
 
-#if 0
-gint send_message_queue(const gchar *file)
-{
-       static HeaderEntry qentry[] = {{"S:",   NULL, FALSE},
-                                      {"SSV:", NULL, FALSE},
-                                      {"R:",   NULL, FALSE},
-                                      {"AID:", NULL, FALSE},
-                                      {NULL,   NULL, FALSE}};
-       FILE *fp;
-       gint val = 0;
-       gchar *from = NULL;
-       gchar *server = NULL;
-       GSList *to_list = NULL;
-       gchar buf[BUFFSIZE];
-       gint hnum;
-       glong fpos;
-       PrefsAccount *ac = NULL, *mailac = NULL, *newsac = NULL;
-
-       g_return_val_if_fail(file != NULL, -1);
-
-       if ((fp = fopen(file, "rb")) == NULL) {
-               FILE_OP_ERROR(file, "fopen");
-               return -1;
-       }
-
-       while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
-              != -1) {
-               gchar *p;
-
-               p = buf + strlen(qentry[hnum].name);
-
-               switch (hnum) {
-               case Q_SENDER:
-                       if (!from) from = g_strdup(p);
-                       break;
-               case Q_SMTPSERVER:
-                       if (!server) server = g_strdup(p);
-                       break;
-               case Q_RECIPIENTS:
-                       to_list = address_list_append(to_list, p);
-                       break;
-               case Q_ACCOUNT_ID:
-                       ac = account_find_from_id(atoi(p));
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (((!ac || (ac && ac->protocol != A_NNTP)) && !to_list) || !from) {
-               g_warning("Queued message header is broken.\n");
-               val = -1;
-       } else if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
-               val = send_message_local(prefs_common.extsend_cmd, fp);
-       } else {
-               if (ac && ac->protocol == A_NNTP) {
-                       newsac = ac;
-
-                       /* search mail account */
-                       mailac = account_find_from_address(from);
-                       if (!mailac) {
-                               if (cur_account &&
-                                   cur_account->protocol != A_NNTP)
-                                       mailac = cur_account;
-                               else {
-                                       mailac = account_get_default();
-                                       if (mailac->protocol == A_NNTP)
-                                               mailac = NULL;
-                               }
-                       }
-               } else if (ac) {
-                       mailac = ac;
-               } else {
-                       ac = account_find_from_smtp_server(from, server);
-                       if (!ac) {
-                               g_warning("Account not found. "
-                                         "Using current account...\n");
-                               ac = cur_account;
-                               if (ac && ac->protocol != A_NNTP)
-                                       mailac = ac;
-                       }
-               }
-
-               fpos = ftell(fp);
-               if (to_list) {
-                       if (mailac)
-                               val = send_message_smtp(mailac, to_list, fp);
-                       else {
-                               PrefsAccount tmp_ac;
-
-                               g_warning("Account not found.\n");
-
-                               memset(&tmp_ac, 0, sizeof(PrefsAccount));
-                               tmp_ac.address = from;
-                               tmp_ac.smtp_server = server;
-                               tmp_ac.smtpport = SMTP_PORT;
-                               val = send_message_smtp(&tmp_ac, to_list, fp);
-                       }
-               }
-
-               if (val == 0 && newsac) {
-                       fseek(fp, fpos, SEEK_SET);
-                       val = news_post_stream(FOLDER(newsac->folder), fp);
-                       if (val < 0)
-                               alertpanel_error_log(_("Error occurred while posting the message to %s ."),
-                                                newsac->nntp_server);
-               }
-       }
-
-       slist_free_strings(to_list);
-       g_slist_free(to_list);
-       g_free(from);
-       g_free(server);
-       fclose(fp);
-
-       return val;
-}
-#endif
-
 gint send_message_local(const gchar *command, FILE *fp)
 {
        FILE *pipefp;
@@ -282,7 +156,7 @@ gint send_message_local(const gchar *command, FILE *fp)
        return 0;
 }
 
-gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
+gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, gboolean keep_session)
 {
        Session *session;
        SMTPSession *smtp_session;
@@ -290,6 +164,7 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
        SendProgressDialog *dialog;
        gchar buf[BUFFSIZE];
        gint ret = 0;
+       gboolean was_inited = FALSE;
 
        g_return_val_if_fail(ac_prefs != NULL, -1);
        g_return_val_if_fail(ac_prefs->address != NULL, -1);
@@ -297,100 +172,117 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
        g_return_val_if_fail(to_list != NULL, -1);
        g_return_val_if_fail(fp != NULL, -1);
 
-       session = smtp_session_new();
-       smtp_session = SMTP_SESSION(session);
-
-       smtp_session->hostname =
-               ac_prefs->set_domain ? g_strdup(ac_prefs->domain) : NULL;
-
-       if (ac_prefs->use_smtp_auth) {
-               smtp_session->forced_auth_type = ac_prefs->smtp_auth_type;
-               if (ac_prefs->smtp_userid && strlen(ac_prefs->smtp_userid)) {
-                       smtp_session->user = g_strdup(ac_prefs->smtp_userid);
-                       if (ac_prefs->smtp_passwd)
-                               smtp_session->pass =
-                                       g_strdup(ac_prefs->smtp_passwd);
-                       else if (ac_prefs->tmp_smtp_pass)
-                               smtp_session->pass =
-                                       g_strdup(ac_prefs->tmp_smtp_pass);
-                       else {
-                               smtp_session->pass =
-                                       input_dialog_query_password
-                                               (ac_prefs->smtp_server,
-                                                smtp_session->user);
-                               if (!smtp_session->pass)
-                                       smtp_session->pass = g_strdup("");
-                               ac_prefs->tmp_smtp_pass =
-                                       g_strdup(smtp_session->pass);
+       if (!ac_prefs->session) {
+               /* we can't reuse a previously initialised session */
+               session = smtp_session_new();
+               smtp_session = SMTP_SESSION(session);
+
+               smtp_session->hostname =
+                       ac_prefs->set_domain ? g_strdup(ac_prefs->domain) : NULL;
+
+               if (ac_prefs->use_smtp_auth) {
+                       smtp_session->forced_auth_type = ac_prefs->smtp_auth_type;
+                       if (ac_prefs->smtp_userid && strlen(ac_prefs->smtp_userid)) {
+                               smtp_session->user = g_strdup(ac_prefs->smtp_userid);
+                               if (ac_prefs->smtp_passwd)
+                                       smtp_session->pass =
+                                               g_strdup(ac_prefs->smtp_passwd);
+                               else if (ac_prefs->tmp_smtp_pass)
+                                       smtp_session->pass =
+                                               g_strdup(ac_prefs->tmp_smtp_pass);
+                               else {
+                                       smtp_session->pass =
+                                               input_dialog_query_password
+                                                       (ac_prefs->smtp_server,
+                                                        smtp_session->user);
+                                       if (!smtp_session->pass)
+                                               smtp_session->pass = g_strdup("");
+                                       ac_prefs->tmp_smtp_pass =
+                                               g_strdup(smtp_session->pass);
+                               }
+                       } else {
+                               smtp_session->user = g_strdup(ac_prefs->userid);
+                               if (ac_prefs->passwd)
+                                       smtp_session->pass = g_strdup(ac_prefs->passwd);
+                               else if (ac_prefs->tmp_pass)
+                                       smtp_session->pass =
+                                               g_strdup(ac_prefs->tmp_pass);
+                               else {
+                                       smtp_session->pass =
+                                               input_dialog_query_password
+                                                       (ac_prefs->smtp_server,
+                                                        smtp_session->user);
+                                       if (!smtp_session->pass)
+                                               smtp_session->pass = g_strdup("");
+                                       ac_prefs->tmp_pass =
+                                               g_strdup(smtp_session->pass);
+                               }
                        }
                } else {
-                       smtp_session->user = g_strdup(ac_prefs->userid);
-                       if (ac_prefs->passwd)
-                               smtp_session->pass = g_strdup(ac_prefs->passwd);
-                       else if (ac_prefs->tmp_pass)
-                               smtp_session->pass =
-                                       g_strdup(ac_prefs->tmp_pass);
-                       else {
-                               smtp_session->pass =
-                                       input_dialog_query_password
-                                               (ac_prefs->smtp_server,
-                                                smtp_session->user);
-                               if (!smtp_session->pass)
-                                       smtp_session->pass = g_strdup("");
-                               ac_prefs->tmp_pass =
-                                       g_strdup(smtp_session->pass);
-                       }
+                       smtp_session->user = NULL;
+                       smtp_session->pass = NULL;
                }
+
+       #if USE_OPENSSL
+               port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
+                       ac_prefs->ssl_smtp == SSL_TUNNEL ? SSMTP_PORT : SMTP_PORT;
+               session->ssl_type = ac_prefs->ssl_smtp;
+               if (ac_prefs->ssl_smtp != SSL_NONE)
+                       session->nonblocking = ac_prefs->use_nonblocking_ssl;
+       #else
+               port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
+       #endif
+
+               dialog = send_progress_dialog_create();
+               dialog->session = session;
+               smtp_session->dialog = dialog;
+
+               progress_dialog_list_set(dialog->dialog, 0, NULL, 
+                                        ac_prefs->smtp_server, 
+                                        _("Connecting"));
+
+               if (ac_prefs->pop_before_smtp
+                   && (ac_prefs->protocol == A_APOP || ac_prefs->protocol == A_POP3)
+                   && (time(NULL) - ac_prefs->last_pop_login_time) > (60 * ac_prefs->pop_before_smtp_timeout)) {
+                       g_snprintf(buf, sizeof(buf), _("Doing POP before SMTP..."));
+                       log_message(buf);
+                       progress_dialog_set_label(dialog->dialog, buf);
+                       progress_dialog_list_set_status(dialog->dialog, 0, _("POP before SMTP"));
+                       GTK_EVENTS_FLUSH();
+                       inc_pop_before_smtp(ac_prefs);
+               }
+
+               g_snprintf(buf, sizeof(buf), _("Connecting to SMTP server: %s ..."),
+                          ac_prefs->smtp_server);
+               progress_dialog_set_label(dialog->dialog, buf);
+               log_message("%s\n", buf);
+
+               session_set_recv_message_notify(session, send_recv_message, dialog);
+               session_set_send_data_progressive_notify
+                       (session, send_send_data_progressive, dialog);
+               session_set_send_data_notify(session, send_send_data_finished, dialog);
+
+               ac_prefs->session = SMTP_SESSION(session);
        } else {
-               smtp_session->user = NULL;
-               smtp_session->pass = NULL;
+               /* everything is ready to start at MAIL FROM:, just
+                * reinit useful variables. 
+                */
+               session = SESSION(ac_prefs->session);
+               smtp_session = SMTP_SESSION(session);
+               smtp_session->state = SMTP_HELO;
+               dialog = (SendProgressDialog *)smtp_session->dialog;
+               was_inited = TRUE;
        }
 
+       /* This has to be initialised for every mail sent */
        smtp_session->from = g_strdup(ac_prefs->address);
        smtp_session->to_list = to_list;
        smtp_session->cur_to = to_list;
        smtp_session->send_data = get_outgoing_rfc2822_str(fp);
        smtp_session->send_data_len = strlen(smtp_session->send_data);
 
-#if USE_OPENSSL
-       port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
-               ac_prefs->ssl_smtp == SSL_TUNNEL ? SSMTP_PORT : SMTP_PORT;
-       session->ssl_type = ac_prefs->ssl_smtp;
-       if (ac_prefs->ssl_smtp != SSL_NONE)
-               session->nonblocking = ac_prefs->use_nonblocking_ssl;
-#else
-       port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
-#endif
-
-       dialog = send_progress_dialog_create();
-       dialog->session = session;
-
-       progress_dialog_list_set(dialog->dialog, 0, NULL, 
-                                ac_prefs->smtp_server, 
-                                _("Connecting"));
-
-       if (ac_prefs->pop_before_smtp
-           && (ac_prefs->protocol == A_APOP || ac_prefs->protocol == A_POP3)
-           && (time(NULL) - ac_prefs->last_pop_login_time) > (60 * ac_prefs->pop_before_smtp_timeout)) {
-               g_snprintf(buf, sizeof(buf), _("Doing POP before SMTP..."));
-               log_message(buf);
-               progress_dialog_set_label(dialog->dialog, buf);
-               progress_dialog_list_set_status(dialog->dialog, 0, _("POP before SMTP"));
-               GTK_EVENTS_FLUSH();
-               inc_pop_before_smtp(ac_prefs);
-       }
-       
-       g_snprintf(buf, sizeof(buf), _("Connecting to SMTP server: %s ..."),
-                  ac_prefs->smtp_server);
-       progress_dialog_set_label(dialog->dialog, buf);
-       log_message("%s\n", buf);
-
-       session_set_recv_message_notify(session, send_recv_message, dialog);
-       session_set_send_data_progressive_notify
-               (session, send_send_data_progressive, dialog);
-       session_set_send_data_notify(session, send_send_data_finished, dialog);
-
-       if (session_connect(session, ac_prefs->smtp_server, port) < 0) {
+       /* connect if necessary */
+       if (!was_inited && session_connect(session, ac_prefs->smtp_server, port) < 0) {
                session_destroy(session);
                send_progress_dialog_destroy(dialog);
                return -1;
@@ -398,7 +290,13 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
 
        debug_print("send_message_smtp(): begin event loop\n");
 
-       while (session_is_connected(session) && dialog->cancelled == FALSE)
+       if (was_inited) {
+               /* as the server is quiet, start sending ourselves */
+               smtp_from(smtp_session);
+       }
+
+       while (session_is_connected(session) && dialog->cancelled == FALSE
+               && SMTP_SESSION(session)->state != SMTP_MAIL_SENT_OK)
                gtk_main_iteration();
 
        if (SMTP_SESSION(session)->error_val == SM_AUTHFAIL) {
@@ -407,6 +305,9 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
                        ac_prefs->tmp_smtp_pass = NULL;
                }
                ret = -1;
+       } else if (SMTP_SESSION(session)->state == SMTP_MAIL_SENT_OK) {
+               log_message("%s\n", _("Mail sent successfully."));
+               ret = 0;
        } else if (session->state == SESSION_EOF &&
                   SMTP_SESSION(session)->state == SMTP_QUIT) {
                /* consider EOF right after QUIT successful */
@@ -427,14 +328,33 @@ gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
                manage_window_focus_out(dialog->dialog->window, NULL, NULL);
        }
 
-       session_destroy(session);
-       send_progress_dialog_destroy(dialog);
+       /* if we should close the connection, let's do it.
+        * Close it in case of error, too, as it helps reinitializing things
+        * easier.
+        */
+       if (!keep_session || ret != 0) {
+               smtp_quit(session);
+               while (session_is_connected(session))
+                       gtk_main_iteration();
+               session_destroy(session);
+               ac_prefs->session = NULL;
+               send_progress_dialog_destroy(dialog);
+       } else {
+               g_free(smtp_session->from);
+               g_free(smtp_session->send_data);
+               g_free(smtp_session->error_msg);
+       }
 
        statusbar_pop_all();
        statusbar_verbosity_set(FALSE);
        return ret;
 }
 
+gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
+{
+       return send_message_smtp_full(ac_prefs, to_list, fp, FALSE);
+}
+
 static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
 {
        gchar buf[BUFFSIZE];