[evolution/account-mgmt: 22/55] Adapt composer to the new ESource API.



commit 72f2ee7be3d6809959f4c639b3a3f1d3742ddffa
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Apr 13 10:31:31 2011 -0400

    Adapt composer to the new ESource API.

 composer/e-composer-from-header.c  |  130 +++-----
 composer/e-composer-from-header.h  |   24 +-
 composer/e-composer-header-table.c |  625 +++++++++++++++----------------
 composer/e-composer-header-table.h |   43 +--
 composer/e-composer-header.c       |  175 ++++++----
 composer/e-composer-header.h       |    5 +-
 composer/e-composer-name-header.c  |  116 +++---
 composer/e-composer-name-header.h  |    3 +-
 composer/e-composer-post-header.c  |  168 ++++-----
 composer/e-composer-post-header.h  |   15 +-
 composer/e-composer-private.c      |  211 +++++++++++-
 composer/e-composer-private.h      |    9 +-
 composer/e-composer-spell-header.c |   20 +-
 composer/e-composer-spell-header.h |   18 +-
 composer/e-composer-text-header.c  |   33 ++-
 composer/e-composer-text-header.h  |    6 +-
 composer/e-msg-composer.c          |  711 ++++++++++++++++--------------------
 composer/e-msg-composer.h          |    4 +-
 18 files changed, 1206 insertions(+), 1110 deletions(-)
---
diff --git a/composer/e-composer-from-header.c b/composer/e-composer-from-header.c
index 0b56971..a844ca3 100644
--- a/composer/e-composer-from-header.c
+++ b/composer/e-composer-from-header.c
@@ -24,16 +24,7 @@
 
 #include "e-composer-from-header.h"
 
-/* Convenience macro */
-#define E_COMPOSER_FROM_HEADER_GET_COMBO_BOX(header) \
-	(E_ACCOUNT_COMBO_BOX (E_COMPOSER_HEADER (header)->input_widget))
-
-enum {
-	REFRESHED,
-	LAST_SIGNAL
-};
-
-static guint signal_ids[LAST_SIGNAL];
+#include <misc/e-mail-identity-combo-box.h>
 
 G_DEFINE_TYPE (
 	EComposerFromHeader,
@@ -41,119 +32,82 @@ G_DEFINE_TYPE (
 	E_TYPE_COMPOSER_HEADER)
 
 static void
-composer_from_header_changed_cb (EAccountComboBox *combo_box,
+composer_from_header_changed_cb (EMailIdentityComboBox *combo_box,
                                  EComposerFromHeader *header)
 {
 	g_signal_emit_by_name (header, "changed");
 }
 
 static void
-composer_from_header_refreshed_cb (EAccountComboBox *combo_box,
-                                   EComposerFromHeader *header)
+composer_from_header_constructed (GObject *object)
 {
-	g_signal_emit (header, signal_ids[REFRESHED], 0);
-}
+	ESourceRegistry *registry;
+	EComposerHeader *header;
+	GtkWidget *widget;
 
-static void
-e_composer_from_header_class_init (EComposerFromHeaderClass *class)
-{
-	signal_ids[REFRESHED] = g_signal_new (
-		"refreshed",
-		G_TYPE_FROM_CLASS (class),
-		G_SIGNAL_RUN_LAST,
-		0, NULL, NULL,
-		g_cclosure_marshal_VOID__VOID,
-		G_TYPE_NONE, 0);
-}
+	header = E_COMPOSER_HEADER (object);
+	registry = e_composer_header_get_registry (header);
 
-static void
-e_composer_from_header_init (EComposerFromHeader *header)
-{
-	GtkWidget *widget;
+	/* Input widget must be set before chaining up. */
 
-	widget = g_object_ref_sink (e_account_combo_box_new ());
+	widget = e_mail_identity_combo_box_new (registry);
 	g_signal_connect (
 		widget, "changed",
 		G_CALLBACK (composer_from_header_changed_cb), header);
-	g_signal_connect (
-		widget, "refreshed",
-		G_CALLBACK (composer_from_header_refreshed_cb), header);
-	E_COMPOSER_HEADER (header)->input_widget = widget;
-}
-
-EComposerHeader *
-e_composer_from_header_new (const gchar *label)
-{
-	return g_object_new (
-		E_TYPE_COMPOSER_FROM_HEADER, "label", label,
-		"button", FALSE, NULL);
-}
-
-EAccountList *
-e_composer_from_header_get_account_list (EComposerFromHeader *header)
-{
-	EAccountComboBox *combo_box;
-
-	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
+	header->input_widget = g_object_ref_sink (widget);
 
-	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
-	return e_account_combo_box_get_account_list (combo_box);
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_composer_from_header_parent_class)->
+		constructed (object);
 }
 
-void
-e_composer_from_header_set_account_list (EComposerFromHeader *header,
-                                         EAccountList *account_list)
+static void
+e_composer_from_header_class_init (EComposerFromHeaderClass *class)
 {
-	EAccountComboBox *combo_box;
-
-	g_return_if_fail (E_IS_COMPOSER_FROM_HEADER (header));
+	GObjectClass *object_class;
 
-	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
-	e_account_combo_box_set_account_list (combo_box, account_list);
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = composer_from_header_constructed;
 }
 
-EAccount *
-e_composer_from_header_get_active (EComposerFromHeader *header)
+static void
+e_composer_from_header_init (EComposerFromHeader *from_header)
 {
-	EAccountComboBox *combo_box;
-
-	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
-
-	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
-	return e_account_combo_box_get_active (combo_box);
 }
 
-gboolean
-e_composer_from_header_set_active (EComposerFromHeader *header,
-                                   EAccount *account)
+EComposerHeader *
+e_composer_from_header_new (ESourceRegistry *registry,
+                            const gchar *label)
 {
-	EAccountComboBox *combo_box;
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
-	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), FALSE);
-
-	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
-	return e_account_combo_box_set_active (combo_box, account);
+	return g_object_new (
+		E_TYPE_COMPOSER_FROM_HEADER,
+		"label", label, "button", FALSE,
+		"registry", registry, NULL);
 }
 
 const gchar *
-e_composer_from_header_get_active_name (EComposerFromHeader *header)
+e_composer_from_header_get_active_id (EComposerFromHeader *header)
 {
-	EAccountComboBox *combo_box;
+	GtkComboBox *combo_box;
 
 	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
 
-	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
-	return e_account_combo_box_get_active_name (combo_box);
+	combo_box = GTK_COMBO_BOX (E_COMPOSER_HEADER (header)->input_widget);
+
+	return gtk_combo_box_get_active_id (combo_box);
 }
 
-gboolean
-e_composer_from_header_set_active_name (EComposerFromHeader *header,
-                                        const gchar *account_name)
+void
+e_composer_from_header_set_active_id (EComposerFromHeader *header,
+                                      const gchar *active_id)
 {
-	EAccountComboBox *combo_box;
+	GtkComboBox *combo_box;
+
+	g_return_if_fail (E_IS_COMPOSER_FROM_HEADER (header));
 
-	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), FALSE);
+	combo_box = GTK_COMBO_BOX (E_COMPOSER_HEADER (header)->input_widget);
 
-	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
-	return e_account_combo_box_set_active_name (combo_box, account_name);
+	gtk_combo_box_set_active_id (combo_box, active_id);
 }
diff --git a/composer/e-composer-from-header.h b/composer/e-composer-from-header.h
index 182a751..b4116e6 100644
--- a/composer/e-composer-from-header.h
+++ b/composer/e-composer-from-header.h
@@ -21,10 +21,6 @@
 #ifndef E_COMPOSER_FROM_HEADER_H
 #define E_COMPOSER_FROM_HEADER_H
 
-#include <libedataserver/e-account.h>
-#include <libedataserver/e-account-list.h>
-
-#include <misc/e-account-combo-box.h>
 #include <composer/e-composer-header.h>
 
 /* Standard GObject macros */
@@ -60,22 +56,14 @@ struct _EComposerFromHeaderClass {
 };
 
 GType		e_composer_from_header_get_type	(void);
-EComposerHeader * e_composer_from_header_new	(const gchar *label);
-EAccountList *	e_composer_from_header_get_account_list
-						(EComposerFromHeader *header);
-void		e_composer_from_header_set_account_list
-						(EComposerFromHeader *header,
-						 EAccountList *account_list);
-EAccount *	e_composer_from_header_get_active
-						(EComposerFromHeader *header);
-gboolean	e_composer_from_header_set_active
-						(EComposerFromHeader *header,
-						 EAccount *account);
-const gchar *	e_composer_from_header_get_active_name
+EComposerHeader *
+		e_composer_from_header_new	(ESourceRegistry *registry,
+						 const gchar *label);
+const gchar *	e_composer_from_header_get_active_id
 						(EComposerFromHeader *header);
-gboolean	e_composer_from_header_set_active_name
+void		e_composer_from_header_set_active_id
 						(EComposerFromHeader *header,
-						 const gchar *account_name);
+						 const gchar *active_id);
 
 G_END_DECLS
 
diff --git a/composer/e-composer-header-table.c b/composer/e-composer-header-table.c
index 51a217d..742ab11 100644
--- a/composer/e-composer-header-table.c
+++ b/composer/e-composer-header-table.c
@@ -23,9 +23,12 @@
 
 #include <glib/gi18n-lib.h>
 #include <libedataserverui/e-name-selector.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
 
 #include <shell/e-shell.h>
-#include <misc/e-signature-combo-box.h>
+#include <misc/e-mail-signature-combo-box.h>
 
 #include "e-msg-composer.h"
 #include "e-composer-private.h"
@@ -53,30 +56,30 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), E_TYPE_COMPOSER_HEADER_TABLE, EComposerHeaderTablePrivate))
 
+struct _EComposerHeaderTablePrivate {
+	EComposerHeader *headers[E_COMPOSER_NUM_HEADERS];
+	GtkWidget *signature_label;
+	GtkWidget *signature_combo_box;
+	ENameSelector *name_selector;
+	ESourceRegistry *registry;
+	EShell *shell;
+};
+
 enum {
 	PROP_0,
-	PROP_ACCOUNT,
-	PROP_ACCOUNT_LIST,
-	PROP_ACCOUNT_NAME,
 	PROP_DESTINATIONS_BCC,
 	PROP_DESTINATIONS_CC,
 	PROP_DESTINATIONS_TO,
+	PROP_IDENTITY_UID,
 	PROP_POST_TO,
+	PROP_REGISTRY,
 	PROP_REPLY_TO,
 	PROP_SHELL,
-	PROP_SIGNATURE,
-	PROP_SIGNATURE_LIST,
+	PROP_SIGNATURE_COMBO_BOX,
+	PROP_SIGNATURE_UID,
 	PROP_SUBJECT
 };
 
-struct _EComposerHeaderTablePrivate {
-	EComposerHeader *headers[E_COMPOSER_NUM_HEADERS];
-	GtkWidget *signature_label;
-	GtkWidget *signature_combo_box;
-	ENameSelector *name_selector;
-	EShell *shell;
-};
-
 G_DEFINE_TYPE (
 	EComposerHeaderTable,
 	e_composer_header_table,
@@ -217,13 +220,13 @@ composer_header_table_bind_widget (const gchar *property_name,
 
 static EDestination **
 composer_header_table_update_destinations (EDestination **old_destinations,
-                                           const gchar *auto_addresses)
+                                           const gchar * const *auto_addresses)
 {
 	CamelAddress *address;
 	CamelInternetAddress *inet_address;
 	EDestination **new_destinations;
 	EDestination *destination;
-	GList *list = NULL;
+	GQueue queue = G_QUEUE_INIT;
 	guint length;
 	gint ii;
 
@@ -235,25 +238,29 @@ composer_header_table_update_destinations (EDestination **old_destinations,
 	inet_address = camel_internet_address_new ();
 	address = CAMEL_ADDRESS (inet_address);
 
-	if (camel_address_decode (address, auto_addresses) != -1) {
-		for (ii = 0; ii < camel_address_length (address); ii++) {
-			const gchar *name, *email;
+	/* XXX Calling camel_address_decode() multiple times on the same
+	 *     CamelInternetAddress has a cumulative effect, which isn't
+	 *     well documented. */
+	for (ii = 0; auto_addresses[ii] != NULL; ii++)
+		camel_address_decode (address, auto_addresses[ii]);
+
+	for (ii = 0; ii < camel_address_length (address); ii++) {
+		const gchar *name, *email;
 
-			if (!camel_internet_address_get (
-				inet_address, ii, &name, &email))
-				continue;
+		if (!camel_internet_address_get (
+			inet_address, ii, &name, &email))
+			continue;
 
-			destination = e_destination_new ();
-			e_destination_set_auto_recipient (destination, TRUE);
+		destination = e_destination_new ();
+		e_destination_set_auto_recipient (destination, TRUE);
 
-			if (name != NULL)
-				e_destination_set_name (destination, name);
+		if (name != NULL)
+			e_destination_set_name (destination, name);
 
-			if (email != NULL)
-				e_destination_set_email (destination, email);
+		if (email != NULL)
+			e_destination_set_email (destination, email);
 
-			list = g_list_prepend (list, destination);
-		}
+		g_queue_push_tail (&queue, destination);
 	}
 
 	g_object_unref (inet_address);
@@ -270,20 +277,19 @@ skip_auto:
 			continue;
 
 		destination = e_destination_copy (old_destinations[ii]);
-		list = g_list_prepend (list, destination);
+		g_queue_push_tail (&queue, destination);
 	}
 
 skip_custom:
 
-	list = g_list_reverse (list);
-	length = g_list_length (list);
-
+	length = g_queue_get_length (&queue);
 	new_destinations = g_new0 (EDestination *, length + 1);
 
-	for (ii = 0; list != NULL; ii++) {
-		new_destinations[ii] = E_DESTINATION (list->data);
-		list = g_list_delete_link (list, list);
-	}
+	for (ii = 0; ii < length; ii++)
+		new_destinations[ii] = g_queue_pop_head (&queue);
+
+	/* Sanity check. */
+	g_warn_if_fail (g_queue_is_empty (&queue));
 
 	return new_destinations;
 }
@@ -294,7 +300,8 @@ from_header_should_be_visible (EComposerHeaderTable *table)
 	EShell *shell;
 	EComposerHeader *header;
 	EComposerHeaderType type;
-	EAccountComboBox *combo_box;
+	GtkComboBox *combo_box;
+	GtkTreeModel *tree_model;
 
 	shell = e_composer_header_table_get_shell (table);
 
@@ -304,9 +311,11 @@ from_header_should_be_visible (EComposerHeaderTable *table)
 
 	type = E_COMPOSER_HEADER_FROM;
 	header = e_composer_header_table_get_header (table, type);
-	combo_box = E_ACCOUNT_COMBO_BOX (header->input_widget);
 
-	return (e_account_combo_box_count_displayed_accounts (combo_box) > 1);
+	combo_box = GTK_COMBO_BOX (header->input_widget);
+	tree_model = gtk_combo_box_get_model (combo_box);
+
+	return (gtk_tree_model_iter_n_children (tree_model, NULL) > 1);
 }
 
 static void
@@ -436,46 +445,127 @@ composer_header_table_setup_post_headers (EComposerHeaderTable *table)
 	g_object_unref (settings);
 }
 
