From f544e10b71f0c80ee0cf8eb2edde0620fd7f4e70 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 30 Oct 2010 20:56:51 -0400 Subject: Skip writing to Outbox when sending. When sending a message from a composer window, it seems pointless to write message to Outbox only to immediately read it back and mark it for deletion. Instead, bypass the Outbox folder when sending, and if an error occurs, offer to save the message to Outbox instead. --- mail/e-mail-session-utils.c | 109 ++++++----------------- mail/e-mail-session-utils.h | 3 +- mail/em-composer-utils.c | 213 ++++++++++++++++++++++++-------------------- 3 files changed, 143 insertions(+), 182 deletions(-) (limited to 'mail') diff --git a/mail/e-mail-session-utils.c b/mail/e-mail-session-utils.c index b436243c10..2369a69d35 100644 --- a/mail/e-mail-session-utils.c +++ b/mail/e-mail-session-utils.c @@ -33,7 +33,6 @@ typedef struct _AsyncContext AsyncContext; struct _AsyncContext { CamelFolder *sent_folder; - CamelFolder *outbox_folder; CamelMimeMessage *message; CamelMessageInfo *info; @@ -63,9 +62,6 @@ async_context_free (AsyncContext *context) if (context->sent_folder != NULL) g_object_unref (context->sent_folder); - if (context->outbox_folder != NULL) - g_object_unref (context->outbox_folder); - if (context->message != NULL) g_object_unref (context->message); @@ -564,19 +560,6 @@ cleanup: /* The send operation was successful; ignore cleanup errors. */ - /* Mark the Outbox message for deletion. */ - camel_folder_set_message_flags ( - context->outbox_folder, context->message_uid, - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN, ~0); - - /* Synchronize the Outbox folder. */ - camel_folder_synchronize_sync ( - context->outbox_folder, FALSE, cancellable, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_clear_error (&error); - } - /* Mark the draft message for deletion, if present. */ e_mail_session_handle_draft_headers_sync ( session, context->message, cancellable, &error); @@ -617,17 +600,23 @@ exit: g_string_free (error_messages, TRUE); } -static void -mail_session_send_to_prepare (CamelFolder *outbox_folder, - GAsyncResult *result, - GSimpleAsyncResult *simple) +void +e_mail_session_send_to (EMailSession *session, + CamelMimeMessage *message, + const gchar *destination, + gint io_priority, + GCancellable *cancellable, + CamelFilterGetFolderFunc get_folder_func, + gpointer get_folder_data, + GAsyncReadyCallback callback, + gpointer user_data) { + GSimpleAsyncResult *simple; AsyncContext *context; CamelAddress *from; CamelAddress *recipients; CamelMedium *medium; CamelMessageInfo *info; - CamelMimeMessage *message; EAccount *account = NULL; GPtrArray *post_to_uris; struct _camel_header_raw *xev; @@ -638,20 +627,7 @@ mail_session_send_to_prepare (CamelFolder *outbox_folder, gchar *sent_folder_uri = NULL; GError *error = NULL; - context = g_simple_async_result_get_op_res_gpointer (simple); - - message = camel_folder_get_message_finish ( - outbox_folder, result, &error); - - if (error != NULL) { - g_warn_if_fail (message == NULL); - g_simple_async_result_set_from_error (simple, error); - g_simple_async_result_complete (simple); - g_object_unref (simple); - g_error_free (error); - return; - } - + g_return_if_fail (E_IS_MAIL_SESSION (session)); g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); medium = CAMEL_MEDIUM (message); @@ -686,7 +662,7 @@ mail_session_send_to_prepare (CamelFolder *outbox_folder, sent_folder_uri = g_strstrip (g_strdup (string)); if (transport_uri == NULL) - transport_uri = g_strdup (context->destination); + transport_uri = g_strdup (destination); post_to_uris = g_ptr_array_new (); for (header = xev; header != NULL; header = header->next) { @@ -750,6 +726,10 @@ mail_session_send_to_prepare (CamelFolder *outbox_folder, /* The rest of the processing happens in a thread. */ + context = g_slice_new0 (AsyncContext); + context->message = g_object_ref (message); + context->destination = g_strdup (destination); + context->io_priority = io_priority; context->from = from; context->recipients = recipients; context->message = g_object_ref (message); @@ -759,46 +739,10 @@ mail_session_send_to_prepare (CamelFolder *outbox_folder, context->transport_uri = transport_uri; context->sent_folder_uri = sent_folder_uri; - g_simple_async_result_run_in_thread ( - simple, (GSimpleAsyncThreadFunc) - mail_session_send_to_thread, - context->io_priority, - context->cancellable); - - g_object_unref (simple); -} - -void -e_mail_session_send_to (EMailSession *session, - CamelFolder *outbox_folder, - const gchar *message_uid, - const gchar *destination, - gint io_priority, - GCancellable *cancellable, - CamelFilterGetFolderFunc get_folder_func, - gpointer get_folder_data, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - AsyncContext *context; - GError *error = NULL; - - g_return_if_fail (E_IS_MAIL_SESSION (session)); - g_return_if_fail (CAMEL_IS_FOLDER (outbox_folder)); - g_return_if_fail (message_uid != NULL); - - context = g_slice_new0 (AsyncContext); - context->outbox_folder = g_object_ref (outbox_folder); - context->message_uid = g_strdup (message_uid); - context->destination = g_strdup (destination); - context->io_priority = io_priority; - if (G_IS_CANCELLABLE (cancellable)) context->cancellable = g_object_ref (cancellable); - /* More convenient to do this here than in the prepare function. - * Failure here emits a runtime warning but is non-fatal. */ + /* Failure here emits a runtime warning but is non-fatal. */ context->driver = camel_session_get_filter_driver ( CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error); if (context->driver != NULL) @@ -810,6 +754,10 @@ e_mail_session_send_to (EMailSession *session, g_error_free (error); } + /* This gets popped in async_context_free(). */ + camel_operation_push_message ( + context->cancellable, _("Sending message")); + simple = g_simple_async_result_new ( G_OBJECT (session), callback, user_data, e_mail_session_send_to); @@ -817,14 +765,13 @@ e_mail_session_send_to (EMailSession *session, g_simple_async_result_set_op_res_gpointer ( simple, context, (GDestroyNotify) async_context_free); - /* This gets popped in async_context_free(). */ - camel_operation_push_message ( - context->cancellable, _("Sending message")); + g_simple_async_result_run_in_thread ( + simple, (GSimpleAsyncThreadFunc) + mail_session_send_to_thread, + context->io_priority, + context->cancellable); - camel_folder_get_message ( - outbox_folder, message_uid, io_priority, - context->cancellable, (GAsyncReadyCallback) - mail_session_send_to_prepare, simple); + g_object_unref (simple); } gboolean diff --git a/mail/e-mail-session-utils.h b/mail/e-mail-session-utils.h index fcbc2636f7..4d97524f5d 100644 --- a/mail/e-mail-session-utils.h +++ b/mail/e-mail-session-utils.h @@ -58,8 +58,7 @@ gboolean e_mail_session_handle_source_headers_finish GAsyncResult *result, GError **error); void e_mail_session_send_to (EMailSession *session, - CamelFolder *outbox_folder, - const gchar *message_uid, + CamelMimeMessage *message, const gchar *destination, gint io_priority, GCancellable *cancellable, diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 02eb039916..91480a38eb 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -488,10 +488,21 @@ composer_send_completed (EMailSession *session, } if (error != NULL) { - e_alert_submit ( - GTK_WIDGET (context->composer), + gint response; + + /* Clear the activity bar before + * presenting the error dialog. */ + g_object_unref (context->activity); + context->activity = NULL; + + response = e_alert_run_dialog_for_args ( + GTK_WINDOW (context->composer), "mail-composer:send-error", error->message, NULL); + if (response == GTK_RESPONSE_OK) /* Try Again */ + e_msg_composer_send (context->composer); + if (response == GTK_RESPONSE_ACCEPT) /* Save to Outbox */ + e_msg_composer_save_to_outbox (context->composer); g_error_free (error); goto exit; } @@ -508,76 +519,13 @@ exit: async_context_free (context); } -static void -composer_send_appended (CamelFolder *outbox_folder, - GAsyncResult *result, - AsyncContext *context) -{ - CamelSession *session; - GCancellable *cancellable; - gchar *message_uid = NULL; - GError *error = NULL; - - e_mail_folder_append_message_finish ( - outbox_folder, result, &message_uid, &error); - - /* Ignore cancellations. */ - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_warn_if_fail (message_uid == NULL); - async_context_free (context); - g_error_free (error); - return; - } - - if (error != NULL) { - g_warn_if_fail (message_uid == NULL); - e_alert_submit ( - GTK_WIDGET (context->composer), - "mail-composer:append-to-outbox-error", - error->message, NULL); - g_warning ("%s", error->message); - async_context_free (context); - g_error_free (error); - return; - } - - session = e_msg_composer_get_session (context->composer); - cancellable = e_activity_get_cancellable (context->activity); - - /* If we're online, go ahead and send the message now. */ - if (camel_session_get_online (session)) - e_mail_session_send_to ( - E_MAIL_SESSION (session), - outbox_folder, message_uid, NULL, - G_PRIORITY_DEFAULT, cancellable, NULL, NULL, - (GAsyncReadyCallback) composer_send_completed, - context); - - /* If we're offline, writing the message to the Outbox - * folder is as much as we can do. Tell the user. */ - else { - g_object_unref (context->activity); - context->activity = NULL; - - e_alert_run_dialog_for_args ( - GTK_WINDOW (context->composer), - "mail-composer:saved-to-outbox", NULL); - - gtk_widget_destroy (GTK_WIDGET (context->composer)); - async_context_free (context); - } - - g_free (message_uid); -} - static void em_utils_composer_send_cb (EMsgComposer *composer, CamelMimeMessage *message, EActivity *activity) { AsyncContext *context; - CamelFolder *outbox_folder; - CamelMessageInfo *info; + CamelSession *session; GCancellable *cancellable; context = g_slice_new0 (AsyncContext); @@ -586,18 +534,13 @@ em_utils_composer_send_cb (EMsgComposer *composer, context->activity = g_object_ref (activity); cancellable = e_activity_get_cancellable (activity); - outbox_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); - - info = camel_message_info_new (NULL); - camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); + session = e_msg_composer_get_session (context->composer); - e_mail_folder_append_message ( - outbox_folder, message, info, - G_PRIORITY_DEFAULT, cancellable, - (GAsyncReadyCallback) composer_send_appended, + e_mail_session_send_to ( + E_MAIL_SESSION (session), message, NULL, + G_PRIORITY_DEFAULT, cancellable, NULL, NULL, + (GAsyncReadyCallback) composer_send_completed, context); - - camel_message_info_free (info); } static void @@ -614,9 +557,9 @@ composer_set_no_change (EMsgComposer *composer) } static void -composer_save_draft_complete (EMailSession *session, - GAsyncResult *result, - AsyncContext *context) +composer_save_to_drafts_complete (EMailSession *session, + GAsyncResult *result, + AsyncContext *context) { GError *error = NULL; @@ -649,9 +592,9 @@ composer_save_draft_complete (EMailSession *session, } static void -composer_save_draft_cleanup (CamelFolder *drafts_folder, - GAsyncResult *result, - AsyncContext *context) +composer_save_to_drafts_cleanup (CamelFolder *drafts_folder, + GAsyncResult *result, + AsyncContext *context) { CamelSession *session; GCancellable *cancellable; @@ -672,7 +615,7 @@ composer_save_draft_cleanup (CamelFolder *drafts_folder, g_warn_if_fail (context->message_uid == NULL); e_alert_submit ( GTK_WIDGET (context->composer), - "mail-composer:save-draft-error", + "mail-composer:save-to-drafts-error", error->message, NULL); async_context_free (context); g_error_free (error); @@ -687,12 +630,12 @@ composer_save_draft_cleanup (CamelFolder *drafts_folder, e_mail_session_handle_draft_headers ( E_MAIL_SESSION (session), context->message, G_PRIORITY_DEFAULT, cancellable, (GAsyncReadyCallback) - composer_save_draft_complete, context); + composer_save_to_drafts_complete, context); } static void -composer_save_draft_append_mail (AsyncContext *context, - CamelFolder *drafts_folder) +composer_save_to_drafts_append_mail (AsyncContext *context, + CamelFolder *drafts_folder) { CamelFolder *local_drafts_folder; GCancellable *cancellable; @@ -714,7 +657,7 @@ composer_save_draft_append_mail (AsyncContext *context, e_mail_folder_append_message ( drafts_folder, context->message, info, G_PRIORITY_DEFAULT, cancellable, - (GAsyncReadyCallback) composer_save_draft_cleanup, + (GAsyncReadyCallback) composer_save_to_drafts_cleanup, context); camel_message_info_free (info); @@ -723,9 +666,9 @@ composer_save_draft_append_mail (AsyncContext *context, } static void -composer_save_draft_got_folder (EMailSession *session, - GAsyncResult *result, - AsyncContext *context) +composer_save_to_drafts_got_folder (EMailSession *session, + GAsyncResult *result, + AsyncContext *context) { CamelFolder *drafts_folder; GError *error = NULL; @@ -761,13 +704,13 @@ composer_save_draft_got_folder (EMailSession *session, } } - composer_save_draft_append_mail (context, drafts_folder); + composer_save_to_drafts_append_mail (context, drafts_folder); } static void -em_utils_composer_save_draft_cb (EMsgComposer *composer, - CamelMimeMessage *message, - EActivity *activity) +em_utils_composer_save_to_drafts_cb (EMsgComposer *composer, + CamelMimeMessage *message, + EActivity *activity) { AsyncContext *context; EComposerHeaderTable *table; @@ -796,7 +739,7 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, drafts_folder_uri = NULL; if (drafts_folder_uri == NULL) { - composer_save_draft_append_mail (context, NULL); + composer_save_to_drafts_append_mail (context, NULL); context->folder_uri = g_strdup (local_drafts_folder_uri); } else { GCancellable *cancellable; @@ -808,10 +751,78 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, E_MAIL_SESSION (session), drafts_folder_uri, 0, G_PRIORITY_DEFAULT, cancellable, (GAsyncReadyCallback) - composer_save_draft_got_folder, context); + composer_save_to_drafts_got_folder, context); } } +static void +composer_save_to_outbox_completed (CamelFolder *outbox_folder, + GAsyncResult *result, + AsyncContext *context) +{ + GError *error = NULL; + + e_mail_folder_append_message_finish ( + outbox_folder, result, NULL, &error); + + /* Ignore cancellations. */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + e_activity_set_state (context->activity, E_ACTIVITY_CANCELLED); + g_error_free (error); + goto exit; + } + + if (error != NULL) { + e_alert_submit ( + GTK_WIDGET (context->composer), + "mail-composer:append-to-outbox-error", + error->message, NULL); + g_error_free (error); + goto exit; + } + + e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED); + + /* Wait for the EActivity's completion message to + * time out and then destroy the composer window. */ + g_object_weak_ref ( + G_OBJECT (context->activity), (GWeakNotify) + gtk_widget_destroy, context->composer); + +exit: + async_context_free (context); +} + +static void +em_utils_composer_save_to_outbox_cb (EMsgComposer *composer, + CamelMimeMessage *message, + EActivity *activity) +{ + AsyncContext *context; + CamelFolder *outbox_folder; + CamelMessageInfo *info; + GCancellable *cancellable; + + context = g_slice_new0 (AsyncContext); + context->message = g_object_ref (message); + context->composer = g_object_ref (composer); + context->activity = g_object_ref (activity); + + cancellable = e_activity_get_cancellable (activity); + outbox_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX); + + info = camel_message_info_new (NULL); + camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); + + e_mail_folder_append_message ( + outbox_folder, message, info, + G_PRIORITY_DEFAULT, cancellable, + (GAsyncReadyCallback) composer_save_to_outbox_completed, + context); + + camel_message_info_free (info); +} + static void em_utils_composer_print_cb (EMsgComposer *composer, GtkPrintOperationAction action, @@ -1260,7 +1271,7 @@ setup_forward_attached_callbacks (EMsgComposer *composer, composer, "send", G_CALLBACK (update_forwarded_flags_cb), data); g_signal_connect ( - composer, "save-draft", + composer, "save-to-drafts", G_CALLBACK (update_forwarded_flags_cb), data); g_object_set_data_full ( @@ -2707,8 +2718,12 @@ em_configure_new_composer (EMsgComposer *composer) G_CALLBACK (em_utils_composer_send_cb), NULL); g_signal_connect ( - composer, "save-draft", - G_CALLBACK (em_utils_composer_save_draft_cb), NULL); + composer, "save-to-drafts", + G_CALLBACK (em_utils_composer_save_to_drafts_cb), NULL); + + g_signal_connect ( + composer, "save-to-outbox", + G_CALLBACK (em_utils_composer_save_to_outbox_cb), NULL); g_signal_connect ( composer, "print", -- cgit