[evolution/wip/webkit2] The second part of making the EMsgComposer creation asynchronous



commit cdfa6caf53a378098314789eecb849c22421da59
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jul 8 17:40:53 2016 +0200

    The second part of making the EMsgComposer creation asynchronous

 calendar/gui/itip-utils.c                          |  234 +++++++-----
 composer/e-composer-actions.c                      |   21 +-
 composer/e-msg-composer.c                          |  214 ++++++++----
 composer/e-msg-composer.h                          |   13 +-
 e-util/e-html-editor.c                             |   42 ++-
 e-util/e-html-editor.h                             |    3 +-
 e-util/e-mail-signature-editor.c                   |    2 +-
 e-util/test-html-editor-units-utils.c              |    2 +-
 e-util/test-html-editor.c                          |    2 +-
 mail/e-mail-notes.c                                |    2 +-
 mail/e-mail-reader-utils.c                         |  384 ++++++++++++++------
 mail/e-mail-reader.c                               |   59 +++-
 mail/em-composer-utils.c                           |  330 ++++++++---------
 mail/em-composer-utils.h                           |   15 +-
 modules/addressbook/eab-composer-util.c            |  279 ++++++++-------
 modules/composer-autosave/e-autosave-utils.c       |   50 ++-
 modules/mail/e-mail-attachment-handler.c           |  102 +++++-
 modules/mail/e-mail-shell-backend.c                |   28 ++-
 modules/webkit-editor/e-webkit-editor.c            |   18 +-
 .../mailing-list-actions/mailing-list-actions.c    |   51 +++-
 plugins/templates/templates.c                      |   93 ++++--
 21 files changed, 1253 insertions(+), 691 deletions(-)
---
diff --git a/calendar/gui/itip-utils.c b/calendar/gui/itip-utils.c
index 5a688b0..c873e99 100644
--- a/calendar/gui/itip-utils.c
+++ b/calendar/gui/itip-utils.c
@@ -1639,17 +1639,18 @@ find_enabled_identity (ESourceRegistry *registry,
        return mail_identity;
 }
 
-static void
-setup_from (ECalComponentItipMethod method,
-            ECalComponent *comp,
-            ECalClient *cal_client,
-            EComposerHeaderTable *table)
+static gchar *
+get_identity_uid_for_from (EShell *shell,
+                          ECalComponentItipMethod method,
+                          ECalComponent *comp,
+                          ECalClient *cal_client)
 {
        EClientCache *client_cache;
        ESourceRegistry *registry;
        ESource *source = NULL;
+       gchar *identity_uid = NULL;
 
-       client_cache = e_composer_header_table_ref_client_cache (table);
+       client_cache = e_shell_get_client_cache (shell);
        registry = e_client_cache_ref_registry (client_cache);
 
        /* always use organizer's email when user is an organizer */
@@ -1673,16 +1674,14 @@ setup_from (ECalComponentItipMethod method,
        }
 
        if (source != NULL) {
-               const gchar *uid;
-
-               uid = e_source_get_uid (source);
-               e_composer_header_table_set_identity_uid (table, uid);
+               identity_uid = g_strdup (e_source_get_uid (source));
 
                g_object_unref (source);
        }
 
-       g_object_unref (client_cache);
        g_object_unref (registry);
+
+       return identity_uid;
 }
 
 typedef struct {
@@ -1771,83 +1770,64 @@ itip_send_component_begin (ItipSendComponentData *isc,
        }
 }
 
+typedef struct _CreateComposerData {
+       gchar *identity_uid;
+       EDestination **destinations;
+       gchar *subject;
+       gchar *ical_string;
+       gchar *content_type;
+       gchar *event_body_text;
+       GSList *attachments_list;
+       ECalComponent *comp;
+       gboolean show_only;
+} CreateComposerData;
+
 static void
-itip_send_component_complete (ItipSendComponentData *isc)
+itip_send_component_composer_created_cb (GObject *source_object,
+                                        GAsyncResult *result,
+                                        gpointer user_data)
 {
-       GSettings *settings;
-       EMsgComposer *composer;
+       CreateComposerData *ccd = user_data;
        EComposerHeaderTable *table;
-       EDestination **destinations;
-       ECalComponent *comp = NULL;
-       icalcomponent *top_level = NULL;
-       icaltimezone *default_zone;
-       gchar *ical_string = NULL;
-       gchar *content_type = NULL;
-       gchar *subject = NULL;
+       EMsgComposer *composer;
+       GSettings *settings;
        gboolean use_24hour_format;
+       GError *error = NULL;
 
-       g_return_if_fail (isc != NULL);
+       g_return_if_fail (ccd != NULL);
 
-       if (isc->completed)
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
                return;
-
-       isc->success = FALSE;
+       }
 
        settings = e_util_ref_settings ("org.gnome.evolution.calendar");
        use_24hour_format = g_settings_get_boolean (settings, "use-24hour-format");
        g_object_unref (settings);
 
-       default_zone = calendar_config_get_icaltimezone ();
-
-       /* Tidy up the comp */
-       comp = comp_compliant (
-               isc->registry, isc->method, isc->send_comp, isc->cal_client,
-               isc->zones, default_zone, isc->strip_alarms);
-
-       if (comp == NULL)
-               goto cleanup;
-
-       /* Recipients */
-       destinations = comp_to_list (
-               isc->registry, isc->method, comp, isc->users, FALSE,
-               isc->only_new_attendees ? g_object_get_data (
-               G_OBJECT (isc->send_comp), "new-attendees") : NULL);
-       if (isc->method != E_CAL_COMPONENT_METHOD_PUBLISH) {
-               if (destinations == NULL) {
-                       /* We sent them all via the server */
-                       isc->success = TRUE;
-                       goto cleanup;
-               }
-       }
-
-       /* Subject information */
-       subject = comp_subject (isc->registry, isc->method, comp);
-
-       composer = e_msg_composer_new (e_shell_get_default ());
        table = e_msg_composer_get_header_table (composer);
 
-       setup_from (isc->method, isc->send_comp, isc->cal_client, table);
-       e_composer_header_table_set_subject (table, subject);
-       e_composer_header_table_set_destinations_to (table, destinations);
-
-       e_destination_freev (destinations);
+       if (ccd->identity_uid)
+               e_composer_header_table_set_identity_uid (table, ccd->identity_uid);
 
-       /* Content type */
-       content_type = comp_content_type (comp, isc->method);
+       e_composer_header_table_set_subject (table, ccd->subject);
+       e_composer_header_table_set_destinations_to (table, ccd->destinations);
 
-       top_level = comp_toplevel_with_zones (isc->method, comp, isc->cal_client, isc->zones);
-       ical_string = icalcomponent_as_ical_string_r (top_level);
-
-       if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_EVENT) {
-               e_msg_composer_set_body (composer, ical_string, content_type);
+       if (e_cal_component_get_vtype (ccd->comp) == E_CAL_COMPONENT_EVENT) {
+               if (ccd->event_body_text)
+                       e_msg_composer_set_body_text (composer, ccd->event_body_text, TRUE);
+               else
+                       e_msg_composer_set_body (composer, ccd->ical_string, ccd->content_type);
        } else {
                CamelMimePart *attachment;
                const gchar *filename;
                gchar *description;
                gchar *body;
 
-               filename = comp_filename (comp);
-               description = comp_description (comp, use_24hour_format);
+               filename = comp_filename (ccd->comp);
+               description = comp_description (ccd->comp, use_24hour_format);
 
                body = camel_text_to_html (description, CAMEL_MIME_FILTER_TOHTML_PRE, 0);
                e_msg_composer_set_body_text (composer, body, TRUE);
@@ -1855,8 +1835,8 @@ itip_send_component_complete (ItipSendComponentData *isc)
 
                attachment = camel_mime_part_new ();
                camel_mime_part_set_content (
-                       attachment, ical_string,
-                       strlen (ical_string), content_type);
+                       attachment, ccd->ical_string,
+                       strlen (ccd->ical_string), ccd->content_type);
                if (filename != NULL && *filename != '\0')
                        camel_mime_part_set_filename (attachment, filename);
                if (description != NULL && *description != '\0')
@@ -1868,23 +1848,89 @@ itip_send_component_complete (ItipSendComponentData *isc)
                g_free (description);
        }
 
-       append_cal_attachments (composer, comp, isc->attachments_list);
-       isc->attachments_list = NULL;
+       append_cal_attachments (composer, ccd->comp, ccd->attachments_list);
+       ccd->attachments_list = NULL;
 
-       if (isc->method == E_CAL_COMPONENT_METHOD_PUBLISH && !isc->users)
+       if (ccd->show_only)
                gtk_widget_show (GTK_WIDGET (composer));
        else
                e_msg_composer_send (composer);
 
+       e_destination_freev (ccd->destinations);
+       g_clear_object (&ccd->comp);
+       g_free (ccd->identity_uid);
+       g_free (ccd->subject);
+       g_free (ccd->ical_string);
+       g_free (ccd->content_type);
+       g_free (ccd->event_body_text);
+       g_free (ccd);
+}
+
+static void
+itip_send_component_complete (ItipSendComponentData *isc)
+{
+       CreateComposerData *ccd;
+       EDestination **destinations;
+       ECalComponent *comp = NULL;
+       EShell *shell;
+       icalcomponent *top_level = NULL;
+       icaltimezone *default_zone;
+
+       g_return_if_fail (isc != NULL);
+
+       if (isc->completed)
+               return;
+
+       isc->success = FALSE;
+
+       default_zone = calendar_config_get_icaltimezone ();
+
+       /* Tidy up the comp */
+       comp = comp_compliant (
+               isc->registry, isc->method, isc->send_comp, isc->cal_client,
+               isc->zones, default_zone, isc->strip_alarms);
+
+       if (comp == NULL)
+               goto cleanup;
+
+       /* Recipients */
+       destinations = comp_to_list (
+               isc->registry, isc->method, comp, isc->users, FALSE,
+               isc->only_new_attendees ? g_object_get_data (
+               G_OBJECT (isc->send_comp), "new-attendees") : NULL);
+       if (isc->method != E_CAL_COMPONENT_METHOD_PUBLISH) {
+               if (destinations == NULL) {
+                       /* We sent them all via the server */
+                       isc->success = TRUE;
+                       goto cleanup;
+               }
+       }
+
+       shell = e_shell_get_default ();
+       top_level = comp_toplevel_with_zones (isc->method, comp, isc->cal_client, isc->zones);
+
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->identity_uid = get_identity_uid_for_from (shell, isc->method, isc->send_comp, isc->cal_client);
+       ccd->destinations = destinations;
+       ccd->subject = comp_subject (isc->registry, isc->method, comp);
+       ccd->ical_string = icalcomponent_as_ical_string_r (top_level);
+       ccd->content_type = comp_content_type (comp, isc->method);
+       ccd->event_body_text = NULL;
+       ccd->attachments_list = isc->attachments_list;
+       ccd->comp = comp;
+       ccd->show_only = isc->method == E_CAL_COMPONENT_METHOD_PUBLISH && !isc->users;
+
+       isc->attachments_list = NULL;
+       comp = NULL;
+
+       e_msg_composer_new (shell, itip_send_component_composer_created_cb, ccd);
+
        isc->success = TRUE;
 
  cleanup:
        g_clear_object (&comp);
        if (top_level != NULL)
                icalcomponent_free (top_level);
-       g_free (content_type);
-       g_free (subject);
-       g_free (ical_string);
 }
 
 static void