+static gboolean
+composer_header_table_show_post_headers (EComposerHeaderTable *table)
+{
+	ESourceRegistry *registry;
+	GList *list, *link;
+	const gchar *extension_name;
+	const gchar *target_uid;
+	gboolean show_post_headers = FALSE;
+
+	registry = e_composer_header_table_get_registry (table);
+	target_uid = e_composer_header_table_get_identity_uid (table);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	/* Look for a mail account referencing this mail identity.
+	 * If the mail account's backend name is "nntp", show the
+	 * post headers.  Otherwise show the mail headers.
+	 *
+	 * XXX What if multiple accounts use this identity but only
+	 *     one is "nntp"?  Maybe it should be indicated by the
+	 *     transport somehow?
+	 */
+	for (link = list; link != NULL; link = link->next) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *backend_name;
+		const gchar *identity_uid;
+
+		extension = e_source_get_extension (source, extension_name);
+
+		backend_name = e_source_backend_get_backend_name (
+			E_SOURCE_BACKEND (extension));
+		identity_uid = e_source_mail_account_get_identity_uid (
+			E_SOURCE_MAIL_ACCOUNT (extension));
+
+		if (g_strcmp0 (identity_uid, target_uid) != 0)
+			continue;
+
+		if (g_strcmp0 (backend_name, "nntp") != 0)
+			continue;
+
+		show_post_headers = TRUE;
+		break;
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	return show_post_headers;
+}
+
 static void
 composer_header_table_from_changed_cb (EComposerHeaderTable *table)
 {
-	EAccount *account;
+	ESource *source = NULL;
+	ESource *mail_account = NULL;
+	ESourceRegistry *registry;
 	EComposerHeader *header;
 	EComposerHeaderType type;
 	EComposerPostHeader *post_header;
 	EComposerTextHeader *text_header;
 	EDestination **old_destinations;
 	EDestination **new_destinations;
-	const gchar *reply_to;
-	const gchar *source_url;
-	gboolean always_cc;
-	gboolean always_bcc;
+	const gchar *reply_to = NULL;
+	const gchar * const *bcc = NULL;
+	const gchar * const *cc = NULL;
+	const gchar *uid;
 
 	/* Keep "Post-To" and "Reply-To" synchronized with "From" */
 
-	account = e_composer_header_table_get_account (table);
-	source_url = e_account_get_string (account, E_ACCOUNT_SOURCE_URL);
+	registry = e_composer_header_table_get_registry (table);
+	uid = e_composer_header_table_get_identity_uid (table);
+
+	if (uid != NULL)
+		source = e_source_registry_ref_source (registry, uid);
+
+	/* Make sure this is really a mail identity source. */
+	if (source != NULL) {
+		const gchar *extension_name;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		if (!e_source_has_extension (source, extension_name)) {
+			g_object_unref (source);
+			source = NULL;
+		}
+	}
+
+	if (source != NULL) {
+		ESourceMailIdentity *mi;
+		ESourceMailComposition *mc;
+		const gchar *extension_name;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		mi = e_source_get_extension (source, extension_name);
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+		mc = e_source_get_extension (source, extension_name);
+
+		reply_to = e_source_mail_identity_get_reply_to (mi);
+		bcc = e_source_mail_composition_get_bcc (mc);
+		cc = e_source_mail_composition_get_cc (mc);
+
+		g_object_unref (source);
+	}
 
 	type = E_COMPOSER_HEADER_POST_TO;
 	header = e_composer_header_table_get_header (table, type);
 	post_header = E_COMPOSER_POST_HEADER (header);
-	e_composer_post_header_set_account (post_header, account);
+	e_composer_post_header_set_mail_account (post_header, mail_account);
 
 	type = E_COMPOSER_HEADER_REPLY_TO;
 	header = e_composer_header_table_get_header (table, type);
-	reply_to = (account != NULL) ? account->id->reply_to : NULL;
 	text_header = E_COMPOSER_TEXT_HEADER (header);
 	e_composer_text_header_set_text (text_header, reply_to);
 
-	always_cc = (account != NULL && account->always_cc);
-	always_bcc = (account != NULL && account->always_bcc);
-
 	/* Update automatic CC destinations. */
 	old_destinations =
 		e_composer_header_table_get_destinations_cc (table);
 	new_destinations =
 		composer_header_table_update_destinations (
-		old_destinations, always_cc ? account->cc_addrs : NULL);
+		old_destinations, cc);
 	e_composer_header_table_set_destinations_cc (table, new_destinations);
 	e_destination_freev (old_destinations);
 	e_destination_freev (new_destinations);
@@ -485,34 +575,28 @@ composer_header_table_from_changed_cb (EComposerHeaderTable *table)
 		e_composer_header_table_get_destinations_bcc (table);
 	new_destinations =
 		composer_header_table_update_destinations (
-		old_destinations, always_bcc ? account->bcc_addrs : NULL);
+		old_destinations, bcc);
 	e_composer_header_table_set_destinations_bcc (table, new_destinations);
 	e_destination_freev (old_destinations);
 	e_destination_freev (new_destinations);
 
-	/* XXX We should NOT be checking specific account types here.
-	 *     Would prefer EAccount have a "send_method" enum item:
-	 *
-	 *         E_ACCOUNT_SEND_METHOD_MAIL
-	 *         E_ACCOUNT_SEND_METHOD_POST
-	 *
-	 *     And that would dictate which set of headers we show
-	 *     in the composer when an account is selected.  Alas,
-	 *     EAccount has no private storage, so it would require
-	 *     an ABI break and I don't want to deal with that now.
-	 *     (But would anything besides Evolution be affected?)
-	 *
-	 *     Currently only NNTP accounts use the "POST" fields.
-	 */
-	if (source_url == NULL)
-		composer_header_table_setup_mail_headers (table);
-	else if (g_ascii_strncasecmp (source_url, "nntp:";, 5) == 0)
+	if (composer_header_table_show_post_headers (table))
 		composer_header_table_setup_post_headers (table);
 	else
 		composer_header_table_setup_mail_headers (table);
 }
 
 static void
