(this is being sent to e-h@ also since this is mostly meant to encourage
discussion.)

There have been a number of complaints that messages don't get saved to
Outbox between the time the user hits the Send button and the time at
which the message is actually sent (and then saved to the Sent folder).

examples:
http://bugzilla.ximian.com/show_bug.cgi?id=23594
http://bugzilla.ximian.com/show_bug.cgi?id=26112
http://bugzilla.ximian.com/show_bug.cgi?id=20495

(Keelyn has also expressed that she would like it to work this way since
that is what Outlook does, in case that matters to anyone)

The attached patch changes the behavior such that composer_send_cb()
does mail_append_mail() rather than mail_send_mail(). The async callback
does pretty much the same thing as before, but if the struct _send_data
passed in has send->postpone == FALSE, then we invoke a send (which
sends everything in Outbox).

This pretty much means that except for the send->postpone option,
composer_send_cb() and composer_postpone_cb() are exactly the same.

Something I noticed while merging the code of these 2 functions was that
they basically did exactly the same thing anyway, except that
composer_postpone_cb() would spawn a thread to append the message to
Outbox but didn't wait for it to finish before destroying the composer
widget. The obvious problem with this is that if the append-to-Outbox
failed, you'd have potentially lost data.

Anyways, that problem is also solved with my newer implementation.

Things I predict NotZed will not like (tm):

- a new function that duplicates a bit of code:
mail-send-recv.c:mail_send()

I'm thinking that I could just use mail_receive_uri() and do the bit of
work it is to get the default transport url in mail-callbacks.c (it's
only like 2 or 3 lines of code).

However, this would also require receive_get_type() (and other parts of
mail-send-recv.c) be fixed to handle the case where a provider is both a
store and a transport. We might also need to change mail_receive_uri()
to take another arument specifying whether or not it should send or
receive (or both?) with the passed-in url. All in all, not a major
problem to solve.


Okay, well - I guess that's all I have to say for the moment.

Jeff

-- 
Jeffrey Stedfast
Evolution Hacker - Ximian, Inc.
[EMAIL PROTECTED]  - www.ximian.com
? message-list-proxy.c
? message-list-proxy.h
? send-queue.patch
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.2246
diff -u -r1.2246 ChangeLog
--- ChangeLog   3 Jul 2002 20:40:11 -0000       1.2246
+++ ChangeLog   3 Jul 2002 23:32:59 -0000
@@ -1,5 +1,29 @@
 2002-07-03  Jeffrey Stedfast  <[EMAIL PROTECTED]>
 
+       * mail-send-recv.c (get_receive_type): If the provider is a
+       transport, return SEND_SEND.
+
+       * mail-callbacks.c (composer_send_queued_cb): Basically do what
+       composer_sent_cb() did but if send->postpone is FALSE, queue an
+       auto-send.
+
+       * mail-config.c (mail_config_get_default_transport): If the
+       default account doesn't have a transport, find the first account
+       that does.
+
+       * mail-callbacks.c (append_mail_cleanup): Don't bother freeing the
+       appended_uid here.
+       (composer_send_internal): New helper function that does all the
+       similar work that composer_send_cb and composer_postpone_cb did.
+       (composer_send_cb): Call composer_send_internal.
+       (composer_postpone_cb): Same.
+
+       * mail-ops.c (append_mail_free): Free the appended uid.
+
+       * mail-callbacks.c (save_draft_done): g_strdup the appended uid.
+
+2002-07-03  Jeffrey Stedfast  <[EMAIL PROTECTED]>
+
        * mail-vfolder.c (vfolder_load_storage): Pass TRUE as the
        auto_connect argument to mail_load_storage_from_uri().
 
Index: mail-callbacks.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-callbacks.c,v
retrieving revision 1.358
diff -u -r1.358 mail-callbacks.c
--- mail-callbacks.c    2 Jul 2002 19:23:07 -0000       1.358
+++ mail-callbacks.c    3 Jul 2002 23:32:59 -0000
@@ -341,27 +341,35 @@
 struct _send_data {
        EMsgComposer *composer;
        struct post_send_data *psd;
+       gboolean postpone;
 };
 
 static void
-composer_sent_cb (char *uri, CamelMimeMessage *message, gboolean sent, void *data)
+composer_send_queued_cb (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo 
+*info,
+                        int queued, const char *appended_uid, void *data)
 {
        struct _send_data *send = data;
        
-       if (sent) {
+       if (queued) {
                if (send->psd) {
                        camel_folder_set_message_flags (send->psd->folder, 
send->psd->uid,
                                                        send->psd->flags, 
send->psd->set);
                }
                gtk_widget_destroy (GTK_WIDGET (send->composer));
+               
+               if (!send->postpone) {
+                       /* queue a message send */
+                       mail_send ();
+               }
        } else {
                e_msg_composer_set_enable_autosave (send->composer, TRUE);
                gtk_widget_show (GTK_WIDGET (send->composer));
        }
        
+       camel_message_info_free (info);
+       
        gtk_object_unref (GTK_OBJECT (send->composer));
        g_free (send);
-       camel_object_unref (CAMEL_OBJECT (message));
 }
 
 static CamelMimeMessage *
@@ -485,74 +493,44 @@
        return message;
 }
 