@@ -2119,15 +2165,11 @@ reply_to_calendar_comp (ESourceRegistry *registry,
                         GSList *attachments_list)
 {
        EShell *shell;
-       EMsgComposer *composer;
-       EComposerHeaderTable *table;
-       EDestination **destinations;
        ECalComponent *comp = NULL;
        icalcomponent *top_level = NULL;
        icaltimezone *default_zone;
-       gchar *subject = NULL;
-       gchar *ical_string = NULL;
        gboolean retval = FALSE;
+       CreateComposerData *ccd;
 
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
 
@@ -2143,24 +2185,15 @@ reply_to_calendar_comp (ESourceRegistry *registry,
        if (comp == NULL)
                goto cleanup;
 
-       /* Recipients */
-       destinations = comp_to_list (
-               registry, method, comp, NULL, reply_all, NULL);
-
-       /* Subject information */
-       subject = comp_subject (registry, method, comp);
-
-       composer = e_msg_composer_new (shell);
-       table = e_msg_composer_get_header_table (composer);
-
-       setup_from (method, send_comp, cal_client, table);
-       e_composer_header_table_set_subject (table, subject);
-       e_composer_header_table_set_destinations_to (table, destinations);
-
-       e_destination_freev (destinations);
-
        top_level = comp_toplevel_with_zones (method, comp, cal_client, zones);
-       ical_string = icalcomponent_as_ical_string_r (top_level);
+
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->identity_uid = get_identity_uid_for_from (shell, method, send_comp, cal_client);
+       ccd->destinations = comp_to_list (registry, method, comp, NULL, reply_all, NULL);
+       ccd->subject = comp_subject (registry, method, comp);
+       ccd->ical_string = icalcomponent_as_ical_string_r (top_level);
+       ccd->comp = comp;
+       ccd->show_only = TRUE;
 
        if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_EVENT) {
 
@@ -2268,11 +2301,12 @@ reply_to_calendar_comp (ESourceRegistry *registry,
                g_string_append (body, html_description);
                g_free (html_description);
 
-               e_msg_composer_set_body_text (composer, body->str, TRUE);
-               g_string_free (body, TRUE);
+               ccd->event_body_text = g_string_free (body, FALSE);
        }
 
-       gtk_widget_show (GTK_WIDGET (composer));
+       comp = NULL;
+
+       e_msg_composer_new (shell, itip_send_component_composer_created_cb, ccd);
 
        retval = TRUE;
 
@@ -2283,8 +2317,6 @@ reply_to_calendar_comp (ESourceRegistry *registry,
        if (top_level != NULL)
                icalcomponent_free (top_level);
 
-       g_free (subject);
-       g_free (ical_string);
        return retval;
 }
 
diff --git a/composer/e-composer-actions.c b/composer/e-composer-actions.c
index cf31d23..fa92322 100644
--- a/composer/e-composer-actions.c
+++ b/composer/e-composer-actions.c
@@ -65,16 +65,31 @@ action_close_cb (GtkAction *action,
 }
 
 static void
+action_new_message_composer_created_cb (GObject *source_object,
+                                       GAsyncResult *result,
+                                       gpointer user_data)
+{
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               gtk_widget_show (GTK_WIDGET (composer));
+       }
+}
+
+static void
 action_new_message_cb (GtkAction *action,
                        EMsgComposer *composer)
 {
-       EMsgComposer *new_composer;
        EShell *shell;
 
        shell = e_msg_composer_get_shell (composer);
 
-       new_composer = e_msg_composer_new (shell);
-       gtk_widget_show (GTK_WIDGET (new_composer));
+       e_msg_composer_new (shell, action_new_message_composer_created_cb, NULL);
 }
 
 static void
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index b423411..0dec505 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -133,7 +133,7 @@ static void add_attachments_from_multipart  (EMsgComposer *composer,
                                                 gboolean just_inlines,
                                                 gint depth);
 
-/* used by e_msg_composer_new_with_message () */
+/* used by e_msg_composer_setup_with_message () */
 static void    handle_multipart                (EMsgComposer *composer,
                                                 CamelMultipart *multipart,
                                                 gboolean keep_signature,
@@ -2226,6 +2226,16 @@ msg_composer_quit_requested_cb (EShell *shell,
 }
 
 static void
+msg_composer_set_editor (EMsgComposer *composer,
+                        EHTMLEditor *editor)
+{
+       g_return_if_fail (E_IS_HTML_EDITOR (editor));
+       g_return_if_fail (composer->priv->editor == NULL);
+
+       composer->priv->editor = g_object_ref_sink (editor);
+}
+
+static void
 msg_composer_set_shell (EMsgComposer *composer,
                         EShell *shell)
 {
@@ -2245,6 +2255,12 @@ msg_composer_set_property (GObject *object,
                            GParamSpec *pspec)
 {
        switch (property_id) {
+               case PROP_EDITOR:
+                       msg_composer_set_editor (
+                               E_MSG_COMPOSER (object),
+                               g_value_get_object (value));
+                       return;
+
                case PROP_SHELL:
                        msg_composer_set_shell (
                                E_MSG_COMPOSER (object),
@@ -2268,6 +2284,12 @@ msg_composer_get_property (GObject *object,
                                E_MSG_COMPOSER (object)));
                        return;
 
+               case PROP_EDITOR:
+                       g_value_set_object (
+                               value, e_msg_composer_get_editor (
+                               E_MSG_COMPOSER (object)));
+                       return;
+
                case PROP_FOCUS_TRACKER:
                        g_value_set_object (
                                value, e_msg_composer_get_focus_tracker (
@@ -2375,6 +2397,7 @@ msg_composer_constructed (GObject *object)
        EComposerHeaderTable *table;
        EHTMLEditor *editor;
        EContentEditor *cnt_editor;
+       EContentEditorContentFlags flags;
        GtkUIManager *ui_manager;
        GtkToggleAction *action;
        GtkTargetList *target_list;
@@ -2384,8 +2407,13 @@ msg_composer_constructed (GObject *object)
        const gchar *id;
        gboolean active;
 
+       /* Chain up to parent's constructed() method. */
+       G_OBJECT_CLASS (e_msg_composer_parent_class)->constructed (object);
+
        composer = E_MSG_COMPOSER (object);
 
+       g_return_if_fail (E_IS_HTML_EDITOR (composer->priv->editor));
+
        shell = e_msg_composer_get_shell (composer);
 
        e_composer_private_constructed (composer);
@@ -2396,6 +2424,10 @@ msg_composer_constructed (GObject *object)
        attachment_view = e_msg_composer_get_attachment_view (composer);
        table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table);
 
+       flags = e_content_editor_get_current_content_flags (cnt_editor);
+       flags |= E_CONTENT_EDITOR_MESSAGE_EDITTING;
+       e_content_editor_set_current_content_flags (cnt_editor, flags);
+
        gtk_window_set_title (GTK_WINDOW (composer), _("Compose Message"));
        gtk_window_set_icon_name (GTK_WINDOW (composer), "mail-message-new");
        gtk_window_set_default_size (GTK_WINDOW (composer), 600, 500);
@@ -2538,8 +2570,6 @@ msg_composer_constructed (GObject *object)
        e_extensible_load_extensions (E_EXTENSIBLE (composer));
 
        e_msg_composer_set_body_text (composer, "", TRUE);
-       /* Chain up to parent's constructed() method. */
-       G_OBJECT_CLASS (e_msg_composer_parent_class)->constructed (object);
 }
 
 static void
@@ -2756,6 +2786,17 @@ e_msg_composer_class_init (EMsgComposerClass *class)
 
        g_object_class_install_property (
                object_class,
+               PROP_EDITOR,
+               g_param_spec_object (
+                       "editor",
+                       NULL,
+                       NULL,
+                       E_TYPE_HTML_EDITOR,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY));
+
+       g_object_class_install_property (
+               object_class,
                PROP_FOCUS_TRACKER,
                g_param_spec_object (
                        "focus-tracker",
@@ -2833,35 +2874,87 @@ e_msg_composer_class_init (EMsgComposerClass *class)
 static void
 e_msg_composer_init (EMsgComposer *composer)
 {
-       EContentEditor *cnt_editor;
-       EContentEditorContentFlags flags;
-
        composer->priv = E_MSG_COMPOSER_GET_PRIVATE (composer);
+}
 
-       composer->priv->editor = g_object_ref_sink (e_html_editor_new ());
-       cnt_editor = e_html_editor_get_content_editor (composer->priv->editor);
+static void
+e_msg_composer_editor_created_cb (GObject *source_object,
+                                 GAsyncResult *result,
+                                 gpointer user_data)
+{
+       GtkWidget *editor;
+       ESimpleAsyncResult *eresult = user_data;
+       GError *error = NULL;
 
-       flags = e_content_editor_get_current_content_flags (cnt_editor);
-       flags |= E_CONTENT_EDITOR_MESSAGE_EDITTING;
-       e_content_editor_set_current_content_flags (cnt_editor, flags);
+       g_return_if_fail (E_IS_SIMPLE_ASYNC_RESULT (eresult));
+
+       editor = e_html_editor_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create HTML editor: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               e_simple_async_result_set_op_pointer (eresult, editor);
+               e_simple_async_result_complete (eresult);
+       }
+
+       g_object_unref (eresult);
 }
 
 /**
  * e_msg_composer_new:
  * @shell: an #EShell
+ * @callback: called when the composer is ready
+ * @user_data: user data passed to @callback
  *
- * Create a new message composer widget.
+ * Asynchronously creates an #EMsgComposer. The operation is finished
+ * with e_msg_composer_new_finish() called from within the @callback.
  *
- * Returns: A pointer to the newly created widget
+ * Since: 3.22
+ **/
+void
+e_msg_composer_new (EShell *shell,
+                   GAsyncReadyCallback callback,
+                   gpointer user_data)
+{
+       ESimpleAsyncResult *eresult;
+
+       g_return_if_fail (E_IS_SHELL (shell));
+       g_return_if_fail (callback != NULL);
+
+       eresult = e_simple_async_result_new (NULL, callback, user_data, e_msg_composer_new);
+       e_simple_async_result_set_user_data (eresult, g_object_ref (shell), g_object_unref);
+
+       e_html_editor_new (e_msg_composer_editor_created_cb, eresult);
+}
+
+/**
+ * e_msg_composer_new_finish:
+ * @result: a #GAsyncResult provided by the callback from e_msg_composer_new()
+ * @error: optional #GError for errors
+ *
+ * Finishes call of e_msg_composer_new().
+ *
+ * Since: 3.22
  **/
 EMsgComposer *
-e_msg_composer_new (EShell *shell)
+e_msg_composer_new_finish (GAsyncResult *result,
+                          GError **error)
 {
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+       ESimpleAsyncResult *eresult;
+       EHTMLEditor *html_editor;
+
+       g_return_val_if_fail (E_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+       g_return_val_if_fail (g_async_result_is_tagged (result, e_msg_composer_new), NULL);
+
+       eresult = E_SIMPLE_ASYNC_RESULT (result);
 
-       return g_object_new (
-               E_TYPE_MSG_COMPOSER,
-               "shell", shell, NULL);
+       html_editor = e_simple_async_result_get_op_pointer (eresult);
+       g_return_val_if_fail (E_IS_HTML_EDITOR (html_editor), NULL);
+
+       return g_object_new (E_TYPE_MSG_COMPOSER,
+               "shell", e_simple_async_result_get_user_data (eresult),
+               "editor", html_editor,
+               NULL);
 }
 
 /**
@@ -3473,25 +3566,25 @@ composer_add_auto_recipients (ESource *source,
 }
 
 /**
- * e_msg_composer_new_with_message:
- * @shell: an #EShell
+ * e_msg_composer_setup_with_message:
+ * @composer: an #EMsgComposer
  * @message: The message to use as the source
  * @keep_signature: Keep message signature, if any
  * @override_identity_uid: (allow none): Optional identity UID to use, or %NULL
  * @cancellable: optional #GCancellable object, or %NULL
  *
- * Create a new message composer widget.
+ * Sets up the message @composer with a specific @message.
  *
  * Note: Designed to work only for messages constructed using Evolution.
  *
- * Returns: A pointer to the newly created widget
+ * Since: 3.22
  **/
-EMsgComposer *
-e_msg_composer_new_with_message (EShell *shell,
-                                 CamelMimeMessage *message,
-                                 gboolean keep_signature,
-                                const gchar *override_identity_uid,
-                                 GCancellable *cancellable)
+void
+e_msg_composer_setup_with_message (EMsgComposer *composer,
+                                  CamelMimeMessage *message,
+                                  gboolean keep_signature,
+                                  const gchar *override_identity_uid,
+                                  GCancellable *cancellable)
 {
        CamelInternetAddress *from, *to, *cc, *bcc;
        GList *To = NULL, *Cc = NULL, *Bcc = NULL, *postto = NULL;
@@ -3501,7 +3594,6 @@ e_msg_composer_new_with_message (EShell *shell,
        CamelContentType *content_type;
        struct _camel_header_raw *headers;
        CamelDataWrapper *content;
-       EMsgComposer *composer;
        EMsgComposerPrivate *priv;
        EComposerHeaderTable *table;
        ESource *source = NULL;
@@ -3514,7 +3606,7 @@ e_msg_composer_new_with_message (EShell *shell,
        gint len, i;
        gboolean is_message_from_draft = FALSE;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
        headers = CAMEL_MIME_PART (message)->headers;
        while (headers != NULL) {
@@ -3528,7 +3620,6 @@ e_msg_composer_new_with_message (EShell *shell,
                headers = headers->next;
        }
 
-       composer = e_msg_composer_new (shell);
        priv = E_MSG_COMPOSER_GET_PRIVATE (composer);
        table = e_msg_composer_get_header_table (composer);
        editor = e_msg_composer_get_editor (composer);
@@ -3554,7 +3645,7 @@ e_msg_composer_new_with_message (EShell *shell,
                }
                if (!identity_uid) {
                        source = em_utils_guess_mail_identity_with_recipients (
-                               e_shell_get_registry (shell), message, NULL, NULL);
+                               e_shell_get_registry (e_msg_composer_get_shell (composer)), message, NULL, 
NULL);
                        if (source)
                                identity_uid = e_source_dup_uid (source);
                }
@@ -3862,38 +3953,36 @@ e_msg_composer_new_with_message (EShell *shell,
        e_msg_composer_flush_pending_body (composer);
 
        set_signature_gui (composer);
-
-       return composer;
 }
 
 /**
- * e_msg_composer_new_redirect:
- * @shell: an #EShell
+ * e_msg_composer_setup_redirect:
+ * @composer: an #EMsgComposer
  * @message: The message to use as the source
+ * @identity_uid: (nullable): an identity UID to use, if any
+ * @cancellable: an optional #GCancellable
  *
- * Create a new message composer widget.
+ * Sets up the message @composer as a redirect of the @message.
  *
- * Returns: A pointer to the newly created widget
+ * Since: 3.22
  **/
-EMsgComposer *
-e_msg_composer_new_redirect (EShell *shell,
-                             CamelMimeMessage *message,
-                             const gchar *identity_uid,
-                             GCancellable *cancellable)
+void
+e_msg_composer_setup_redirect (EMsgComposer *composer,
+                              CamelMimeMessage *message,
+                              const gchar *identity_uid,
+                              GCancellable *cancellable)
 {
-       EMsgComposer *composer;
        EComposerHeaderTable *table;
        EHTMLEditor *editor;
        EContentEditor *cnt_editor;
        const gchar *subject;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
-       composer = e_msg_composer_new_with_message (
-               shell, message, TRUE, identity_uid, cancellable);
-       table = e_msg_composer_get_header_table (composer);
+       e_msg_composer_setup_with_message (composer, message, TRUE, identity_uid, cancellable);
 
+       table = e_msg_composer_get_header_table (composer);
        subject = camel_mime_message_get_subject (message);
 
        composer->priv->redirect = message;
@@ -3904,8 +3993,6 @@ e_msg_composer_new_redirect (EShell *shell,
        editor = e_msg_composer_get_editor (composer);
        cnt_editor = e_html_editor_get_content_editor (editor);
        e_content_editor_set_editable (cnt_editor, FALSE);
-
-       return composer;
 }
 
 /**
@@ -4611,27 +4698,22 @@ handle_mailto (EMsgComposer *composer,
 }
 
 /**
- * e_msg_composer_new_from_url:
- * @shell: an #EShell
+ * e_msg_composer_setup_from_url:
+ * @composer: an #EMsgComposer
  * @url: a mailto URL
  *
- * Create a new message composer widget, and fill in fields as
- * defined by the provided URL.
+ * Sets up the message @composer content as defined by the provided URL.
+ *
+ * Since: 3.22
  **/
-EMsgComposer *
-e_msg_composer_new_from_url (EShell *shell,
-                             const gchar *url)
+void
+e_msg_composer_setup_from_url (EMsgComposer *composer,
+                              const gchar *url)
 {
-       EMsgComposer *composer;
-
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
-       g_return_val_if_fail (g_ascii_strncasecmp (url, "mailto:";, 7) == 0, NULL);
-
-       composer = e_msg_composer_new (shell);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (g_ascii_strncasecmp (url, "mailto:";, 7) == 0);
 
        handle_mailto (composer, url);
-
-       return composer;
 }
 
 /**
diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h
index daaca2b..c0986a5 100644
--- a/composer/e-msg-composer.h
+++ b/composer/e-msg-composer.h
@@ -81,15 +81,20 @@ struct _EMsgComposerClass {
 };
 
 GType          e_msg_composer_get_type         (void);
-EMsgComposer * e_msg_composer_new              (EShell *shell);
-EMsgComposer * e_msg_composer_new_with_message (EShell *shell,
+void           e_msg_composer_new              (EShell *shell,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+EMsgComposer * e_msg_composer_new_finish       (GAsyncResult *result,
+                                                GError **error);
+void           e_msg_composer_setup_with_message
+                                               (EMsgComposer *composer,
                                                 CamelMimeMessage *message,
                                                 gboolean keep_signature,
                                                 const gchar *override_identity_uid,
                                                 GCancellable *cancellable);
-EMsgComposer * e_msg_composer_new_from_url     (EShell *shell,
+void           e_msg_composer_setup_from_url   (EMsgComposer *composer,
                                                 const gchar *url);
-EMsgComposer * e_msg_composer_new_redirect     (EShell *shell,
+void           e_msg_composer_setup_redirect   (EMsgComposer *composer,
                                                 CamelMimeMessage *message,
                                                 const gchar *identity_uid,
                                                 GCancellable *cancellable);
diff --git a/e-util/e-html-editor.c b/e-util/e-html-editor.c
index 88d546c..a9582fd 100644
--- a/e-util/e-html-editor.c
+++ b/e-util/e-html-editor.c
@@ -885,19 +885,6 @@ e_html_editor_init (EHTMLEditor *editor)
        g_free (filename);
 }
 
-/**
- * e_html_editor_new:
- *
- * Constructs a new #EHTMLEditor.
- *
- * Returns: (transfer-full): A newly created widget.
- */
-GtkWidget *
-e_html_editor_new (void)
-{
-       return g_object_new (E_TYPE_HTML_EDITOR, NULL);
-}
-
 static void
 e_html_editor_content_editor_initialized (EContentEditor *content_editor,
                                          gpointer user_data)
@@ -934,9 +921,19 @@ e_html_editor_content_editor_initialized (EContentEditor *content_editor,
        g_object_unref (async_result);
 }
 
+/**
+ * e_html_editor_new:
+ * @callback: a callback to be called when the editor is ready
+ * @user_data: a used data passed into the @callback
+ *
+ * Constructs a new #EHTMLEditor asynchronously. The result is returned
+ * by e_html_editor_new_finish(), which should be called inside @callback.
+ *
+ * Since: 3.22
+ **/
 void
-e_html_editor_new_async (GAsyncReadyCallback callback,
-                        gpointer user_data)
+e_html_editor_new (GAsyncReadyCallback callback,
+                  gpointer user_data)
 {
        EHTMLEditor *html_editor;
        EContentEditor *content_editor;
@@ -945,13 +942,24 @@ e_html_editor_new_async (GAsyncReadyCallback callback,
        g_return_if_fail (callback != NULL);
 
        html_editor = g_object_new (E_TYPE_HTML_EDITOR, NULL);
-       async_result = e_simple_async_result_new (NULL, callback, user_data, e_html_editor_new_async);
+       async_result = e_simple_async_result_new (NULL, callback, user_data, e_html_editor_new);
        e_simple_async_result_set_user_data (async_result, html_editor, g_object_unref);
 
        content_editor = e_html_editor_get_content_editor (html_editor);
        e_content_editor_initialize (content_editor, e_html_editor_content_editor_initialized, async_result);
 }
 
+/**
+ * e_html_editor_new_finish:
+ * @result: a #GAsyncResult passed to callback from e_html_editor_new()
+ * @error: an optional #GError
+ *
+ * Finishes the call of e_html_editor_new().
+ *
+ * Returns: (transfer-full): A newly created #EHTMLEditor.
+ *
+ * Since: 3.22
+ **/
 GtkWidget *
 e_html_editor_new_finish (GAsyncResult *result,
                          GError **error)
@@ -959,7 +967,7 @@ e_html_editor_new_finish (GAsyncResult *result,
        ESimpleAsyncResult *eresult;
 
        g_return_val_if_fail (E_IS_SIMPLE_ASYNC_RESULT (result), NULL);
-       g_return_val_if_fail (g_async_result_is_tagged (result, e_html_editor_new_async), NULL);
+       g_return_val_if_fail (g_async_result_is_tagged (result, e_html_editor_new), NULL);
 
        eresult = E_SIMPLE_ASYNC_RESULT (result);
 
diff --git a/e-util/e-html-editor.h b/e-util/e-html-editor.h
index ea94dd8..e1381da 100644
--- a/e-util/e-html-editor.h
+++ b/e-util/e-html-editor.h
@@ -70,8 +70,7 @@ struct _EHTMLEditorClass {
 };
 
 GType          e_html_editor_get_type          (void) G_GNUC_CONST;
-GtkWidget *    e_html_editor_new               (void);
-void           e_html_editor_new_async         (GAsyncReadyCallback callback,
+void           e_html_editor_new               (GAsyncReadyCallback callback,
                                                 gpointer user_data);
 GtkWidget *    e_html_editor_new_finish        (GAsyncResult *result,
                                                 GError **error);
diff --git a/e-util/e-mail-signature-editor.c b/e-util/e-mail-signature-editor.c
index 28ebb53..c6afe5a 100644
--- a/e-util/e-mail-signature-editor.c
+++ b/e-util/e-mail-signature-editor.c
@@ -807,7 +807,7 @@ e_mail_signature_editor_new (ESourceRegistry *registry,
        eresult = e_simple_async_result_new (NULL, callback, user_data, e_mail_signature_editor_new);
        e_simple_async_result_set_user_data (eresult, ced, create_editor_data_free);
 
-       e_html_editor_new_async (mail_signature_editor_html_editor_created_cb, eresult);
+       e_html_editor_new (mail_signature_editor_html_editor_created_cb, eresult);
 }
 
 GtkWidget *
diff --git a/e-util/test-html-editor-units-utils.c b/e-util/test-html-editor-units-utils.c
index 56a4a36..4196bc7 100644
--- a/e-util/test-html-editor-units-utils.c
+++ b/e-util/test-html-editor-units-utils.c
@@ -202,7 +202,7 @@ test_utils_fixture_set_up (TestFixture *fixture,
        create_data.async_data = test_utils_async_call_prepare ();
        create_data.fixture = fixture;
 
-       e_html_editor_new_async (test_utils_html_editor_created_cb, &create_data);
+       e_html_editor_new (test_utils_html_editor_created_cb, &create_data);
 
        test_utils_async_call_wait (create_data.async_data, 5);
 }
diff --git a/e-util/test-html-editor.c b/e-util/test-html-editor.c
index 335aba8..b295abe 100644
--- a/e-util/test-html-editor.c
+++ b/e-util/test-html-editor.c
@@ -557,7 +557,7 @@ create_new_editor (void)
 {
        glob_editors++;
 
-       e_html_editor_new_async (create_new_editor_cb, NULL);
+       e_html_editor_new (create_new_editor_cb, NULL);
 }
 
 gint
diff --git a/mail/e-mail-notes.c b/mail/e-mail-notes.c
index 9a60246..94a8396 100644
--- a/mail/e-mail-notes.c
+++ b/mail/e-mail-notes.c
@@ -1146,7 +1146,7 @@ e_mail_notes_edit (GtkWindow *parent,
        ad->folder = g_object_ref (folder);
        ad->uid = g_strdup (uid);
 
-       e_html_editor_new_async (e_mail_notes_editor_ready_cb, ad);
+       e_html_editor_new (e_mail_notes_editor_ready_cb, ad);
 }
 
 gboolean
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index decf60c..c850bba 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -1729,6 +1729,76 @@ e_mail_reader_remove_duplicates (EMailReader *reader)
        g_ptr_array_unref (uids);
 }
 
+typedef struct _CreateComposerData {
+       EMailReader *reader;
+       CamelFolder *folder;
+       CamelMimeMessage *message;
+       gchar *message_uid;
+       gboolean keep_signature;
+
+       EMailPartList *part_list;
+       EMailReplyType reply_type;
+       EMailReplyStyle reply_style;
+       CamelInternetAddress *address;
+       EMailPartValidityFlags validity_pgp_sum;
+       EMailPartValidityFlags validity_smime_sum;
+
+       EMailForwardStyle forward_style;
+
+       CamelMimePart *attached_part;
+       gchar *attached_subject;
+       GPtrArray *attached_uids;
+} CreateComposerData;
+
+static void
+create_composer_data_free (CreateComposerData *ccd)
+{
+       if (ccd) {
+               if (ccd->attached_uids)
+                       g_ptr_array_unref (ccd->attached_uids);
+
+               g_clear_object (&ccd->reader);
+               g_clear_object (&ccd->folder);
+               g_clear_object (&ccd->message);
+               g_clear_object (&ccd->part_list);
+               g_clear_object (&ccd->address);
+               g_clear_object (&ccd->attached_part);
+               g_free (ccd->message_uid);
+               g_free (ccd->attached_subject);
+               g_free (ccd);
+       }
+}
+
+static void
+mail_reader_edit_messages_composer_created_cb (GObject *source_object,
+                                              GAsyncResult *result,
+                                              gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (ccd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               camel_medium_remove_header (
+                       CAMEL_MEDIUM (ccd->message), "X-Mailer");
+
+               em_utils_edit_message (
+                       composer, ccd->folder, ccd->message, ccd->message_uid,
+                       ccd->keep_signature);
+
+               e_mail_reader_composer_created (
+                       ccd->reader, composer, ccd->message);
+       }
+
+       create_composer_data_free (ccd);
+}
+
 static void
 mail_reader_edit_messages_cb (GObject *source_object,
                               GAsyncResult *result,
@@ -1780,24 +1850,17 @@ mail_reader_edit_messages_cb (GObject *source_object,
        g_hash_table_iter_init (&iter, hash_table);
 
        while (g_hash_table_iter_next (&iter, &key, &value)) {
-               EMsgComposer *composer;
-               CamelMimeMessage *message;
-               const gchar *message_uid = NULL;
-
-               if (async_context->replace)
-                       message_uid = (const gchar *) key;
+               CreateComposerData *ccd;
 
-               message = CAMEL_MIME_MESSAGE (value);
-
-               camel_medium_remove_header (
-                       CAMEL_MEDIUM (message), "X-Mailer");
+               ccd = g_new0 (CreateComposerData, 1);
+               ccd->reader = g_object_ref (async_context->reader);
+               ccd->folder = g_object_ref (folder);
+               ccd->message = g_object_ref (CAMEL_MIME_MESSAGE (value));
 
-               composer = em_utils_edit_message (
-                       shell, folder, message, message_uid,
-                       async_context->keep_signature);
+               if (async_context->replace)
+                       ccd->message_uid = g_strdup ((const gchar *) key);
 
-               e_mail_reader_composer_created (
-                       async_context->reader, composer, message);
+               e_msg_composer_new (shell, mail_reader_edit_messages_composer_created_cb, ccd);
        }
 
        g_hash_table_unref (hash_table);
@@ -1843,6 +1906,44 @@ e_mail_reader_edit_messages (EMailReader *reader,
 }
 
 static void
+mail_reader_forward_attached_composer_created_cb (GObject *source_object,
+                                                 GAsyncResult *result,
+                                                 gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               CamelDataWrapper *content;
+
+               em_utils_forward_attachment (composer, ccd->attached_part, ccd->attached_subject, 
ccd->folder, ccd->attached_uids);
+
+               content = camel_medium_get_content (CAMEL_MEDIUM (ccd->attached_part));
+               if (CAMEL_IS_MIME_MESSAGE (content)) {
+                       e_mail_reader_composer_created (ccd->reader, composer, CAMEL_MIME_MESSAGE (content));
+               } else {
+                       /* XXX What to do for the multipart/digest case?
+                        *     Extract the first message from the digest, or
+                        *     change the argument type to CamelMimePart and
+                        *     just pass the whole digest through?
+                        *
+                        *     This signal is primarily serving EMailBrowser,
+                        *     which can only forward one message at a time.
+                        *     So for the moment it doesn't matter, but still
+                        *     something to consider. */
+                       e_mail_reader_composer_created (ccd->reader, composer, NULL);
+               }
+       }
+
+       create_composer_data_free (ccd);
+}
+
+static void
 mail_reader_forward_attachment_cb (GObject *source_object,
                                    GAsyncResult *result,
                                    gpointer user_data)
@@ -1851,9 +1952,9 @@ mail_reader_forward_attachment_cb (GObject *source_object,
        EMailBackend *backend;
        EActivity *activity;
        EAlertSink *alert_sink;
+       EShell *shell;
        CamelMimePart *part;
-       CamelDataWrapper *content;
-       EMsgComposer *composer;
+       CreateComposerData *ccd;
        gchar *subject = NULL;
        AsyncContext *async_context;
        GError *local_error = NULL;
@@ -1887,40 +1988,53 @@ mail_reader_forward_attachment_cb (GObject *source_object,
                goto exit;
        }
 
-       backend = e_mail_reader_get_backend (async_context->reader);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->reader = g_object_ref (async_context->reader);
+       ccd->folder = g_object_ref (folder);
+       ccd->attached_part = part;
+       ccd->attached_subject = subject;
+       ccd->attached_uids = async_context->uids ? g_ptr_array_ref (async_context->uids) : NULL;
 
-       composer = em_utils_forward_attachment (
-               backend, part, subject, folder, async_context->uids);
+       backend = e_mail_reader_get_backend (async_context->reader);
+       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
-       content = camel_medium_get_content (CAMEL_MEDIUM (part));
-       if (CAMEL_IS_MIME_MESSAGE (content)) {
-               e_mail_reader_composer_created (
-                       async_context->reader, composer,
-                       CAMEL_MIME_MESSAGE (content));
-       } else {
-               /* XXX What to do for the multipart/digest case?
-                *     Extract the first message from the digest, or
-                *     change the argument type to CamelMimePart and
-                *     just pass the whole digest through?
-                *
-                *     This signal is primarily serving EMailBrowser,
-                *     which can only forward one message at a time.
-                *     So for the moment it doesn't matter, but still
-                *     something to consider. */
-               e_mail_reader_composer_created (
-                       async_context->reader, composer, NULL);
-       }
+       e_msg_composer_new (shell, mail_reader_forward_attached_composer_created_cb, ccd);
 
        e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
 
-       g_object_unref (part);
-       g_free (subject);
-
 exit:
        async_context_free (async_context);
 }
 
 static void
+mail_reader_forward_message_composer_created_cb (GObject *source_object,
+                                                GAsyncResult *result,
+                                                gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (ccd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               em_utils_forward_message (
+                       composer, ccd->message,
+                       ccd->forward_style,
+                       ccd->folder, ccd->message_uid);
+
+               e_mail_reader_composer_created (
+                       ccd->reader, composer, ccd->message);
+       }
+
+       create_composer_data_free (ccd);
+}
+
+static void
 mail_reader_forward_messages_cb (GObject *source_object,
                                  GAsyncResult *result,
                                  gpointer user_data)
@@ -1929,6 +2043,7 @@ mail_reader_forward_messages_cb (GObject *source_object,
        EMailBackend *backend;
        EActivity *activity;
        EAlertSink *alert_sink;
+       EShell *shell;
        GHashTable *hash_table;
        GHashTableIter iter;
        gpointer key, value;
@@ -1942,6 +2057,7 @@ mail_reader_forward_messages_cb (GObject *source_object,
        alert_sink = e_activity_get_alert_sink (activity);
 
        backend = e_mail_reader_get_backend (async_context->reader);
+       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
        hash_table = e_mail_folder_get_multiple_messages_finish (
                folder, result, &local_error);
@@ -1969,20 +2085,21 @@ mail_reader_forward_messages_cb (GObject *source_object,
        g_hash_table_iter_init (&iter, hash_table);
 
        while (g_hash_table_iter_next (&iter, &key, &value)) {
-               EMsgComposer *composer;
+               CreateComposerData *ccd;
                CamelMimeMessage *message;
                const gchar *message_uid;
 
                message_uid = (const gchar *) key;
                message = CAMEL_MIME_MESSAGE (value);
 
-               composer = em_utils_forward_message (
-                       backend, message,
-                       async_context->forward_style,
-                       folder, message_uid);
+               ccd = g_new0 (CreateComposerData, 1);
+               ccd->reader = g_object_ref (async_context->reader);
+               ccd->folder = g_object_ref (folder);
+               ccd->message = g_object_ref (message);
+               ccd->message_uid = g_strdup (message_uid);
+               ccd->forward_style = async_context->forward_style;
 
-               e_mail_reader_composer_created (
-                       async_context->reader, composer, message);
+               e_msg_composer_new (shell, mail_reader_forward_message_composer_created_cb, ccd);
        }
 
        g_hash_table_unref (hash_table);
@@ -2087,6 +2204,41 @@ html_contains_nonwhitespace (const gchar *html,
 }
 
 static void
+mail_reader_reply_composer_created_cb (GObject *object,
+                                      GAsyncResult *result,
+                                      gpointer user_data)
+{
+       AsyncContext *async_context = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (async_context != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               CamelMimeMessage *message;
+
+               message = e_mail_part_list_get_message (async_context->part_list);
+
+               em_utils_reply_to_message (
+                       composer, message,
+                       async_context->folder,
+                       async_context->message_uid,
+                       async_context->reply_type,
+                       async_context->reply_style,
+                       async_context->part_list,
+                       async_context->address);
+
+               e_mail_reader_composer_created (async_context->reader, composer, message);
+       }
+
+       async_context_free (async_context);
+}
+
+static void
 mail_reader_reply_message_parsed (GObject *object,
                                   GAsyncResult *result,
                                   gpointer user_data)
@@ -2094,15 +2246,12 @@ mail_reader_reply_message_parsed (GObject *object,
        EShell *shell;
        EMailBackend *backend;
        EMailReader *reader = E_MAIL_READER (object);
-       EMailPartList *part_list;
-       EMsgComposer *composer;
-       CamelMimeMessage *message;
        AsyncContext *async_context;
        GError *local_error = NULL;
 
        async_context = (AsyncContext *) user_data;
 
-       part_list = e_mail_reader_parse_message_finish (reader, result, &local_error);
+       async_context->part_list = e_mail_reader_parse_message_finish (reader, result, &local_error);
 
        if (local_error) {
                g_warn_if_fail (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
@@ -2113,25 +2262,10 @@ mail_reader_reply_message_parsed (GObject *object,
                return;
        }
 
-       message = e_mail_part_list_get_message (part_list);
-
        backend = e_mail_reader_get_backend (async_context->reader);
        shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
-       composer = em_utils_reply_to_message (
-               shell, message,
-               async_context->folder,
-               async_context->message_uid,
-               async_context->reply_type,
-               async_context->reply_style,
-               part_list,
-               async_context->address);
-
-       e_mail_reader_composer_created (reader, composer, message);
-
-       g_object_unref (part_list);
-
-       async_context_free (async_context);
+       e_msg_composer_new (shell, mail_reader_reply_composer_created_cb, async_context);
 }
 
 static void
@@ -2186,6 +2320,60 @@ mail_reader_get_message_ready_cb (GObject *source_object,
        g_object_unref (message);
 }
 
+static void
+mail_reader_reply_to_message_composer_created_cb (GObject *source_object,
+                                                 GAsyncResult *result,
+                                                 gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (ccd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               em_utils_reply_to_message (
+                       composer, ccd->message, ccd->folder, ccd->message_uid,
+                       ccd->reply_type, ccd->reply_style, ccd->part_list, ccd->address);
+
+               if (ccd->validity_pgp_sum != 0 || ccd->validity_smime_sum != 0) {
+                       GtkToggleAction *action;
+
+                       if ((ccd->validity_pgp_sum & E_MAIL_PART_VALIDITY_PGP) != 0) {
+                               if ((ccd->validity_pgp_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) {
+                                       action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_SIGN (composer));
+                                       gtk_toggle_action_set_active (action, TRUE);
+                               }
+
+                               if ((ccd->validity_pgp_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) {
+                                       action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_ENCRYPT (composer));
+                                       gtk_toggle_action_set_active (action, TRUE);
+                               }
+                       }
+
+                       if ((ccd->validity_smime_sum & E_MAIL_PART_VALIDITY_SMIME) != 0) {
+                               if ((ccd->validity_smime_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) {
+                                       action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_SIGN (composer));
+                                       gtk_toggle_action_set_active (action, TRUE);
+                               }
+
+                               if ((ccd->validity_smime_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) {
+                                       action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_ENCRYPT 
(composer));
+                                       gtk_toggle_action_set_active (action, TRUE);
+                               }
+                       }
+               }
+
+               e_mail_reader_composer_created (ccd->reader, composer, ccd->message);
+       }
+
+       create_composer_data_free (ccd);
+}
+
 void
 e_mail_reader_reply_to_message (EMailReader *reader,
                                 CamelMimeMessage *src_message,
@@ -2208,7 +2396,7 @@ e_mail_reader_reply_to_message (EMailReader *reader,
        gint length;
        gchar *mail_uri;
        CamelObjectBag *registry;
-       EMsgComposer *composer;
+       CreateComposerData *ccd;
        EMailPartValidityFlags validity_pgp_sum = 0;
        EMailPartValidityFlags validity_smime_sum = 0;
 
@@ -2338,40 +2526,16 @@ e_mail_reader_reply_to_message (EMailReader *reader,
                CAMEL_MIME_PART (new_message),
                selection, length, "text/html; charset=utf-8");
 
-       composer = em_utils_reply_to_message (
-               shell, new_message, folder, uid,
-               reply_type, reply_style, NULL, address);
-       if (validity_pgp_sum != 0 || validity_smime_sum != 0) {
-               GtkToggleAction *action;
-
-               if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_PGP) != 0) {
-                       if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) {
-                               action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_SIGN (composer));
-                               gtk_toggle_action_set_active (action, TRUE);
-                       }
-
-                       if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) {
-                               action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_ENCRYPT (composer));
-                               gtk_toggle_action_set_active (action, TRUE);
-                       }
-               }
-
-               if ((validity_smime_sum & E_MAIL_PART_VALIDITY_SMIME) != 0) {
-                       if ((validity_smime_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) {
-                               action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_SIGN (composer));
-                               gtk_toggle_action_set_active (action, TRUE);
-                       }
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->reader = g_object_ref (reader);
+       ccd->folder = g_object_ref (folder);
+       ccd->message_uid = g_strdup (uid);
+       ccd->message = new_message;
+       ccd->reply_type = reply_type;
+       ccd->reply_style = reply_style;
+       ccd->address = address ? g_object_ref (address) : NULL;
 
-                       if ((validity_smime_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) {
-                               action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer));
-                               gtk_toggle_action_set_active (action, TRUE);
-                       }
-               }
-       }
-
-       e_mail_reader_composer_created (reader, composer, new_message);
-
-       g_object_unref (new_message);
+       e_msg_composer_new (shell, mail_reader_reply_to_message_composer_created_cb, ccd);
 
        goto exit;
 
@@ -2406,11 +2570,17 @@ whole_message:
                g_object_unref (activity);
 
        } else {
-               composer = em_utils_reply_to_message (
-                       shell, src_message, folder, uid,
-                       reply_type, reply_style, part_list, address);
-
-               e_mail_reader_composer_created (reader, composer, src_message);
+               ccd = g_new0 (CreateComposerData, 1);
+               ccd->reader = g_object_ref (reader);
+               ccd->folder = g_object_ref (folder);
+               ccd->message_uid = g_strdup (uid);
+               ccd->message = g_object_ref (src_message);
+               ccd->reply_type = reply_type;
+               ccd->reply_style = reply_style;
+               ccd->part_list = part_list ? g_object_ref (part_list) : NULL;
+               ccd->address = address ? g_object_ref (address) : NULL;
+
+               e_msg_composer_new (shell, mail_reader_reply_to_message_composer_created_cb, ccd);
        }
 
 exit:
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 5301f3f..808eb8b 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -915,6 +915,43 @@ action_mail_message_edit_cb (GtkAction *action,
        g_ptr_array_unref (uids);
 }
 
+typedef struct _CreateComposerData {
+       EMailReader *reader;
+       CamelMimeMessage *message;
+       CamelFolder *folder;
+       gboolean is_redirect;
+} CreateComposerData;
+
+static void
+mail_reader_new_composer_created_cb (GObject *source_object,
+                                    GAsyncResult *result,
+                                    gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (ccd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               if (ccd->is_redirect)
+                       em_utils_redirect_message (composer, ccd->message);
+               else
+                       em_utils_compose_new_message (composer, ccd->folder);
+
+               e_mail_reader_composer_created (ccd->reader, composer, ccd->message);
+       }
+
+       g_clear_object (&ccd->reader);
+       g_clear_object (&ccd->message);
+       g_clear_object (&ccd->folder);
+       g_free (ccd);
+}
+
 static void
 action_mail_message_new_cb (GtkAction *action,
                             EMailReader *reader)
@@ -923,7 +960,7 @@ action_mail_message_new_cb (GtkAction *action,
        EMailBackend *backend;
        EShellBackend *shell_backend;
        CamelFolder *folder;
-       EMsgComposer *composer;
+       CreateComposerData *ccd;
 
        folder = e_mail_reader_ref_folder (reader);
        backend = e_mail_reader_get_backend (reader);
@@ -931,11 +968,12 @@ action_mail_message_new_cb (GtkAction *action,
        shell_backend = E_SHELL_BACKEND (backend);
        shell = e_shell_backend_get_shell (shell_backend);
 
-       composer = em_utils_compose_new_message (shell, folder);
-
-       e_mail_reader_composer_created (reader, composer, NULL);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->reader = g_object_ref (reader);
+       ccd->folder = folder;
+       ccd->is_redirect = FALSE;
 
-       g_clear_object (&folder);
+       e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
 }
 
 static void
@@ -1140,7 +1178,7 @@ mail_reader_redirect_cb (CamelFolder *folder,
        EMailBackend *backend;
        EAlertSink *alert_sink;
        CamelMimeMessage *message;
-       EMsgComposer *composer;
+       CreateComposerData *ccd;
        GError *error = NULL;
 
        alert_sink = e_activity_get_alert_sink (closure->activity);
@@ -1168,11 +1206,12 @@ mail_reader_redirect_cb (CamelFolder *folder,
        backend = e_mail_reader_get_backend (closure->reader);
        shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
-       composer = em_utils_redirect_message (shell, message);
-
-       e_mail_reader_composer_created (closure->reader, composer, message);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->reader = g_object_ref (closure->reader);
+       ccd->message = message;
+       ccd->is_redirect = TRUE;
 
-       g_object_unref (message);
+       e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
 
        mail_reader_closure_free (closure);
 }
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index a9441c9..915539d 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -1291,20 +1291,17 @@ em_utils_composer_print_cb (EMsgComposer *composer,
 
 /* Composing messages... */
 
-static EMsgComposer *
-create_new_composer (EShell *shell,
-                     const gchar *subject,
-                     CamelFolder *folder)
+static void
+set_up_new_composer (EMsgComposer *composer,
+                    const gchar *subject,
+                    CamelFolder *folder)
 {
-       EMsgComposer *composer;
        EClientCache *client_cache;
        ESourceRegistry *registry;
        EComposerHeaderTable *table;
        ESource *source = NULL;
        gchar *identity = NULL;
 
-       composer = e_msg_composer_new (shell);
-
        table = e_msg_composer_get_header_table (composer);
 
        client_cache = e_composer_header_table_ref_client_cache (table);
@@ -1335,41 +1332,37 @@ create_new_composer (EShell *shell,
        e_composer_header_table_set_subject (table, subject);
        e_composer_header_table_set_identity_uid (table, identity);
 
-       em_utils_apply_send_account_override_to_composer (composer, shell, folder);
+       em_utils_apply_send_account_override_to_composer (composer, folder);
 
        g_free (identity);
 
        g_object_unref (client_cache);
        g_object_unref (registry);
-
-       return composer;
 }
 
 /**
  * em_utils_compose_new_message:
- * @shell: an #EShell
- * @folder: a #CamelFolder, or %NULL
+ * @composer: an #EMsgComposer
+ * @folder: (nullable): a #CamelFolder, or %NULL
  *
- * Opens a new composer window as a child window of @parent's toplevel
- * window.
+ * Sets up a new @composer window.
  *
- * Returns: the resulting #EMsgComposer
+ * Since: 3.22
  **/
-EMsgComposer *
-em_utils_compose_new_message (EShell *shell,
+void
+em_utils_compose_new_message (EMsgComposer *composer,
                               CamelFolder *folder)
 {
-       EMsgComposer *composer;
        EHTMLEditor *editor;
        EContentEditor *cnt_editor;
        EContentEditorContentFlags flags;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
        if (folder != NULL)
-               g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+               g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
-       composer = create_new_composer (shell, "", folder);
+       set_up_new_composer (composer, "", folder);
        composer_set_no_change (composer);
        editor = e_msg_composer_get_editor (composer);
        cnt_editor = e_html_editor_get_content_editor (editor);
@@ -1379,8 +1372,6 @@ em_utils_compose_new_message (EShell *shell,
        e_content_editor_set_current_content_flags (cnt_editor, flags);
 
        gtk_widget_show (GTK_WIDGET (composer));
-
-       return composer;
 }
 
 static CamelMimeMessage *
@@ -1460,37 +1451,50 @@ em_utils_get_composer_recipients_as_message (EMsgComposer *composer)
        return message;
 }
 
-/**
- * em_utils_compose_new_message_with_mailto:
- * @shell: an #EShell
- * @mailto: a mailto URL
- * @folder: a #CamelFolder, or %NULL
- *
- * Opens a new composer window as a child window of @parent's toplevel
- * window. If @mailto is non-NULL, the composer fields will be filled in
- * according to the values in the mailto URL.
- **/
-EMsgComposer *
-em_utils_compose_new_message_with_mailto (EShell *shell,
-                                          const gchar *mailto,
-                                          CamelFolder *folder)
+typedef struct _CreateComposerData {
+       gchar *mailto;
+       CamelFolder *folder;
+} CreateComposerData;
+
+static void
+create_composer_data_free (gpointer ptr)
 {
+       CreateComposerData *ccd = ptr;
+
+       if (ccd) {
+               g_clear_object (&ccd->folder);
+               g_free (ccd->mailto);
+               g_free (ccd);
+       }
+}
+
+static void
+msg_composer_created_with_mailto_cb (GObject *source_object,
+                                    GAsyncResult *result,
+                                    gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
        EMsgComposer *composer;
        EComposerHeaderTable *table;
        EClientCache *client_cache;
        ESourceRegistry *registry;
+       GError *error = NULL;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+       g_return_if_fail (ccd != NULL);
 
-       if (folder != NULL)
-               g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+               create_composer_data_free (ccd);
 
-       if (mailto != NULL)
-               composer = e_msg_composer_new_from_url (shell, mailto);
-       else
-               composer = e_msg_composer_new (shell);
+               return;
+       }
+
+       if (ccd->mailto)
+               e_msg_composer_setup_from_url (composer, ccd->mailto);
 
-       em_utils_apply_send_account_override_to_composer (composer, shell, folder);
+       em_utils_apply_send_account_override_to_composer (composer, ccd->folder);
 
        table = e_msg_composer_get_header_table (composer);
 
@@ -1502,11 +1506,11 @@ em_utils_compose_new_message_with_mailto (EShell *shell,
        /* If a CamelFolder was given, we need to backtrack and find
         * the corresponding ESource with a Mail Identity extension. */
 
-       if (folder != NULL) {
+       if (ccd->folder) {
                ESource *source;
                CamelStore *store;
 
-               store = camel_folder_get_parent_store (folder);
+               store = camel_folder_get_parent_store (ccd->folder);
                source = em_utils_ref_mail_identity_for_store (registry, store);
 
                if (source != NULL) {
@@ -1521,7 +1525,36 @@ em_utils_compose_new_message_with_mailto (EShell *shell,
 
        gtk_window_present (GTK_WINDOW (composer));
 
-       return composer;
+       create_composer_data_free (ccd);
+}
+
+/**
+ * em_utils_compose_new_message_with_mailto:
+ * @shell: an #EShell
+ * @mailto: a mailto URL
+ * @folder: a #CamelFolder, or %NULL
+ *
+ * Opens a new composer window as a child window of @parent's toplevel
+ * window. If @mailto is non-NULL, the composer fields will be filled in
+ * according to the values in the mailto URL.
+ **/
+void
+em_utils_compose_new_message_with_mailto (EShell *shell,
+                                          const gchar *mailto,
+                                          CamelFolder *folder)
+{
+       CreateComposerData *ccd;
+
+       g_return_if_fail (E_IS_SHELL (shell));
+
+       if (folder != NULL)
+               g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->folder = folder ? g_object_ref (folder) : NULL;
+       ccd->mailto = g_strdup (mailto);
+
+       e_msg_composer_new (shell, msg_composer_created_with_mailto_cb, ccd);
 }
 
 static gboolean
@@ -1726,22 +1759,22 @@ quoting_text (QuotingTextEnum type)
 
 /**
  * em_utils_edit_message:
- * @shell: an #EShell
+ * @composer: an #EMsgComposer
  * @folder: a #CamelFolder
  * @message: a #CamelMimeMessage
  * @message_uid: UID of @message, or %NULL
  *
- * Opens a composer filled in with the headers/mime-parts/etc of
- * @message.
+ * Sets up the @composer with the headers/mime-parts/etc of the @message.
+ *
+ * Since: 3.22
  **/
-EMsgComposer *
-em_utils_edit_message (EShell *shell,
+void
+em_utils_edit_message (EMsgComposer *composer,
                        CamelFolder *folder,
                        CamelMimeMessage *message,
                        const gchar *message_uid,
                        gboolean keep_signature)
 {
-       EMsgComposer *composer;
        ESourceRegistry *registry;
        ESource *source;
        gboolean folder_is_sent;
@@ -1750,12 +1783,12 @@ em_utils_edit_message (EShell *shell,
        gboolean folder_is_templates;
        gchar *override_identity_uid = NULL;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
        if (folder)
-               g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+               g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
-       registry = e_shell_get_registry (shell);
+       registry = e_shell_get_registry (e_msg_composer_get_shell (composer));
 
        if (folder) {
                folder_is_sent = em_utils_folder_is_sent (registry, folder);
@@ -1807,7 +1840,7 @@ em_utils_edit_message (EShell *shell,
                        }
                }
 
-               source = em_utils_check_send_account_override (shell, message, folder);
+               source = em_utils_check_send_account_override (e_msg_composer_get_shell (composer), message, 
folder);
                if (source) {
                        g_free (override_identity_uid);
                        override_identity_uid = e_source_dup_uid (source);
@@ -1815,7 +1848,7 @@ em_utils_edit_message (EShell *shell,
                }
        }
 
-       composer = e_msg_composer_new_with_message (shell, message, keep_signature, override_identity_uid, 
NULL);
+       e_msg_composer_setup_with_message (composer, message, keep_signature, override_identity_uid, NULL);
 
        g_free (override_identity_uid);
 
@@ -1858,8 +1891,6 @@ em_utils_edit_message (EShell *shell,
        composer_set_no_change (composer);
 
        gtk_widget_show (GTK_WIDGET (composer));
-
-       return composer;
 }
 
 static void
@@ -2075,39 +2106,36 @@ setup_forward_attached_callbacks (EMsgComposer *composer,
                (GDestroyNotify) forward_data_free);
 }
 
-static EMsgComposer *
-forward_non_attached (EMailBackend *backend,
+static void
+forward_non_attached (EMsgComposer *composer,
                       CamelFolder *folder,
                       const gchar *uid,
                       CamelMimeMessage *message,
                       EMailForwardStyle style)
 {
-       EMsgComposer *composer = NULL;
-       EMailSession *session;
-       EShell *shell;
+       CamelSession *session;
        gchar *text, *forward;
        guint32 validity_found = 0;
        guint32 flags;
 
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+
+       session = e_msg_composer_ref_session (composer);
+
        flags = E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS |
                E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG;
        if (style == E_MAIL_FORWARD_STYLE_QUOTED)
                flags |= E_MAIL_FORMATTER_QUOTE_FLAG_CITE;
 
-       session = e_mail_backend_get_session (backend);
-       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
-
        forward = quoting_text (QUOTING_FORWARD);
-       text = em_utils_message_to_html (
-               CAMEL_SESSION (session), message,
-               forward, flags, NULL, NULL, NULL, &validity_found);
+       text = em_utils_message_to_html (session, message, forward, flags, NULL, NULL, NULL, &validity_found);
 
        if (text != NULL) {
                CamelDataWrapper *content;
                gchar *subject;
 
                subject = mail_tool_generate_forward_subject (message);
-               composer = create_new_composer (shell, subject, folder);
+               set_up_new_composer (composer, subject, folder);
                g_free (subject);
 
                content = camel_medium_get_content (CAMEL_MEDIUM (message));
@@ -2134,26 +2162,24 @@ forward_non_attached (EMailBackend *backend,
                        g_free (tmp_message_uid);
                }
 
-               emu_update_composers_security (
-                       composer, validity_found);
+               emu_update_composers_security (composer, validity_found);
                composer_set_no_change (composer);
                gtk_widget_show (GTK_WIDGET (composer));
 
                g_free (text);
        }
 
+       g_clear_object (&session);
        g_free (forward);
-
-       return composer;
 }
 
 /**
  * em_utils_forward_message:
- * @backend: an #EMailBackend
+ * @composer: an #EMsgComposer
  * @message: a #CamelMimeMessage to forward
  * @style: the forward style to use
- * @folder: a #CamelFolder, or %NULL
- * @uid: the UID of %message, or %NULL
+ * @folder: (nullable):  a #CamelFolder, or %NULL
+ * @uid: (nullable): the UID of %message, or %NULL
  *
  * Forwards @message in the given @style.
  *
@@ -2171,8 +2197,8 @@ forward_non_attached (EMailBackend *backend,
  * in its own composer window in 'quoted' form (each line starting with
  * a "> ").
  **/
-EMsgComposer *
-em_utils_forward_message (EMailBackend *backend,
+void
+em_utils_forward_message (EMsgComposer *composer,
                           CamelMimeMessage *message,
                           EMailForwardStyle style,
                           CamelFolder *folder,
@@ -2180,10 +2206,9 @@ em_utils_forward_message (EMailBackend *backend,
 {
        CamelMimePart *part;
        gchar *subject;
-       EMsgComposer *composer = NULL;
 
-       g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
        switch (style) {
                case E_MAIL_FORWARD_STYLE_ATTACHED:
@@ -2191,8 +2216,7 @@ em_utils_forward_message (EMailBackend *backend,
                        part = mail_tool_make_message_attachment (message);
                        subject = mail_tool_generate_forward_subject (message);
 
-                       composer = em_utils_forward_attachment (
-                               backend, part, subject, NULL, NULL);
+                       em_utils_forward_attachment (composer, part, subject, NULL, NULL);
 
                        g_object_unref (part);
                        g_free (subject);
@@ -2200,34 +2224,27 @@ em_utils_forward_message (EMailBackend *backend,
 
                case E_MAIL_FORWARD_STYLE_INLINE:
                case E_MAIL_FORWARD_STYLE_QUOTED:
-                       composer = forward_non_attached (
-                               backend, folder, uid, message, style);
+                       forward_non_attached (composer, folder, uid, message, style);
                        break;
        }
-
-       return composer;
 }
 
-EMsgComposer *
-em_utils_forward_attachment (EMailBackend *backend,
+void
+em_utils_forward_attachment (EMsgComposer *composer,
                              CamelMimePart *part,
                              const gchar *subject,
                              CamelFolder *folder,
                              GPtrArray *uids)
 {
-       EShell *shell;
        CamelDataWrapper *content;
-       EMsgComposer *composer;
 
-       g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_PART (part), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_PART (part));
 
        if (folder != NULL)
-               g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+               g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
-       composer = create_new_composer (shell, subject, folder);
+       set_up_new_composer (composer, subject, folder);
 
        e_msg_composer_attach (composer, part);
 
@@ -2268,8 +2285,6 @@ em_utils_forward_attachment (EMailBackend *backend,
        composer_set_no_change (composer);
 
        gtk_widget_show (GTK_WIDGET (composer));
-
-       return composer;
 }
 
 static gint
@@ -2345,18 +2360,30 @@ sort_sources_by_ui (GList **psources,
        g_hash_table_destroy (uids_order);
 }
 
-/* Redirecting messages... */
-
-static EMsgComposer *
-redirect_get_composer (EShell *shell,
-                       CamelMimeMessage *message)
+/**
+ * em_utils_redirect_message:
+ * @composer: an #EMsgComposer
+ * @message: message to redirect
+ *
+ * Sets up the @composer to redirect @message (Note: only headers will be
+ * editable). Adds Resent-From/Resent-To/etc headers.
+ *
+ * Since: 3.22
+ **/
+void
+em_utils_redirect_message (EMsgComposer *composer,
+                           CamelMimeMessage *message)
 {
-       EMsgComposer *composer;
        ESourceRegistry *registry;
-       CamelMedium *medium;
        ESource *source;
+       EShell *shell;
+       CamelMedium *medium;
        gchar *identity_uid = NULL;
 
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+
+       shell = e_msg_composer_get_shell (composer);
        medium = CAMEL_MEDIUM (message);
 
        /* QMail will refuse to send a message if it finds one of
@@ -2384,40 +2411,13 @@ redirect_get_composer (EShell *shell,
                g_object_unref (source);
        }
 
-       composer = e_msg_composer_new_redirect (
-               shell, message, identity_uid, NULL);
+       e_msg_composer_setup_redirect (composer, message, identity_uid, NULL);
 
        g_free (identity_uid);
 
-       return composer;
-}
-
-/**
- * em_utils_redirect_message:
- * @shell: an #EShell
- * @message: message to redirect
- *
- * Opens a composer to redirect @message (Note: only headers will be
- * editable). Adds Resent-From/Resent-To/etc headers.
- *
- * Returns: the resulting #EMsgComposer
- **/
-EMsgComposer *
-em_utils_redirect_message (EShell *shell,
-                           CamelMimeMessage *message)
-{
-       EMsgComposer *composer;
-
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
-
-       composer = redirect_get_composer (shell, message);
-
        gtk_widget_show (GTK_WIDGET (composer));
 
        composer_set_no_change (composer);
-
-       return composer;
 }
 
 /* Replying to messages... */
@@ -2457,33 +2457,30 @@ em_utils_camel_address_to_destination (CamelInternetAddress *iaddr)
        return destv;
 }
 
-static EMsgComposer *
-reply_get_composer (EShell *shell,
-                    CamelMimeMessage *message,
-                    const gchar *identity_uid,
-                    CamelInternetAddress *to,
-                    CamelInternetAddress *cc,
-                    CamelFolder *folder,
-                   const gchar *message_uid,
-                    CamelNNTPAddress *postto)
+static void
+reply_setup_composer (EMsgComposer *composer,
+                     CamelMimeMessage *message,
+                     const gchar *identity_uid,
+                     CamelInternetAddress *to,
+                     CamelInternetAddress *cc,
+                     CamelFolder *folder,
+                     const gchar *message_uid,
+                    CamelNNTPAddress *postto)
 {
        gchar *message_id, *references;
        EDestination **tov, **ccv;
-       EMsgComposer *composer;
        EComposerHeaderTable *table;
        CamelMedium *medium;
        gchar *subject;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
        if (to != NULL)
-               g_return_val_if_fail (CAMEL_IS_INTERNET_ADDRESS (to), NULL);
+               g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (to));
 
        if (cc != NULL)
-               g_return_val_if_fail (CAMEL_IS_INTERNET_ADDRESS (cc), NULL);
-
-       composer = e_msg_composer_new (shell);
+               g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (cc));
 
        /* construct the tov/ccv */
        tov = em_utils_camel_address_to_destination (to);
@@ -2582,8 +2579,6 @@ reply_get_composer (EShell *shell,
 
        g_free (message_id);
        g_free (references);
-
-       return composer;
 }
 
 static gboolean
@@ -3304,8 +3299,8 @@ emcu_folder_is_inbox (CamelFolder *folder)
  * @folder and @message_uid may be supplied in order to update the message
  * flags once it has been replied to.
  **/
-EMsgComposer *
-em_utils_reply_to_message (EShell *shell,
+void
+em_utils_reply_to_message (EMsgComposer *composer,
                            CamelMimeMessage *message,
                            CamelFolder *folder,
                            const gchar *message_uid,
@@ -3317,19 +3312,20 @@ em_utils_reply_to_message (EShell *shell,
        ESourceRegistry *registry;
        CamelInternetAddress *to, *cc;
        CamelNNTPAddress *postto = NULL;
-       EMsgComposer *composer;
+       EShell *shell;
        ESourceMailCompositionReplyStyle prefer_reply_style = E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DEFAULT;
        ESource *source;
        gchar *identity_uid = NULL;
        const gchar *evo_source_header;
        guint32 flags;
 
-       g_return_val_if_fail (E_IS_SHELL (shell), NULL);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
        to = camel_internet_address_new ();
        cc = camel_internet_address_new ();
 
+       shell = e_msg_composer_get_shell (composer);
        registry = e_shell_get_registry (shell);
 
        /* This returns a new ESource reference. */
@@ -3388,8 +3384,7 @@ em_utils_reply_to_message (EShell *shell,
                break;
        }
 
-       composer = reply_get_composer (
-               shell, message, identity_uid, to, cc, folder, message_uid, postto);
+       reply_setup_composer (composer, message, identity_uid, to, cc, folder, message_uid, postto);
        e_msg_composer_add_message_attachments (composer, message, TRUE);
 
        if (postto)
@@ -3468,15 +3463,13 @@ em_utils_reply_to_message (EShell *shell,
        }
 
        /* because some reply types can change recipients after the composer is populated */
-       em_utils_apply_send_account_override_to_composer (composer, shell, folder);
+       em_utils_apply_send_account_override_to_composer (composer, folder);
 
        composer_set_no_change (composer);
 
        gtk_widget_show (GTK_WIDGET (composer));
 
        g_free (identity_uid);
-
-       return composer;
 }
 
 static void
@@ -3664,15 +3657,16 @@ em_utils_check_send_account_override (EShell *shell,
 
 void
 em_utils_apply_send_account_override_to_composer (EMsgComposer *composer,
-                                                  EShell *shell,
                                                   CamelFolder *folder)
 {
        CamelMimeMessage *message;
        EComposerHeaderTable *header_table;
+       EShell *shell;
        ESource *source;
 
        g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
+       shell = e_msg_composer_get_shell (composer);
        message = em_utils_get_composer_recipients_as_message (composer);
        source = em_utils_check_send_account_override (shell, message, folder);
        g_clear_object (&message);
diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h
index fc5c0aa..891f68a 100644
--- a/mail/em-composer-utils.h
+++ b/mail/em-composer-utils.h
@@ -33,28 +33,28 @@
 
 G_BEGIN_DECLS
 
-EMsgComposer * em_utils_compose_new_message    (EShell *shell,
+void           em_utils_compose_new_message    (EMsgComposer *composer,
                                                 CamelFolder *folder);
-EMsgComposer * em_utils_compose_new_message_with_mailto
+void           em_utils_compose_new_message_with_mailto
                                                (EShell *shell,
                                                 const gchar *mailto,
                                                 CamelFolder *folder);
-EMsgComposer * em_utils_edit_message           (EShell *shell,
+void           em_utils_edit_message           (EMsgComposer *composer,
                                                 CamelFolder *folder,
                                                 CamelMimeMessage *message,
                                                 const gchar *message_uid,
                                                 gboolean keep_signature);
-EMsgComposer * em_utils_forward_message        (EMailBackend *backend,
+void           em_utils_forward_message        (EMsgComposer *composer,
                                                 CamelMimeMessage *message,
                                                 EMailForwardStyle style,
                                                 CamelFolder *folder,
                                                 const gchar *uid);
-EMsgComposer * em_utils_forward_attachment     (EMailBackend *backend,
+void           em_utils_forward_attachment     (EMsgComposer *composer,
                                                 CamelMimePart *part,
                                                 const gchar *subject,
                                                 CamelFolder *folder,
                                                 GPtrArray *uids);
-EMsgComposer * em_utils_redirect_message       (EShell *shell,
+void           em_utils_redirect_message       (EMsgComposer *composer,
                                                 CamelMimeMessage *message);
 gchar *                em_utils_construct_composer_text
                                                (CamelSession *session,
@@ -69,7 +69,7 @@ void          em_utils_get_reply_all          (ESourceRegistry *registry,
                                                 CamelInternetAddress *to,
                                                 CamelInternetAddress *cc,
                                                 CamelNNTPAddress *postto);
-EMsgComposer * em_utils_reply_to_message       (EShell *shell,
+void           em_utils_reply_to_message       (EMsgComposer *composer,
                                                 CamelMimeMessage *message,
                                                 CamelFolder *folder,
                                                 const gchar *message_uid,
@@ -92,7 +92,6 @@ ESource *     em_utils_check_send_account_override
                                                 CamelFolder *folder);
 void           em_utils_apply_send_account_override_to_composer
                                                (EMsgComposer *composer,
-                                                EShell *shell,
                                                 CamelFolder *folder);
 
 G_END_DECLS
diff --git a/modules/addressbook/eab-composer-util.c b/modules/addressbook/eab-composer-util.c
index b2d79de..94e8aaf 100644
--- a/modules/addressbook/eab-composer-util.c
+++ b/modules/addressbook/eab-composer-util.c
@@ -29,28 +29,156 @@
 #include "addressbook/util/eab-book-util.h"
 #include "addressbook/gui/widgets/eab-gui-util.h"
 
+static const gchar *
+get_email (EContact *contact,
+           EContactField field_id,
+           gchar **to_free)
+{
+       gchar *name = NULL, *mail = NULL;
+       const gchar *value = e_contact_get_const (contact, field_id);
+
+       *to_free = NULL;
+
+       if (eab_parse_qp_email (value, &name, &mail)) {
+               *to_free = g_strdup_printf ("%s <%s>", name, mail);
+               value = *to_free;
+       }
+
+       g_free (name);
+       g_free (mail);
+
+       return value;
+}
+
+typedef struct _CreateComposerData {
+       EDestination **to_destinations;
+       EDestination **bcc_destinations;
+       GSList *attachment_destinations;
+} CreateComposerData;
+
+static void
+eab_composer_created_cb (GObject *source_object,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EComposerHeaderTable *table;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (ccd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               table = e_msg_composer_get_header_table (composer);
+
+               if (ccd->to_destinations)
+                       e_composer_header_table_set_destinations_to (table, ccd->to_destinations);
+
+               if (ccd->bcc_destinations)
+                       e_composer_header_table_set_destinations_bcc (table, ccd->bcc_destinations);
+
+               if (ccd->attachment_destinations) {
+                       CamelMimePart *attachment;
+                       GSList *contacts, *iter;
+                       gchar *data;
+
+                       attachment = camel_mime_part_new ();
+
+                       contacts = g_slist_copy (ccd->attachment_destinations);
+                       for (iter = contacts; iter != NULL; iter = iter->next)
+                               iter->data = e_destination_get_contact (iter->data);
+                       data = eab_contact_list_to_string (contacts);
+                       g_slist_free (contacts);
+
+                       camel_mime_part_set_content (attachment, data, strlen (data), "text/x-vcard");
+
+                       if (ccd->attachment_destinations->next != NULL) {
+                               camel_mime_part_set_description (attachment, _("Multiple vCards"));
+                       } else {
+                               EContact *contact;
+                               const gchar *file_as;
+                               gchar *description;
+
+                               contact = e_destination_get_contact (ccd->attachment_destinations->data);
+                               file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
+                               description = g_strdup_printf (_("vCard for %s"), file_as);
+                               camel_mime_part_set_description (attachment, description);
+                               g_free (description);
+                       }
+
+                       camel_mime_part_set_disposition (attachment, "attachment");
+
+                       e_msg_composer_attach (composer, attachment);
+                       g_object_unref (attachment);
+
+                       if (ccd->attachment_destinations->next != NULL) {
+                               e_composer_header_table_set_subject (table, _("Contact information"));
+                       } else {
+                               EContact *contact;
+                               gchar *tempstr;
+                               const gchar *tempstr2;
+                               gchar *tempfree = NULL;
+
+                               contact = e_destination_get_contact (ccd->attachment_destinations->data);
+                               tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS);
+                               if (!tempstr2 || !*tempstr2)
+                                       tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
+                               if (!tempstr2 || !*tempstr2)
+                                       tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG);
+                               if (!tempstr2 || !*tempstr2) {
+                                       g_free (tempfree);
+                                       tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree);
+                               }
+                               if (!tempstr2 || !*tempstr2) {
+                                       g_free (tempfree);
+                                       tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree);
+                               }
+                               if (!tempstr2 || !*tempstr2) {
+                                       g_free (tempfree);
+                                       tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree);
+                               }
+
+                               if (!tempstr2 || !*tempstr2)
+                                       tempstr = g_strdup_printf (_("Contact information"));
+                               else
+                                       tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2);
+
+                               e_composer_header_table_set_subject (table, tempstr);
+
+                               g_free (tempstr);
+                               g_free (tempfree);
+                       }
+               }
+
+               gtk_widget_show (GTK_WIDGET (composer));
+       }
+
+       if (ccd->to_destinations)
+               e_destination_freev (ccd->to_destinations);
+       if (ccd->bcc_destinations)
+               e_destination_freev (ccd->bcc_destinations);
+       g_slist_free_full (ccd->attachment_destinations, g_object_unref);
+
+       g_free (ccd);
+}
+
 void
 eab_send_as_to (EShell *shell,
                 GSList *destinations)
 {
-       EMsgComposer *composer;
-       EComposerHeaderTable *table;
        GPtrArray *to_array;
        GPtrArray *bcc_array;
-
-       union {
-               gpointer *pdata;
-               EDestination **destinations;
-       } convert;
+       CreateComposerData *ccd;
 
        g_return_if_fail (E_IS_SHELL (shell));
 
        if (destinations == NULL)
                return;
 
-       composer = e_msg_composer_new (shell);
-       table = e_msg_composer_get_header_table (composer);
-
        to_array = g_ptr_array_new ();
        bcc_array = g_ptr_array_new ();
 
@@ -60,11 +188,11 @@ eab_send_as_to (EShell *shell,
 
                if (e_destination_is_evolution_list (destination)) {
                        if (e_destination_list_show_addresses (destination))
-                               g_ptr_array_add (to_array, destination);
+                               g_ptr_array_add (to_array, e_destination_copy (destination));
                        else
-                               g_ptr_array_add (bcc_array, destination);
+                               g_ptr_array_add (bcc_array, e_destination_copy (destination));
                } else
-                       g_ptr_array_add (to_array, destination);
+                       g_ptr_array_add (to_array, e_destination_copy (destination));
 
                destinations = g_slist_next (destinations);
        }
@@ -73,133 +201,28 @@ eab_send_as_to (EShell *shell,
        g_ptr_array_add (to_array, NULL);
        g_ptr_array_add (bcc_array, NULL);
 
-       /* XXX Acrobatics like this make me question whether NULL-terminated
-        *     arrays are really the best argument type for passing a list of
-        *     destinations to the header table. */
-
-       /* Set "To" destinations. */
-       convert.pdata = to_array->pdata;
-       e_composer_header_table_set_destinations_to (
-               table, convert.destinations);
-       g_ptr_array_free (to_array, FALSE);
-
-       /* Add "Bcc" destinations. */
-       convert.pdata = bcc_array->pdata;
-       e_composer_header_table_add_destinations_bcc (
-               table, convert.destinations);
-       g_ptr_array_free (bcc_array, FALSE);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->to_destinations = (EDestination **) g_ptr_array_free (to_array, FALSE);
+       ccd->bcc_destinations = (EDestination **) g_ptr_array_free (bcc_array, FALSE);
+       ccd->attachment_destinations = NULL;
 
-       gtk_widget_show (GTK_WIDGET (composer));
-}
-
-static const gchar *
-get_email (EContact *contact,
-           EContactField field_id,
-           gchar **to_free)
-{
-       gchar *name = NULL, *mail = NULL;
-       const gchar *value = e_contact_get_const (contact, field_id);
-
-       *to_free = NULL;
-
-       if (eab_parse_qp_email (value, &name, &mail)) {
-               *to_free = g_strdup_printf ("%s <%s>", name, mail);
-               value = *to_free;
-       }
-
-       g_free (name);
-       g_free (mail);
-
-       return value;
+       e_msg_composer_new (shell, eab_composer_created_cb, ccd);
 }
 
 void
 eab_send_as_attachment (EShell *shell,
                         GSList *destinations)
 {
-       EMsgComposer *composer;
-       EComposerHeaderTable *table;
-       CamelMimePart *attachment;
-       GSList *contacts, *iter;
-       gchar *data;
+       CreateComposerData *ccd;
 
        g_return_if_fail (E_IS_SHELL (shell));
 
        if (destinations == NULL)
                return;
 
-       composer = e_msg_composer_new (shell);
-       table = e_msg_composer_get_header_table (composer);
-
-       attachment = camel_mime_part_new ();
-
-       contacts = g_slist_copy (destinations);
-       for (iter = contacts; iter != NULL; iter = iter->next)
-               iter->data = e_destination_get_contact (iter->data);
-       data = eab_contact_list_to_string (contacts);
-       g_slist_free (contacts);
-
-       camel_mime_part_set_content (
-               attachment, data, strlen (data), "text/x-vcard");
-
-       if (destinations->next != NULL)
-               camel_mime_part_set_description (
-                       attachment, _("Multiple vCards"));
-       else {
-               EContact *contact;
-               const gchar *file_as;
-               gchar *description;
-
-               contact = e_destination_get_contact (destinations->data);
-               file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
-               description = g_strdup_printf (_("vCard for %s"), file_as);
-               camel_mime_part_set_description (attachment, description);
-               g_free (description);
-       }
-
-       camel_mime_part_set_disposition (attachment, "attachment");
-
-       e_msg_composer_attach (composer, attachment);
-       g_object_unref (attachment);
-
-       if (destinations->next != NULL)
-               e_composer_header_table_set_subject (
-                       table, _("Contact information"));
-       else {
-               EContact *contact;
-               gchar *tempstr;
-               const gchar *tempstr2;
-               gchar *tempfree = NULL;
-
-               contact = e_destination_get_contact (destinations->data);
-               tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS);
-               if (!tempstr2 || !*tempstr2)
-                       tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
-               if (!tempstr2 || !*tempstr2)
-                       tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG);
-               if (!tempstr2 || !*tempstr2) {
-                       g_free (tempfree);
-                       tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree);
-               }
-               if (!tempstr2 || !*tempstr2) {
-                       g_free (tempfree);
-                       tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree);
-               }
-               if (!tempstr2 || !*tempstr2) {
-                       g_free (tempfree);
-                       tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree);
-               }
-
-               if (!tempstr2 || !*tempstr2)
-                       tempstr = g_strdup_printf (_("Contact information"));
-               else
-                       tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2);
-
-               e_composer_header_table_set_subject (table, tempstr);
-
-               g_free (tempstr);
-               g_free (tempfree);
-       }
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->attachment_destinations = g_slist_copy (destinations);
+       g_slist_foreach (ccd->attachment_destinations, (GFunc) g_object_ref, NULL);
 
-       gtk_widget_show (GTK_WIDGET (composer));
+       e_msg_composer_new (shell, eab_composer_created_cb, ccd);
 }
diff --git a/modules/composer-autosave/e-autosave-utils.c b/modules/composer-autosave/e-autosave-utils.c
index 2e83b2a..ce8b9f2 100644
--- a/modules/composer-autosave/e-autosave-utils.c
+++ b/modules/composer-autosave/e-autosave-utils.c
@@ -116,6 +116,39 @@ create_snapshot_file (EMsgComposer *composer,
        return snapshot_file;
 }
 
+typedef struct _CreateComposerData {
+       LoadContext *context;
+       CamelMimeMessage *message;
+       GFile *snapshot_file;
+} CreateComposerData;
+
+static void
+autosave_composer_created_cb (GObject *source_object,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               e_msg_composer_setup_with_message (composer, ccd->message, TRUE, NULL, NULL);
+               g_object_set_data_full (
+                       G_OBJECT (composer),
+                       SNAPSHOT_FILE_KEY, g_object_ref (ccd->snapshot_file),
+                       (GDestroyNotify) delete_snapshot_file);
+               ccd->context->composer = g_object_ref_sink (composer);
+       }
+
+       g_clear_object (&ccd->message);
+       g_clear_object (&ccd->snapshot_file);
+       g_free (ccd);
+}
+
 static void
 load_snapshot_loaded_cb (GFile *snapshot_file,
                          GAsyncResult *result,
@@ -124,11 +157,11 @@ load_snapshot_loaded_cb (GFile *snapshot_file,
        EShell *shell;
        GObject *object;
        LoadContext *context;
-       EMsgComposer *composer;
        CamelMimeMessage *message;
        CamelStream *camel_stream;
        gchar *contents = NULL;
        gsize length;
+       CreateComposerData *ccd;
        GError *local_error = NULL;
 
        context = g_simple_async_result_get_op_res_gpointer (simple);
@@ -167,14 +200,13 @@ load_snapshot_loaded_cb (GFile *snapshot_file,
         * restore its snapshot file so it continues auto-saving to
         * the same file. */
        shell = E_SHELL (object);
-       g_object_ref (snapshot_file);
-       composer = e_msg_composer_new_with_message (shell, message, TRUE, NULL, NULL);
-       g_object_set_data_full (
-               G_OBJECT (composer),
-               SNAPSHOT_FILE_KEY, snapshot_file,
-               (GDestroyNotify) delete_snapshot_file);
-       context->composer = g_object_ref_sink (composer);
-       g_object_unref (message);
+
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->context = context;
+       ccd->message = message;
+       ccd->snapshot_file = g_object_ref (snapshot_file);
+
+       e_msg_composer_new (shell, autosave_composer_created_cb, ccd);
 
        g_object_unref (object);
 
diff --git a/modules/mail/e-mail-attachment-handler.c b/modules/mail/e-mail-attachment-handler.c
index 50d0c74..a5252b8 100644
--- a/modules/mail/e-mail-attachment-handler.c
+++ b/modules/mail/e-mail-attachment-handler.c
@@ -167,6 +167,65 @@ exit:
        return message;
 }
 
+typedef struct _CreateComposerData {
+       CamelMimeMessage *message;
+       CamelFolder *folder;
+       gboolean is_redirect;
+
+       gboolean is_reply;
+       EMailReplyType reply_type;
+
+       gboolean is_forward;
+       EMailForwardStyle forward_style;
+} CreateComposerData;
+
+static void
+create_composer_data_free (CreateComposerData *ccd)
+{
+       if (ccd) {
+               g_clear_object (&ccd->message);
+               g_clear_object (&ccd->folder);
+               g_free (ccd);
+       }
+}
+
+static void
+mail_attachment_handler_composer_created_cb (GObject *source_object,
+                                            GAsyncResult *result,
+                                            gpointer user_data)
+{
+       CreateComposerData *ccd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (ccd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               if (ccd->is_redirect) {
+                       em_utils_redirect_message (composer, ccd->message);
+               } else if (ccd->is_reply) {
+                       GSettings *settings;
+                       EMailReplyStyle style;
+
+                       settings = e_util_ref_settings ("org.gnome.evolution.mail");
+                       style = g_settings_get_enum (settings, "reply-style-name");
+                       g_object_unref (settings);
+
+                       em_utils_reply_to_message (composer, ccd->message, NULL, NULL, ccd->reply_type, 
style, NULL, NULL);
+               } else if (ccd->is_forward) {
+                       em_utils_forward_message (composer, ccd->message, ccd->forward_style, ccd->folder, 
NULL);
+               } else {
+                       em_utils_edit_message (composer, ccd->folder, ccd->message, NULL, TRUE);
+               }
+       }
+
+       create_composer_data_free (ccd);
+}
+
 static void
 mail_attachment_handler_forward_with_style (EAttachmentHandler *handler,
                                            EMailForwardStyle style)
@@ -174,6 +233,8 @@ mail_attachment_handler_forward_with_style (EAttachmentHandler *handler,
        EMailAttachmentHandlerPrivate *priv;
        CamelMimeMessage *message;
        CamelFolder *folder;
+       CreateComposerData *ccd;
+       EShell *shell;
 
        priv = E_MAIL_ATTACHMENT_HANDLER_GET_PRIVATE (handler);
 
@@ -181,11 +242,15 @@ mail_attachment_handler_forward_with_style (EAttachmentHandler *handler,
        g_return_if_fail (message != NULL);
 
        folder = mail_attachment_handler_guess_folder_ref (handler);
+       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (priv->backend));
 
-       em_utils_forward_message (priv->backend, message, style, folder, NULL);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->message = message;
+       ccd->folder = folder;
+       ccd->is_forward = TRUE;
+       ccd->forward_style = style;
 
-       g_clear_object (&folder);
-       g_object_unref (message);
+       e_msg_composer_new (shell, mail_attachment_handler_composer_created_cb, ccd);
 }
 
 static void
@@ -207,9 +272,8 @@ mail_attachment_handler_reply (EAttachmentHandler *handler,
                                EMailReplyType reply_type)
 {
        EMailAttachmentHandlerPrivate *priv;
-       GSettings *settings;
-       EMailReplyStyle style;
        CamelMimeMessage *message;
+       CreateComposerData *ccd;
        EShellBackend *shell_backend;
        EShell *shell;
 
@@ -218,17 +282,15 @@ mail_attachment_handler_reply (EAttachmentHandler *handler,
        message = mail_attachment_handler_get_selected_message (handler);
        g_return_if_fail (message != NULL);
 
-       settings = e_util_ref_settings ("org.gnome.evolution.mail");
-       style = g_settings_get_enum (settings, "reply-style-name");
-       g_object_unref (settings);
-
        shell_backend = E_SHELL_BACKEND (priv->backend);
        shell = e_shell_backend_get_shell (shell_backend);
 
-       em_utils_reply_to_message (
-               shell, message, NULL, NULL, reply_type, style, NULL, NULL);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->message = message;
+       ccd->reply_type = reply_type;
+       ccd->is_reply = TRUE;
 
-       g_object_unref (message);
+       e_msg_composer_new (shell, mail_attachment_handler_composer_created_cb, ccd);
 }
 
 static void
@@ -259,6 +321,7 @@ mail_attachment_handler_message_edit (GtkAction *action,
        EMailAttachmentHandlerPrivate *priv;
        CamelMimeMessage *message;
        CamelFolder *folder;
+       CreateComposerData *ccd;
        EShell *shell;
 
        priv = E_MAIL_ATTACHMENT_HANDLER_GET_PRIVATE (handler);
@@ -269,10 +332,11 @@ mail_attachment_handler_message_edit (GtkAction *action,
        shell = e_shell_backend_get_shell (E_SHELL_BACKEND (priv->backend));
        folder = mail_attachment_handler_guess_folder_ref (handler);
 
-       em_utils_edit_message (shell, folder, message, NULL, TRUE);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->message = message;
+       ccd->folder = folder;
 
-       g_clear_object (&folder);
-       g_object_unref (message);
+       e_msg_composer_new (shell, mail_attachment_handler_composer_created_cb, ccd);
 }
 
 static void
@@ -301,6 +365,7 @@ mail_attachment_handler_redirect (GtkAction *action,
 {
        EMailAttachmentHandlerPrivate *priv;
        CamelMimeMessage *message;
+       CreateComposerData *ccd;
        EShell *shell;
 
        priv = E_MAIL_ATTACHMENT_HANDLER_GET_PRIVATE (handler);
@@ -310,9 +375,12 @@ mail_attachment_handler_redirect (GtkAction *action,
 
        shell = e_shell_backend_get_shell (E_SHELL_BACKEND (priv->backend));
 
-       em_utils_redirect_message (shell, message);
+       ccd = g_new0 (CreateComposerData, 1);
+       ccd->message = message;
+       ccd->folder = NULL;
+       ccd->is_redirect = TRUE;
 
-       g_object_unref (message);
+       e_msg_composer_new (shell, mail_attachment_handler_composer_created_cb, ccd);
 }
 
 static GtkActionEntry standard_entries[] = {
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index 4bfce75..506b0d7 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -293,6 +293,29 @@ action_mail_account_new_cb (GtkAction *action,
 }
 
 static void
+action_mail_message_new_composer_created_cb (GObject *source_object,
+                                            GAsyncResult *result,
+                                            gpointer user_data)
+{
+       CamelFolder *folder = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       if (folder)
+               g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               em_utils_compose_new_message (composer, folder);
+       }
+
+       g_clear_object (&folder);
+}
+
+static void
 action_mail_message_new_cb (GtkAction *action,
                             EShellWindow *shell_window)
 {
@@ -342,8 +365,9 @@ action_mail_message_new_cb (GtkAction *action,
                g_free (folder_name);
        }
 
-exit:
-       em_utils_compose_new_message (shell, folder);
+ exit:
+       e_msg_composer_new (shell, action_mail_message_new_composer_created_cb,
+               folder ? g_object_ref (folder) : NULL);
 }
 
 static GtkActionEntry item_entries[] = {
diff --git a/modules/webkit-editor/e-webkit-editor.c b/modules/webkit-editor/e-webkit-editor.c
index a2bce79..50abf15 100644
--- a/modules/webkit-editor/e-webkit-editor.c
+++ b/modules/webkit-editor/e-webkit-editor.c
@@ -428,12 +428,8 @@ web_extension_undo_redo_state_changed_cb (GDBusConnection *connection,
 static void
 dispatch_pending_operations (EWebKitEditor *wk_editor)
 {
-       if (!wk_editor->priv->web_extension) {
-               g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
-               return;
-       }
-
-       if (wk_editor->priv->webkit_load_event != WEBKIT_LOAD_FINISHED)
+       if (wk_editor->priv->webkit_load_event != WEBKIT_LOAD_FINISHED ||
+           !wk_editor->priv->web_extension)
                return;
 
        /* Dispatch queued operations - as we are using this just for load
@@ -1394,8 +1390,6 @@ webkit_editor_insert_content (EContentEditor *editor,
                }
        }
 
-       wk_editor->priv->reload_in_progress = TRUE;
-
        if ((flags & E_CONTENT_EDITOR_INSERT_CONVERT) &&
            !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL)) {
                // e_html_editor_view_convert_and_insert_plain_text
@@ -1417,6 +1411,7 @@ webkit_editor_insert_content (EContentEditor *editor,
        } else if ((flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL) &&
                   (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML)) {
                if (wk_editor->priv->content_flags & E_CONTENT_EDITOR_MESSAGE_DRAFT) {
+                       wk_editor->priv->reload_in_progress = TRUE;
                        webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, "file://");
                        return;
                }
@@ -1425,6 +1420,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                    !(wk_editor->priv->html_mode)) {
                        if (content && *content)
                                set_convert_in_situ (wk_editor, TRUE);
+                       wk_editor->priv->reload_in_progress = TRUE;
                        webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, "file://");
                        return;
                }
@@ -1433,6 +1429,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                if (!(wk_editor->priv->html_mode)) {
                        if (strstr (content, "<!-- text/html -->")) {
                                if (!show_lose_formatting_dialog (wk_editor)) {
+                                       wk_editor->priv->reload_in_progress = TRUE;
                                        webkit_editor_set_html_mode (wk_editor, TRUE);
                                        webkit_web_view_load_html (
                                                WEBKIT_WEB_VIEW (wk_editor), content, "file://");
@@ -1443,6 +1440,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                                set_convert_in_situ (wk_editor, TRUE);
                }
 
+               wk_editor->priv->reload_in_progress = TRUE;
                webkit_web_view_load_html (WEBKIT_WEB_VIEW (wk_editor), content, "file://");
        } else if ((flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL) &&
                   (flags & E_CONTENT_EDITOR_INSERT_TEXT_PLAIN)) {
@@ -5572,9 +5570,9 @@ webkit_editor_load_changed_cb (EWebKitEditor *wk_editor,
        else
                wk_editor->priv->emit_load_finished_when_extension_is_ready = TRUE;
 
-       dispatch_pending_operations (wk_editor);
-
        wk_editor->priv->reload_in_progress = FALSE;
+
+       dispatch_pending_operations (wk_editor);
 }
 
 static void
diff --git a/plugins/mailing-list-actions/mailing-list-actions.c 
b/plugins/mailing-list-actions/mailing-list-actions.c
index 498a94d..58f58f6 100644
--- a/plugins/mailing-list-actions/mailing-list-actions.c
+++ b/plugins/mailing-list-actions/mailing-list-actions.c
@@ -116,6 +116,44 @@ async_context_free (AsyncContext *context)
        g_slice_free (AsyncContext, context);
 }
 
+typedef struct _SendMessageData {
+       gchar *url;
+       gchar *uid;
+} SendMessageData;
+
+static void
+send_message_composer_created_cb (GObject *source_object,
+                                 GAsyncResult *result,
+                                 gpointer user_data)
+{
+       SendMessageData *smd = user_data;
+       EMsgComposer *composer;
+       GError *error = NULL;
+
+       g_return_if_fail (smd != NULL);
+
+       composer = e_msg_composer_new_finish (result, &error);
+       if (error) {
+               g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
+               g_clear_error (&error);
+       } else {
+               EComposerHeaderTable *table;
+
+               /* directly send message */
+               e_msg_composer_setup_from_url (composer, smd->url);
+               table = e_msg_composer_get_header_table (composer);
+
+               if (smd->uid)
+                       e_composer_header_table_set_identity_uid (table, smd->uid);
+
+               e_msg_composer_send (composer);
+       }
+
+       g_free (smd->url);
+       g_free (smd->uid);
+       g_free (smd);
+}
+
 static void
 emla_list_action_cb (CamelFolder *folder,
                      GAsyncResult *result,
@@ -124,7 +162,6 @@ emla_list_action_cb (CamelFolder *folder,
        const gchar *header = NULL, *headerpos;
        gchar *end, *url = NULL;
        gint t;
-       EMsgComposer *composer;
        EAlertSink *alert_sink;
        CamelMimeMessage *message;
        gint send_message_response;
@@ -239,15 +276,13 @@ emla_list_action_cb (CamelFolder *folder,
                                        url, NULL);
 
                        if (send_message_response == GTK_RESPONSE_YES) {
-                               EComposerHeaderTable *table;
+                               SendMessageData *smd;
 
-                               /* directly send message */
-                               composer = e_msg_composer_new_from_url (shell, url);
-                               table = e_msg_composer_get_header_table (composer);
+                               smd = g_new0 (SendMessageData, 1);
+                               smd->url = g_strdup (url);
+                               smd->uid = g_strdup (uid);
 
-                               if (uid != NULL)
-                                       e_composer_header_table_set_identity_uid (table, uid);
-                               e_msg_composer_send (composer);
+                               e_msg_composer_new (shell, send_message_composer_created_cb, smd);
                        } else if (send_message_response == GTK_RESPONSE_NO) {
                                /* show composer */
                                em_utils_compose_new_message_with_mailto (shell, url, folder);
diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c
index 57229dd..3f98a6e 100644
--- a/plugins/templates/templates.c
+++ b/plugins/templates/templates.c
@@ -51,6 +51,7 @@ struct _AsyncContext {
        EActivity *activity;
        EMailReader *reader;
        CamelMimeMessage *message;
+       CamelMimeMessage *template;
        CamelFolder *template_folder;
        gchar *source_folder_uri;
        gchar *message_uid;
@@ -123,17 +124,11 @@ static gboolean plugin_enabled;
 static void
 async_context_free (AsyncContext *context)
 {
-       if (context->activity != NULL)
-               g_object_unref (context->activity);
-
-       if (context->reader != NULL)
-               g_object_unref (context->reader);
-
-       if (context->message != NULL)
-               g_object_unref (context->message);
-
-       if (context->template_folder != NULL)
-               g_object_unref (context->template_folder);
+       g_clear_object (&context->activity);
+       g_clear_object (&context->reader);
+       g_clear_object (&context->message);
+       g_clear_object (&context->template);
+       g_clear_object (&context->template_folder);
 
        g_free (context->source_folder_uri);
        g_free (context->message_uid);
@@ -846,10 +841,11 @@ find_template_part_in_multipart (CamelMultipart *multipart,
 }
 
 static void
-create_new_message (CamelFolder *folder,
-                    GAsyncResult *result,
-                    AsyncContext *context)
+create_new_message_composer_created_cb (GObject *source_object,
+                                       GAsyncResult *result,
+                                       gpointer user_data)
 {
+       AsyncContext *context = user_data;
        EAlertSink *alert_sink;
        CamelMimeMessage *new;
        CamelMimeMessage *message;
@@ -859,24 +855,26 @@ create_new_message (CamelFolder *folder,
        struct _camel_header_raw *header;
        EMailBackend *backend;
        EMailSession *session;
-       EShell *shell;
        const gchar *message_uid;
        EMsgComposer *composer;
        GError *error = NULL;
        CamelMimePart *template_part = NULL;
+       CamelFolder *folder;
+
+       g_return_if_fail (context != NULL);
 
        alert_sink = e_activity_get_alert_sink (context->activity);
 
-       template = camel_folder_get_message_finish (folder, result, &error);
+       composer = e_msg_composer_new_finish (result, &error);
 
        if (e_activity_handle_cancellation (context->activity, error)) {
-               g_warn_if_fail (template == NULL);
+               g_warn_if_fail (context->template == NULL);
                async_context_free (context);
                g_error_free (error);
                return;
 
        } else if (error != NULL) {
-               g_warn_if_fail (template == NULL);
+               g_warn_if_fail (context->template == NULL);
                e_alert_submit (
                        alert_sink, "mail:no-retrieve-message",
                        error->message, NULL);
@@ -885,17 +883,16 @@ create_new_message (CamelFolder *folder,
                return;
        }
 
-       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (template));
+       g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
        message = context->message;
        message_uid = context->message_uid;
+       template = context->template;
 
        backend = e_mail_reader_get_backend (context->reader);
        session = e_mail_backend_get_session (backend);
-       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
-       folder = e_mail_session_get_local_folder (
-               session, E_MAIL_LOCAL_FOLDER_TEMPLATES);
+       folder = e_mail_session_get_local_folder (session, E_MAIL_LOCAL_FOLDER_TEMPLATES);
 
        new = camel_mime_message_new ();
        new_multipart = camel_multipart_new ();
@@ -989,14 +986,12 @@ create_new_message (CamelFolder *folder,
                        template, CAMEL_RECIPIENT_TYPE_BCC));
 
        /* Create the composer */
-       composer = em_utils_edit_message (
-               shell, folder, new, message_uid, TRUE);
+       em_utils_edit_message (composer, folder, new, message_uid, TRUE);
        if (composer && context->source_folder_uri && context->message_uid)
                e_msg_composer_set_source_headers (
                        composer, context->source_folder_uri,
                        context->message_uid, CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN);
 
-       g_object_unref (template);
        g_object_unref (new_multipart);
        g_object_unref (new);
 
@@ -1004,6 +999,51 @@ create_new_message (CamelFolder *folder,
 }
 
 static void
+create_new_message (GObject *source_object,
+                    GAsyncResult *result,
+                    gpointer user_data)
+{
+       AsyncContext *context = user_data;
+       EAlertSink *alert_sink;
+       EMailBackend *backend;
+       EShell *shell;
+       CamelFolder *folder;
+       GError *error = NULL;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (source_object));
+       g_return_if_fail (context != NULL);
+
+       folder = CAMEL_FOLDER (source_object);
+
+       alert_sink = e_activity_get_alert_sink (context->activity);
+
+       context->template = camel_folder_get_message_finish (folder, result, &error);
+
+       if (e_activity_handle_cancellation (context->activity, error)) {
+               g_warn_if_fail (context->template == NULL);
+               async_context_free (context);
+               g_error_free (error);
+               return;
+
+       } else if (error != NULL) {
+               g_warn_if_fail (context->template == NULL);
+               e_alert_submit (
+                       alert_sink, "mail:no-retrieve-message",
+                       error->message, NULL);
+               async_context_free (context);
+               g_error_free (error);
+               return;
+       }
+
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (context->template));
+
+       backend = e_mail_reader_get_backend (context->reader);
+       shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+
+       e_msg_composer_new (shell, create_new_message_composer_created_cb, context);
+}
+
+static void
 template_got_source_message (CamelFolder *folder,
                              GAsyncResult *result,
                              AsyncContext *context)
@@ -1044,8 +1084,7 @@ template_got_source_message (CamelFolder *folder,
                context->template_folder,
                context->template_message_uid,
                G_PRIORITY_DEFAULT, cancellable,
-               (GAsyncReadyCallback) create_new_message,
-               context);
+               create_new_message, context);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]