+composer_header_table_set_registry (EComposerHeaderTable *table,
+                                    ESourceRegistry *registry)
+{
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+	g_return_if_fail (table->priv->registry == NULL);
+
+	table->priv->registry = g_object_ref (registry);
+}
+
+static void
 composer_header_table_set_shell (EComposerHeaderTable *table,
                                  EShell *shell)
 {
@@ -532,24 +616,6 @@ composer_header_table_set_property (GObject *object,
 	GList *list;
 
 	switch (property_id) {
-		case PROP_ACCOUNT:
-			e_composer_header_table_set_account (
-				E_COMPOSER_HEADER_TABLE (object),
-				g_value_get_object (value));
-			return;
-
-		case PROP_ACCOUNT_LIST:
-			e_composer_header_table_set_account_list (
-				E_COMPOSER_HEADER_TABLE (object),
-				g_value_get_object (value));
-			return;
-
-		case PROP_ACCOUNT_NAME:
-			e_composer_header_table_set_account_name (
-				E_COMPOSER_HEADER_TABLE (object),
-				g_value_get_string (value));
-			return;
-
 		case PROP_DESTINATIONS_BCC:
 			destinations = g_value_dup_destinations (value);
 			e_composer_header_table_set_destinations_bcc (
@@ -574,6 +640,12 @@ composer_header_table_set_property (GObject *object,
 			e_destination_freev (destinations);
 			return;
 
+		case PROP_IDENTITY_UID:
+			e_composer_header_table_set_identity_uid (
+				E_COMPOSER_HEADER_TABLE (object),
+				g_value_get_string (value));
+			return;
+
 		case PROP_POST_TO:
 			list = g_value_dup_string_list (value);
 			e_composer_header_table_set_post_to_list (
@@ -582,6 +654,12 @@ composer_header_table_set_property (GObject *object,
 			g_list_free (list);
 			return;
 
+		case PROP_REGISTRY:
+			composer_header_table_set_registry (
+				E_COMPOSER_HEADER_TABLE (object),
+				g_value_get_object (value));
+			return;
+
 		case PROP_REPLY_TO:
 			e_composer_header_table_set_reply_to (
 				E_COMPOSER_HEADER_TABLE (object),
@@ -594,16 +672,10 @@ composer_header_table_set_property (GObject *object,
 				g_value_get_object (value));
 			return;
 
-		case PROP_SIGNATURE:
-			e_composer_header_table_set_signature (
+		case PROP_SIGNATURE_UID:
+			e_composer_header_table_set_signature_uid (
 				E_COMPOSER_HEADER_TABLE (object),
-				g_value_get_object (value));
-			return;
-
-		case PROP_SIGNATURE_LIST:
-			e_composer_header_table_set_signature_list (
-				E_COMPOSER_HEADER_TABLE (object),
-				g_value_get_object (value));
+				g_value_get_string (value));
 			return;
 
 		case PROP_SUBJECT:
@@ -626,27 +698,6 @@ composer_header_table_get_property (GObject *object,
 	GList *list;
 
 	switch (property_id) {
-		case PROP_ACCOUNT:
-			g_value_set_object (
-				value,
-				e_composer_header_table_get_account (
-				E_COMPOSER_HEADER_TABLE (object)));
-			return;
-
-		case PROP_ACCOUNT_LIST:
-			g_value_set_object (
-				value,
-				e_composer_header_table_get_account_list (
-				E_COMPOSER_HEADER_TABLE (object)));
-			return;
-
-		case PROP_ACCOUNT_NAME:
-			g_value_set_string (
-				value,
-				e_composer_header_table_get_account_name (
-				E_COMPOSER_HEADER_TABLE (object)));
-			return;
-
 		case PROP_DESTINATIONS_BCC:
 			destinations =
 				e_composer_header_table_get_destinations_bcc (
@@ -671,6 +722,13 @@ composer_header_table_get_property (GObject *object,
 			e_destination_freev (destinations);
 			return;
 
+		case PROP_IDENTITY_UID:
+			g_value_set_string (
+				value,
+				e_composer_header_table_get_identity_uid (
+				E_COMPOSER_HEADER_TABLE (object)));
+			return;
+
 		case PROP_POST_TO:
 			list = e_composer_header_table_get_post_to (
 				E_COMPOSER_HEADER_TABLE (object));
@@ -679,6 +737,13 @@ composer_header_table_get_property (GObject *object,
 			g_list_free (list);
 			return;
 
+		case PROP_REGISTRY:
+			g_value_set_object (
+				value,
+				e_composer_header_table_get_registry (
+				E_COMPOSER_HEADER_TABLE (object)));
+			return;
+
 		case PROP_REPLY_TO:
 			g_value_set_string (
 				value,
@@ -693,17 +758,17 @@ composer_header_table_get_property (GObject *object,
 				E_COMPOSER_HEADER_TABLE (object)));
 			return;
 
-		case PROP_SIGNATURE:
+		case PROP_SIGNATURE_COMBO_BOX:
 			g_value_set_object (
 				value,
-				e_composer_header_table_get_signature (
+				e_composer_header_table_get_signature_combo_box (
 				E_COMPOSER_HEADER_TABLE (object)));
 			return;
 
-		case PROP_SIGNATURE_LIST:
-			g_value_set_object (
+		case PROP_SIGNATURE_UID:
+			g_value_set_string (
 				value,
-				e_composer_header_table_get_signature_list (
+				e_composer_header_table_get_signature_uid (
 				E_COMPOSER_HEADER_TABLE (object)));
 			return;
 
@@ -744,6 +809,11 @@ composer_header_table_dispose (GObject *object)
 		priv->name_selector = NULL;
 	}
 
+	if (priv->registry != NULL) {
+		g_object_unref (priv->registry);
+		priv->registry = NULL;
+	}
+
 	if (priv->shell != NULL) {
 		g_object_unref (priv->shell);
 		priv->shell = NULL;
@@ -758,6 +828,7 @@ composer_header_table_constructed (GObject *object)
 {
 	EComposerHeaderTable *table;
 	ENameSelector *name_selector;
+	ESourceRegistry *registry;
 	EComposerHeader *header;
 	GtkWidget *widget;
 	EShell *shell;
@@ -771,51 +842,52 @@ composer_header_table_constructed (GObject *object)
 
 	table = E_COMPOSER_HEADER_TABLE (object);
 	shell = e_composer_header_table_get_shell (table);
+	registry = e_composer_header_table_get_registry (table);
 
 	small_screen_mode = e_shell_get_small_screen_mode (shell);
 
-	name_selector = e_name_selector_new ();
+	name_selector = e_name_selector_new (registry);
 	table->priv->name_selector = name_selector;
 
-	header = e_composer_from_header_new (_("Fr_om:"));
-	composer_header_table_bind_header ("account", "changed", header);
-	composer_header_table_bind_header ("account-list", "refreshed", header);
-	composer_header_table_bind_header ("account-name", "changed", header);
+	header = e_composer_from_header_new (registry, _("Fr_om:"));
+	composer_header_table_bind_header ("identity-uid", "changed", header);
 	g_signal_connect_swapped (
 		header, "changed", G_CALLBACK (
 		composer_header_table_from_changed_cb), table);
 	table->priv->headers[E_COMPOSER_HEADER_FROM] = header;
 
-	header = e_composer_text_header_new_label (_("_Reply-To:"));
+	header = e_composer_text_header_new_label (registry, _("_Reply-To:"));
 	composer_header_table_bind_header ("reply-to", "changed", header);
 	table->priv->headers[E_COMPOSER_HEADER_REPLY_TO] = header;
 
-	header = e_composer_name_header_new (_("_To:"), name_selector);
+	header = e_composer_name_header_new (
+		registry, _("_To:"), name_selector);
 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_TO);
 	composer_header_table_bind_header ("destinations-to", "changed", header);
 	table->priv->headers[E_COMPOSER_HEADER_TO] = header;
 
-	header = e_composer_name_header_new (_("_Cc:"), name_selector);
+	header = e_composer_name_header_new (
+		registry, _("_Cc:"), name_selector);
 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_CC);
 	composer_header_table_bind_header ("destinations-cc", "changed", header);
 	table->priv->headers[E_COMPOSER_HEADER_CC] = header;
 
-	header = e_composer_name_header_new (_("_Bcc:"), name_selector);
+	header = e_composer_name_header_new (
+		registry, _("_Bcc:"), name_selector);
 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_BCC);
 	composer_header_table_bind_header ("destinations-bcc", "changed", header);
 	table->priv->headers[E_COMPOSER_HEADER_BCC] = header;
 
-	header = e_composer_post_header_new (_("_Post To:"));
+	header = e_composer_post_header_new (registry, _("_Post To:"));
 	composer_header_table_bind_header ("post-to", "changed", header);
 	table->priv->headers[E_COMPOSER_HEADER_POST_TO] = header;
 
-	header = e_composer_spell_header_new_label (_("S_ubject:"));
+	header = e_composer_spell_header_new_label (registry, _("S_ubject:"));
 	composer_header_table_bind_header ("subject", "changed", header);
 	table->priv->headers[E_COMPOSER_HEADER_SUBJECT] = header;
 
-	widget = e_signature_combo_box_new ();
-	composer_header_table_bind_widget ("signature", "changed", widget);
-	composer_header_table_bind_widget ("signature-list", "refreshed", widget);
+	widget = e_mail_signature_combo_box_new (registry);
+	composer_header_table_bind_widget ("signature-uid", "changed", widget);
 	table->priv->signature_combo_box = g_object_ref_sink (widget);
 
 	widget = gtk_label_new_with_mnemonic (_("Si_gnature:"));
@@ -823,20 +895,6 @@ composer_header_table_constructed (GObject *object)
 		GTK_LABEL (widget), table->priv->signature_combo_box);
 	table->priv->signature_label = g_object_ref_sink (widget);
 
-	/* XXX EComposerHeader ought to do this itself, but I need to
-	 *     make the title_widget and input_widget members private. */
-	for (ii = 0; ii < E_COMPOSER_NUM_HEADERS; ii++) {
-		header = table->priv->headers[ii];
-		g_object_bind_property (
-			header, "visible",
-			header->title_widget, "visible",
-			G_BINDING_SYNC_CREATE);
-		g_object_bind_property (
-			header, "visible",
-			header->input_widget, "visible",
-			G_BINDING_SYNC_CREATE);
-	}
-
 	/* Use "ypadding" instead of "row-spacing" because some rows may
 	 * be invisible and we don't want spacing around them. */
 
@@ -899,6 +957,9 @@ composer_header_table_constructed (GObject *object)
 			3, 4, ii, ii + 1, GTK_FILL, 0, 0, row_padding);
 		gtk_widget_hide (box);
 	}
+
+	/* Initialize the headers. */
+	composer_header_table_from_changed_cb (table);
 }
 
 static void
@@ -915,36 +976,6 @@ e_composer_header_table_class_init (EComposerHeaderTableClass *class)
 	object_class->dispose = composer_header_table_dispose;
 	object_class->constructed = composer_header_table_constructed;
 
-	g_object_class_install_property (
-		object_class,
-		PROP_ACCOUNT,
-		g_param_spec_object (
-			"account",
-			NULL,
-			NULL,
-			E_TYPE_ACCOUNT,
-			G_PARAM_READWRITE));
-
-	g_object_class_install_property (
-		object_class,
-		PROP_ACCOUNT_LIST,
-		g_param_spec_object (
-			"account-list",
-			NULL,
-			NULL,
-			E_TYPE_ACCOUNT_LIST,
-			G_PARAM_READWRITE));
-
-	g_object_class_install_property (
-		object_class,
-		PROP_ACCOUNT_NAME,
-		g_param_spec_string (
-			"account-name",
-			NULL,
-			NULL,
-			NULL,
-			G_PARAM_READWRITE));
-
 	/* floating reference */
 	element_spec = g_param_spec_object (
 		"value-array-element",
@@ -987,6 +1018,17 @@ e_composer_header_table_class_init (EComposerHeaderTableClass *class)
 			G_PARAM_READWRITE |
 			G_PARAM_STATIC_STRINGS));
 
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_UID,
+		g_param_spec_string (
+			"identity-uid",
+			NULL,
+			NULL,
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
 	/* floating reference */
 	element_spec = g_param_spec_string (
 		"value-array-element",
@@ -1009,6 +1051,18 @@ e_composer_header_table_class_init (EComposerHeaderTableClass *class)
 
 	g_object_class_install_property (
 		object_class,
+		PROP_REGISTRY,
+		g_param_spec_object (
+			"registry",
+			NULL,
+			NULL,
+			E_TYPE_SOURCE_REGISTRY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
 		PROP_REPLY_TO,
 		g_param_spec_string (
 			"reply-to",
@@ -1032,23 +1086,23 @@ e_composer_header_table_class_init (EComposerHeaderTableClass *class)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_SIGNATURE,
-		g_param_spec_object (
-			"signature",
+		PROP_SIGNATURE_COMBO_BOX,
+		g_param_spec_string (
+			"signature-combo-box",
 			NULL,
 			NULL,
-			E_TYPE_SIGNATURE,
-			G_PARAM_READWRITE |
+			NULL,
+			G_PARAM_READABLE |
 			G_PARAM_STATIC_STRINGS));
 
 	g_object_class_install_property (
 		object_class,
-		PROP_SIGNATURE_LIST,
-		g_param_spec_object (
-			"signature-list",
+		PROP_SIGNATURE_UID,
+		g_param_spec_string (
+			"signature-uid",
+			NULL,
 			NULL,
 			NULL,
-			E_TYPE_SIGNATURE_LIST,
 			G_PARAM_READWRITE |
 			G_PARAM_STATIC_STRINGS));
 
@@ -1095,13 +1149,15 @@ e_composer_header_table_init (EComposerHeaderTable *table)
 }
 
 GtkWidget *
-e_composer_header_table_new (EShell *shell)
+e_composer_header_table_new (EShell *shell,
+                             ESourceRegistry *registry)
 {
 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
 	return g_object_new (
 		E_TYPE_COMPOSER_HEADER_TABLE,
-		"shell", shell, NULL);
+		"shell", shell, "registry", registry, NULL);
 }
 
 EShell *
@@ -1112,113 +1168,30 @@ e_composer_header_table_get_shell (EComposerHeaderTable *table)
 	return table->priv->shell;
 }
 
-EComposerHeader *
-e_composer_header_table_get_header (EComposerHeaderTable *table,
-                                    EComposerHeaderType type)
-{
-	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
-	g_return_val_if_fail (type < E_COMPOSER_NUM_HEADERS, NULL);
-
-	return table->priv->headers[type];
-}
-
-EAccount *
-e_composer_header_table_get_account (EComposerHeaderTable *table)
+ESourceRegistry *
+e_composer_header_table_get_registry (EComposerHeaderTable *table)
 {
-	EComposerHeader *header;
-	EComposerHeaderType type;
-	EComposerFromHeader *from_header;
-
 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
 
-	type = E_COMPOSER_HEADER_FROM;
-	header = e_composer_header_table_get_header (table, type);
-	from_header = E_COMPOSER_FROM_HEADER (header);
-
-	return e_composer_from_header_get_active (from_header);
-}
-
-gboolean
-e_composer_header_table_set_account (EComposerHeaderTable *table,
-                                     EAccount *account)
-{
-	EComposerHeader *header;
-	EComposerHeaderType type;
-	EComposerFromHeader *from_header;
-
-	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), FALSE);
-
-	type = E_COMPOSER_HEADER_FROM;
-	header = e_composer_header_table_get_header (table, type);
-	from_header = E_COMPOSER_FROM_HEADER (header);
-
-	return e_composer_from_header_set_active (from_header, account);
+	return table->priv->registry;
 }
 
-EAccountList *
-e_composer_header_table_get_account_list (EComposerHeaderTable *table)
+EComposerHeader *
+e_composer_header_table_get_header (EComposerHeaderTable *table,
+                                    EComposerHeaderType type)
 {
-	EComposerHeader *header;
-	EComposerHeaderType type;
-	EComposerFromHeader *from_header;
-
 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
+	g_return_val_if_fail (type < E_COMPOSER_NUM_HEADERS, NULL);
 
-	type = E_COMPOSER_HEADER_FROM;
-	header = e_composer_header_table_get_header (table, type);
-	from_header = E_COMPOSER_FROM_HEADER (header);
-
-	return e_composer_from_header_get_account_list (from_header);
-}
-
-void
-e_composer_header_table_set_account_list (EComposerHeaderTable *table,
-                                          EAccountList *account_list)
-{
-	EComposerHeader *header;
-	EComposerHeaderType type;
-	EComposerFromHeader *from_header;
-
-	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
-
-	type = E_COMPOSER_HEADER_FROM;
-	header = e_composer_header_table_get_header (table, type);
-	from_header = E_COMPOSER_FROM_HEADER (header);
-
-	e_composer_from_header_set_account_list (from_header, account_list);
+	return table->priv->headers[type];
 }
 
-const gchar *
-e_composer_header_table_get_account_name (EComposerHeaderTable *table)
+EMailSignatureComboBox *
+e_composer_header_table_get_signature_combo_box (EComposerHeaderTable *table)
 {
-	EComposerHeader *header;
-	EComposerHeaderType type;
-	EComposerFromHeader *from_header;
-
 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
 
-	type = E_COMPOSER_HEADER_FROM;
-	header = e_composer_header_table_get_header (table, type);
-	from_header = E_COMPOSER_FROM_HEADER (header);
-
-	return e_composer_from_header_get_active_name (from_header);
-}
-
-gboolean
-e_composer_header_table_set_account_name (EComposerHeaderTable *table,
-                                          const gchar *account_name)
-{
-	EComposerHeader *header;
-	EComposerHeaderType type;
-	EComposerFromHeader *from_header;
-
-	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), FALSE);
-
-	type = E_COMPOSER_HEADER_FROM;
-	header = e_composer_header_table_get_header (table, type);
-	from_header = E_COMPOSER_FROM_HEADER (header);
-
-	return e_composer_from_header_set_active_name (from_header, account_name);
+	return E_MAIL_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
 }
 
 EDestination **
@@ -1423,6 +1396,39 @@ e_composer_header_table_set_destinations_to (EComposerHeaderTable *table,
 	e_composer_name_header_set_destinations (name_header, destinations);
 }
 
+const gchar *
+e_composer_header_table_get_identity_uid (EComposerHeaderTable *table)
+{
+	EComposerHeader *header;
+	EComposerHeaderType type;
+	EComposerFromHeader *from_header;
+
+	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
+
+	type = E_COMPOSER_HEADER_FROM;
+	header = e_composer_header_table_get_header (table, type);
+	from_header = E_COMPOSER_FROM_HEADER (header);
+
+	return e_composer_from_header_get_active_id (from_header);
+}
+
+void
+e_composer_header_table_set_identity_uid (EComposerHeaderTable *table,
+                                          const gchar *identity_uid)
+{
+	EComposerHeader *header;
+	EComposerHeaderType type;
+	EComposerFromHeader *from_header;
+
+	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
+
+	type = E_COMPOSER_HEADER_FROM;
+	header = e_composer_header_table_get_header (table, type);
+	from_header = E_COMPOSER_FROM_HEADER (header);
+
+	e_composer_from_header_set_active_id (from_header, identity_uid);
+}
+
 GList *
 e_composer_header_table_get_post_to (EComposerHeaderTable *table)
 {
@@ -1510,50 +1516,29 @@ e_composer_header_table_set_reply_to (EComposerHeaderTable *table,
 		e_composer_header_set_visible (header, TRUE);
 }
 
-ESignature *
-e_composer_header_table_get_signature (EComposerHeaderTable *table)
+const gchar *
+e_composer_header_table_get_signature_uid (EComposerHeaderTable *table)
 {
-	ESignatureComboBox *combo_box;
+	EMailSignatureComboBox *combo_box;
 
 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
 
-	combo_box = E_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
-	return e_signature_combo_box_get_active (combo_box);
-}
-
-gboolean
-e_composer_header_table_set_signature (EComposerHeaderTable *table,
-                                       ESignature *signature)
-{
-	ESignatureComboBox *combo_box;
+	combo_box = e_composer_header_table_get_signature_combo_box (table);
 
-	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), FALSE);
-
-	combo_box = E_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
-	return e_signature_combo_box_set_active (combo_box, signature);
-}
-
-ESignatureList *
-e_composer_header_table_get_signature_list (EComposerHeaderTable *table)
-{
-	ESignatureComboBox *combo_box;
-
-	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
-
-	combo_box = E_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
-	return e_signature_combo_box_get_signature_list (combo_box);
+	return gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
 }
 
 void
-e_composer_header_table_set_signature_list (EComposerHeaderTable *table,
-                                            ESignatureList *signature_list)
+e_composer_header_table_set_signature_uid (EComposerHeaderTable *table,
+                                           const gchar *signature_uid)
 {
-	ESignatureComboBox *combo_box;
+	EMailSignatureComboBox *combo_box;
 
 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
 
-	combo_box = E_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
-	e_signature_combo_box_set_signature_list (combo_box, signature_list);
+	combo_box = e_composer_header_table_get_signature_combo_box (table);
+
+	gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), signature_uid);
 }
 
 const gchar *
diff --git a/composer/e-composer-header-table.h b/composer/e-composer-header-table.h
index 9d6a83f..b76e9b6 100644
--- a/composer/e-composer-header-table.h
+++ b/composer/e-composer-header-table.h
@@ -18,14 +18,11 @@
 #ifndef E_COMPOSER_HEADER_TABLE_H
 #define E_COMPOSER_HEADER_TABLE_H
 
-#include <libedataserver/e-account.h>
-#include <libedataserver/e-account-list.h>
 #include <libebook/e-destination.h>
 
 #include <shell/e-shell.h>
 #include <composer/e-composer-header.h>
-#include <libemail-utils/e-signature.h>
-#include <libemail-utils/e-signature-list.h>
+#include <misc/e-mail-signature-combo-box.h>
 
 /* Standard GObject macros */
 #define E_TYPE_COMPOSER_HEADER_TABLE \
@@ -74,28 +71,20 @@ struct _EComposerHeaderTableClass {
 };
 
 GType		e_composer_header_table_get_type (void);
-GtkWidget *	e_composer_header_table_new	(EShell *shell);
+GtkWidget *	e_composer_header_table_new	(EShell *shell,
+						 ESourceRegistry *registry);
 EShell *	e_composer_header_table_get_shell
 						(EComposerHeaderTable *table);
+ESourceRegistry *
+		e_composer_header_table_get_registry
+						(EComposerHeaderTable *table);
 EComposerHeader *
 		e_composer_header_table_get_header
 						(EComposerHeaderTable *table,
 						 EComposerHeaderType type);
-EAccount *	e_composer_header_table_get_account
-						(EComposerHeaderTable *table);
-gboolean	e_composer_header_table_set_account
-						(EComposerHeaderTable *table,
-						 EAccount *account);
-EAccountList *	e_composer_header_table_get_account_list
-						(EComposerHeaderTable *table);
-void		e_composer_header_table_set_account_list
-						(EComposerHeaderTable *table,
-						 EAccountList *account_list);
-const gchar *	e_composer_header_table_get_account_name
+EMailSignatureComboBox *
+		e_composer_header_table_get_signature_combo_box
 						(EComposerHeaderTable *table);
-gboolean	e_composer_header_table_set_account_name
-						(EComposerHeaderTable *table,
-						 const gchar *account_name);
 EDestination ** e_composer_header_table_get_destinations
 						(EComposerHeaderTable *table);
 EDestination **	e_composer_header_table_get_destinations_bcc
@@ -122,6 +111,11 @@ void		e_composer_header_table_add_destinations_to
 void		e_composer_header_table_set_destinations_to
 						(EComposerHeaderTable *table,
 						 EDestination **destinations);
+const gchar *	e_composer_header_table_get_identity_uid
+						(EComposerHeaderTable *table);
+void		e_composer_header_table_set_identity_uid
+						(EComposerHeaderTable *table,
+						 const gchar *identity_uid);
 GList *		e_composer_header_table_get_post_to
 						(EComposerHeaderTable *table);
 void		e_composer_header_table_set_post_to_base
@@ -136,16 +130,11 @@ const gchar *	e_composer_header_table_get_reply_to
 void		e_composer_header_table_set_reply_to
 						(EComposerHeaderTable *table,
 						 const gchar *reply_to);
-ESignature *	e_composer_header_table_get_signature
-						(EComposerHeaderTable *table);
-gboolean	e_composer_header_table_set_signature
-						(EComposerHeaderTable *table,
-						 ESignature *signature);
-ESignatureList *e_composer_header_table_get_signature_list
+const gchar *	e_composer_header_table_get_signature_uid
 						(EComposerHeaderTable *table);
-void		e_composer_header_table_set_signature_list
+void		e_composer_header_table_set_signature_uid
 						(EComposerHeaderTable *table,
-						 ESignatureList *signature_list);
+						 const gchar *signature_uid);
 const gchar *	e_composer_header_table_get_subject
 						(EComposerHeaderTable *table);
 void		e_composer_header_table_set_subject
diff --git a/composer/e-composer-header.c b/composer/e-composer-header.c
index c92b069..5ef5e41 100644
--- a/composer/e-composer-header.c
+++ b/composer/e-composer-header.c
@@ -36,12 +36,8 @@
 struct _EComposerHeaderPrivate {
 	gchar *label;
 	gboolean button;
-	GtkWidget *action_label;
 
-	GtkWidget *add_icon;
-	GtkWidget *remove_icon;
-	GtkWidget *show_label;
-	GtkWidget *hide_label;
+	ESourceRegistry *registry;
 
 	guint sensitive : 1;
 	guint visible   : 1;
@@ -55,6 +51,7 @@ enum {
 	PROP_0,
 	PROP_BUTTON,
 	PROP_LABEL,
+	PROP_REGISTRY,
 	PROP_SENSITIVE,
 	PROP_VISIBLE
 };
@@ -80,48 +77,14 @@ composer_header_button_clicked_cb (GtkButton *button,
 	g_signal_emit (header, signal_ids[CLICKED], 0);
 }
 
-static GObject *
-composer_header_constructor (GType type,
-                             guint n_construct_properties,
-                             GObjectConstructParam *construct_properties)
+static void
+composer_header_set_registry (EComposerHeader *header,
+                              ESourceRegistry *registry)
 {
-	GObject *object;
-	GtkWidget *widget;
-	EComposerHeader *header;
-	GtkWidget *label;
-
-	/* Chain up to parent's constructor() method. */
-	object = G_OBJECT_CLASS (
-		e_composer_header_parent_class)->constructor (
-		type, n_construct_properties, construct_properties);
-
-	header = E_COMPOSER_HEADER (object);
-
-	if (header->priv->button) {
-		widget = gtk_button_new_with_mnemonic (header->priv->label);
-		gtk_widget_set_can_focus (widget, FALSE);
-		g_signal_connect (
-			widget, "clicked",
-			G_CALLBACK (composer_header_button_clicked_cb),
-			header);
-		label = gtk_bin_get_child (GTK_BIN (widget));
-	} else {
-		widget = gtk_label_new_with_mnemonic (header->priv->label);
-		gtk_label_set_mnemonic_widget (
-			GTK_LABEL (widget), header->input_widget);
-		label = widget;
-	}
-
-	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
-
-	header->priv->action_label = NULL;
-
-	header->title_widget = g_object_ref_sink (widget);
-
-	g_free (header->priv->label);
-	header->priv->label = NULL;
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+	g_return_if_fail (header->priv->registry == NULL);
 
-	return object;
+	header->priv->registry = g_object_ref (registry);
 }
 
 static void
@@ -143,6 +106,12 @@ composer_header_set_property (GObject *object,
 			priv->label = g_value_dup_string (value);
 			return;
 
+		case PROP_REGISTRY:
+			composer_header_set_registry (
+				E_COMPOSER_HEADER (object),
+				g_value_get_object (value));
+			return;
+
 		case PROP_SENSITIVE:
 			e_composer_header_set_sensitive (
 				E_COMPOSER_HEADER (object),
@@ -175,8 +144,12 @@ composer_header_get_property (GObject *object,
 			return;
 
 		case PROP_LABEL:	/* construct only */
-			g_value_take_string (
-				value, e_composer_header_get_label (
+			g_value_set_string (value, priv->label);
+			return;
+
+		case PROP_REGISTRY:
+			g_value_set_object (
+				value, e_composer_header_get_registry (
 				E_COMPOSER_HEADER (object)));
 			return;
 
@@ -211,11 +184,75 @@ composer_header_dispose (GObject *object)
 		header->input_widget = NULL;
 	}
 
+	if (header->priv->registry != NULL) {
+		g_object_unref (header->priv->registry);
+		header->priv->registry = NULL;
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (e_composer_header_parent_class)->dispose (object);
 }
 
 static void
+composer_header_finalize (GObject *object)
+{
+	EComposerHeaderPrivate *priv;
+
+	priv = E_COMPOSER_HEADER_GET_PRIVATE (object);
+
+	g_free (priv->label);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_composer_header_parent_class)->finalize (object);
+}
+
+static void
+composer_header_constructed (GObject *object)
+{
+	EComposerHeader *header;
+	GtkWidget *widget;
+	GtkWidget *label;
+
+	header = E_COMPOSER_HEADER (object);
+
+	if (header->input_widget == NULL) {
+		g_critical (
+			"EComposerHeader's input_widget "
+			"must be set before chaining up");
+		return;
+	}
+
+	if (header->priv->button) {
+		widget = gtk_button_new_with_mnemonic (header->priv->label);
+		gtk_widget_set_can_focus (widget, FALSE);
+		g_signal_connect (
+			widget, "clicked",
+			G_CALLBACK (composer_header_button_clicked_cb),
+			header);
+		label = gtk_bin_get_child (GTK_BIN (widget));
+	} else {
+		widget = gtk_label_new_with_mnemonic (header->priv->label);
+		gtk_label_set_mnemonic_widget (
+			GTK_LABEL (widget), header->input_widget);
+		label = widget;
+	}
+
+	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+
+	header->title_widget = g_object_ref_sink (widget);
+
+	g_object_bind_property (
+		header, "visible",
+		header->title_widget, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		header, "visible",
+		header->input_widget, "visible",
+		G_BINDING_SYNC_CREATE);
+}
+
+static void
 e_composer_header_class_init (EComposerHeaderClass *class)
 {
 	GObjectClass *object_class;
@@ -223,10 +260,11 @@ e_composer_header_class_init (EComposerHeaderClass *class)
 	g_type_class_add_private (class, sizeof (EComposerHeaderPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->constructor = composer_header_constructor;
 	object_class->set_property = composer_header_set_property;
 	object_class->get_property = composer_header_get_property;
 	object_class->dispose = composer_header_dispose;
+	object_class->finalize = composer_header_finalize;
+	object_class->constructed = composer_header_constructed;
 
 	g_object_class_install_property (
 		object_class,
@@ -254,6 +292,18 @@ e_composer_header_class_init (EComposerHeaderClass *class)
 
 	g_object_class_install_property (
 		object_class,
+		PROP_REGISTRY,
+		g_param_spec_object (
+			"registry",
+			NULL,
+			NULL,
+			E_TYPE_SOURCE_REGISTRY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
 		PROP_SENSITIVE,
 		g_param_spec_boolean (
 			"sensitive",
@@ -299,17 +349,20 @@ e_composer_header_init (EComposerHeader *header)
 	header->priv = E_COMPOSER_HEADER_GET_PRIVATE (header);
 }
 
-gchar *
+const gchar *
 e_composer_header_get_label (EComposerHeader *header)
 {
-	gchar *label;
-
 	g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), NULL);
 
-	/* GtkButton and GtkLabel both have a "label" property. */
-	g_object_get (header->title_widget, "label", &label, NULL);
+	return header->priv->label;
+}
 
-	return label;
+ESourceRegistry *
+e_composer_header_get_registry (EComposerHeader *header)
+{
+	g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), NULL);
+
+	return header->priv->registry;
 }
 
 gboolean
@@ -347,20 +400,6 @@ e_composer_header_set_visible (EComposerHeader *header,
 
 	header->priv->visible = visible;
 
-	if (header->priv->action_label) {
-		if (!visible) {
-			gtk_widget_show (header->priv->add_icon);
-			gtk_widget_show (header->priv->show_label);
-			gtk_widget_hide (header->priv->remove_icon);
-			gtk_widget_hide (header->priv->hide_label);
-		} else {
-			gtk_widget_hide (header->priv->add_icon);
-			gtk_widget_hide (header->priv->show_label);
-			gtk_widget_show (header->priv->remove_icon);
-			gtk_widget_show (header->priv->hide_label);
-		}
-	}
-
 	g_object_notify (G_OBJECT (header), "visible");
 }
 
diff --git a/composer/e-composer-header.h b/composer/e-composer-header.h
index 08db97a..24bfb7d 100644
--- a/composer/e-composer-header.h
+++ b/composer/e-composer-header.h
@@ -19,6 +19,7 @@
 #define E_COMPOSER_HEADER_H
 
 #include <composer/e-composer-common.h>
+#include <libedataserver/e-source-registry.h>
 
 /* Standard GObject macros */
 #define E_TYPE_COMPOSER_HEADER \
@@ -61,7 +62,9 @@ struct _EComposerHeaderClass {
 };
 
 GType		e_composer_header_get_type	(void);
-gchar *		e_composer_header_get_label	(EComposerHeader *header);
+const gchar *	e_composer_header_get_label	(EComposerHeader *header);
+ESourceRegistry *
+		e_composer_header_get_registry	(EComposerHeader *header);
 gboolean	e_composer_header_get_sensitive	(EComposerHeader *header);
 void		e_composer_header_set_sensitive	(EComposerHeader *header,
 						 gboolean sensitive);
diff --git a/composer/e-composer-name-header.c b/composer/e-composer-name-header.c
index 740ecee..3857f39 100644
--- a/composer/e-composer-name-header.c
+++ b/composer/e-composer-name-header.c
@@ -110,63 +110,6 @@ composer_name_header_entry_query_tooltip_cb (GtkEntry *entry,
 	return TRUE;
 }
 
-static GObject *
-composer_name_header_constructor (GType type,
-                                  guint n_construct_properties,
-                                  GObjectConstructParam *construct_properties)
-{
-	EComposerNameHeaderPrivate *priv;
-	ENameSelectorModel *model;
-	ENameSelectorEntry *entry;
-	GObject *object;
-	GList *sections;
-	gchar *label;
-
-	/* Chain up to parent's constructor() method. */
-	object = G_OBJECT_CLASS (
-		e_composer_name_header_parent_class)->constructor (
-		type, n_construct_properties, construct_properties);
-
-	priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
-	g_assert (E_IS_NAME_SELECTOR (priv->name_selector));
-
-	model = e_name_selector_peek_model (priv->name_selector);
-	label = e_composer_header_get_label (E_COMPOSER_HEADER (object));
-	g_assert (label != NULL);
-
-	sections = e_name_selector_model_list_sections (model);
-	priv->destination_index = g_list_length (sections);
-	e_name_selector_model_add_section (model, label, label, NULL);
-	g_list_foreach (sections, (GFunc) g_free, NULL);
-	g_list_free (sections);
-
-	e_composer_header_set_title_tooltip (
-		E_COMPOSER_HEADER (object),
-		_("Click here for the address book"));
-
-	entry = E_NAME_SELECTOR_ENTRY (
-		e_name_selector_peek_section_list (
-		priv->name_selector, label));
-
-	e_name_selector_entry_set_contact_editor_func (
-		entry, contact_editor_fudge_new);
-	e_name_selector_entry_set_contact_list_editor_func (
-		entry, contact_list_editor_fudge_new);
-
-	g_signal_connect (
-		entry, "changed",
-		G_CALLBACK (composer_name_header_entry_changed_cb), object);
-	g_signal_connect (
-		entry, "query-tooltip",
-		G_CALLBACK (composer_name_header_entry_query_tooltip_cb),
-		NULL);
-	E_COMPOSER_HEADER (object)->input_widget = g_object_ref_sink (entry);
-
-	g_free (label);
-
-	return object;
-}
-
 static void
 composer_name_header_set_property (GObject *object,
                                    guint property_id,
@@ -222,6 +165,57 @@ composer_name_header_dispose (GObject *object)
 }
 
 static void
+composer_name_header_constructed (GObject *object)
+{
+	EComposerNameHeaderPrivate *priv;
+	ENameSelectorModel *model;
+	ENameSelectorEntry *entry;
+	GList *sections;
+	const gchar *label;
+
+	/* Input widget must be set before chaining up. */
+
+	priv = E_COMPOSER_NAME_HEADER_GET_PRIVATE (object);
+	g_assert (E_IS_NAME_SELECTOR (priv->name_selector));
+
+	model = e_name_selector_peek_model (priv->name_selector);
+	label = e_composer_header_get_label (E_COMPOSER_HEADER (object));
+	g_assert (label != NULL);
+
+	sections = e_name_selector_model_list_sections (model);
+	priv->destination_index = g_list_length (sections);
+	e_name_selector_model_add_section (model, label, label, NULL);
+	g_list_foreach (sections, (GFunc) g_free, NULL);
+	g_list_free (sections);
+
+	entry = E_NAME_SELECTOR_ENTRY (
+		e_name_selector_peek_section_list (
+		priv->name_selector, label));
+
+	e_name_selector_entry_set_contact_editor_func (
+		entry, contact_editor_fudge_new);
+	e_name_selector_entry_set_contact_list_editor_func (
+		entry, contact_list_editor_fudge_new);
+
+	g_signal_connect (
+		entry, "changed",
+		G_CALLBACK (composer_name_header_entry_changed_cb), object);
+	g_signal_connect (
+		entry, "query-tooltip",
+		G_CALLBACK (composer_name_header_entry_query_tooltip_cb),
+		NULL);
+	E_COMPOSER_HEADER (object)->input_widget = g_object_ref_sink (entry);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_composer_name_header_parent_class)->
+		constructed (object);
+
+	e_composer_header_set_title_tooltip (
+		E_COMPOSER_HEADER (object),
+		_("Click here for the address book"));
+}
+
+static void
 composer_name_header_clicked (EComposerHeader *header)
 {
 	EComposerNameHeaderPrivate *priv;
@@ -247,10 +241,10 @@ e_composer_name_header_class_init (EComposerNameHeaderClass *class)
 	g_type_class_add_private (class, sizeof (EComposerNameHeaderPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->constructor = composer_name_header_constructor;
 	object_class->set_property = composer_name_header_set_property;
 	object_class->get_property = composer_name_header_get_property;
 	object_class->dispose = composer_name_header_dispose;
+	object_class->constructed = composer_name_header_constructed;
 
 	header_class = E_COMPOSER_HEADER_CLASS (class);
 	header_class->clicked = composer_name_header_clicked;
@@ -274,16 +268,18 @@ e_composer_name_header_init (EComposerNameHeader *header)
 }
 
 EComposerHeader *
-e_composer_name_header_new (const gchar *label,
+e_composer_name_header_new (ESourceRegistry *registry,
+                            const gchar *label,
                             ENameSelector *name_selector)
 {
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 	g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
 
 	return g_object_new (
 		E_TYPE_COMPOSER_NAME_HEADER,
 		"label", label, "button", TRUE,
 		"name-selector", name_selector,
-		 NULL);
+		"registry", registry, NULL);
 }
 
 ENameSelector *
diff --git a/composer/e-composer-name-header.h b/composer/e-composer-name-header.h
index e2f5e00..cb4dc03 100644
--- a/composer/e-composer-name-header.h
+++ b/composer/e-composer-name-header.h
@@ -58,7 +58,8 @@ struct _EComposerNameHeaderClass {
 };
 
 GType		e_composer_name_header_get_type	(void);
-EComposerHeader * e_composer_name_header_new	(const gchar *label,
+EComposerHeader * e_composer_name_header_new	(ESourceRegistry *registry,
+						 const gchar *label,
 						 ENameSelector *name_selector);
 ENameSelector *	e_composer_name_header_get_name_selector
 						(EComposerNameHeader *header);
diff --git a/composer/e-composer-post-header.c b/composer/e-composer-post-header.c
index a2a4f48..cc01324 100644
--- a/composer/e-composer-post-header.c
+++ b/composer/e-composer-post-header.c
@@ -34,11 +34,11 @@
 
 enum {
 	PROP_0,
-	PROP_ACCOUNT
+	PROP_MAIL_ACCOUNT
 };
 
 struct _EComposerPostHeaderPrivate {
-	EAccount *account;
+	ESource *mail_account;
 	gchar *base_url;  /* derived from account */
 	gboolean custom;
 };
@@ -77,26 +77,16 @@ composer_post_header_folder_name_to_string (EComposerPostHeader *header,
 static void
 composer_post_header_set_base_url (EComposerPostHeader *header)
 {
-	EAccount *account = header->priv->account;
-	CamelURL *camel_url;
-	gchar *url;
+	ESource *source;
+	const gchar *uid;
 
-	if (account == NULL || account->source == NULL)
+	source = header->priv->mail_account;
+	if (source == NULL)
 		return;
 
-	url = account->source->url;
-	if (url == NULL || *url == '\0')
-		return;
-
-	camel_url = camel_url_new (url, NULL);
-	if (camel_url == NULL)
-		return;
-
-	url = camel_url_to_string (camel_url, CAMEL_URL_HIDE_ALL);
-	camel_url_free (camel_url);
-
+	uid = e_source_get_uid (source);
 	g_free (header->priv->base_url);
-	header->priv->base_url = url;
+	header->priv->base_url = g_strdup_printf ("folder://%s", uid);
 }
 
 static GList *
@@ -118,25 +108,6 @@ composer_post_header_split_csv (const gchar *csv)
 	return g_list_reverse (list);
 }
 
-static GObject *
-composer_post_header_constructor (GType type,
-                                  guint n_construct_properties,
-                                  GObjectConstructParam *construct_properties)
-{
-	GObject *object;
-
-	/* Chain up to parent's constructor() method. */
-	object = G_OBJECT_CLASS (
-		e_composer_post_header_parent_class)->constructor (
-		type, n_construct_properties, construct_properties);
-
-	e_composer_header_set_title_tooltip (
-		E_COMPOSER_HEADER (object),
-		_("Click here to select folders to post to"));
-
-	return object;
-}
-
 static void
 composer_post_header_set_property (GObject *object,
                                    guint property_id,
@@ -144,8 +115,8 @@ composer_post_header_set_property (GObject *object,
                                    GParamSpec *pspec)
 {
 	switch (property_id) {
-		case PROP_ACCOUNT:
-			e_composer_post_header_set_account (
+		case PROP_MAIL_ACCOUNT:
+			e_composer_post_header_set_mail_account (
 				E_COMPOSER_POST_HEADER (object),
 				g_value_get_object (value));
 			return;
@@ -161,9 +132,10 @@ composer_post_header_get_property (GObject *object,
                                    GParamSpec *pspec)
 {
 	switch (property_id) {
-		case PROP_ACCOUNT:
+		case PROP_MAIL_ACCOUNT:
 			g_value_set_object (
-				value, e_composer_post_header_get_account (
+				value,
+				e_composer_post_header_get_mail_account (
 				E_COMPOSER_POST_HEADER (object)));
 			return;
 	}
@@ -178,9 +150,9 @@ composer_post_header_dispose (GObject *object)
 
 	priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (object);
 
-	if (priv->account != NULL) {
-		g_object_unref (priv->account);
-		priv->account = NULL;
+	if (priv->mail_account != NULL) {
+		g_object_unref (priv->mail_account);
+		priv->mail_account = NULL;
 	}
 
 	/* Chain up to parent's dispose() method. */
@@ -201,6 +173,18 @@ composer_post_header_finalize (GObject *object)
 }
 
 static void
+composer_post_header_constructed (GObject *object)
+{
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_composer_post_header_parent_class)->
+		constructed (object);
+
+	e_composer_header_set_title_tooltip (
+		E_COMPOSER_HEADER (object),
+		_("Click here to select folders to post to"));
+}
+
+static void
 composer_post_header_changed (EComposerHeader *header)
 {
 	EComposerPostHeaderPrivate *priv;
@@ -229,11 +213,11 @@ e_composer_post_header_class_init (EComposerPostHeaderClass *class)
 	g_type_class_add_private (class, sizeof (EComposerPostHeaderPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->constructor = composer_post_header_constructor;
 	object_class->set_property = composer_post_header_set_property;
 	object_class->get_property = composer_post_header_get_property;
 	object_class->dispose = composer_post_header_dispose;
 	object_class->finalize = composer_post_header_finalize;
+	object_class->constructed = composer_post_header_constructed;
 
 	header_class = E_COMPOSER_HEADER_CLASS (class);
 	header_class->changed = composer_post_header_changed;
@@ -241,12 +225,12 @@ e_composer_post_header_class_init (EComposerPostHeaderClass *class)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_ACCOUNT,
+		PROP_MAIL_ACCOUNT,
 		g_param_spec_object (
-			"account",
+			"mail-account",
 			NULL,
 			NULL,
-			E_TYPE_ACCOUNT,
+			E_TYPE_SOURCE,
 			G_PARAM_READWRITE));
 }
 
@@ -257,51 +241,15 @@ e_composer_post_header_init (EComposerPostHeader *header)
 }
 
 EComposerHeader *
-e_composer_post_header_new (const gchar *label)
+e_composer_post_header_new (ESourceRegistry *registry,
+                            const gchar *label)
 {
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	return g_object_new (
 		E_TYPE_COMPOSER_POST_HEADER,
-		"label", label, "button", TRUE, NULL);
-}
-
-EAccount *
-e_composer_post_header_get_account (EComposerPostHeader *header)
-{
-	g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL);
-
-	return header->priv->account;
-}
-
-void
-e_composer_post_header_set_account (EComposerPostHeader *header,
-                                    EAccount *account)
-{
-	GList *folders = NULL;
-
-	g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header));
-
-	if (account != NULL) {
-		g_return_if_fail (E_IS_ACCOUNT (account));
-		g_object_ref (account);
-	}
-
-	if (!header->priv->custom)
-		folders = e_composer_post_header_get_folders (header);
-
-	if (header->priv->account != NULL)
-		g_object_unref (header->priv->account);
-
-	header->priv->account = account;
-	composer_post_header_set_base_url (header);
-
-	/* Make folders relative to the new account. */
-	if (!header->priv->custom) {
-		e_composer_post_header_set_folders (header, folders);
-		g_list_foreach (folders, (GFunc) g_free, NULL);
-		g_list_free (folders);
-	}
-
-	g_object_notify (G_OBJECT (header), "account");
+		"label", label, "button", TRUE,
+		"registry", registry, NULL);
 }
 
 GList *
@@ -385,3 +333,43 @@ e_composer_post_header_set_folders_base (EComposerPostHeader *header,
 	g_list_foreach (list, (GFunc) g_free, NULL);
 	g_list_free (list);
 }
+
+ESource *
+e_composer_post_header_get_mail_account (EComposerPostHeader *header)
+{
+	g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL);
+
+	return header->priv->mail_account;
+}
+
+void
+e_composer_post_header_set_mail_account (EComposerPostHeader *header,
+                                         ESource *mail_account)
+{
+	GList *folders = NULL;
+
+	g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header));
+
+	if (mail_account != NULL) {
+		g_return_if_fail (E_IS_SOURCE (mail_account));
+		g_object_ref (mail_account);
+	}
+
+	if (!header->priv->custom)
+		folders = e_composer_post_header_get_folders (header);
+
+	if (header->priv->mail_account != NULL)
+		g_object_unref (header->priv->mail_account);
+
+	header->priv->mail_account = mail_account;
+	composer_post_header_set_base_url (header);
+
+	/* Make folders relative to the new account. */
+	if (!header->priv->custom) {
+		e_composer_post_header_set_folders (header, folders);
+		g_list_foreach (folders, (GFunc) g_free, NULL);
+		g_list_free (folders);
+	}
+
+	g_object_notify (G_OBJECT (header), "mail-account");
+}
diff --git a/composer/e-composer-post-header.h b/composer/e-composer-post-header.h
index c6fff3e..999f1eb 100644
--- a/composer/e-composer-post-header.h
+++ b/composer/e-composer-post-header.h
@@ -21,8 +21,6 @@
 #ifndef E_COMPOSER_POST_HEADER_H
 #define E_COMPOSER_POST_HEADER_H
 
-#include <libedataserver/e-account.h>
-
 #include <composer/e-composer-text-header.h>
 
 /* Standard GObject macros */
@@ -63,12 +61,8 @@ struct _EComposerPostHeaderClass {
 
 GType		e_composer_post_header_get_type	(void);
 EComposerHeader *
-		e_composer_post_header_new	(const gchar *label);
-EAccount *	e_composer_post_header_get_account
-						(EComposerPostHeader *header);
-void		e_composer_post_header_set_account
-						(EComposerPostHeader *header,
-						 EAccount *account);
+		e_composer_post_header_new	(ESourceRegistry *registry,
+						 const gchar *label);
 GList *		e_composer_post_header_get_folders
 						(EComposerPostHeader *header);
 void		e_composer_post_header_set_folders
@@ -78,6 +72,11 @@ void		e_composer_post_header_set_folders_base
 						(EComposerPostHeader *header,
 						 const gchar *base_url,
 						 const gchar *folders);
+ESource *	e_composer_post_header_get_mail_account
+						(EComposerPostHeader *header);
+void		e_composer_post_header_set_mail_account
+						(EComposerPostHeader *header,
+						 ESource *mail_account);
 
 G_END_DECLS
 
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index 03cfbf1..5a4ac31 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -142,6 +142,7 @@ e_composer_private_constructed (EMsgComposer *composer)
 	EShell *shell;
 	EShellSettings *shell_settings;
 	EWebViewGtkHTML *web_view;
+	ESourceRegistry *registry;
 	GtkhtmlEditor *editor;
 	GtkUIManager *ui_manager;
 	GtkAction *action;
@@ -160,6 +161,7 @@ e_composer_private_constructed (EMsgComposer *composer)
 	ui_manager = gtkhtml_editor_get_ui_manager (editor);
 
 	shell = e_msg_composer_get_shell (composer);
+	registry = e_shell_get_registry (shell);
 	shell_settings = e_shell_get_shell_settings (shell);
 	web_view = e_msg_composer_get_web_view (composer);
 	small_screen_mode = e_shell_get_small_screen_mode (shell);
@@ -283,7 +285,7 @@ e_composer_private_constructed (EMsgComposer *composer)
 
 	/* Construct the header table. */
 
-	widget = e_composer_header_table_new (shell);
+	widget = e_composer_header_table_new (shell, registry);
 	gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
 	if (small_screen_mode)
@@ -930,3 +932,210 @@ e_composer_selection_is_image_uris (EMsgComposer *composer,
 
 	return all_image_uris;
 }
+
+static gboolean
+add_signature_delimiter (EMsgComposer *composer)
+{
+	EShell *shell;
+	EShellSettings *shell_settings;
+
+	/* FIXME This preference should be an EMsgComposer property. */
+
+	shell = e_msg_composer_get_shell (composer);
+	shell_settings = e_shell_get_shell_settings (shell);
+
+	return !e_shell_settings_get_boolean (
+		shell_settings, "composer-no-signature-delim");
+}
+
+static gboolean
+use_top_signature (EMsgComposer *composer)
+{
+	EShell *shell;
+	EShellSettings *shell_settings;
+
+	/* FIXME This preference should be an EMsgComposer property. */
+
+	shell = e_msg_composer_get_shell (composer);
+	shell_settings = e_shell_get_shell_settings (shell);
+
+	return e_shell_settings_get_boolean (
+		shell_settings, "composer-top-signature");
+}
+
+static void
+composer_load_signature_cb (EMailSignatureComboBox *combo_box,
+                            GAsyncResult *result,
+                            EMsgComposer *composer)
+{
+	GString *html_buffer = NULL;
+	GtkhtmlEditor *editor;
+	gchar *contents = NULL;
+	gsize length = 0;
+	const gchar *active_id;
+	gchar *encoded_uid = NULL;
+	gboolean top_signature;
+	gboolean is_html;
+	GError *error = NULL;
+
+	e_mail_signature_combo_box_load_selected_finish (
+		combo_box, result, &contents, &length, &is_html, &error);
+
+	/* FIXME Use an EAlert here. */
+	if (error != NULL) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+		goto exit;
+	}
+
+	/* "Edit as New Message" sets "priv->is_from_message".
+	 * Always put the signature at the bottom for that case. */
+	top_signature =
+		use_top_signature (composer) &&
+		!composer->priv->is_from_message;
+
+	if (contents == NULL)
+		goto insert;
+
+	/* Generate HTML code for the signature. */
+
+	html_buffer = g_string_sized_new (1024);
+
+	/* The combo box active ID is the signature's ESource UID. */
+	active_id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
+
+	if (active_id != NULL && *active_id != '\0')
+		encoded_uid = e_composer_encode_clue_value (active_id);
+
+	g_string_append_printf (
+		html_buffer,
+		"<!--+GtkHTML:<DATA class=\"ClueFlow\" "
+		"    key=\"signature\" value=\"1\">-->"
+		"<!--+GtkHTML:<DATA class=\"ClueFlow\" "
+		"    key=\"signature_name\" value=\"uid:%s\"-->",
+		(encoded_uid != NULL) ? encoded_uid : "");
+
+	g_string_append (
+		html_buffer,
+		"<TABLE WIDTH=\"100%%\" CELLSPACING=\"0\""
+		" CELLPADDING=\"0\"><TR><TD>");
+
+	if (!is_html)
+		g_string_append (html_buffer, "<PRE>\n");
+
+	/* The signature dash convention ("-- \n") is specified
+	 * in the "Son of RFC 1036", section 4.3.2.
+	 * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html
+	 */
+	if (add_signature_delimiter (composer)) {
+		const gchar *delim;
+		const gchar *delim_nl;
+
+		if (is_html) {
+			delim = "-- \n<BR>";
+			delim_nl = "\n-- \n<BR>";
+		} else {
+			delim = "-- \n";
+			delim_nl = "\n-- \n";
+		}
+
+		/* Skip the delimiter if the signature already has one. */
+		if (g_ascii_strncasecmp (contents, delim, strlen (delim)) == 0)
+			;  /* skip */
+		else if (e_util_strstrcase (contents, delim_nl) != NULL)
+			;  /* skip */
+		else
+			g_string_append (html_buffer, delim);
+	}
+
+	g_string_append_len (html_buffer, contents, length);
+
+	if (!is_html)
+		g_string_append (html_buffer, "</PRE>\n");
+
+	if (top_signature)
+		g_string_append (html_buffer, "<BR>");
+
+	g_string_append (html_buffer, "</TD></TR></TABLE>");
+
+	g_free (encoded_uid);
+	g_free (contents);
+
+insert:
+	/* Remove the old signature and insert the new one. */
+
+	editor = GTKHTML_EDITOR (composer);
+
+	/* This prevents our command before/after callbacks from
+	 * screwing around with the signature as we insert it. */
+	composer->priv->in_signature_insert = TRUE;
+
+	gtkhtml_editor_freeze (editor);
+	gtkhtml_editor_run_command (editor, "cursor-position-save");
+	gtkhtml_editor_undo_begin (editor, "Set signature", "Reset signature");
+
+	gtkhtml_editor_run_command (editor, "block-selection");
+	gtkhtml_editor_run_command (editor, "cursor-bod");
+	if (gtkhtml_editor_search_by_data (editor, 1, "ClueFlow", "signature", "1")) {
+		gtkhtml_editor_run_command (editor, "select-paragraph");
+		gtkhtml_editor_run_command (editor, "delete");
+		gtkhtml_editor_set_paragraph_data (editor, "signature", "0");
+		gtkhtml_editor_run_command (editor, "delete-back");
+	}
+	gtkhtml_editor_run_command (editor, "unblock-selection");
+
+	if (html_buffer != NULL) {
+		gtkhtml_editor_run_command (editor, "insert-paragraph");
+		if (!gtkhtml_editor_run_command (editor, "cursor-backward"))
+			gtkhtml_editor_run_command (editor, "insert-paragraph");
+		else
+			gtkhtml_editor_run_command (editor, "cursor-forward");
+
+		gtkhtml_editor_set_paragraph_data (editor, "orig", "0");
+		gtkhtml_editor_run_command (editor, "indent-zero");
+		gtkhtml_editor_run_command (editor, "style-normal");
+		gtkhtml_editor_insert_html (editor, html_buffer->str);
+
+		g_string_free (html_buffer, TRUE);
+
+	} else if (top_signature) {
+		/* Insert paragraph after the signature ClueFlow stuff. */
+		if (gtkhtml_editor_run_command (editor, "cursor-forward"))
+			gtkhtml_editor_run_command (editor, "insert-paragraph");
+	}
+
+	gtkhtml_editor_undo_end (editor);
+	gtkhtml_editor_run_command (editor, "cursor-position-restore");
+	gtkhtml_editor_thaw (editor);
+
+	composer->priv->in_signature_insert = FALSE;
+
+exit:
+	g_object_unref (composer);
+}
+
+void
+e_composer_update_signature (EMsgComposer *composer)
+{
+	EComposerHeaderTable *table;
+	EMailSignatureComboBox *combo_box;
+
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+
+	/* Do nothing if we're redirecting a message. */
+	if (composer->priv->redirect)
+		return;
+
+	table = e_msg_composer_get_header_table (composer);
+	combo_box = e_composer_header_table_get_signature_combo_box (table);
+
+	/* XXX Signature files should be local and therefore load quickly,
+	 *     so while we do load them asynchronously we don't allow for
+	 *     user cancellation and we keep the composer alive until the
+	 *     asynchronous loading is complete. */
+	e_mail_signature_combo_box_load_selected (
+		combo_box, G_PRIORITY_DEFAULT, NULL,
+		(GAsyncReadyCallback) composer_load_signature_cb,
+		g_object_ref (composer));
+}
+
diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h
index 990c5b6..4c40872 100644
--- a/composer/e-composer-private.h
+++ b/composer/e-composer-private.h
@@ -31,6 +31,12 @@
 #include <glib/gi18n-lib.h>
 
 #include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-signature.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-openpgp.h>
+#include <libedataserver/e-source-smime.h>
 
 #include "e-composer-actions.h"
 #include "e-composer-activity.h"
@@ -48,9 +54,9 @@
 #include "widgets/misc/e-attachment-icon-view.h"
 #include "widgets/misc/e-attachment-paned.h"
 #include "widgets/misc/e-attachment-store.h"
+#include "widgets/misc/e-mail-signature-combo-box.h"
 #include "widgets/misc/e-picture-gallery.h"
 #include "widgets/misc/e-preferences-window.h"
-#include "widgets/misc/e-signature-combo-box.h"
 #include "widgets/misc/e-web-view-gtkhtml.h"
 #include "shell/e-shell.h"
 
@@ -141,6 +147,7 @@ gboolean	e_composer_paste_uris		(EMsgComposer *composer,
 gboolean	e_composer_selection_is_image_uris
 						(EMsgComposer *composer,
 						 GtkSelectionData *selection);
+void		e_composer_update_signature	(EMsgComposer *composer);
 
 G_END_DECLS
 
diff --git a/composer/e-composer-spell-header.c b/composer/e-composer-spell-header.c
index aff5dbf..ad4ddca 100644
--- a/composer/e-composer-spell-header.c
+++ b/composer/e-composer-spell-header.c
@@ -43,32 +43,38 @@ e_composer_spell_header_init (EComposerSpellHeader *header)
 }
 
 EComposerHeader *
-e_composer_spell_header_new_label (const gchar *label)
+e_composer_spell_header_new_label (ESourceRegistry *registry,
+                                   const gchar *label)
 {
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	return g_object_new (
 		E_TYPE_COMPOSER_SPELL_HEADER,
 		"label", label, "button", FALSE,
-		NULL);
+		"registry", registry, NULL);
 }
 
 EComposerHeader *
-e_composer_spell_header_new_button (const gchar *label)
+e_composer_spell_header_new_button (ESourceRegistry *registry,
+                                    const gchar *label)
 {
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	return g_object_new (
 		E_TYPE_COMPOSER_SPELL_HEADER,
 		"label", label, "button", TRUE,
-		NULL);
+		"registry", registry, NULL);
 }
 
 void
-e_composer_spell_header_set_languages (EComposerSpellHeader *spell_header,
+e_composer_spell_header_set_languages (EComposerSpellHeader *header,
                                        GList *languages)
 {
 	ESpellEntry *spell_entry;
 
-	g_return_if_fail (spell_header != NULL);
+	g_return_if_fail (header != NULL);
 
-	spell_entry = E_SPELL_ENTRY (E_COMPOSER_HEADER (spell_header)->input_widget);
+	spell_entry = E_SPELL_ENTRY (E_COMPOSER_HEADER (header)->input_widget);
 	g_return_if_fail (spell_entry != NULL);
 
 	e_spell_entry_set_languages (spell_entry, languages);
diff --git a/composer/e-composer-spell-header.h b/composer/e-composer-spell-header.h
index 44ac8d1..b8812e8 100644
--- a/composer/e-composer-spell-header.h
+++ b/composer/e-composer-spell-header.h
@@ -57,11 +57,19 @@ struct _EComposerSpellHeaderClass {
 	GType entry_type;
 };
 
-GType			e_composer_spell_header_get_type	(void);
-EComposerHeader *	e_composer_spell_header_new_label	(const gchar *label);
-EComposerHeader *	e_composer_spell_header_new_button	(const gchar *label);
-void			e_composer_spell_header_set_languages	(EComposerSpellHeader *spell_header,
-								 GList *languages);
+GType		e_composer_spell_header_get_type
+						(void) G_GNUC_CONST;
+EComposerHeader *
+		e_composer_spell_header_new_label
+						(ESourceRegistry *registry,
+						 const gchar *label);
+EComposerHeader *
+		e_composer_spell_header_new_button
+						(ESourceRegistry *registry,
+						 const gchar *label);
+void		e_composer_spell_header_set_languages
+						(EComposerSpellHeader *header,
+						 GList *languages);
 
 G_END_DECLS
 
diff --git a/composer/e-composer-text-header.c b/composer/e-composer-text-header.c
index 8506541..7bcd26d 100644
--- a/composer/e-composer-text-header.c
+++ b/composer/e-composer-text-header.c
@@ -66,17 +66,18 @@ composer_text_header_query_tooltip_cb (GtkEntry *entry,
 }
 
 static void
-e_composer_text_header_constructed (GObject *object)
+composer_text_header_constructed (GObject *object)
 {
 	GtkWidget *widget;
 	EComposerTextHeader *header;
-
-	G_OBJECT_CLASS (e_composer_text_header_parent_class)->constructed (object);
+	EComposerTextHeaderClass *class;
 
 	header = E_COMPOSER_TEXT_HEADER (object);
-	g_return_if_fail (header != NULL);
+	class = E_COMPOSER_TEXT_HEADER_GET_CLASS (header);
+
+	/* Input widget must be set before chaining up. */
 
-	widget = g_object_ref_sink (g_object_new (E_COMPOSER_TEXT_HEADER_GET_CLASS (header)->entry_type, NULL));
+	widget = g_object_new (class->entry_type, NULL);
 	g_signal_connect (
 		widget, "changed",
 		G_CALLBACK (composer_text_header_changed_cb), header);
@@ -84,7 +85,11 @@ e_composer_text_header_constructed (GObject *object)
 		widget, "query-tooltip",
 		G_CALLBACK (composer_text_header_query_tooltip_cb), NULL);
 	gtk_widget_set_has_tooltip (widget, TRUE);
-	E_COMPOSER_HEADER (header)->input_widget = widget;
+	E_COMPOSER_HEADER (object)->input_widget = g_object_ref_sink (widget);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_composer_text_header_parent_class)->
+		constructed (object);
 }
 
 static void
@@ -95,7 +100,7 @@ e_composer_text_header_class_init (EComposerTextHeaderClass *class)
 	class->entry_type = GTK_TYPE_ENTRY;
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->constructed = e_composer_text_header_constructed;
+	object_class->constructed = composer_text_header_constructed;
 }
 
 static void
@@ -104,21 +109,27 @@ e_composer_text_header_init (EComposerTextHeader *header)
 }
 
 EComposerHeader *
-e_composer_text_header_new_label (const gchar *label)
+e_composer_text_header_new_label (ESourceRegistry *registry,
+                                  const gchar *label)
 {
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	return g_object_new (
 		E_TYPE_COMPOSER_TEXT_HEADER,
 		"label", label, "button", FALSE,
-		NULL);
+		"registry", registry, NULL);
 }
 
 EComposerHeader *
-e_composer_text_header_new_button (const gchar *label)
+e_composer_text_header_new_button (ESourceRegistry *registry,
+                                   const gchar *label)
 {
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	return g_object_new (
 		E_TYPE_COMPOSER_TEXT_HEADER,
 		"label", label, "button", TRUE,
-		NULL);
+		"registry", registry, NULL);
 }
 
 const gchar *
diff --git a/composer/e-composer-text-header.h b/composer/e-composer-text-header.h
index af97e7a..5fd8c21 100644
--- a/composer/e-composer-text-header.h
+++ b/composer/e-composer-text-header.h
@@ -60,10 +60,12 @@ struct _EComposerTextHeaderClass {
 GType		e_composer_text_header_get_type	(void);
 EComposerHeader *
 		e_composer_text_header_new_label
-						(const gchar *label);
+						(ESourceRegistry *registry,
+						 const gchar *label);
 EComposerHeader *
 		e_composer_text_header_new_button
-						(const gchar *label);
+						(ESourceRegistry *registry,
+						 const gchar *label);
 const gchar *	e_composer_text_header_get_text	(EComposerTextHeader *header);
 void		e_composer_text_header_set_text (EComposerTextHeader *header,
 						 const gchar *text);
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 50c51b6..ae50482 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -42,8 +42,6 @@
 #include <e-util/e-util-private.h>
 #include <em-format/em-format.h>
 #include <em-format/em-format-quote.h>
-#include <libemail-utils/e-account-utils.h>
-#include <libemail-utils/e-signature-utils.h>
 
 #include "e-composer-private.h"
 
@@ -56,7 +54,7 @@ struct _AsyncContext {
 	CamelDataWrapper *top_level_part;
 	CamelDataWrapper *text_plain_part;
 
-	EAccount *account;
+	ESource *source;
 	CamelSession *session;
 	CamelInternetAddress *from;
 
@@ -151,8 +149,8 @@ async_context_free (AsyncContext *context)
 	if (context->text_plain_part != NULL)
 		g_object_unref (context->text_plain_part);
 
-	if (context->account != NULL)
-		g_object_unref (context->account);
+	if (context->source != NULL)
+		g_object_unref (context->source);
 
 	if (context->session != NULL)
 		g_object_unref (context->session);
@@ -515,27 +513,47 @@ build_message_headers (EMsgComposer *composer,
 {
 	EComposerHeaderTable *table;
 	EComposerHeader *header;
-	EAccount *account;
+	ESourceRegistry *registry;
+	ESource *source;
 	const gchar *subject;
 	const gchar *reply_to;
+	const gchar *uid;
 
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
 	table = e_msg_composer_get_header_table (composer);
 
+	registry = e_composer_header_table_get_registry (table);
+	uid = e_composer_header_table_get_identity_uid (table);
+	source = e_source_registry_ref_source (registry, uid);
+
 	/* Subject: */
 	subject = e_composer_header_table_get_subject (table);
 	camel_mime_message_set_subject (message, subject);
 
-	account = e_composer_header_table_get_account (table);
-	if (account != NULL) {
+	if (source != NULL) {
 		CamelMedium *medium;
 		CamelInternetAddress *addr;
+		ESourceMailIdentity *mi;
+		ESourceMailSubmission *ms;
+		const gchar *extension_name;
 		const gchar *header_name;
-		const gchar *name = account->id->name;
-		const gchar *address = account->id->address;
-		gchar *transport_uid;
+		const gchar *name, *address;
+		const gchar *transport_uid;
+		const gchar *sent_folder;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		mi = e_source_get_extension (source, extension_name);
+
+		name = e_source_mail_identity_get_name (mi);
+		address = e_source_mail_identity_get_address (mi);
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+		ms = e_source_get_extension (source, extension_name);
+
+		sent_folder = e_source_mail_submission_get_sent_folder (ms);
+		transport_uid = e_source_mail_submission_get_transport_uid (ms);
 
 		medium = CAMEL_MEDIUM (message);
 
@@ -554,18 +572,17 @@ build_message_headers (EMsgComposer *composer,
 
 		/* X-Evolution-Account */
 		header_name = "X-Evolution-Account";
-		camel_medium_set_header (medium, header_name, account->uid);
+		camel_medium_set_header (medium, header_name, uid);
 
 		/* X-Evolution-Fcc */
 		header_name = "X-Evolution-Fcc";
-		camel_medium_set_header (medium, header_name, account->sent_folder_uri);
+		camel_medium_set_header (medium, header_name, sent_folder);
 
 		/* X-Evolution-Transport */
 		header_name = "X-Evolution-Transport";
-		transport_uid = g_strconcat (
-			account->uid, "-transport", NULL);
 		camel_medium_set_header (medium, header_name, transport_uid);
-		g_free (transport_uid);
+
+		g_object_unref (source);
 	}
 
 	/* Reply-To: */
@@ -672,20 +689,27 @@ composer_build_message_pgp (AsyncContext *context,
                             GCancellable *cancellable,
                             GError **error)
 {
+	ESourceOpenPGP *extension;
 	CamelCipherContext *cipher;
 	CamelDataWrapper *content;
 	CamelMimePart *mime_part;
-	const gchar *pgp_userid;
-	gboolean have_pgp_key;
+	const gchar *extension_name;
+	const gchar *pgp_key_id;
+	const gchar *signing_algorithm;
+	gboolean always_trust;
+	gboolean encrypt_to_self;
 
 	/* Return silently if we're not signing or encrypting with PGP. */
 	if (!context->pgp_sign && !context->pgp_encrypt)
 		return TRUE;
 
-	have_pgp_key =
-		(context->account != NULL) &&
-		(context->account->pgp_key != NULL) &&
-		(context->account->pgp_key[0] != '\0');
+	extension_name = E_SOURCE_EXTENSION_OPENPGP;
+	extension = e_source_get_extension (context->source, extension_name);
+
+	always_trust = e_source_openpgp_get_always_trust (extension);
+	encrypt_to_self = e_source_openpgp_get_encrypt_to_self (extension);
+	pgp_key_id = e_source_openpgp_get_key_id (extension);
+	signing_algorithm = e_source_openpgp_get_signing_algorithm (extension);
 
 	mime_part = camel_mime_part_new ();
 
@@ -700,11 +724,9 @@ composer_build_message_pgp (AsyncContext *context,
 	g_object_unref (context->top_level_part);
 	context->top_level_part = NULL;
 
-	if (have_pgp_key)
-		pgp_userid = context->account->pgp_key;
-	else
+	if (pgp_key_id == NULL || *pgp_key_id == '\0')
 		camel_internet_address_get (
-			context->from, 0, NULL, &pgp_userid);
+			context->from, 0, NULL, &pgp_key_id);
 
 	if (context->pgp_sign) {
 		CamelMimePart *npart;
@@ -713,17 +735,12 @@ composer_build_message_pgp (AsyncContext *context,
 		npart = camel_mime_part_new ();
 
 		cipher = camel_gpg_context_new (context->session);
-		if (context->account != NULL)
-			camel_gpg_context_set_always_trust (
-				CAMEL_GPG_CONTEXT (cipher),
-				context->account->pgp_always_trust);
+		camel_gpg_context_set_always_trust (
+			CAMEL_GPG_CONTEXT (cipher), always_trust);
 
 		success = camel_cipher_context_sign_sync (
-			cipher, pgp_userid,
-			account_hash_algo_to_camel_hash (
-				(context->account != NULL) ?
-				e_account_get_string (context->account,
-				E_ACCOUNT_PGP_HASH_ALGORITHM) : NULL),
+			cipher, pgp_key_id,
+			account_hash_algo_to_camel_hash (signing_algorithm),
 			mime_part, npart, cancellable, error);
 
 		g_object_unref (cipher);
@@ -740,36 +757,28 @@ composer_build_message_pgp (AsyncContext *context,
 
 	if (context->pgp_encrypt) {
 		CamelMimePart *npart;
-		gboolean encrypt_to_self;
 		gboolean success;
 
-		encrypt_to_self =
-			(context->account != NULL) &&
-			(context->account->pgp_encrypt_to_self) &&
-			(pgp_userid != NULL);
-
 		npart = camel_mime_part_new ();
 
 		/* Check to see if we should encrypt to self.
-		 * NB gets removed immediately after use */
-		if (encrypt_to_self)
+		 * NB: Gets removed immediately after use. */
+		if (encrypt_to_self && pgp_key_id != NULL)
 			g_ptr_array_add (
 				context->recipients,
-				g_strdup (pgp_userid));
+				g_strdup (pgp_key_id));
 
 		cipher = camel_gpg_context_new (context->session);
-		if (context->account != NULL)
-			camel_gpg_context_set_always_trust (
-				CAMEL_GPG_CONTEXT (cipher),
-				context->account->pgp_always_trust);
+		camel_gpg_context_set_always_trust (
+			CAMEL_GPG_CONTEXT (cipher), always_trust);
 
 		success = camel_cipher_context_encrypt_sync (
-			cipher, pgp_userid, context->recipients,
+			cipher, pgp_key_id, context->recipients,
 			mime_part, npart, cancellable, error);
 
 		g_object_unref (cipher);
 
-		if (encrypt_to_self)
+		if (encrypt_to_self && pgp_key_id != NULL)
 			g_ptr_array_set_size (
 				context->recipients,
 				context->recipients->len - 1);
@@ -798,8 +807,14 @@ composer_build_message_smime (AsyncContext *context,
                               GCancellable *cancellable,
                               GError **error)
 {
+	ESourceSMIME *extension;
 	CamelCipherContext *cipher;
 	CamelMimePart *mime_part;
+	const gchar *extension_name;
+	const gchar *signing_algorithm;
+	const gchar *signing_certificate;
+	const gchar *encryption_certificate;
+	gboolean encrypt_to_self;
 	gboolean have_signing_certificate;
 	gboolean have_encryption_certificate;
 
@@ -807,15 +822,28 @@ composer_build_message_smime (AsyncContext *context,
 	if (!context->smime_sign && !context->smime_encrypt)
 		return TRUE;
 
+	extension_name = E_SOURCE_EXTENSION_SMIME;
+	extension = e_source_get_extension (context->source, extension_name);
+
+	encrypt_to_self =
+		e_source_smime_get_encrypt_to_self (extension);
+
+	signing_algorithm =
+		e_source_smime_get_signing_algorithm (extension);
+
+	signing_certificate =
+		e_source_smime_get_signing_certificate (extension);
+
+	encryption_certificate =
+		e_source_smime_get_encryption_certificate (extension);
+
 	have_signing_certificate =
-		(context->account != NULL) &&
-		(context->account->smime_sign_key != NULL) &&
-		(context->account->smime_sign_key[0] != '\0');
+		(signing_certificate != NULL) &&
+		(*signing_certificate != '\0');
 
 	have_encryption_certificate =
-		(context->account != NULL) &&
-		(context->account->smime_encrypt_key != NULL) &&
-		(context->account->smime_encrypt_key[0] != '\0');
+		(encryption_certificate != NULL) &&
+		(*encryption_certificate != '\0');
 
 	if (context->smime_sign && !have_signing_certificate) {
 		g_set_error (
@@ -862,20 +890,17 @@ composer_build_message_smime (AsyncContext *context,
 				(CamelSMIMEContext *) cipher,
 				CAMEL_SMIME_SIGN_ENVELOPED);
 			camel_smime_context_set_encrypt_key (
-				(CamelSMIMEContext *) cipher, TRUE,
-				context->account->smime_encrypt_key);
+				(CamelSMIMEContext *) cipher,
+				TRUE, encryption_certificate);
 		} else if (have_encryption_certificate) {
 			camel_smime_context_set_encrypt_key (
-				(CamelSMIMEContext *) cipher, TRUE,
-				context->account->smime_encrypt_key);
+				(CamelSMIMEContext *) cipher,
+				TRUE, encryption_certificate);
 		}
 
 		success = camel_cipher_context_sign_sync (
-			cipher, context->account->smime_sign_key,
-			account_hash_algo_to_camel_hash (
-				(context->account != NULL) ?
-				e_account_get_string (context->account,
-				E_ACCOUNT_SMIME_HASH_ALGORITHM) : NULL),
+			cipher, signing_certificate,
+			account_hash_algo_to_camel_hash (signing_algorithm),
 			mime_part, npart, cancellable, error);
 
 		g_object_unref (cipher);
@@ -893,16 +918,17 @@ composer_build_message_smime (AsyncContext *context,
 	if (context->smime_encrypt) {
 		gboolean success;
 
-		/* check to see if we should encrypt to self, NB removed after use */
-		if (context->account->smime_encrypt_to_self)
+		/* Check to see if we should encrypt to self.
+		 * NB: Gets removed immediately after use. */
+		if (encrypt_to_self)
 			g_ptr_array_add (
 				context->recipients, g_strdup (
-				context->account->smime_encrypt_key));
+				encryption_certificate));
 
 		cipher = camel_smime_context_new (context->session);
 		camel_smime_context_set_encrypt_key (
 			(CamelSMIMEContext *) cipher, TRUE,
-			context->account->smime_encrypt_key);
+			encryption_certificate);
 
 		success = camel_cipher_context_encrypt_sync (
 			cipher, NULL,
@@ -915,7 +941,7 @@ composer_build_message_smime (AsyncContext *context,
 		if (!success)
 			return FALSE;
 
-		if (context->account->smime_encrypt_to_self)
+		if (encrypt_to_self)
 			g_ptr_array_set_size (
 				context->recipients,
 				context->recipients->len - 1);
@@ -1033,7 +1059,12 @@ composer_build_message (EMsgComposer *composer,
 	EAttachmentStore *store;
 	EComposerHeaderTable *table;
 	CamelDataWrapper *html;
+	ESourceMailIdentity *mi;
+	ESourceRegistry *registry;
+	const gchar *extension_name;
 	const gchar *iconv_charset = NULL;
+	const gchar *identity_uid;
+	const gchar *organization;
 	CamelMultipart *body = NULL;
 	CamelContentType *type;
 	CamelSession *session;
@@ -1041,23 +1072,27 @@ composer_build_message (EMsgComposer *composer,
 	CamelStream *mem_stream;
 	CamelMimePart *part;
 	GByteArray *data;
-	EAccount *account;
+	ESource *source;
 	gchar *charset;
 	gint i;
 
 	priv = composer->priv;
 	editor = GTKHTML_EDITOR (composer);
 	table = e_msg_composer_get_header_table (composer);
-	account = e_composer_header_table_get_account (table);
 	view = e_msg_composer_get_attachment_view (composer);
 	store = e_attachment_view_get_store (view);
 	session = e_msg_composer_get_session (composer);
 
+	registry = e_composer_header_table_get_registry (table);
+	identity_uid = e_composer_header_table_get_identity_uid (table);
+	source = e_source_registry_ref_source (registry, identity_uid);
+	g_return_if_fail (source != NULL);
+
 	/* Do all the non-blocking work here, and defer
 	 * any blocking operations to a separate thread. */
 
 	context = g_slice_new0 (AsyncContext);
-	context->account = g_object_ref (account);
+	context->source = source;  /* takes the reference */
 	context->session = g_object_ref (session);
 	context->from = e_msg_composer_get_from (composer);
 
@@ -1110,16 +1145,21 @@ composer_build_message (EMsgComposer *composer,
 			priv->extra_hdr_values->pdata[i]);
 	}
 
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	mi = e_source_get_extension (source, extension_name);
+	organization = e_source_mail_identity_get_organization (mi);
+
 	/* Disposition-Notification-To */
 	if (flags & COMPOSER_FLAG_REQUEST_READ_RECEIPT) {
-		gchar *mdn_address = account->id->reply_to;
-
-		if (mdn_address == NULL || *mdn_address == '\0')
-			mdn_address = account->id->address;
-
-		camel_medium_add_header (
-			CAMEL_MEDIUM (context->message),
-			"Disposition-Notification-To", mdn_address);
+		const gchar *mdn_address;
+
+		mdn_address = e_source_mail_identity_get_reply_to (mi);
+		if (mdn_address == NULL)
+			mdn_address = e_source_mail_identity_get_address (mi);
+		if (mdn_address != NULL)
+			camel_medium_add_header (
+				CAMEL_MEDIUM (context->message),
+				"Disposition-Notification-To", mdn_address);
 	}
 
 	/* X-Priority */
@@ -1129,15 +1169,15 @@ composer_build_message (EMsgComposer *composer,
 			"X-Priority", "1");
 
 	/* Organization */
-	if (account != NULL && account->id->organization != NULL) {
-		gchar *organization;
+	if (organization != NULL && *organization != '\0') {
+		gchar *encoded_organization;
 
-		organization = camel_header_encode_string (
-			(const guchar *) account->id->organization);
+		encoded_organization = camel_header_encode_string (
+			(const guchar *) organization);
 		camel_medium_set_header (
 			CAMEL_MEDIUM (context->message),
-			"Organization", organization);
-		g_free (organization);
+			"Organization", encoded_organization);
+		g_free (encoded_organization);
 	}
 
 	/* X-Evolution-Format */
@@ -1402,7 +1442,7 @@ composer_build_message_finish (EMsgComposer *composer,
 /* Signatures */
 
 static gboolean
-is_top_signature (EMsgComposer *composer)
+use_top_signature (EMsgComposer *composer)
 {
 	EShell *shell;
 	EShellSettings *shell_settings;
@@ -1424,20 +1464,6 @@ is_top_signature (EMsgComposer *composer)
 		shell_settings, "composer-top-signature");
 }
 
-static gboolean
-add_signature_delim (EMsgComposer *composer)
-{
-	EShell *shell;
-	EShellSettings *shell_settings;
-
-	shell = e_msg_composer_get_shell (composer);
-	shell_settings = e_shell_get_shell_settings (shell);
-
-	return !e_shell_settings_get_boolean (
-		shell_settings, "composer-no-signature-delim");
-}
-
-#define CONVERT_SPACES CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES
 #define NO_SIGNATURE_TEXT	\
 	"<!--+GtkHTML:<DATA class=\"ClueFlow\" " \
 	"                     key=\"signature\" " \
@@ -1446,115 +1472,6 @@ add_signature_delim (EMsgComposer *composer)
 	"                     key=\"signature_name\" " \
 	"                   value=\"uid:Noname\">--><BR>"
 
-static gchar *
-get_signature_html (EMsgComposer *composer)
-{
-	EComposerHeaderTable *table;
-	gchar *text = NULL, *html = NULL;
-	ESignature *signature;
-	gboolean format_html, add_delim;
-
-	table = e_msg_composer_get_header_table (composer);
-	signature = e_composer_header_table_get_signature (table);
-
-	if (!signature)
-		return NULL;
-
-	add_delim = add_signature_delim (composer);
-
-	if (!e_signature_get_autogenerated (signature)) {
-		const gchar *filename;
-
-		filename = e_signature_get_filename (signature);
-		if (filename == NULL)
-			return NULL;
-
-		format_html = e_signature_get_is_html (signature);
-
-		if (e_signature_get_is_script (signature))
-			text = e_run_signature_script (filename);
-		else
-			text = e_read_signature_file (signature, TRUE, NULL);
-	} else {
-		EAccount *account;
-		EAccountIdentity *id;
-		gchar *organization = NULL;
-		gchar *address = NULL;
-		gchar *name = NULL;
-
-		account = e_composer_header_table_get_account (table);
-		if (!account)
-			return NULL;
-
-		id = account->id;
-		if (id->address != NULL)
-			address = camel_text_to_html (
-				id->address, CONVERT_SPACES, 0);
-		if (id->name != NULL)
-			name = camel_text_to_html (
-				id->name, CONVERT_SPACES, 0);
-		if (id->organization != NULL)
-			organization = camel_text_to_html (
-				id->organization, CONVERT_SPACES, 0);
-
-		text = g_strdup_printf ("%s%s%s%s%s%s%s%s%s",
-					add_delim ? "-- \n<BR>" : "",
-					name ? name : "",
-					(address && *address) ? " &lt;<A HREF=\"mailto:"; : "",
-					address ? address : "",
-					(address && *address) ? "\">" : "",
-					address ? address : "",
-					(address && *address) ? "</A>&gt;" : "",
-					(organization && *organization) ? "<BR>" : "",
-					organization ? organization : "");
-		g_free (address);
-		g_free (name);
-		g_free (organization);
-		format_html = TRUE;
-	}
-
-	/* printf ("text: %s\n", text); */
-	if (text) {
-		gchar *encoded_uid = NULL;
-		const gchar *sig_delim = format_html ? "-- \n<BR>" : "-- \n";
-		const gchar *sig_delim_ent = format_html ? "\n-- \n<BR>" : "\n-- \n";
-
-		if (signature != NULL) {
-			const gchar *uid = e_signature_get_uid (signature);
-			encoded_uid = e_composer_encode_clue_value (uid);
-		}
-
-		/* The signature dash convention ("-- \n") is specified
-		 * in the "Son of RFC 1036", section 4.3.2.
-		 * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html
-		 */
-		html = g_strdup_printf (
-			"<!--+GtkHTML:<DATA class=\"ClueFlow\" "
-			"    key=\"signature\" value=\"1\">-->"
-			"<!--+GtkHTML:<DATA class=\"ClueFlow\" "
-			"    key=\"signature_name\" value=\"uid:%s\">-->"
-			"<TABLE WIDTH=\"100%%\" CELLSPACING=\"0\""
-			" CELLPADDING=\"0\"><TR><TD>"
-			"%s%s%s%s"
-			"%s</TD></TR></TABLE>",
-			encoded_uid ? encoded_uid : "",
-			format_html ? "" : "<PRE>\n",
-			!add_delim ? "" :
-				(!strncmp (
-				sig_delim, text, strlen (sig_delim)) ||
-				strstr (text, sig_delim_ent))
-				? "" : sig_delim,
-			text,
-			format_html ? "" : "</PRE>\n",
-			is_top_signature (composer) ? "<BR>" : "");
-		g_free (text);
-		g_free (encoded_uid);
-		text = html;
-	}
-
-	return text;
-}
-
 static void
 set_editor_text (EMsgComposer *composer,
                  const gchar *text,
@@ -1579,7 +1496,9 @@ set_editor_text (EMsgComposer *composer,
 	 *
 	 */
 
-	if (is_top_signature (composer)) {
+	/* "Edit as New Message" sets "priv->is_from_message".
+	 * Always put the signature at the bottom for that case. */
+	if (!composer->priv->is_from_message && use_top_signature (composer)) {
 		/* put marker to the top */
 		body = g_strdup_printf ("<BR>" NO_SIGNATURE_TEXT "%s", text);
 	} else {
@@ -1590,7 +1509,7 @@ set_editor_text (EMsgComposer *composer,
 	gtkhtml_editor_set_text_html (GTKHTML_EDITOR (composer), body, -1);
 
 	if (set_signature)
-		e_msg_composer_show_sig_file (composer);
+		e_composer_update_signature (composer);
 
 	g_free (body);
 }
@@ -1624,43 +1543,65 @@ msg_composer_subject_changed_cb (EMsgComposer *composer)
 }
 
 static void
-msg_composer_account_changed_cb (EMsgComposer *composer)
+msg_composer_mail_identity_changed_cb (EMsgComposer *composer)
 {
 	EMsgComposerPrivate *p = composer->priv;
+	EMailSignatureComboBox *combo_box;
+	ESourceRegistry *registry;
+	ESourceMailComposition *mc;
+	ESourceOpenPGP *pgp;
+	ESourceSMIME *smime;
 	EComposerHeaderTable *table;
 	GtkToggleAction *action;
-	ESignature *signature;
-	EAccount *account;
-	gboolean active, can_sign;
+	ESource *source;
+	gboolean can_sign;
+	gboolean pgp_sign;
+	gboolean smime_sign;
+	gboolean smime_encrypt;
+	const gchar *extension_name;
 	const gchar *uid;
 
 	table = e_msg_composer_get_header_table (composer);
-	account = e_composer_header_table_get_account (table);
+	registry = e_composer_header_table_get_registry (table);
+	uid = e_composer_header_table_get_identity_uid (table);
 
-	if (account == NULL) {
-		e_msg_composer_show_sig_file (composer);
+	/* Silently return if no identity is selected. */
+	if (uid == NULL)
 		return;
-	}
 
-	can_sign = (!account->pgp_no_imip_sign || p->mime_type == NULL ||
-		g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) != 0);
+	source = e_source_registry_ref_source (registry, uid);
+	g_return_if_fail (source != NULL);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	mc = e_source_get_extension (source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_OPENPGP;
+	pgp = e_source_get_extension (source, extension_name);
+	pgp_sign = e_source_openpgp_get_sign_by_default (pgp);
+
+	extension_name = E_SOURCE_EXTENSION_SMIME;
+	smime = e_source_get_extension (source, extension_name);
+	smime_sign = e_source_smime_get_sign_by_default (smime);
+	smime_encrypt = e_source_smime_get_encrypt_by_default (smime);
+
+	can_sign =
+		(p->mime_type == NULL) ||
+		e_source_mail_composition_get_sign_imip (mc) ||
+		(g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) != 0);
 
 	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
-	active = account->pgp_always_sign && can_sign;
-	gtk_toggle_action_set_active (action, active);
+	gtk_toggle_action_set_active (action, can_sign && pgp_sign);
 
 	action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
-	active = account->smime_sign_default && can_sign;
-	gtk_toggle_action_set_active (action, active);
+	gtk_toggle_action_set_active (action, can_sign && smime_sign);
 
 	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
-	active = account->smime_encrypt_default;
-	gtk_toggle_action_set_active (action, active);
+	gtk_toggle_action_set_active (action, smime_encrypt);
+
+	combo_box = e_composer_header_table_get_signature_combo_box (table);
+	e_mail_signature_combo_box_set_identity_uid (combo_box, uid);
 
-	uid = account->id->sig_uid;
-	signature = uid ? e_get_signature_by_uid (uid) : NULL;
-	e_composer_header_table_set_signature (table, signature);
-	e_msg_composer_show_sig_file (composer);
+	g_object_unref (source);
 }
 
 static void
@@ -2066,14 +2007,6 @@ msg_composer_constructed (GObject *object)
 
 	/* Configure Headers */
 
-	e_composer_header_table_set_account_list (
-		table, e_get_account_list ());
-	e_composer_header_table_set_signature_list (
-		table, e_get_signature_list ());
-
-	g_signal_connect_swapped (
-		table, "notify::account",
-		G_CALLBACK (msg_composer_account_changed_cb), composer);
 	g_signal_connect_swapped (
 		table, "notify::destinations-bcc",
 		G_CALLBACK (msg_composer_notify_header_cb), composer);
@@ -2084,11 +2017,14 @@ msg_composer_constructed (GObject *object)
 		table, "notify::destinations-to",
 		G_CALLBACK (msg_composer_notify_header_cb), composer);
 	g_signal_connect_swapped (
+		table, "notify::identity-uid",
+		G_CALLBACK (msg_composer_mail_identity_changed_cb), composer);
+	g_signal_connect_swapped (
 		table, "notify::reply-to",
 		G_CALLBACK (msg_composer_notify_header_cb), composer);
 	g_signal_connect_swapped (
-		table, "notify::signature",
-		G_CALLBACK (e_msg_composer_show_sig_file), composer);
+		table, "notify::signature-uid",
+		G_CALLBACK (e_composer_update_signature), composer);
 	g_signal_connect_swapped (
 		table, "notify::subject",
 		G_CALLBACK (msg_composer_subject_changed_cb), composer);
@@ -2096,7 +2032,7 @@ msg_composer_constructed (GObject *object)
 		table, "notify::subject",
 		G_CALLBACK (msg_composer_notify_header_cb), composer);
 
-	msg_composer_account_changed_cb (composer);
+	msg_composer_mail_identity_changed_cb (composer);
 
 	/* Attachments */
 
@@ -3031,28 +2967,75 @@ set_signature_gui (EMsgComposer *composer)
 {
 	GtkhtmlEditor *editor;
 	EComposerHeaderTable *table;
-	ESignature *signature = NULL;
+	EMailSignatureComboBox *combo_box;
 	const gchar *data;
-	gchar *decoded;
+	gchar *uid;
 
 	editor = GTKHTML_EDITOR (composer);
 	table = e_msg_composer_get_header_table (composer);
+	combo_box = e_composer_header_table_get_signature_combo_box (table);
 
 	if (!gtkhtml_editor_search_by_data (editor, 1, "ClueFlow", "signature", "1"))
 		return;
 
 	data = gtkhtml_editor_get_paragraph_data (editor, "signature_name");
-	if (g_str_has_prefix (data, "uid:")) {
-		decoded = e_composer_decode_clue_value (data + 4);
-		signature = e_get_signature_by_uid (decoded);
-		g_free (decoded);
-	} else if (g_str_has_prefix (data, "name:")) {
-		decoded = e_composer_decode_clue_value (data + 5);
-		signature = e_get_signature_by_name (decoded);
-		g_free (decoded);
+
+	if (!g_str_has_prefix (data, "uid:"))
+		return;
+
+	/* The combo box active ID is the signature's ESource UID. */
+	uid = e_composer_decode_clue_value (data + 4);
+	gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), uid);
+	g_free (uid);
+}
+
+static void
+composer_add_auto_recipients (ESource *source,
+                              const gchar *property_name,
+                              GHashTable *hash_table)
+{
+	ESourceMailComposition *extension;
+	CamelInternetAddress *inet_addr;
+	const gchar *extension_name;
+	gchar *comma_separated_addrs;
+	gchar **addr_array = NULL;
+	gint length, ii;
+	gint retval;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	extension = e_source_get_extension (source, extension_name);
+
+	g_object_get (extension, property_name, &addr_array, NULL);
+
+	if (addr_array == NULL)
+		return;
+
+	inet_addr = camel_internet_address_new ();
+	comma_separated_addrs = g_strjoinv (", ", addr_array);
+
+	retval = camel_address_decode (
+		CAMEL_ADDRESS (inet_addr), comma_separated_addrs);
+
+	g_free (comma_separated_addrs);
+	g_strfreev (addr_array);
+
+	if (retval == -1)
+		return;
+
+	length = camel_address_length (CAMEL_ADDRESS (inet_addr));
+
+	for (ii = 0; ii < length; ii++) {
+		const gchar *name;
+		const gchar *addr;
+
+		if (camel_internet_address_get (inet_addr, ii, &name, &addr))
+			g_hash_table_insert (
+				hash_table,
+				g_strdup (addr),
+				GINT_TO_POINTER (1));
 	}
 
-	e_composer_header_table_set_signature (table, signature);
+	g_object_unref (inet_addr);
 }
 
 /**
@@ -3080,13 +3063,14 @@ e_msg_composer_new_with_message (EShell *shell,
 	struct _camel_header_raw *headers;
 	CamelDataWrapper *content;
 	CamelSession *session;
-	EAccount *account = NULL;
-	gchar *account_name;
 	EMsgComposer *composer;
 	EMsgComposerPrivate *priv;
 	EComposerHeaderTable *table;
+	ESourceRegistry *registry;
+	ESource *source = NULL;
 	GtkToggleAction *action;
 	struct _camel_header_raw *xev;
+	gchar *identity_uid;
 	gint len, i;
 
 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
@@ -3107,6 +3091,7 @@ e_msg_composer_new_with_message (EShell *shell,
 	priv = E_MSG_COMPOSER_GET_PRIVATE (composer);
 	session = e_msg_composer_get_session (composer);
 	table = e_msg_composer_get_header_table (composer);
+	registry = e_composer_header_table_get_registry (table);
 
 	if (postto) {
 		e_composer_header_table_set_post_to_list (table, postto);
@@ -3115,22 +3100,12 @@ e_msg_composer_new_with_message (EShell *shell,
 		postto = NULL;
 	}
 
-	/* Restore the Account preference */
-	account_name = (gchar *) camel_medium_get_header (
-		CAMEL_MEDIUM (message), "X-Evolution-Account");
-	if (account_name) {
-		account_name = g_strdup (account_name);
-		g_strstrip (account_name);
-
-		account = e_get_account_by_uid (account_name);
-		if (account == NULL)
-			/* XXX Backwards compatibility */
-			account = e_get_account_by_name (account_name);
-
-		if (account != NULL) {
-			g_free (account_name);
-			account_name = g_strdup (account->name);
-		}
+	/* Restore the mail identity preference. */
+	identity_uid = (gchar *) camel_medium_get_header (
+		CAMEL_MEDIUM (message), "X-Evolution-Identity");
+	if (identity_uid != NULL) {
+		identity_uid = g_strstrip (g_strdup (identity_uid));
+		source = e_source_registry_ref_source (registry, identity_uid);
 	}
 
 	if (postto == NULL) {
@@ -3144,45 +3119,9 @@ e_msg_composer_new_with_message (EShell *shell,
 			(GDestroyNotify) g_free,
 			(GDestroyNotify) NULL);
 
-		if (account) {
-			CamelInternetAddress *iaddr;
-
-			/* hash our auto-recipients for this account */
-			if (account->always_cc) {
-				iaddr = camel_internet_address_new ();
-				if (camel_address_decode (CAMEL_ADDRESS (iaddr), account->cc_addrs) != -1) {
-					for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
-						const gchar *name, *addr;
-
-						if (!camel_internet_address_get (iaddr, i, &name, &addr))
-							continue;
-
-						g_hash_table_insert (
-							auto_cc,
-							g_strdup (addr),
-							GINT_TO_POINTER (TRUE));
-					}
-				}
-				g_object_unref (iaddr);
-			}
-
-			if (account->always_bcc) {
-				iaddr = camel_internet_address_new ();
-				if (camel_address_decode (CAMEL_ADDRESS (iaddr), account->bcc_addrs) != -1) {
-					for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
-						const gchar *name, *addr;
-
-						if (!camel_internet_address_get (iaddr, i, &name, &addr))
-							continue;
-
-						g_hash_table_insert (
-							auto_bcc,
-							g_strdup (addr),
-							GINT_TO_POINTER (TRUE));
-					}
-				}
-				g_object_unref (iaddr);
-			}
+		if (source != NULL) {
+			composer_add_auto_recipients (source, "cc", auto_cc);
+			composer_add_auto_recipients (source, "bcc", auto_bcc);
 		}
 
 		to = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
@@ -3200,6 +3139,7 @@ e_msg_composer_new_with_message (EShell *shell,
 				To = g_list_append (To, dest);
 			}
 		}
+
 		Tov = destination_list_to_vector (To);
 		g_list_free (To);
 
@@ -3248,15 +3188,18 @@ e_msg_composer_new_with_message (EShell *shell,
 		Bccv = NULL;
 	}
 
+	if (source != NULL)
+		g_object_unref (source);
+
 	subject = camel_mime_message_get_subject (message);
 
-	e_composer_header_table_set_account_name (table, account_name);
+	e_composer_header_table_set_identity_uid (table, identity_uid);
 	e_composer_header_table_set_destinations_to (table, Tov);
 	e_composer_header_table_set_destinations_cc (table, Ccv);
 	e_composer_header_table_set_destinations_bcc (table, Bccv);
 	e_composer_header_table_set_subject (table, subject);
 
-	g_free (account_name);
+	g_free (identity_uid);
 
 	e_destination_freev (Tov);
 	e_destination_freev (Ccv);
@@ -3410,7 +3353,7 @@ e_msg_composer_new_with_message (EShell *shell,
 EMsgComposer *
 e_msg_composer_new_redirect (EShell *shell,
                              CamelMimeMessage *message,
-                             const gchar *resent_from,
+                             const gchar *identity_uid,
                              GCancellable *cancellable)
 {
 	EMsgComposer *composer;
@@ -3430,7 +3373,7 @@ e_msg_composer_new_redirect (EShell *shell,
 	composer->priv->redirect = message;
 	g_object_ref (message);
 
-	e_composer_header_table_set_account_name (table, resent_from);
+	e_composer_header_table_set_identity_uid (table, identity_uid);
 	e_composer_header_table_set_subject (table, subject);
 
 	web_view = e_msg_composer_get_web_view (composer);
@@ -4198,16 +4141,24 @@ e_msg_composer_set_body (EMsgComposer *composer,
                          const gchar *body,
                          const gchar *mime_type)
 {
-	EMsgComposerPrivate *p = composer->priv;
+	EMsgComposerPrivate *priv = composer->priv;
 	EComposerHeaderTable *table;
 	EWebViewGtkHTML *web_view;
+	ESourceRegistry *registry;
+	ESource *source;
+	const gchar *identity_uid;
 	gchar *buff;
 
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
 	table = e_msg_composer_get_header_table (composer);
+	registry = e_composer_header_table_get_registry (table);
+
+	identity_uid = e_composer_header_table_get_identity_uid (table);
+	source = e_source_registry_ref_source (registry, identity_uid);
 
-	buff = g_markup_printf_escaped ("<b>%s</b>",
+	buff = g_markup_printf_escaped (
+		"<b>%s</b>",
 		_("The composer contains a non-text "
 		  "message body, which cannot be edited."));
 	set_editor_text (composer, buff, FALSE);
@@ -4218,16 +4169,19 @@ e_msg_composer_set_body (EMsgComposer *composer,
 	web_view = e_msg_composer_get_web_view (composer);
 	e_web_view_gtkhtml_set_editable (web_view, FALSE);
 
-	g_free (p->mime_body);
-	p->mime_body = g_strdup (body);
-	g_free (p->mime_type);
-	p->mime_type = g_strdup (mime_type);
+	g_free (priv->mime_body);
+	priv->mime_body = g_strdup (body);
+	g_free (priv->mime_type);
+	priv->mime_type = g_strdup (mime_type);
+
+	if (g_ascii_strncasecmp (priv->mime_type, "text/calendar", 13) == 0) {
+		ESourceMailComposition *extension;
+		const gchar *extension_name;
 
-	if (g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) == 0) {
-		EAccount *account;
+		extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+		extension = e_source_get_extension (source, extension_name);
 
-		account = e_composer_header_table_get_account (table);
-		if (account && account->pgp_no_imip_sign) {
+		if (!e_source_mail_composition_get_sign_imip (extension)) {
 			GtkToggleAction *action;
 
 			action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
@@ -4237,6 +4191,8 @@ e_msg_composer_set_body (EMsgComposer *composer,
 			gtk_toggle_action_set_active (action, FALSE);
 		}
 	}
+
+	g_object_unref (source);
 }
 
 /**
@@ -4739,88 +4695,45 @@ e_msg_composer_get_message_draft_finish (EMsgComposer *composer,
 	return g_object_ref (message);
 }
 
-/**
- * e_msg_composer_show_sig:
- * @composer: A message composer widget
- *
- * Set a signature
- **/
-void
-e_msg_composer_show_sig_file (EMsgComposer *composer)
-{
-	GtkhtmlEditor *editor;
-	gchar *html_text;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	editor = GTKHTML_EDITOR (composer);
-
-	if (composer->priv->redirect)
-		return;
-
-	composer->priv->in_signature_insert = TRUE;
-
-	gtkhtml_editor_freeze (editor);
-	gtkhtml_editor_run_command (editor, "cursor-position-save");
-	gtkhtml_editor_undo_begin (editor, "Set signature", "Reset signature");
-
-	/* Delete the old signature. */
-	gtkhtml_editor_run_command (editor, "block-selection");
-	gtkhtml_editor_run_command (editor, "cursor-bod");
-	if (gtkhtml_editor_search_by_data (editor, 1, "ClueFlow", "signature", "1")) {
-		gtkhtml_editor_run_command (editor, "select-paragraph");
-		gtkhtml_editor_run_command (editor, "delete");
-		gtkhtml_editor_set_paragraph_data (editor, "signature", "0");
-		gtkhtml_editor_run_command (editor, "delete-back");
-	}
-	gtkhtml_editor_run_command (editor, "unblock-selection");
-
-	html_text = get_signature_html (composer);
-	if (html_text) {
-		gtkhtml_editor_run_command (editor, "insert-paragraph");
-		if (!gtkhtml_editor_run_command (editor, "cursor-backward"))
-			gtkhtml_editor_run_command (editor, "insert-paragraph");
-		else
-			gtkhtml_editor_run_command (editor, "cursor-forward");
-
-		gtkhtml_editor_set_paragraph_data (editor, "orig", "0");
-		gtkhtml_editor_run_command (editor, "indent-zero");
-		gtkhtml_editor_run_command (editor, "style-normal");
-		gtkhtml_editor_insert_html (editor, html_text);
-		g_free (html_text);
-	} else if (is_top_signature (composer)) {
-		/* insert paragraph after the signature ClueFlow things */
-		if (gtkhtml_editor_run_command (editor, "cursor-forward"))
-			gtkhtml_editor_run_command (editor, "insert-paragraph");
-	}
-
-	gtkhtml_editor_undo_end (editor);
-	gtkhtml_editor_run_command (editor, "cursor-position-restore");
-	gtkhtml_editor_thaw (editor);
-
-	composer->priv->in_signature_insert = FALSE;
-}
-
 CamelInternetAddress *
 e_msg_composer_get_from (EMsgComposer *composer)
 {
-	CamelInternetAddress *address;
+	CamelInternetAddress *inet_address = NULL;
+	ESourceMailIdentity *mail_identity;
 	EComposerHeaderTable *table;
-	EAccount *account;
+	ESourceRegistry *registry;
+	ESource *source;
+	const gchar *extension_name;
+	const gchar *uid;
+	gchar *name;
+	gchar *address;
 
 	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
 	table = e_msg_composer_get_header_table (composer);
 
-	account = e_composer_header_table_get_account (table);
-	if (account == NULL)
-		return NULL;
+	registry = e_composer_header_table_get_registry (table);
+	uid = e_composer_header_table_get_identity_uid (table);
+	source = e_source_registry_ref_source (registry, uid);
+	g_return_val_if_fail (source != NULL, NULL);
 
-	address = camel_internet_address_new ();
-	camel_internet_address_add (
-		address, account->id->name, account->id->address);
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	mail_identity = e_source_get_extension (source, extension_name);
 
-	return address;
+	name = e_source_mail_identity_dup_name (mail_identity);
+	address = e_source_mail_identity_dup_address (mail_identity);
+
+	g_object_unref (source);
+
+	if (name != NULL && address != NULL) {
+		inet_address = camel_internet_address_new ();
+		camel_internet_address_add (inet_address, name, address);
+	}
+
+	g_free (name);
+	g_free (address);
+
+	return inet_address;
 }
 
 CamelInternetAddress *
@@ -4840,8 +4753,8 @@ e_msg_composer_get_reply_to (EMsgComposer *composer)
 
 	address = camel_internet_address_new ();
 	if (camel_address_unformat (CAMEL_ADDRESS (address), reply_to) == -1) {
-		g_object_unref (CAMEL_OBJECT (address));
-		return NULL;
+		g_object_unref (address);
+		address = NULL;
 	}
 
 	return address;
diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h
index aa63b0e..318165d 100644
--- a/composer/e-msg-composer.h
+++ b/composer/e-msg-composer.h
@@ -25,7 +25,6 @@
 #define E_MSG_COMPOSER_H
 
 #include <camel/camel.h>
-#include <libedataserver/e-account.h>
 #include <libebook/e-destination.h>
 #include <gtkhtml-editor.h>
 #include <misc/e-attachment-view.h>
@@ -94,7 +93,7 @@ EMsgComposer *	e_msg_composer_new_from_url	(EShell *shell,
 						 const gchar *url);
 EMsgComposer *	e_msg_composer_new_redirect	(EShell *shell,
 						 CamelMimeMessage *message,
-						 const gchar *resent_from,
+						 const gchar *identity_uid,
 						 GCancellable *cancellable);
 EFocusTracker *	e_msg_composer_get_focus_tracker
 						(EMsgComposer *composer);
@@ -172,7 +171,6 @@ CamelMimeMessage *
 						(EMsgComposer *composer,
 						 GAsyncResult *result,
 						 GError **error);
-void		e_msg_composer_show_sig_file	(EMsgComposer *composer);
 
 CamelInternetAddress *
 		e_msg_composer_get_from		(EMsgComposer *composer);



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