-void
-composer_send_cb (EMsgComposer *composer, gpointer data)
+static void
+composer_send_internal (EMsgComposer *composer, struct post_send_data *psd, gboolean 
+postpone)
 {
-       const MailConfigService *transport;
+       extern CamelFolder *outbox_folder;
        CamelMimeMessage *message;
-       struct post_send_data *psd = data;
+       CamelMessageInfo *info;
        struct _send_data *send;
        
-       if (!mail_config_is_configured ()) {
-               GtkWidget *dialog;
-               
-               dialog = gnome_ok_dialog_parented (_("You must configure an account 
before you "
-                                                    "can send this email."),
-                                                  GTK_WINDOW (composer));
-               gnome_dialog_set_close (GNOME_DIALOG (dialog), TRUE);
-               gtk_widget_show (dialog);
-               return;
-       }
-       
        message = composer_get_message (composer);
        if (!message)
                return;
        
-       transport = mail_config_get_default_transport ();
-       if (!transport)
-               return;
+       info = camel_message_info_new ();
+       info->flags = CAMEL_MESSAGE_SEEN;
        
        send = g_malloc (sizeof (*send));
        send->psd = psd;
+       send->postpone = postpone;
        send->composer = composer;
        gtk_object_ref (GTK_OBJECT (composer));
        gtk_widget_hide (GTK_WIDGET (composer));
+       
        e_msg_composer_set_enable_autosave (composer, FALSE);
        
-       mail_send_mail (transport->url, message, composer_sent_cb, send);
+       mail_append_mail (outbox_folder, message, NULL, composer_send_queued_cb, send);
+       camel_object_unref (message);
 }
 
