static void mail_session_send_to_thread (GSimpleAsyncResult *simple, EMailSession *session, GCancellable *cancellable) { AsyncContext *context; CamelProvider *provider; CamelFolder *folder = NULL; CamelFolder *local_sent_folder; CamelServiceConnectionStatus status; GString *error_messages; gboolean copy_to_sent = TRUE; gboolean did_connect = FALSE; guint ii; GError *error = NULL; context = g_simple_async_result_get_op_res_gpointer (simple); if (camel_address_length (context->recipients) == 0) goto skip_send; /* Send the message to all recipients. */ /* XXX Leave this untranslated in gnome-3-8. * It was added during the string freeze, * but should rarely ever be seen by users. */ if (context->transport == NULL) { g_simple_async_result_set_error ( simple, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, "No mail transport service available"); return; } status = camel_service_get_connection_status (context->transport); if (status != CAMEL_SERVICE_CONNECTED) { did_connect = TRUE; camel_service_connect_sync ( context->transport, cancellable, &error); if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } provider = camel_service_get_provider (context->transport); if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER) copy_to_sent = FALSE; camel_transport_send_to_sync ( CAMEL_TRANSPORT (context->transport), context->message, context->from, context->recipients, cancellable, &error); if (did_connect) { /* Disconnect regardless of error or cancellation, * but be mindful of these conditions when calling * camel_service_disconnect_sync(). */ if (g_cancellable_is_cancelled (cancellable)) { camel_service_disconnect_sync ( context->transport, FALSE, NULL, NULL); } else if (error != NULL) { camel_service_disconnect_sync ( context->transport, FALSE, cancellable, NULL); } else { camel_service_disconnect_sync ( context->transport, TRUE, cancellable, &error); } if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } skip_send: /* Post the message to requested folders. */ for (ii = 0; ii < context->post_to_uris->len; ii++) { CamelFolder *folder; const gchar *folder_uri; folder_uri = g_ptr_array_index (context->post_to_uris, ii); folder = e_mail_session_uri_to_folder_sync ( session, folder_uri, 0, cancellable, &error); if (error != NULL) { g_warn_if_fail (folder == NULL); g_simple_async_result_take_error (simple, error); return; } g_return_if_fail (CAMEL_IS_FOLDER (folder)); camel_folder_append_message_sync ( folder, context->message, context->info, NULL, cancellable, &error); g_object_unref (folder); if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } /*** Post Processing ***/ /* This accumulates error messages during post-processing. */ error_messages = g_string_sized_new (256); mail_tool_restore_xevolution_headers (context->message, context->xev); /* Run filters on the outgoing message. */ if (context->driver != NULL) { camel_filter_driver_filter_message ( context->driver, context->message, context->info, NULL, NULL, NULL, "", cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error != NULL) { g_string_append_printf ( error_messages, _("Failed to apply outgoing filters: %s"), error->message); g_clear_error (&error); } if ((camel_message_info_flags (context->info) & CAMEL_MESSAGE_DELETED) != 0) copy_to_sent = FALSE; } if (!copy_to_sent) goto cleanup; /* Append the sent message to a Sent folder. */ local_sent_folder = e_mail_session_get_local_folder ( session, E_MAIL_LOCAL_FOLDER_SENT); folder = e_mail_session_get_fcc_for_message_sync ( session, context->message, cancellable, &error); /* Sanity check. */ g_return_if_fail ( ((folder != NULL) && (error == NULL)) || ((folder == NULL) && (error != NULL))); /* Append the message. */ if (folder != NULL) camel_folder_append_message_sync ( folder, context->message, context->info, NULL, cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error == NULL) goto cleanup; if (folder != NULL && folder != local_sent_folder) { const gchar *description; description = camel_folder_get_description (folder); if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to %s: %s\n" "Appending to local 'Sent' folder instead."), description, error->message); } /* If appending to a remote Sent folder failed, * try appending to the local Sent folder. */ if (folder != local_sent_folder) { g_clear_error (&error); camel_folder_append_message_sync ( local_sent_folder, context->message, context->info, NULL, cancellable, &error); } if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; /* We can't even append to the local Sent folder? * In that case just leave the message in Outbox. */ if (error != NULL) { if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to local 'Sent' folder: %s"), error->message); g_clear_error (&error); goto exit; } cleanup: /* The send operation was successful; ignore cleanup errors. */ /* Mark the draft message for deletion, if present. */ e_mail_session_handle_draft_headers_sync ( session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } /* Set flags on the original source message, if present. * Source message refers to the message being forwarded * or replied to. */ e_mail_session_handle_source_headers_sync ( session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } exit: /* If we were cancelled, disregard any other errors. */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_simple_async_result_take_error (simple, error); /* Stuff the accumulated error messages in a GError. */ } else if (error_messages->len > 0) { g_simple_async_result_set_error ( simple, E_MAIL_ERROR, E_MAIL_ERROR_POST_PROCESSING, "%s", error_messages->str); } /* Synchronize the Sent folder. */ if (folder != NULL) { camel_folder_synchronize_sync ( folder, FALSE, cancellable, NULL); g_object_unref (folder); } g_string_free (error_messages, TRUE); }
static void mail_session_send_to_thread (GSimpleAsyncResult *simple, EMailSession *session, GCancellable *cancellable) { AsyncContext *context; CamelFolder *local_sent_folder; GString *error_messages; gboolean copy_to_sent = TRUE; guint ii; GError *error = NULL; context = g_simple_async_result_get_op_res_gpointer (simple); /* Send the message to all recipients. */ if (camel_address_length (context->recipients) > 0) { CamelProvider *provider; CamelService *service; gboolean did_connect = FALSE; service = camel_session_get_service ( CAMEL_SESSION (session), context->transport_uid); if (!CAMEL_IS_TRANSPORT (service)) { g_simple_async_result_set_error (simple, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_URL_INVALID, _("Cannot get transport for account '%s'"), context->transport_uid); return; } if (camel_service_get_connection_status (service) != CAMEL_SERVICE_CONNECTED) { did_connect = TRUE; /* XXX This API does not allow for cancellation. */ if (!em_utils_connect_service_sync (service, cancellable, &error)) { g_simple_async_result_take_error (simple, error); return; } } provider = camel_service_get_provider (service); if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER) copy_to_sent = FALSE; camel_transport_send_to_sync ( CAMEL_TRANSPORT (service), context->message, context->from, context->recipients, cancellable, &error); if (did_connect) em_utils_disconnect_service_sync ( service, error == NULL, cancellable, error ? NULL : &error); if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } /* Post the message to requested folders. */ for (ii = 0; ii < context->post_to_uris->len; ii++) { CamelFolder *folder; const gchar *folder_uri; folder_uri = g_ptr_array_index (context->post_to_uris, ii); folder = e_mail_session_uri_to_folder_sync ( session, folder_uri, 0, cancellable, &error); if (error != NULL) { g_warn_if_fail (folder == NULL); g_simple_async_result_take_error (simple, error); return; } g_return_if_fail (CAMEL_IS_FOLDER (folder)); camel_folder_append_message_sync ( folder, context->message, context->info, NULL, cancellable, &error); g_object_unref (folder); if (error != NULL) { g_simple_async_result_take_error (simple, error); return; } } /*** Post Processing ***/ /* This accumulates error messages during post-processing. */ error_messages = g_string_sized_new (256); mail_tool_restore_xevolution_headers (context->message, context->xev); /* Run filters on the outgoing message. */ if (context->driver != NULL) { camel_filter_driver_filter_message ( context->driver, context->message, context->info, NULL, NULL, NULL, "", cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error != NULL) { g_string_append_printf ( error_messages, _("Failed to apply outgoing filters: %s"), error->message); g_clear_error (&error); } } if (!copy_to_sent) goto cleanup; /* Append the sent message to a Sent folder. */ local_sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT); /* Try to extract a CamelFolder from the Sent folder URI. */ if (context->sent_folder_uri != NULL) { context->sent_folder = e_mail_session_uri_to_folder_sync ( session, context->sent_folder_uri, 0, cancellable, &error); if (error != NULL) { g_warn_if_fail (context->sent_folder == NULL); if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to %s: %s\n" "Appending to local 'Sent' folder instead."), context->sent_folder_uri, error->message); g_clear_error (&error); } } /* Fall back to the local Sent folder. */ if (context->sent_folder == NULL) context->sent_folder = g_object_ref (local_sent_folder); /* Append the message. */ camel_folder_append_message_sync ( context->sent_folder, context->message, context->info, NULL, cancellable, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; if (error == NULL) goto cleanup; /* If appending to a remote Sent folder failed, * try appending to the local Sent folder. */ if (context->sent_folder != local_sent_folder) { const gchar *description; description = camel_folder_get_description ( context->sent_folder); if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to %s: %s\n" "Appending to local 'Sent' folder instead."), description, error->message); g_clear_error (&error); camel_folder_append_message_sync ( local_sent_folder, context->message, context->info, NULL, cancellable, &error); } if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) goto exit; /* We can't even append to the local Sent folder? * In that case just leave the message in Outbox. */ if (error != NULL) { if (error_messages->len > 0) g_string_append (error_messages, "\n\n"); g_string_append_printf ( error_messages, _("Failed to append to local 'Sent' folder: %s"), error->message); g_clear_error (&error); goto exit; } cleanup: /* The send operation was successful; ignore cleanup errors. */ /* Mark the draft message for deletion, if present. */ e_mail_session_handle_draft_headers_sync ( session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } /* Set flags on the original source message, if present. * Source message refers to the message being forwarded * or replied to. */ e_mail_session_handle_source_headers_sync ( session, context->message, cancellable, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } exit: /* If we were cancelled, disregard any other errors. */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_simple_async_result_take_error (simple, error); /* Stuff the accumulated error messages in a GError. */ } else if (error_messages->len > 0) { g_simple_async_result_set_error ( simple, E_MAIL_ERROR, E_MAIL_ERROR_POST_PROCESSING, "%s", error_messages->str); } /* Synchronize the Sent folder. */ if (context->sent_folder != NULL) camel_folder_synchronize_sync ( context->sent_folder, FALSE, cancellable, NULL); g_string_free (error_messages, TRUE); }