-static void
-append_mail_cleanup (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo 
*info,
-                    int ok, char *appended_uid, void *data)
+void
+composer_send_cb (EMsgComposer *composer, gpointer data)
 {
-       camel_message_info_free (info);
-       if (appended_uid)
-               g_free (appended_uid);
+       composer_send_internal (composer, data, FALSE);
 }
 
 void
 composer_postpone_cb (EMsgComposer *composer, gpointer data)
 {
-       extern CamelFolder *outbox_folder;
-       CamelMimeMessage *message;
-       CamelMessageInfo *info;
-       struct post_send_data *psd = data;
-       
-       message = composer_get_message (composer);
-       if (message == NULL)
-               return;
-       
-       info = camel_message_info_new ();
-       info->flags = CAMEL_MESSAGE_SEEN;
-       
-       mail_append_mail (outbox_folder, message, info, append_mail_cleanup, NULL);
-       camel_object_unref (CAMEL_OBJECT (message));
-       
-       if (psd)
-               camel_folder_set_message_flags (psd->folder, psd->uid, psd->flags, 
psd->set);
-       
-       gtk_widget_destroy (GTK_WIDGET (composer));
+       composer_send_internal (composer, data, TRUE);
 }
 
 struct _save_draft_info {
@@ -562,7 +540,7 @@
 
 static void
 save_draft_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info, 
int ok,
-                char *appended_uid, void *data)
+                const char *appended_uid, void *data)
 {
        struct _save_draft_info *sdi = data;
        char *old_uid;
@@ -580,7 +558,7 @@
        
        if (appended_uid) {
                gtk_object_set_data_full (GTK_OBJECT (sdi->composer),
-                                         "draft_uid", appended_uid,
+                                         "draft_uid", g_strdup (appended_uid),
                                          (GtkDestroyNotify) g_free);
        } else {
                gtk_object_set_data (GTK_OBJECT (sdi->composer),
Index: mail-config.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-config.c,v
retrieving revision 1.221
diff -u -r1.221 mail-config.c
--- mail-config.c       26 Jun 2002 22:25:10 -0000      1.221
+++ mail-config.c       3 Jul 2002 23:33:00 -0000
@@ -2449,12 +2449,24 @@
 mail_config_get_default_transport (void)
 {
        const MailConfigAccount *account;
+       const GSList *accounts;
        
        account = mail_config_get_default_account ();
-       if (account)
+       if (account && account->transport && account->transport->url)
                return account->transport;
-       else
-               return NULL;
+       
+       /* return the first account with a transport? */
+       accounts = config->accounts;
+       while (accounts) {
+               account = accounts->data;
+               
+               if (account->transport && account->transport->url)
+                       return account->transport;
+               
+               accounts = accounts->next;
+       }
+       
+       return NULL;
 }
 
 const MailConfigService *
Index: mail-ops.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-ops.c,v
retrieving revision 1.368
diff -u -r1.368 mail-ops.c
--- mail-ops.c  3 Jun 2002 21:54:54 -0000       1.368
+++ mail-ops.c  3 Jul 2002 23:33:00 -0000
@@ -863,6 +863,7 @@
 
        camel_object_unref((CamelObject *)m->message);
        camel_object_unref((CamelObject *)m->folder);
+       g_free (m->appended_uid);
 }
 
 static struct _mail_msg_op append_mail_op = {
@@ -874,7 +875,7 @@
 
 void
 mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo 
*info,
-                 void (*done)(CamelFolder *folder, CamelMimeMessage *msg, 
CamelMessageInfo *info, int ok, char *appended_uid, void *data),
+                 void (*done)(CamelFolder *folder, CamelMimeMessage *msg, 
+CamelMessageInfo *info, int ok, const char *appended_uid, void *data),
                  void *data)
 {
        struct _append_msg *m;
Index: mail-ops.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-ops.h,v
retrieving revision 1.55
diff -u -r1.55 mail-ops.h
--- mail-ops.h  15 May 2002 12:39:17 -0000      1.55
+++ mail-ops.h  3 Jul 2002 23:33:00 -0000
@@ -39,7 +39,8 @@
 #include "e-util/e-msgport.h"
 
 void mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, 
CamelMessageInfo *info,
-                      void (*done)(CamelFolder *folder, CamelMimeMessage *msg, 
CamelMessageInfo *info, int ok, char *appended_uid, void *data),
+                      void (*done)(CamelFolder *folder, CamelMimeMessage *msg, 
+CamelMessageInfo *info, int ok,
+                                   const char *appended_uid, void *data),
                       void *data);
 
 void mail_transfer_messages (CamelFolder *source, GPtrArray *uids,
Index: mail-send-recv.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-send-recv.c,v
retrieving revision 1.58
diff -u -r1.58 mail-send-recv.c
--- mail-send-recv.c    30 May 2002 21:55:01 -0000      1.58
+++ mail-send-recv.c    3 Jul 2002 23:33:00 -0000
@@ -262,10 +262,16 @@
        if (!provider)
                return SEND_INVALID;
        
-       if (provider->flags & CAMEL_PROVIDER_IS_STORAGE)
-               return SEND_UPDATE;
-       else
-               return SEND_RECEIVE;
+       if (provider->object_types[CAMEL_PROVIDER_STORE]) {
+               if (provider->flags & CAMEL_PROVIDER_IS_STORAGE)
+                       return SEND_UPDATE;
+               else
+                       return SEND_RECEIVE;
+       } else if (provider->object_types[CAMEL_PROVIDER_TRANSPORT]) {
+               return SEND_SEND;
+       }
+       
+       return SEND_INVALID;
 }
 
 static struct _send_data *
@@ -853,4 +859,57 @@
        default:
                g_assert_not_reached ();
        }
+}
+
+void
+mail_send (void)
+{
+       extern CamelFolder *outbox_folder;
+       const MailConfigService *transport;
+       struct _send_info *info;
+       struct _send_data *data;
+       send_info_t type;
+       
+       transport = mail_config_get_default_transport ();
+       if (!transport || !transport->url)
+               return;
+       
+       data = setup_send_data ();
+       info = g_hash_table_lookup (data->active, transport->url);
+       if (info != NULL) {
+               d(printf("send of %s still in progress\n", transport->url));
+               return;
+       }
+       
+       d(printf("starting non-interactive send of '%s'\n", transport->url));
+       
+       type = get_receive_type (transport->url);
+       if (type == SEND_INVALID) {
+               d(printf ("unsupported provider: '%s'\n", transport->url));
+               return;
+       }
+       
+       info = g_malloc0 (sizeof (*info));
+       info->type = SEND_SEND;
+       info->bar = NULL;
+       info->status = NULL;
+       info->uri = g_strdup (transport->url);
+       info->keep = FALSE;
+       info->cancel = camel_operation_new (operation_status, info);
+       info->stop = NULL;
+       info->data = data;
+       info->state = SEND_ACTIVE;
+       info->timeout_id = 0;
+       
+       d(printf("Adding new info %p\n", info));
+       
+       g_hash_table_insert (data->active, info->uri, info);
+       
+       /* todo, store the folder in info? */
+       mail_send_queue (outbox_folder, info->uri,
+                        FILTER_SOURCE_OUTGOING,
+                        info->cancel,
+                        receive_get_folder, info,
+                        receive_status, info,
+                        receive_done, info);
 }
Index: mail-send-recv.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-send-recv.h,v
retrieving revision 1.8
diff -u -r1.8 mail-send-recv.h
--- mail-send-recv.h    21 Mar 2002 00:07:40 -0000      1.8
+++ mail-send-recv.h    3 Jul 2002 23:33:00 -0000
@@ -26,7 +26,7 @@
 #ifdef __cplusplus
 extern "C" {
 #pragma }
-#endif /* __cplusplus }*/
+#endif /* __cplusplus */
 
 #include "mail-config.h"
 
@@ -34,6 +34,7 @@
 void mail_send_receive(void);
 /* receive a single uri */
 void mail_receive_uri(const char *uri, int keep);
+void mail_send (void);
 /* setup auto receive stuff */
 void mail_autoreceive_setup(void);
 

Reply via email to