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



commit 7431440aed00a00b2aa0d84481db5febc2db41b1
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Apr 13 10:30:40 2011 -0400

    Adapt mail to the new ESource API.

 libemail-engine/Makefile.am            |    2 +
 libemail-engine/e-mail-authenticator.c |  267 ++
 libemail-engine/e-mail-authenticator.h |   76 +
 libemail-engine/e-mail-session-utils.c |   40 +-
 libemail-engine/e-mail-session.c       | 1055 ++++--
 libemail-engine/e-mail-session.h       |   30 +-
 libemail-engine/e-mail-utils.c         |  591 +++--
 libemail-engine/e-mail-utils.h         |   38 +-
 libemail-engine/mail-config.c          |   21 -
 libemail-engine/mail-config.h          |    1 -
 libemail-engine/mail-folder-cache.c    |   11 +-
 libemail-engine/mail-ops.c             |  360 ++-
 libemail-engine/mail-ops.h             |    1 -
 libemail-utils/Makefile.am             |    8 -
 mail/Makefile.am                       |   61 +-
 mail/e-mail-account-manager.c          |   61 +-
 mail/e-mail-account-manager.h          |    6 +-
 mail/e-mail-account-store.c            |  315 +-
 mail/e-mail-autoconfig.c               |  883 +++++
 mail/e-mail-autoconfig.h               |   89 +
 mail/e-mail-backend.c                  |  246 +-
 mail/e-mail-config-assistant.c         | 1157 +++++++
 mail/e-mail-config-assistant.h         |   96 +
 mail/e-mail-config-auth-check.c        |  446 +++
 mail/e-mail-config-auth-check.h        |   73 +
 mail/e-mail-config-confirm-page.c      |  205 ++
 mail/e-mail-config-confirm-page.h      |   75 +
 mail/e-mail-config-defaults-page.c     |  868 +++++
 mail/e-mail-config-defaults-page.h     |   79 +
 mail/e-mail-config-identity-page.c     |  738 ++++
 mail/e-mail-config-identity-page.h     |   91 +
 mail/e-mail-config-lookup-page.c       |  109 +
 mail/e-mail-config-lookup-page.h       |   73 +
 mail/e-mail-config-notebook.c          |  764 +++++
 mail/e-mail-config-notebook.h          |   98 +
 mail/e-mail-config-page.c              |  176 +
 mail/e-mail-config-page.h              |   72 +
 mail/e-mail-config-provider-page.c     |  774 +++++
 mail/e-mail-config-provider-page.h     |   81 +
 mail/e-mail-config-receiving-page.c    |   70 +
 mail/e-mail-config-receiving-page.h    |   69 +
 mail/e-mail-config-security-page.c     |  672 ++++
 mail/e-mail-config-security-page.h     |   73 +
 mail/e-mail-config-sending-page.c      |   70 +
 mail/e-mail-config-sending-page.h      |   68 +
 mail/e-mail-config-service-backend.c   |  477 +++
 mail/e-mail-config-service-backend.h   |  121 +
 mail/e-mail-config-service-notebook.c  |  365 ++
 mail/e-mail-config-service-notebook.h  |   77 +
 mail/e-mail-config-service-page.c      | 1039 ++++++
 mail/e-mail-config-service-page.h      |  107 +
 mail/e-mail-config-sidebar.c           |  415 +++
 mail/e-mail-config-sidebar.h           |   72 +
 mail/e-mail-config-summary-page.c      | 1064 ++++++
 mail/e-mail-config-summary-page.h      |  101 +
 mail/e-mail-config-welcome-page.c      |  203 ++
 mail/e-mail-config-welcome-page.h      |   75 +
 mail/e-mail-config-window.c            |  524 +++
 mail/e-mail-config-window.h            |   71 +
 mail/e-mail-folder-pane.c              |   17 +-
 mail/e-mail-migrate.c                  |  524 +---
 mail/e-mail-paned-view.c               |    8 +-
 mail/e-mail-reader-utils.c             |   27 +-
 mail/e-mail-reader.c                   |   51 +-
 mail/e-mail-ui-session.c               |  321 +-
 mail/e-mail-ui-session.h               |    8 +-
 mail/e-mail.h                          |    1 +
 mail/em-account-editor.c               | 5834 --------------------------------
 mail/em-account-editor.h               |  124 -
 mail/em-composer-utils.c               |  338 ++-
 mail/em-composer-utils.h               |    3 +-
 mail/em-filter-source-element.c        |  114 +-
 mail/em-folder-tree-model.c            |   98 +-
 mail/em-format-html.c                  |   22 +-
 mail/em-subscription-editor.c          |   14 +-
 mail/em-utils.c                        |   52 +-
 mail/em-utils.h                        |    6 -
 mail/mail-config.ui                    | 3188 +-----------------
 mail/mail-send-recv.c                  |  292 +--
 mail/mail.error.xml                    |   28 -
 mail/test-mail-autoconfig.c            |   53 +
 81 files changed, 15589 insertions(+), 11404 deletions(-)
---
diff --git a/libemail-engine/Makefile.am b/libemail-engine/Makefile.am
index 4c64ea8..103a9d5 100644
--- a/libemail-engine/Makefile.am
+++ b/libemail-engine/Makefile.am
@@ -22,6 +22,7 @@ libemail_engine_la_CPPFLAGS = \
 libmailengineincludedir = $(privincludedir)/libemail-engine
 libmailengineinclude_HEADERS =  \
 	camel-null-store.h \
+	e-mail-authenticator.h \
 	e-mail-enums.h \
 	e-mail-enumtypes.h \
 	e-mail-folder-utils.h \
@@ -40,6 +41,7 @@ libmailengineinclude_HEADERS =  \
 libemail_engine_la_SOURCES =  \
 	$(libmailengineinclude_HEADERS) \
 	camel-null-store.c \
+	e-mail-authenticator.c \
 	e-mail-enumtypes.c \
 	e-mail-folder-utils.c \
 	e-mail-junk-filter.c \
diff --git a/libemail-engine/e-mail-authenticator.c b/libemail-engine/e-mail-authenticator.c
new file mode 100644
index 0000000..9729d35
--- /dev/null
+++ b/libemail-engine/e-mail-authenticator.c
@@ -0,0 +1,267 @@
+/*
+ * e-mail-authenticator.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-authenticator.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#define E_MAIL_AUTHENTICATOR_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_AUTHENTICATOR, EMailAuthenticatorPrivate))
+
+struct _EMailAuthenticatorPrivate {
+	CamelService *service;
+	gchar *mechanism;
+};
+
+enum {
+	PROP_0,
+	PROP_MECHANISM,
+	PROP_SERVICE
+};
+
+/* Forward Declarations */
+static void	e_mail_authenticator_interface_init
+				(ESourceAuthenticatorInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailAuthenticator,
+	e_mail_authenticator,
+	G_TYPE_OBJECT,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_mail_authenticator_interface_init))
+
+static void
+mail_authenticator_set_mechanism (EMailAuthenticator *auth,
+                                  const gchar *mechanism)
+{
+	g_return_if_fail (auth->priv->mechanism == NULL);
+
+	auth->priv->mechanism = g_strdup (mechanism);
+}
+
+static void
+mail_authenticator_set_service (EMailAuthenticator *auth,
+                                CamelService *service)
+{
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+	g_return_if_fail (auth->priv->service == NULL);
+
+	auth->priv->service = g_object_ref (service);
+}
+
+static void
+mail_authenticator_set_property (GObject *object,
+                                 guint property_id,
+                                 const GValue *value,
+                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_MECHANISM:
+			mail_authenticator_set_mechanism (
+				E_MAIL_AUTHENTICATOR (object),
+				g_value_get_string (value));
+			return;
+
+		case PROP_SERVICE:
+			mail_authenticator_set_service (
+				E_MAIL_AUTHENTICATOR (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_authenticator_get_property (GObject *object,
+                                 guint property_id,
+                                 GValue *value,
+                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_MECHANISM:
+			g_value_set_string (
+				value,
+				e_mail_authenticator_get_mechanism (
+				E_MAIL_AUTHENTICATOR (object)));
+			return;
+
+		case PROP_SERVICE:
+			g_value_set_object (
+				value,
+				e_mail_authenticator_get_service (
+				E_MAIL_AUTHENTICATOR (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_authenticator_dispose (GObject *object)
+{
+	EMailAuthenticatorPrivate *priv;
+
+	priv = E_MAIL_AUTHENTICATOR_GET_PRIVATE (object);
+
+	if (priv->service != NULL) {
+		g_object_unref (priv->service);
+		priv->service = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_authenticator_parent_class)->dispose (object);
+}
+
+static void
+mail_authenticator_finalize (GObject *object)
+{
+	EMailAuthenticatorPrivate *priv;
+
+	priv = E_MAIL_AUTHENTICATOR_GET_PRIVATE (object);
+
+	g_free (priv->mechanism);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_authenticator_parent_class)->finalize (object);
+}
+
+static ESourceAuthenticationResult
+mail_authenticator_try_password_sync (ESourceAuthenticator *auth,
+                                      const GString *password,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+	CamelService *service;
+	EMailAuthenticator *mail_auth;
+	CamelAuthenticationResult camel_result;
+	ESourceAuthenticationResult source_result;
+	const gchar *mechanism;
+
+	mail_auth = E_MAIL_AUTHENTICATOR (auth);
+	service = e_mail_authenticator_get_service (mail_auth);
+	mechanism = e_mail_authenticator_get_mechanism (mail_auth);
+
+	camel_service_set_password (service, password->str);
+
+	camel_result = camel_service_authenticate_sync (
+		service, mechanism, cancellable, error);
+
+	switch (camel_result) {
+		case CAMEL_AUTHENTICATION_ERROR:
+			source_result = E_SOURCE_AUTHENTICATION_ERROR;
+			break;
+		case CAMEL_AUTHENTICATION_ACCEPTED:
+			source_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+			break;
+		case CAMEL_AUTHENTICATION_REJECTED:
+			source_result = E_SOURCE_AUTHENTICATION_REJECTED;
+			break;
+		default:
+			g_set_error (
+				error, CAMEL_SERVICE_ERROR,
+				CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+				_("Invalid authentication result code (%d)"),
+				camel_result);
+			source_result = E_SOURCE_AUTHENTICATION_ERROR;
+			break;
+	}
+
+	return source_result;
+}
+
+static void
+e_mail_authenticator_class_init (EMailAuthenticatorClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailAuthenticatorPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_authenticator_set_property;
+	object_class->get_property = mail_authenticator_get_property;
+	object_class->dispose = mail_authenticator_dispose;
+	object_class->finalize = mail_authenticator_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_MECHANISM,
+		g_param_spec_string (
+			"mechanism",
+			"Mechanism",
+			"Authentication mechanism",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SERVICE,
+		g_param_spec_object (
+			"service",
+			"Service",
+			"The CamelService to authenticate",
+			CAMEL_TYPE_SERVICE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_authenticator_interface_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = mail_authenticator_try_password_sync;
+}
+
+static void
+e_mail_authenticator_init (EMailAuthenticator *auth)
+{
+	auth->priv = E_MAIL_AUTHENTICATOR_GET_PRIVATE (auth);
+}
+
+ESourceAuthenticator *
+e_mail_authenticator_new (CamelService *service,
+                          const gchar *mechanism)
+{
+	g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_AUTHENTICATOR,
+		"service", service, "mechanism", mechanism, NULL);
+}
+
+CamelService *
+e_mail_authenticator_get_service (EMailAuthenticator *auth)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTHENTICATOR (auth), NULL);
+
+	return auth->priv->service;
+}
+
+const gchar *
+e_mail_authenticator_get_mechanism (EMailAuthenticator *auth)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTHENTICATOR (auth), NULL);
+
+	return auth->priv->mechanism;
+}
+
diff --git a/libemail-engine/e-mail-authenticator.h b/libemail-engine/e-mail-authenticator.h
new file mode 100644
index 0000000..bcc3299
--- /dev/null
+++ b/libemail-engine/e-mail-authenticator.h
@@ -0,0 +1,76 @@
+/*
+ * e-mail-authenticator.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_AUTHENTICATOR_H
+#define E_MAIL_AUTHENTICATOR_H
+
+#include <camel/camel.h>
+#include <libedataserver/e-source-authenticator.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_AUTHENTICATOR \
+	(e_mail_authenticator_get_type ())
+#define E_MAIL_AUTHENTICATOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_AUTHENTICATOR, EMailAuthenticator))
+#define E_MAIL_AUTHENTICATOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_AUTHENTICATOR, EMailAuthenticatorClass))
+#define E_IS_MAIL_AUTHENTICATOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_AUTHENTICATOR))
+#define E_IS_MAIL_AUTHENTICATOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_AUTHENTICATOR))
+#define E_MAIL_AUTHENTICATOR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_AUTHENTICATOR, EMailAuthenticatorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAuthenticator EMailAuthenticator;
+typedef struct _EMailAuthenticatorClass EMailAuthenticatorClass;
+typedef struct _EMailAuthenticatorPrivate EMailAuthenticatorPrivate;
+
+/**
+ * EMailAuthenticator:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ **/
+struct _EMailAuthenticator {
+	GObject parent;
+	EMailAuthenticatorPrivate *priv;
+};
+
+struct _EMailAuthenticatorClass {
+	GObjectClass parent_class;
+};
+
+GType		e_mail_authenticator_get_type	(void);
+ESourceAuthenticator *
+		e_mail_authenticator_new	(CamelService *service,
+						 const gchar *mechanism);
+CamelService *	e_mail_authenticator_get_service
+						(EMailAuthenticator *auth);
+const gchar *	e_mail_authenticator_get_mechanism
+						(EMailAuthenticator *auth);
+
+G_END_DECLS
+
+#endif /* E_MAIL_AUTHENTICATOR_H */
diff --git a/libemail-engine/e-mail-session-utils.c b/libemail-engine/e-mail-session-utils.c
index de1dec1..26d4639 100644
--- a/libemail-engine/e-mail-session-utils.c
+++ b/libemail-engine/e-mail-session-utils.c
@@ -23,11 +23,11 @@
 #include "e-mail-session-utils.h"
 
 #include <glib/gi18n-lib.h>
+#include <libedataserver/e-source-mail-submission.h>
 
 #include <libemail-engine/e-mail-folder-utils.h>
 #include <libemail-engine/e-mail-utils.h>
 #include <libemail-engine/mail-tools.h>
-#include <libemail-utils/e-account-utils.h>
 
 /* X-Mailer header value */
 #define X_MAILER ("Evolution " VERSION SUB_VERSION " " VERSION_COMMENT)
@@ -671,7 +671,8 @@ e_mail_session_send_to (EMailSession *session,
 	CamelAddress *recipients;
 	CamelMedium *medium;
 	CamelMessageInfo *info;
-	EAccount *account = NULL;
+	ESourceRegistry *registry;
+	ESource *source = NULL;
 	GPtrArray *post_to_uris;
 	struct _camel_header_raw *xev;
 	struct _camel_header_raw *header;
@@ -684,6 +685,8 @@ e_mail_session_send_to (EMailSession *session,
 	g_return_if_fail (E_IS_MAIL_SESSION (session));
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
+	registry = e_mail_session_get_registry (session);
+
 	medium = CAMEL_MEDIUM (message);
 
 	camel_medium_set_header (medium, "X-Mailer", X_MAILER);
@@ -692,28 +695,27 @@ e_mail_session_send_to (EMailSession *session,
 
 	/* Extract directives from X-Evolution headers. */
 
-	string = camel_header_raw_find (&xev, "X-Evolution-Account", NULL);
+	string = camel_header_raw_find (&xev, "X-Evolution-Identity", NULL);
 	if (string != NULL) {
-		gchar *account_uid;
-
-		account_uid = g_strstrip (g_strdup (string));
-		account = e_get_account_by_uid (account_uid);
-		g_free (account_uid);
+		gchar *uid = g_strstrip (g_strdup (string));
+		source = e_source_registry_ref_source (registry, uid);
+		g_free (uid);
 	}
 
-	if (account != NULL) {
-		if (account->transport != NULL) {
+	if (E_IS_SOURCE (source)) {
+		ESourceMailSubmission *extension;
+		const gchar *extension_name;
 
-			/* XXX Transport UIDs are kludgy right now.  We
-			 *     use the EAccount's regular UID and tack on
-			 *     "-transport".  Will be better soon. */
-			transport_uid = g_strconcat (
-				account->uid, "-transport", NULL);
+		extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+		extension = e_source_get_extension (source, extension_name);
 
-			/* to reprompt password on sending if needed */
-			account->transport->get_password_canceled = FALSE;
-		}
-		sent_folder_uri = g_strdup (account->sent_folder_uri);
+		string = e_source_mail_submission_get_sent_folder (extension);
+		sent_folder_uri = g_strdup (string);
+
+		string = e_source_mail_submission_get_transport_uid (extension);
+		transport_uid = g_strdup (string);
+
+		g_object_unref (source);
 	}
 
 	string = camel_header_raw_find (&xev, "X-Evolution-Fcc", NULL);
diff --git a/libemail-engine/e-mail-session.c b/libemail-engine/e-mail-session.c
index bc72e98..ee1427e 100644
--- a/libemail-engine/e-mail-session.c
+++ b/libemail-engine/e-mail-session.c
@@ -45,15 +45,22 @@
 #include <libedataserver/e-flag.h>
 #include <libedataserver/e-proxy.h>
 #include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-mail-transport.h>
+#include <libedataserver/e-source-refresh.h>
 #include <libedataserverui/e-passwords.h>
 #include <libedataserver/e-data-server-util.h>
 
-#include "libemail-utils/e-account-utils.h"
 #include "libemail-utils/mail-mt.h"
 
 /* This is our hack, not part of libcamel. */
 #include "camel-null-store.h"
 
+#include "e-mail-authenticator.h"
 #include "e-mail-junk-filter.h"
 #include "e-mail-session.h"
 #include "e-mail-folder-utils.h"
@@ -70,9 +77,14 @@ typedef struct _AsyncContext AsyncContext;
 
 struct _EMailSessionPrivate {
 	MailFolderCache *folder_cache;
+	ESourceRegistry *registry;
 
-	EAccountList *account_list;
-	gulong account_added_handler_id;
+	/* ESource UID -> Timeout ID */
+	GHashTable *auto_refresh_table;
+
+	gulong source_added_handler_id;
+	gulong source_removed_handler_id;
+	gulong default_mail_account_handler_id;
 
 	CamelStore *local_store;
 	CamelStore *vfolder_store;
@@ -101,6 +113,7 @@ enum {
 	PROP_FOLDER_CACHE,
 	PROP_JUNK_FILTER_NAME,
 	PROP_LOCAL_STORE,
+	PROP_REGISTRY,
 	PROP_VFOLDER_STORE
 };
 
@@ -115,6 +128,7 @@ static const gchar *local_folder_names[E_MAIL_NUM_LOCAL_FOLDERS] = {
 
 enum {
 	FLUSH_OUTBOX,
+	REFRESH_SERVICE,
 	STORE_ADDED,
 	STORE_REMOVED,
 	LAST_SIGNAL
@@ -317,21 +331,72 @@ async_context_free (AsyncContext *context)
 }
 
 static gchar *
-mail_session_make_key (CamelService *service,
-                       const gchar *item)
+mail_session_resolve_popb4smtp (ESourceRegistry *registry,
+                                CamelService *smtp_service)
 {
-	gchar *key;
+	GList *list, *link;
+	const gchar *extension_name;
+	const gchar *smtp_uid;
+	gchar *pop_uid = NULL;
 
-	if (service != NULL) {
-		CamelURL *url;
+	/* Find a POP account that uses the given smtp_service as its
+	 * transport.  XXX This isn't foolproof though, since we don't
+	 * check that the POP server is at the same domain as the SMTP
+	 * server, which is kind of the point of POPB4SMTP. */
 
-		url = camel_service_new_camel_url (service);
-		key = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-		camel_url_free (url);
-	} else
-		key = g_strdup (item);
+	smtp_uid = camel_service_get_uid (smtp_service);
+	g_return_val_if_fail (smtp_uid != NULL, NULL);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *backend_name;
+		gchar *uid;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+		extension = e_source_get_extension (source, extension_name);
+
+		/* We're only interested in POP accounts. */
+
+		backend_name = e_source_backend_get_backend_name (
+			E_SOURCE_BACKEND (extension));
+		if (g_strcmp0 (backend_name, "pop") != 0)
+			continue;
+
+		/* Get the mail account's default mail identity. */
+
+		uid = e_source_mail_account_dup_identity_uid (
+			E_SOURCE_MAIL_ACCOUNT (extension));
+		source = e_source_registry_ref_source (registry, uid);
+		g_free (uid);
+
+		if (source == NULL)
+			continue;
+
+		/* Get the mail identity's default mail transport. */
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+		extension = e_source_get_extension (source, extension_name);
+
+		uid = e_source_mail_submission_dup_transport_uid (
+			E_SOURCE_MAIL_SUBMISSION (extension));
+
+		g_object_unref (source);
 
-	return key;
+		if (g_strcmp0 (uid, smtp_uid) == 0) {
+			pop_uid = uid;
+			break;
+		}
+
+		g_free (uid);
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	return pop_uid;
 }
 
 static void
@@ -406,135 +471,181 @@ mail_session_set_junk_filter_name (EMailSession *session,
 }
 
 static void
-mail_session_add_by_account (EMailSession *session,
-                             EAccount *account)
-{
-	CamelService *service = NULL;
-	CamelProvider *provider;
-	CamelURL *url = NULL;
-	const gchar *protocol = NULL;
-	gboolean have_source_url;
-	GError *error = NULL;
-
-	have_source_url =
-		(account->source != NULL) &&
-		(account->source->url != NULL);
+mail_session_refresh_cb (ESource *source,
+                         CamelSession *session)
+{
+	CamelService *service;
+	const gchar *uid;
 
-	if (have_source_url)
-		url = camel_url_new (account->source->url, NULL);
+	uid = e_source_get_uid (source);
+	service = camel_session_get_service (session, uid);
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
 
-	protocol = (url != NULL) ? url->protocol : "none";
-	provider = camel_provider_get (protocol, &error);
+	g_signal_emit (session, signals[REFRESH_SERVICE], 0, service);
+}
 
-	if (url != NULL)
-		camel_url_free (url);
+static void
+mail_session_add_from_source (EMailSession *session,
+                              CamelProviderType type,
+                              ESource *source)
+{
+	ESourceBackend *extension;
+	const gchar *uid;
+	const gchar *backend_name;
+	const gchar *display_name;
+	const gchar *extension_name;
+	GError *error = NULL;
 
-	if (error != NULL) {
-		g_warn_if_fail (provider == NULL);
-		g_warning ("%s", error->message);
-		g_error_free (error);
-		return;
+	switch (type) {
+		case CAMEL_PROVIDER_STORE:
+			extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+			break;
+		case CAMEL_PROVIDER_TRANSPORT:
+			extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+			break;
+		default:
+			g_return_if_reached ();
 	}
 
-	g_return_if_fail (provider != NULL);
+	uid = e_source_get_uid (source);
+	display_name = e_source_get_display_name (source);
+
+	extension = e_source_get_extension (source, extension_name);
+	backend_name = e_source_backend_get_backend_name (extension);
 
-	/* Load the service, but don't connect.  Check its provider,
-	 * and if this belongs in the folder tree model, add it. */
+	/* Sanity checks. */
+	g_return_if_fail (uid != NULL);
+	g_return_if_fail (backend_name != NULL);
 
-	service = camel_session_add_service (
-		CAMEL_SESSION (session),
-		account->uid, provider->protocol,
-		CAMEL_PROVIDER_STORE, &error);
+	/* Our own CamelSession.add_service() method will handle the
+	 * resulting CamelService, so we don't need the return value. */
+	camel_session_add_service (
+		CAMEL_SESSION (session), uid,
+		backend_name, type, &error);
 
 	if (error != NULL) {
 		g_warning (
-			"Failed to add service: %s: %s",
-			account->name, error->message);
+			"Failed to add service '%s' (%s): %s",
+			display_name, uid, error->message);
 		g_error_free (error);
-		return;
 	}
 
-	camel_service_set_display_name (service, account->name);
+	/* Set up auto-refresh. */
+	extension_name = E_SOURCE_EXTENSION_REFRESH;
+	if (e_source_has_extension (source, extension_name)) {
+		guint timeout_id;
 
-	/* While we're at it, add the account's transport (if it has one)
-	 * to the CamelSession.  The transport's UID is a kludge for now.
-	 * We take the EAccount's UID and tack on "-transport". */
+		/* Transports should not have a refresh extension. */
+		g_warn_if_fail (type != CAMEL_PROVIDER_TRANSPORT);
 
-	if (account->transport) {
-		GError *transport_error = NULL;
+		timeout_id = e_source_refresh_add_timeout (
+			source, NULL, (ESourceRefreshFunc)
+			mail_session_refresh_cb, session,
+			(GDestroyNotify) NULL);
 
-		url = camel_url_new (
-			account->transport->url,
-			&transport_error);
+		g_hash_table_insert (
+			session->priv->auto_refresh_table,
+			g_strdup (uid),
+			GUINT_TO_POINTER (timeout_id));
+	}
+}
 
-		if (url != NULL) {
-			provider = camel_provider_get (
-				url->protocol, &transport_error);
-			camel_url_free (url);
-		} else
-			provider = NULL;
+static void
+mail_session_source_added_cb (ESourceRegistry *registry,
+                              ESource *source,
+                              EMailSession *session)
+{
+	CamelProviderType provider_type;
+	const gchar *extension_name;
 
-		if (provider != NULL) {
-			gchar *transport_uid;
+	provider_type = CAMEL_PROVIDER_STORE;
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
 
-			transport_uid = g_strconcat (
-				account->uid, "-transport", NULL);
+	if (e_source_has_extension (source, extension_name))
+		mail_session_add_from_source (session, provider_type, source);
 
-			camel_session_add_service (
-				CAMEL_SESSION (session),
-				transport_uid, provider->protocol,
-				CAMEL_PROVIDER_TRANSPORT, &transport_error);
+	provider_type = CAMEL_PROVIDER_TRANSPORT;
+	extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
 
-			g_free (transport_uid);
-		}
+	if (e_source_has_extension (source, extension_name))
+		mail_session_add_from_source (session, provider_type, source);
+}
 
-		if (transport_error) {
-			g_warning (
-				"%s: Failed to add transport service: %s",
-				G_STRFUNC, transport_error->message);
-			g_error_free (transport_error);
-		}
-	}
+static void
+mail_session_source_removed_cb (ESourceRegistry *registry,
+                                ESource *source,
+                                EMailSession *session)
+{
+	CamelSession *camel_session;
+	CamelService *service;
+	const gchar *uid;
+
+	camel_session = CAMEL_SESSION (session);
+
+	uid = e_source_get_uid (source);
+	service = camel_session_get_service (camel_session, uid);
+
+	if (CAMEL_IS_SERVICE (service))
+		camel_session_remove_service (camel_session, service);
 }
 
 static void
-mail_session_account_added_cb (EAccountList *account_list,
-                               EAccount *account,
-                               EMailSession *session)
+mail_session_default_mail_account_cb (ESourceRegistry *registry,
+                                      GParamSpec *pspec,
+                                      EMailSession *session)
 {
-	mail_session_add_by_account (session, account);
+	ESource *source;
+	ESourceMailAccount *extension;
+	const gchar *extension_name;
+	gchar *uid;
+
+	/* If the default mail account names a valid mail
+	 * identity, make it the default mail identity. */
+
+	/* XXX I debated whether to have ESourceRegistry do this
+	 *     itself but it seems like an Evolution policy to me
+	 *     right now.  I may change my mind in the future, or
+	 *     decide not to do this synchronization at all. */
+
+	source = e_source_registry_ref_default_mail_account (registry);
+	g_return_if_fail (source != NULL);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+	uid = e_source_mail_account_dup_identity_uid (extension);
+
+	g_object_unref (source);
+	source = NULL;
+
+	if (uid != NULL) {
+		source = e_source_registry_ref_source (registry, uid);
+		g_free (uid);
+	}
+
+	if (source != NULL) {
+		e_source_registry_set_default_mail_identity (registry, source);
+		g_object_unref (source);
+	}
 }
 
 static void
-mail_session_add_local_store (EMailSession *session)
+mail_session_configure_local_store (EMailSession *session)
 {
 	CamelLocalSettings *local_settings;
 	CamelSession *camel_session;
 	CamelSettings *settings;
 	CamelService *service;
 	const gchar *data_dir;
+	const gchar *uid;
 	gchar *path;
 	gint ii;
-	GError *error = NULL;
 
 	camel_session = CAMEL_SESSION (session);
 
-	service = camel_session_add_service (
-		camel_session, E_MAIL_SESSION_LOCAL_UID,
-		"maildir", CAMEL_PROVIDER_STORE, &error);
-
-	/* XXX One could argue this is a fatal error
-	 *     since we depend on it in so many places. */
-	if (error != NULL) {
-		g_critical ("%s: %s", G_STRFUNC, error->message);
-		g_error_free (error);
-		return;
-	}
-
+	uid = E_MAIL_SESSION_LOCAL_UID;
+	service = camel_session_get_service (camel_session, uid);
 	g_return_if_fail (CAMEL_IS_SERVICE (service));
 
-	camel_service_set_display_name (service, _("On This Computer"));
-
 	settings = camel_service_get_settings (service);
 	local_settings = CAMEL_LOCAL_SETTINGS (settings);
 	data_dir = camel_session_get_user_data_dir (camel_session);
@@ -582,6 +693,115 @@ mail_session_add_local_store (EMailSession *session)
 }
 
 static void
+mail_session_force_refresh (EMailSession *session)
+{
+	ESourceRegistry *registry;
+	GHashTableIter iter;
+	GSettings *settings;
+	gboolean unconditionally;
+	gpointer key;
+
+	/* Only refresh when the session is online. */
+	if (!camel_session_get_online (CAMEL_SESSION (session)))
+		return;
+
+	/* FIXME EMailSession should define properties for these. */
+	settings = g_settings_new ("org.gnome.evolution.mail");
+	unconditionally =
+		g_settings_get_boolean (settings, "send-recv-on-start") &&
+		g_settings_get_boolean (settings, "send-recv-all-on-start");
+	g_object_unref (settings);
+
+	registry = e_mail_session_get_registry (session);
+	g_hash_table_iter_init (&iter, session->priv->auto_refresh_table);
+
+	while (g_hash_table_iter_next (&iter, &key, NULL)) {
+		ESource *source;
+		ESourceRefresh *extension;
+		const gchar *extension_name;
+		gboolean refresh_enabled;
+
+		/* The hash table key is the ESource UID. */
+		source = e_source_registry_ref_source (registry, key);
+
+		if (source == NULL)
+			continue;
+
+		extension_name = E_SOURCE_EXTENSION_REFRESH;
+		extension = e_source_get_extension (source, extension_name);
+		refresh_enabled = e_source_refresh_get_enabled (extension);
+
+		if (refresh_enabled || unconditionally)
+			e_source_refresh_force_timeout (source);
+
+		g_object_unref (source);
+	}
+}
+
+static void
+mail_session_cancel_refresh (EMailSession *session)
+{
+	ESourceRegistry *registry;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	registry = e_mail_session_get_registry (session);
+	g_hash_table_iter_init (&iter, session->priv->auto_refresh_table);
+
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		ESource *source;
+		guint timeout_id;
+
+		/* The hash table key is the ESource UID. */
+		source = e_source_registry_ref_source (registry, key);
+
+		/* The hash table value is the refresh timeout ID. */
+		timeout_id = GPOINTER_TO_UINT (value);
+
+		if (source == NULL)
+			continue;
+
+		e_source_refresh_remove_timeout (source, timeout_id);
+
+		g_object_unref (source);
+	}
+
+	/* All timeouts cancelled so clear the auto-refresh table. */
+	g_hash_table_remove_all (session->priv->auto_refresh_table);
+}
+
+static gboolean
+mail_session_idle_refresh_cb (EMailSession *session)
+{
+	/* This only runs once at startup (if settings allow). */
+
+	if (camel_session_get_online (CAMEL_SESSION (session))) {
+		mail_session_force_refresh (session);
+
+		/* Also flush the Outbox. */
+		g_signal_emit (session, signals[FLUSH_OUTBOX], 0);
+	}
+
+	/* Listen for network state changes and force a
+	 * mail store refresh when coming back online. */
+	g_signal_connect (
+		session, "notify::online",
+		G_CALLBACK (mail_session_force_refresh), NULL);
+
+	return FALSE;
+}
+
+static void
+mail_session_set_registry (EMailSession *session,
+                           ESourceRegistry *registry)
+{
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+	g_return_if_fail (session->priv->registry == NULL);
+
+	session->priv->registry = g_object_ref (registry);
+}
+
+static void
 mail_session_set_property (GObject *object,
                            guint property_id,
                            const GValue *value,
@@ -593,6 +813,12 @@ mail_session_set_property (GObject *object,
 				E_MAIL_SESSION (object),
 				g_value_get_string (value));
 			return;
+
+		case PROP_REGISTRY:
+			mail_session_set_registry (
+				E_MAIL_SESSION (object),
+				g_value_get_object (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -626,6 +852,13 @@ mail_session_get_property (GObject *object,
 				E_MAIL_SESSION (object)));
 			return;
 
+		case PROP_REGISTRY:
+			g_value_set_object (
+				value,
+				e_mail_session_get_registry (
+				E_MAIL_SESSION (object)));
+			return;
+
 		case PROP_VFOLDER_STORE:
 			g_value_set_object (
 				value,
@@ -649,12 +882,22 @@ mail_session_dispose (GObject *object)
 		priv->folder_cache = NULL;
 	}
 
-	if (priv->account_list != NULL) {
+	if (priv->registry != NULL) {
+		g_signal_handler_disconnect (
+			priv->registry,
+			priv->source_added_handler_id);
 		g_signal_handler_disconnect (
-			priv->account_list,
-			priv->account_added_handler_id);
-		g_object_unref (priv->account_list);
-		priv->account_list = NULL;
+			priv->registry,
+			priv->source_removed_handler_id);
+		g_signal_handler_disconnect (
+			priv->registry,
+			priv->default_mail_account_handler_id);
+
+		/* This requires the registry. */
+		mail_session_cancel_refresh (E_MAIL_SESSION (object));
+
+		g_object_unref (priv->registry);
+		priv->registry = NULL;
 	}
 
 	if (priv->local_store != NULL) {
@@ -674,27 +917,18 @@ mail_session_dispose (GObject *object)
 }
 
 static void
-mail_session_add_vfolder_store (EMailSession *session)
+mail_session_configure_vfolder_store (EMailSession *session)
 {
 	CamelSession *camel_session;
 	CamelService *service;
-	GError *error = NULL;
+	const gchar *uid;
 
 	camel_session = CAMEL_SESSION (session);
 
-	service = camel_session_add_service (
-		camel_session, E_MAIL_SESSION_VFOLDER_UID,
-		"vfolder", CAMEL_PROVIDER_STORE, &error);
-
-	if (error != NULL) {
-		g_critical ("%s: %s", G_STRFUNC, error->message);
-		g_error_free (error);
-		return;
-	}
-
+	uid = E_MAIL_SESSION_VFOLDER_UID;
+	service = camel_session_get_service (camel_session, uid);
 	g_return_if_fail (CAMEL_IS_SERVICE (service));
 
-	camel_service_set_display_name (service, _("Search Folders"));
 	camel_service_connect_sync (service, NULL, NULL);
 
 	/* XXX There's more configuration to do in vfolder_load_storage()
@@ -712,6 +946,7 @@ mail_session_finalize (GObject *object)
 
 	priv = E_MAIL_SESSION_GET_PRIVATE (object);
 
+	g_hash_table_destroy (priv->auto_refresh_table);
 	g_hash_table_destroy (priv->junk_filters);
 	g_object_unref (priv->proxy);
 
@@ -737,73 +972,76 @@ mail_session_notify (GObject *object,
 		g_object_notify (object, "junk-filter-name");
 }
 
-static gboolean
-mail_session_initialize_stores_idle (gpointer user_data)
-{
-	EMailSession *session = user_data;
-	EAccountList *account_list;
-	EAccount *account;
-	EIterator *iter;
-
-	g_return_val_if_fail (session != NULL, FALSE);
-
-	account_list = e_get_account_list ();
-	iter = e_list_get_iterator (E_LIST (account_list));
-
-	while (e_iterator_is_valid (iter)) {
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iter);
-
-		mail_session_add_by_account (session, account);
-
-		e_iterator_next (iter);
-	}
-
-	g_object_unref (iter);
-
-	return FALSE;
-}
-
 static void
 mail_session_constructed (GObject *object)
 {
 	EMailSession *session;
 	EExtensible *extensible;
+	ESourceRegistry *registry;
 	GType extension_type;
 	GList *list, *link;
 	GSettings *settings;
-	EAccountList *account_list;
+	CamelProviderType provider_type;
+	const gchar *extension_name;
 	gulong handler_id;
 
 	session = E_MAIL_SESSION (object);
+	registry = e_mail_session_get_registry (session);
 
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (e_mail_session_parent_class)->constructed (object);
 
-	account_list = e_get_account_list ();
-	session->priv->account_list = g_object_ref (account_list);
+	/* Add available mail accounts. */
 
-	/* This must be created after the account store. */
-	session->priv->folder_cache = mail_folder_cache_new (session);
+	provider_type = CAMEL_PROVIDER_STORE;
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
 
-	/* Add built-in CamelStores. */
-	mail_session_add_local_store (session);
-	mail_session_add_vfolder_store (session);
+	list = e_source_registry_list_sources (registry, extension_name);
 
-	/* Give it a chance to load user settings, they are not loaded yet.
-	 *
-	 * XXX Is this the case where hiding such natural things like loading
-	 *     user setting into an EExtension strikes back and proves itself
-	 *     being suboptimal?
-	 */
-	g_idle_add (mail_session_initialize_stores_idle, object);
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+
+		mail_session_add_from_source (session, provider_type, source);
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	/* Add available mail transports. */
+
+	provider_type = CAMEL_PROVIDER_TRANSPORT;
+	extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+
+	list = e_source_registry_list_sources (registry, extension_name);
 
-	/* Listen for account list updates. */
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+
+		mail_session_add_from_source (session, provider_type, source);
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	/* Built-in stores require extra configuration. */
+
+	mail_session_configure_local_store (session);
+	mail_session_configure_vfolder_store (session);
+
+	/* Listen for registry changes. */
+
+	handler_id = g_signal_connect (
+		registry, "source-added",
+		G_CALLBACK (mail_session_source_added_cb), session);
+	session->priv->source_added_handler_id = handler_id;
 
 	handler_id = g_signal_connect (
-		account_list, "account-added",
-		G_CALLBACK (mail_session_account_added_cb), session);
-	session->priv->account_added_handler_id = handler_id;
+		registry, "source-removed",
+		G_CALLBACK (mail_session_source_removed_cb), session);
+	session->priv->source_removed_handler_id = handler_id;
+
+	handler_id = g_signal_connect (
+		registry, "notify::default-mail-account",
+		G_CALLBACK (mail_session_default_mail_account_cb), session);
+	session->priv->default_mail_account_handler_id = handler_id;
 
 	extensible = E_EXTENSIBLE (object);
 	e_extensible_load_extensions (extensible);
@@ -852,10 +1090,11 @@ mail_session_constructed (GObject *object)
 
 	g_list_free (list);
 
+	settings = g_settings_new ("org.gnome.evolution.mail");
+
 	/* Bind the "junk-default-plugin" GSettings
 	 * key to our "junk-filter-name" property. */
 
-	settings = g_settings_new ("org.gnome.evolution.mail");
 	g_settings_bind (
 		settings, "junk-default-plugin",
 		object, "junk-filter-name",
@@ -872,6 +1111,19 @@ mail_session_constructed (GObject *object)
 
 	e_proxy_setup_proxy (session->priv->proxy);
 
+	/* Initialize the legacy message-passing framework
+	 * before starting the first mail store refresh. */
+	mail_msg_init ();
+
+	/* The application is not yet fully initialized at this point,
+	 * so run the first mail store refresh from an idle callback. */
+	if (g_settings_get_boolean (settings, "send-recv-on-start"))
+		g_idle_add_full (
+			G_PRIORITY_DEFAULT,
+			(GSourceFunc) mail_session_idle_refresh_cb,
+			g_object_ref (session),
+			(GDestroyNotify) g_object_unref);
+
 	g_object_unref (settings);
 }
 
@@ -882,53 +1134,49 @@ mail_session_add_service (CamelSession *session,
                           CamelProviderType type,
                           GError **error)
 {
+	ESourceRegistry *registry;
 	CamelService *service;
+	const gchar *extension_name;
+
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+	extension_name = e_source_camel_get_extension_name (protocol);
 
 	/* Chain up to parents add_service() method. */
 	service = CAMEL_SESSION_CLASS (e_mail_session_parent_class)->
 		add_service (session, uid, protocol, type, error);
 
-	/* Initialize the CamelSettings object from CamelURL parameters.
-	 * This is temporary; soon we'll read settings from key files. */
+	/* Configure the CamelService from the corresponding ESource. */
 
 	if (CAMEL_IS_SERVICE (service)) {
-		EAccount *account;
-		CamelURL *url = NULL;
-
-		account = e_get_account_by_uid (uid);
-		if (account != NULL) {
-			const gchar *url_string = NULL;
-
-			switch (type) {
-				case CAMEL_PROVIDER_STORE:
-					url_string = account->source->url;
-					break;
-				case CAMEL_PROVIDER_TRANSPORT:
-					url_string = account->transport->url;
-					break;
-				default:
-					break;
-			}
-
-			/* Be lenient about malformed URLs. */
-			if (url_string != NULL)
-				url = camel_url_new (url_string, NULL);
+		ESource *source;
+		ESource *tmp_source;
+
+		/* Each CamelService has a corresponding ESource. */
+		source = e_source_registry_ref_source (registry, uid);
+		g_return_val_if_fail (source != NULL, service);
+
+		tmp_source = e_source_registry_find_extension (
+			registry, source, extension_name);
+		if (tmp_source != NULL) {
+			g_object_unref (source);
+			source = tmp_source;
 		}
 
-		if (url != NULL) {
-			CamelSettings *settings;
+		/* This handles all the messy property bindings. */
+		e_source_camel_configure_service (source, service);
 
-			settings = camel_service_get_settings (service);
-			camel_settings_load_from_url (settings, url);
-			camel_url_free (url);
+		g_object_bind_property (
+			source, "display-name",
+			service, "display-name",
+			G_BINDING_BIDIRECTIONAL |
+			G_BINDING_SYNC_CREATE);
 
-			g_object_notify (G_OBJECT (service), "settings");
+		/* Migrate files for this service from its old
+		 * URL-based directory to a UID-based directory
+		 * if necessary. */
+		camel_service_migrate_files (service);
 
-			/* Migrate files for this service from its old
-			 * URL-based directory to a UID-based directory
-			 * if necessary. */
-			camel_service_migrate_files (service);
-		}
+		g_object_unref (source);
 	}
 
 	return service;
@@ -942,114 +1190,69 @@ mail_session_get_password (CamelSession *session,
                            guint32 flags,
                            GError **error)
 {
-	EAccount *account = NULL;
-	const gchar *display_name = NULL;
-	const gchar *uid = NULL;
-	gchar *ret = NULL;
+	ESourceRegistry *registry;
+	gchar *password = NULL;
 
-	if (CAMEL_IS_SERVICE (service)) {
-		display_name = camel_service_get_display_name (service);
-		uid = camel_service_get_uid (service);
-		account = e_get_account_by_uid (uid);
-	}
+	/* XXX This method is now only for fringe cases.  For normal
+	 *     CamelService authentication, use authenticate_sync().
+	 *
+	 *     The two known fringe cases that still need this are:
+	 *
+	 *     1) CamelSaslPOPB4SMTP, where the CamelService is an SMTP
+	 *        transport and the item name is always "popb4smtp_uid".
+	 *        (This is a dirty hack, Camel just needs some way to
+	 *        pair up a CamelService and CamelTransport.  Not sure
+	 *        what that should look like just yet...)
+	 *
+	 *     2) CamelGpgContext, where the CamelService is NULL and
+	 *        the item name is a user ID (I think).  (Seahorse, or
+	 *        one of its dependent libraries, ought to handle this
+	 *        transparently once Camel fully transitions to GIO.)
+	 */
 
-	if (!strcmp(item, "popb4smtp_uid")) {
-		/* not 100% mt safe, but should be ok */
-		ret = g_strdup ((account != NULL) ? account->uid : uid);
-	} else {
-		gchar *key = mail_session_make_key (service, item);
-		EAccountService *config_service = NULL;
-
-		ret = e_passwords_get_password (NULL, key);
-		if (ret == NULL || (flags & CAMEL_SESSION_PASSWORD_REPROMPT)) {
-			gboolean remember;
-
-			g_free (ret);
-			ret = NULL;
-
-			if (account != NULL) {
-				if (CAMEL_IS_STORE (service))
-					config_service = account->source;
-				if (CAMEL_IS_TRANSPORT (service))
-					config_service = account->transport;
-			}
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
 
-			remember = config_service ? config_service->save_passwd : FALSE;
-
-			if (!config_service || (config_service &&
-				!config_service->get_password_canceled)) {
-				guint32 eflags;
-				gchar *title;
-
-				if (flags & CAMEL_SESSION_PASSPHRASE) {
-					if (display_name != NULL)
-						title = g_strdup_printf (
-							_("Enter Passphrase for %s"),
-							display_name);
-					else
-						title = g_strdup (
-							_("Enter Passphrase"));
-				} else {
-					if (display_name != NULL)
-						title = g_strdup_printf (
-							_("Enter Password for %s"),
-							display_name);
-					else
-						title = g_strdup (
-							_("Enter Password"));
-				}
-				if ((flags & CAMEL_SESSION_PASSWORD_STATIC) != 0)
-					eflags = E_PASSWORDS_REMEMBER_NEVER;
-				else if (config_service == NULL)
-					eflags = E_PASSWORDS_REMEMBER_SESSION;
-				else
-					eflags = E_PASSWORDS_REMEMBER_FOREVER;
-
-				if (flags & CAMEL_SESSION_PASSWORD_REPROMPT)
-					eflags |= E_PASSWORDS_REPROMPT;
-
-				if (flags & CAMEL_SESSION_PASSWORD_SECRET)
-					eflags |= E_PASSWORDS_SECRET;
-
-				if (flags & CAMEL_SESSION_PASSPHRASE)
-					eflags |= E_PASSWORDS_PASSPHRASE;
-
-				/* HACK: breaks abstraction ...
-				 * e_account_writable() doesn't use the
-				 * EAccount, it also uses the same writable
-				 * key for source and transport. */
-				if (!e_account_writable (NULL, E_ACCOUNT_SOURCE_SAVE_PASSWD))
-					eflags |= E_PASSWORDS_DISABLE_REMEMBER;
-
-				ret = e_passwords_ask_password (
-					title, NULL, key, prompt,
-					eflags, &remember, NULL);
-
-				if (!ret)
-					e_passwords_forget_password (NULL, key);
-
-				g_free (title);
-
-				if (ret && config_service) {
-					config_service->save_passwd = remember;
-					e_account_list_save (e_get_account_list ());
-				}
-
-				if (config_service)
-					config_service->get_password_canceled = ret == NULL;
-			}
-		}
+	/* Handle the CamelSaslPOPB4SMTP case. */
+	if (g_strcmp0 (item, "popb4smtp_uid") == 0)
+		return mail_session_resolve_popb4smtp (registry, service);
+
+	/* Otherwise this had better be the CamelGpgContext case. */
+	g_return_val_if_fail (service == NULL, NULL);
+
+	password = e_passwords_get_password (NULL, item);
+
+	if (password == NULL || (flags & CAMEL_SESSION_PASSWORD_REPROMPT)) {
+		gboolean remember;
+		guint eflags = 0;
+
+		if (flags & CAMEL_SESSION_PASSWORD_STATIC)
+			eflags |= E_PASSWORDS_REMEMBER_NEVER;
+		else
+			eflags |= E_PASSWORDS_REMEMBER_SESSION;
+
+		if (flags & CAMEL_SESSION_PASSWORD_REPROMPT)
+			eflags |= E_PASSWORDS_REPROMPT;
+
+		if (flags & CAMEL_SESSION_PASSWORD_SECRET)
+			eflags |= E_PASSWORDS_SECRET;
 
-		g_free (key);
+		if (flags & CAMEL_SESSION_PASSPHRASE)
+			eflags |= E_PASSWORDS_PASSPHRASE;
+
+		password = e_passwords_ask_password (
+			"", NULL, item, prompt, eflags, &remember, NULL);
+
+		if (password == NULL)
+			e_passwords_forget_password (NULL, item);
 	}
 
-	if (ret == NULL)
+	if (password == NULL)
 		g_set_error (
 			error, G_IO_ERROR,
 			G_IO_ERROR_CANCELLED,
-			_("User canceled operation."));
+			_("User cancelled operation"));
 
-	return ret;
+	return password;
 }
 
 static gboolean
@@ -1058,13 +1261,13 @@ mail_session_forget_password (CamelSession *session,
                               const gchar *item,
                               GError **error)
 {
-	gchar *key;
-
-	key = mail_session_make_key (service, item);
+	/* XXX The only remaining user of this method is CamelGpgContext,
+	 *     which does not provide a CamelService.  Use 'item' as the
+	 *     password key. */
 
-	e_passwords_forget_password (NULL, key);
+	g_return_val_if_fail (service == NULL, FALSE);
 
-	g_free (key);
+	e_passwords_forget_password (NULL, item);
 
 	return TRUE;
 }
@@ -1124,16 +1327,19 @@ static gboolean
 mail_session_lookup_addressbook (CamelSession *session,
                                  const gchar *name)
 {
+	ESourceRegistry *registry;
 	CamelInternetAddress *addr;
 	gboolean ret;
 
 	if (!mail_config_get_lookup_book ())
 		return FALSE;
 
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
 	addr = camel_internet_address_new ();
 	camel_address_decode ((CamelAddress *) addr, name);
 	ret = em_utils_in_addressbook (
-		addr, mail_config_get_lookup_book_local_only ());
+		registry, addr, mail_config_get_lookup_book_local_only ());
 	g_object_unref (addr);
 
 	return ret;
@@ -1146,13 +1352,16 @@ mail_session_forward_to (CamelSession *session,
                          const gchar *address,
                          GError **error)
 {
-	EAccount *account;
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceMailIdentity *extension;
 	CamelMimeMessage *forward;
 	CamelStream *mem;
 	CamelInternetAddress *addr;
 	CamelFolder *out_folder;
 	CamelMessageInfo *info;
 	CamelMedium *medium;
+	const gchar *extension_name;
 	const gchar *from_address;
 	const gchar *from_name;
 	const gchar *header_name;
@@ -1166,22 +1375,28 @@ mail_session_forward_to (CamelSession *session,
 	if (!*address) {
 		g_set_error (
 			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
-			_("No destination address provided, forward "
+			_("No destination address provided, forwarding "
 			  "of the message has been cancelled."));
 		return FALSE;
 	}
 
-	account = em_utils_guess_account_with_recipients (message, folder);
-	if (!account) {
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+	/* This returns a new ESource reference. */
+	source = em_utils_guess_mail_identity_with_recipients (
+		registry, message, folder);
+	if (source == NULL) {
 		g_set_error (
 			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
-			_("No account found to use, forward of the "
-			  "message has been cancelled."));
+			_("No identity found to use, forwarding "
+			  "of the message has been cancelled."));
 		return FALSE;
 	}
 
-	from_address = account->id->address;
-	from_name = account->id->name;
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	extension = e_source_get_extension (source, extension_name);
+	from_address = e_source_mail_identity_get_address (extension);
+	from_name = e_source_mail_identity_get_name (extension);
 
 	forward = camel_mime_message_new ();
 
@@ -1255,6 +1470,8 @@ mail_session_forward_to (CamelSession *session,
 
 	camel_message_info_free (info);
 
+	g_object_unref (source);
+
 	return TRUE;
 }
 
@@ -1301,19 +1518,23 @@ mail_session_authenticate_sync (CamelSession *session,
                                 GCancellable *cancellable,
                                 GError **error)
 {
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceAuthenticator *auth;
 	CamelServiceAuthType *authtype = NULL;
 	CamelAuthenticationResult result;
-	CamelProvider *provider;
-	CamelSettings *settings;
-	const gchar *password;
-	guint32 password_flags;
+	const gchar *uid;
+	gboolean authenticated;
 	GError *local_error = NULL;
 
 	/* Do not chain up.  Camel's default method is only an example for
 	 * subclasses to follow.  Instead we mimic most of its logic here. */
 
-	provider = camel_service_get_provider (service);
-	settings = camel_service_get_settings (service);
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+	/* Treat a mechanism name of "none" as NULL. */
+	if (g_strcmp0 (mechanism, "none") == 0)
+		mechanism = NULL;
 
 	/* APOP is one case where a non-SASL mechanism name is passed, so
 	 * don't bail if the CamelServiceAuthType struct comes back NULL. */
@@ -1366,58 +1587,28 @@ mail_session_authenticate_sync (CamelSession *session,
 
 	g_clear_error (&local_error);
 
-	password_flags = CAMEL_SESSION_PASSWORD_SECRET;
-
-retry:
-	password = camel_service_get_password (service);
-
-	if (password == NULL) {
-		CamelNetworkSettings *network_settings;
-		const gchar *host;
-		const gchar *user;
-		gchar *prompt;
-		gchar *new_passwd;
+	/* Find a matching ESource for this CamelService. */
+	uid = camel_service_get_uid (service);
+	source = e_source_registry_ref_source (registry, uid);
 
-		network_settings = CAMEL_NETWORK_SETTINGS (settings);
-		host = camel_network_settings_get_host (network_settings);
-		user = camel_network_settings_get_user (network_settings);
-
-		prompt = camel_session_build_password_prompt (
-			provider->name, user, host);
-
-		new_passwd = camel_session_get_password (
-			session, service, prompt, "password",
-			password_flags, &local_error);
-		camel_service_set_password (service, new_passwd);
-		password = camel_service_get_password (service);
-		g_free (new_passwd);
-
-		g_free (prompt);
+	if (source == NULL) {
+		g_set_error (
+			error, CAMEL_SERVICE_ERROR,
+			CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+			_("No data source found for UID '%s'"), uid);
+		return FALSE;
+	}
 
-		if (local_error != NULL) {
-			g_propagate_error (error, local_error);
-			return FALSE;
-		}
+	auth = e_mail_authenticator_new (service, mechanism);
 
-		if (password == NULL) {
-			g_set_error (
-				error, CAMEL_SERVICE_ERROR,
-				CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
-				_("No password was provided"));
-			return FALSE;
-		}
-	}
+	authenticated = e_source_registry_authenticate_sync (
+		registry, source, auth, cancellable, error);
 
-	result = camel_service_authenticate_sync (
-		service, mechanism, cancellable, error);
+	g_object_unref (auth);
 
-	if (result == CAMEL_AUTHENTICATION_REJECTED) {
-		password_flags |= CAMEL_SESSION_PASSWORD_REPROMPT;
-		camel_service_set_password (service, NULL);
-		goto retry;
-	}
+	g_object_unref (source);
 
-	return (result == CAMEL_AUTHENTICATION_ACCEPTED);
+	return authenticated;
 }
 
 static EMVFolderContext *
@@ -1493,6 +1684,18 @@ e_mail_session_class_init (EMailSessionClass *class)
 
 	g_object_class_install_property (
 		object_class,
+		PROP_REGISTRY,
+		g_param_spec_object (
+			"registry",
+			"Registry",
+			"Data source registry",
+			E_TYPE_SOURCE_REGISTRY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
 		PROP_VFOLDER_STORE,
 		g_param_spec_object (
 			"vfolder-store",
@@ -1512,15 +1715,32 @@ e_mail_session_class_init (EMailSessionClass *class)
 		"flush-outbox",
 		G_OBJECT_CLASS_TYPE (object_class),
 		G_SIGNAL_RUN_FIRST,
-		0, /* struct offset */
-		NULL, NULL, /* accumulator */
+		G_STRUCT_OFFSET (EMailSessionClass, flush_outbox),
+		NULL, NULL,
 		g_cclosure_marshal_VOID__VOID,
 		G_TYPE_NONE, 0);
 
 	/**
+	 * EMailSession::refresh-service
+	 * @session: the #EMailSession that emitted the signal
+	 * @service: a #CamelService
+	 *
+	 * Emitted when @service should be refreshed.
+	 **/
+	signals[REFRESH_SERVICE] = g_signal_new (
+		"refresh-service",
+		G_OBJECT_CLASS_TYPE (object_class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailSessionClass, refresh_service),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		CAMEL_TYPE_SERVICE);
+
+	/**
 	 * EMailSession::store-added
-	 * @session: the email session
-	 * @store: the CamelStore
+	 * @session: the #EMailSession that emitted the signal
+	 * @store: a #CamelStore
 	 *
 	 * Emitted when a store is added
 	 **/
@@ -1528,16 +1748,16 @@ e_mail_session_class_init (EMailSessionClass *class)
 		"store-added",
 		G_OBJECT_CLASS_TYPE (object_class),
 		G_SIGNAL_RUN_FIRST,
-		0, /* struct offset */
-		NULL, NULL, /* accumulator */
+		G_STRUCT_OFFSET (EMailSessionClass, store_added),
+		NULL, NULL,
 		g_cclosure_marshal_VOID__OBJECT,
 		G_TYPE_NONE, 1,
 		CAMEL_TYPE_STORE);
 
 	/**
 	 * EMailSession::store-removed
-	 * @session: the email session
-	 * @store: the CamelStore
+	 * @session: the #EMailSession that emitted the signal
+	 * @store: a #CamelStore
 	 *
 	 * Emitted when a store is removed 
 	 **/
@@ -1545,25 +1765,37 @@ e_mail_session_class_init (EMailSessionClass *class)
 		"store-removed",
 		G_OBJECT_CLASS_TYPE (object_class),
 		G_SIGNAL_RUN_FIRST,
-		0, /* struct offset */
-		NULL, NULL, /* accumulator */
+		G_STRUCT_OFFSET (EMailSessionClass, store_removed),
+		NULL, NULL,
 		g_cclosure_marshal_VOID__OBJECT,
 		G_TYPE_NONE, 1,
 		CAMEL_TYPE_STORE);
 
 	camel_null_store_register_provider ();
+
+	/* Make sure ESourceCamel picks up the "none" provider. */
+	e_source_camel_register_types ();
 }
 
 static void
 e_mail_session_init (EMailSession *session)
 {
+	GHashTable *auto_refresh_table;
 	GHashTable *junk_filters;
 
+	auto_refresh_table = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) NULL);
+
 	junk_filters = g_hash_table_new (
 		(GHashFunc) g_str_hash,
 		(GEqualFunc) g_str_equal);
 
 	session->priv = E_MAIL_SESSION_GET_PRIVATE (session);
+	session->priv->folder_cache = mail_folder_cache_new (session);
+	session->priv->auto_refresh_table = auto_refresh_table;
 	session->priv->junk_filters = junk_filters;
 	session->priv->proxy = e_proxy_new ();
 
@@ -1573,17 +1805,16 @@ e_mail_session_init (EMailSession *session)
 	session->priv->local_folder_uris =
 		g_ptr_array_new_with_free_func (
 		(GDestroyNotify) g_free);
-
-	/* Initialize the EAccount setup. */
-	e_account_writable (NULL, E_ACCOUNT_SOURCE_SAVE_PASSWD);
 }
 
 EMailSession *
-e_mail_session_new (void)
+e_mail_session_new (ESourceRegistry *registry)
 {
 	const gchar *user_data_dir;
 	const gchar *user_cache_dir;
 
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	user_data_dir = mail_session_get_data_dir ();
 	user_cache_dir = mail_session_get_cache_dir ();
 
@@ -1591,9 +1822,18 @@ e_mail_session_new (void)
 		E_TYPE_MAIL_SESSION,
 		"user-data-dir", user_data_dir,
 		"user-cache-dir", user_cache_dir,
+		"registry", registry,
 		NULL);
 }
 
+ESourceRegistry *
+e_mail_session_get_registry (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return session->priv->registry;
+}
+
 MailFolderCache *
 e_mail_session_get_folder_cache (EMailSession *session)
 {
@@ -1989,6 +2229,67 @@ e_mail_session_uri_to_folder_finish (EMailSession *session,
 	return g_object_ref (context->folder);
 }
 
+gboolean
+e_binding_transform_service_to_source (GBinding *binding,
+                                       const GValue *source_value,
+                                       GValue *target_value,
+                                       gpointer session)
+{
+	CamelService *service;
+	ESourceRegistry *registry;
+	ESource *source;
+	const gchar *uid;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
+
+	service = g_value_get_object (source_value);
+
+	if (!CAMEL_IS_SERVICE (service))
+		return FALSE;
+
+	uid = camel_service_get_uid (service);
+	registry = e_mail_session_get_registry (session);
+	source = e_source_registry_ref_source (registry, uid);
+
+	if (source != NULL) {
+		g_value_take_object (target_value, source);
+		success = TRUE;
+	}
+
+	return success;
+}
+
+gboolean
+e_binding_transform_source_to_service (GBinding *binding,
+                                       const GValue *source_value,
+                                       GValue *target_value,
+                                       gpointer session)
+{
+	CamelService *service;
+	ESource *source;
+	const gchar *uid;
+
+	g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
+
+	source = g_value_get_object (source_value);
+
+	if (!E_IS_SOURCE (source))
+		return FALSE;
+
+	uid = e_source_get_uid (source);
+	service = camel_session_get_service (session, uid);
+
+	if (!CAMEL_IS_SERVICE (service))
+		return FALSE;
+
+	g_value_set_object (target_value, service);
+
+	return TRUE;
+}
+
 /******************************** Legacy API *********************************/
 
 void
diff --git a/libemail-engine/e-mail-session.h b/libemail-engine/e-mail-session.h
index 16a6592..bf436c7 100644
--- a/libemail-engine/e-mail-session.h
+++ b/libemail-engine/e-mail-session.h
@@ -26,6 +26,7 @@
 #define E_MAIL_SESSION_H
 
 #include <camel/camel.h>
+#include <libedataserver/e-source-registry.h>
 #include <libemail-engine/e-mail-enums.h>
 #include <libemail-engine/mail-folder-cache.h>
 #include <libemail-utils/em-vfolder-context.h>
@@ -67,12 +68,22 @@ struct _EMailSession {
 struct _EMailSessionClass {
 	CamelSessionClass parent_class;
 
-	EMVFolderContext *	(*create_vfolder_context)		(EMailSession *session);
-
+	EMVFolderContext *
+			(*create_vfolder_context)
+						(EMailSession *session);
+	void		(*flush_outbox)		(EMailSession *session);
+	void		(*refresh_service)	(EMailSession *session,
+						 CamelService *service);
+	void		(*store_added)		(EMailSession *session,
+						 CamelStore *store);
+	void		(*store_removed)	(EMailSession *session,
+						 CamelStore *store);
 };
 
 GType		e_mail_session_get_type		(void);
-EMailSession *	e_mail_session_new		(void);
+EMailSession *	e_mail_session_new		(ESourceRegistry *registry);
+ESourceRegistry *
+		e_mail_session_get_registry	(EMailSession *session);
 MailFolderCache *
 		e_mail_session_get_folder_cache	(EMailSession *session);
 CamelStore *	e_mail_session_get_local_store	(EMailSession *session);
@@ -131,6 +142,19 @@ CamelFolder *	e_mail_session_uri_to_folder_finish
 EMVFolderContext *
 		e_mail_session_create_vfolder_context
 						(EMailSession *session);
+
+/* Useful GBinding transform functions */
+gboolean	e_binding_transform_service_to_source
+						(GBinding *binding,
+						 const GValue *source_value,
+						 GValue *target_value,
+						 gpointer session);
+gboolean	e_binding_transform_source_to_service
+						(GBinding *binding,
+						 const GValue *source_value,
+						 GValue *target_value,
+						 gpointer session);
+
 /*** Legacy API ***/
 
 void		mail_session_flush_filter_log	(EMailSession *session);
diff --git a/libemail-engine/e-mail-utils.c b/libemail-engine/e-mail-utils.c
index 61ef8d6..3838de3 100644
--- a/libemail-engine/e-mail-utils.c
+++ b/libemail-engine/e-mail-utils.c
@@ -46,9 +46,14 @@
 #include <libedataserver/e-data-server-util.h>
 #include <libedataserver/e-flag.h>
 #include <libedataserver/e-proxy.h>
+#include <libedataserver/e-source-address-book.h>
+#include <libedataserver/e-source-autocomplete.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
 
-#include "libemail-utils/e-account-utils.h"
-#include "libemail-utils/mail-mt.h"
+#include <libemail-utils/mail-mt.h>
 
 #include "e-mail-folder-utils.h"
 #include "e-mail-session.h"
@@ -58,131 +63,141 @@
 #define d(x)
 
 /**
- * em_utils_folder_is_templates:
+ * em_utils_folder_is_drafts:
+ * @registry: an #ESourceRegistry
  * @folder: a #CamelFolder
  *
- * Decides if @folder is a Templates folder.
+ * Decides if @folder is a Drafts folder.
  *
- * Returns %TRUE if this is a Templates folder or %FALSE otherwise.
+ * Returns %TRUE if this is a Drafts folder or %FALSE otherwise.
  **/
-
 gboolean
-em_utils_folder_is_templates (CamelFolder *folder)
+em_utils_folder_is_drafts (ESourceRegistry *registry,
+                           CamelFolder *folder)
 {
-	CamelFolder *local_templates_folder;
+	CamelFolder *local_drafts_folder;
 	CamelSession *session;
 	CamelStore *store;
-	EAccountList *account_list;
-	EIterator *iterator;
+	GList *list, *iter;
 	gchar *folder_uri;
-	gboolean is_templates = FALSE;
+	gboolean is_drafts = FALSE;
+	const gchar *extension_name;
 
 	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
 
 	store = camel_folder_get_parent_store (folder);
 	session = camel_service_get_session (CAMEL_SERVICE (store));
 
-	local_templates_folder =
+	local_drafts_folder =
 		e_mail_session_get_local_folder (
-		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_TEMPLATES);
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS);
 
-	if (folder == local_templates_folder)
+	if (folder == local_drafts_folder)
 		return TRUE;
 
 	folder_uri = e_mail_folder_uri_from_folder (folder);
 
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
+	store = camel_folder_get_parent_store (folder);
+	session = camel_service_get_session (CAMEL_SERVICE (store));
 
-	while (!is_templates && e_iterator_is_valid (iterator)) {
-		EAccount *account;
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iterator);
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		ESource *source = E_SOURCE (iter->data);
+		ESourceExtension *extension;
+		const gchar *drafts_folder_uri;
 
-		if (account->templates_folder_uri != NULL)
-			is_templates = e_mail_folder_uri_equal (
-				session, folder_uri,
-				account->templates_folder_uri);
+		extension = e_source_get_extension (source, extension_name);
+
+		drafts_folder_uri =
+			e_source_mail_composition_get_drafts_folder (
+			E_SOURCE_MAIL_COMPOSITION (extension));
+
+		if (drafts_folder_uri != NULL)
+			is_drafts = e_mail_folder_uri_equal (
+				session, folder_uri, drafts_folder_uri);
 
-		e_iterator_next (iterator);
+		if (is_drafts)
+			break;
 	}
 
-	g_object_unref (iterator);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 	g_free (folder_uri);
 
-	return is_templates;
+	return is_drafts;
 }
 
 /**
- * em_utils_folder_is_drafts:
+ * em_utils_folder_is_templates:
+ * @registry: an #ESourceRegistry
  * @folder: a #CamelFolder
  *
- * Decides if @folder is a Drafts folder.
+ * Decides if @folder is a Templates folder.
  *
- * Returns %TRUE if this is a Drafts folder or %FALSE otherwise.
+ * Returns %TRUE if this is a Templates folder or %FALSE otherwise.
  **/
+
 gboolean
-em_utils_folder_is_drafts (CamelFolder *folder)
+em_utils_folder_is_templates (ESourceRegistry *registry,
+                              CamelFolder *folder)
 {
-	CamelFolder *local_drafts_folder;
+	CamelFolder *local_templates_folder;
 	CamelSession *session;
 	CamelStore *store;
-	MailFolderCache *cache;
-	EMailSession *mail_session;
-	CamelFolderInfoFlags flags = 0;
-	EAccountList *account_list;
-	EIterator *iterator;
+	GList *list, *iter;
 	gchar *folder_uri;
-	gboolean is_drafts = FALSE;
+	gboolean is_templates = FALSE;
+	const gchar *extension_name;
 
 	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
 
 	store = camel_folder_get_parent_store (folder);
 	session = camel_service_get_session (CAMEL_SERVICE (store));
-	mail_session = E_MAIL_SESSION (session);
 
-	local_drafts_folder =
+	local_templates_folder =
 		e_mail_session_get_local_folder (
-		mail_session, E_MAIL_LOCAL_FOLDER_DRAFTS);
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_TEMPLATES);
 
-	if (folder == local_drafts_folder)
+	if (folder == local_templates_folder)
 		return TRUE;
 
-	cache = e_mail_session_get_folder_cache (mail_session);
+	folder_uri = e_mail_folder_uri_from_folder (folder);
 
-	/* user can select Inbox as his Draft folder - in that case prefer Inbox type */
-	if (mail_folder_cache_get_folder_info_flags (cache, folder, &flags) &&
-	    (flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX)
-		return FALSE;
+	store = camel_folder_get_parent_store (folder);
+	session = camel_service_get_session (CAMEL_SERVICE (store));
 
-	folder_uri = e_mail_folder_uri_from_folder (folder);
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		ESource *source = E_SOURCE (iter->data);
+		ESourceExtension *extension;
+		const gchar *templates_folder_uri;
 
-	while (!is_drafts && e_iterator_is_valid (iterator)) {
-		EAccount *account;
+		extension = e_source_get_extension (source, extension_name);
 
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iterator);
+		templates_folder_uri =
+			e_source_mail_composition_get_templates_folder (
+			E_SOURCE_MAIL_COMPOSITION (extension));
 
-		if (account->drafts_folder_uri != NULL)
-			is_drafts = e_mail_folder_uri_equal (
-				session, folder_uri,
-				account->drafts_folder_uri);
+		if (templates_folder_uri != NULL)
+			is_templates = e_mail_folder_uri_equal (
+				session, folder_uri, templates_folder_uri);
 
-		e_iterator_next (iterator);
+		if (is_templates)
+			break;
 	}
 
-	g_object_unref (iterator);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 	g_free (folder_uri);
 
-	return is_drafts;
+	return is_templates;
 }
 
 /**
  * em_utils_folder_is_sent:
+ * @registry: an #ESourceRegistry
  * @folder: a #CamelFolder
  *
  * Decides if @folder is a Sent folder.
@@ -190,59 +205,57 @@ em_utils_folder_is_drafts (CamelFolder *folder)
  * Returns %TRUE if this is a Sent folder or %FALSE otherwise.
  **/
 gboolean
-em_utils_folder_is_sent (CamelFolder *folder)
+em_utils_folder_is_sent (ESourceRegistry *registry,
+                         CamelFolder *folder)
 {
 	CamelFolder *local_sent_folder;
 	CamelSession *session;
 	CamelStore *store;
-	MailFolderCache *cache;
-	EMailSession *mail_session;
-	CamelFolderInfoFlags flags = 0;
-	EAccountList *account_list;
-	EIterator *iterator;
+	GList *list, *iter;
 	gchar *folder_uri;
 	gboolean is_sent = FALSE;
+	const gchar *extension_name;
 
 	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
 
 	store = camel_folder_get_parent_store (folder);
 	session = camel_service_get_session (CAMEL_SERVICE (store));
-	mail_session = E_MAIL_SESSION (session);
 
 	local_sent_folder =
 		e_mail_session_get_local_folder (
-		mail_session, E_MAIL_LOCAL_FOLDER_SENT);
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_SENT);
 
 	if (folder == local_sent_folder)
 		return TRUE;
 
-	cache = e_mail_session_get_folder_cache (mail_session);
+	folder_uri = e_mail_folder_uri_from_folder (folder);
 
-	/* user can select Inbox as his Sent folder - in that case prefer Inbox type */
-	if (mail_folder_cache_get_folder_info_flags (cache, folder, &flags) &&
-	    (flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX)
-		return FALSE;
+	store = camel_folder_get_parent_store (folder);
+	session = camel_service_get_session (CAMEL_SERVICE (store));
 
-	folder_uri = e_mail_folder_uri_from_folder (folder);
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		ESource *source = E_SOURCE (iter->data);
+		ESourceExtension *extension;
+		const gchar *sent_folder_uri;
 
-	while (!is_sent && e_iterator_is_valid (iterator)) {
-		EAccount *account;
+		extension = e_source_get_extension (source, extension_name);
 
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iterator);
+		sent_folder_uri =
+			e_source_mail_submission_get_sent_folder (
+			E_SOURCE_MAIL_SUBMISSION (extension));
 
-		if (account->sent_folder_uri != NULL)
+		if (sent_folder_uri != NULL)
 			is_sent = e_mail_folder_uri_equal (
-				session, folder_uri,
-				account->sent_folder_uri);
+				session, folder_uri, sent_folder_uri);
 
-		e_iterator_next (iterator);
+		if (is_sent)
+			break;
 	}
 
-	g_object_unref (iterator);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 	g_free (folder_uri);
 
 	return is_sent;
@@ -250,6 +263,7 @@ em_utils_folder_is_sent (CamelFolder *folder)
 
 /**
  * em_utils_folder_is_outbox:
+ * @registry: an #ESourceRegistry
  * @folder: a #CamelFolder
  *
  * Decides if @folder is an Outbox folder.
@@ -257,7 +271,8 @@ em_utils_folder_is_sent (CamelFolder *folder)
  * Returns %TRUE if this is an Outbox folder or %FALSE otherwise.
  **/
 gboolean
-em_utils_folder_is_outbox (CamelFolder *folder)
+em_utils_folder_is_outbox (ESourceRegistry *registry,
+                           CamelFolder *folder)
 {
 	CamelStore *store;
 	CamelSession *session;
@@ -277,19 +292,6 @@ em_utils_folder_is_outbox (CamelFolder *folder)
 
 /* ********************************************************************** */
 
-/* runs sync, in main thread */
-static gpointer
-emu_addr_setup (gpointer user_data)
-{
-	GError *err = NULL;
-	ESourceList **psource_list = user_data;
-
-	if (!e_book_client_get_sources (psource_list, &err))
-		g_error_free (err);
-
-	return NULL;
-}
-
 static void
 emu_addr_cancel_stop (gpointer data)
 {
@@ -405,33 +407,31 @@ static GHashTable *emu_books_hash = NULL;
  * broken books, which failed to open for some reason */
 static GHashTable *emu_broken_books_hash = NULL;
 
-static ESourceList *emu_books_source_list = NULL;
-
 static gboolean
-search_address_in_addressbooks (const gchar *address,
+search_address_in_addressbooks (ESourceRegistry *registry,
+                                const gchar *address,
                                 gboolean local_only,
                                 gboolean (*check_contact) (EContact *contact,
                                                            gpointer user_data),
                                 gpointer user_data)
 {
+	GList *list, *link;
+	GList *addr_sources = NULL;
 	gboolean found = FALSE, stop = FALSE, found_any = FALSE;
 	gchar *lowercase_addr;
 	gpointer ptr;
 	EBookQuery *book_query;
 	gchar *query;
-	GSList *s, *g, *addr_sources = NULL;
 	GHook *hook_cancellable;
 	GCancellable *cancellable;
+	const gchar *extension_name;
 
 	if (!address || !*address)
 		return FALSE;
 
 	G_LOCK (contact_cache);
 
-	if (!emu_books_source_list) {
-		mail_call_main (
-			MAIL_CALL_p_p, (MailMainFunc)
-			emu_addr_setup, &emu_books_source_list);
+	if (emu_books_hash == NULL) {
 		emu_books_hash = g_hash_table_new_full (
 			g_str_hash, g_str_equal, g_free, g_object_unref);
 		emu_broken_books_hash = g_hash_table_new_full (
@@ -440,11 +440,6 @@ search_address_in_addressbooks (const gchar *address,
 			g_str_hash, g_str_equal, g_free, NULL);
 	}
 
-	if (!emu_books_source_list) {
-		G_UNLOCK (contact_cache);
-		return FALSE;
-	}
-
 	lowercase_addr = g_utf8_strdown (address, -1);
 	ptr = g_hash_table_lookup (contact_cache, lowercase_addr);
 	if (ptr != NULL && (check_contact == NULL || ptr == NOT_FOUND_BOOK)) {
@@ -457,35 +452,48 @@ search_address_in_addressbooks (const gchar *address,
 	query = e_book_query_to_string (book_query);
 	e_book_query_unref (book_query);
 
-	for (g = e_source_list_peek_groups (emu_books_source_list);
-			g; g = g_slist_next (g)) {
-		ESourceGroup *group = g->data;
+	extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-		if (!group)
-			continue;
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *backend_name;
+		gboolean source_is_local;
+		gboolean autocomplete;
+
+		extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+		extension = e_source_get_extension (source, extension_name);
+
+		backend_name = e_source_backend_get_backend_name (
+			E_SOURCE_BACKEND (extension));
+
+		source_is_local = (g_strcmp0 (backend_name, "local") == 0);
 
-		if (local_only && !(e_source_group_peek_base_uri (group) &&
-			g_str_has_prefix (
-			e_source_group_peek_base_uri (group), "local:")))
+		if (local_only && !source_is_local)
 			continue;
 
-		for (s = e_source_group_peek_sources (group); s; s = g_slist_next (s)) {
-			ESource *source = s->data;
-			const gchar *completion = e_source_get_property (source, "completion");
+		extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+		extension = e_source_get_extension (source, extension_name);
 
-			if (completion && g_ascii_strcasecmp (completion, "true") == 0) {
-				addr_sources = g_slist_prepend (
-					addr_sources, g_object_ref (source));
-			}
-		}
+		autocomplete = e_source_autocomplete_get_include_me (
+			E_SOURCE_AUTOCOMPLETE (extension));
+
+		if (!autocomplete)
+			continue;
+
+		addr_sources = g_list_prepend (
+			addr_sources, g_object_ref (source));
 	}
 
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
 	cancellable = g_cancellable_new ();
 	hook_cancellable = mail_cancel_hook_add (
 		emu_addr_cancel_cancellable, cancellable);
 
-	for (s = addr_sources; !stop && !found && s; s = g_slist_next (s)) {
-		ESource *source = s->data;
+	for (link = addr_sources; !stop && !found && link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
 		GSList *contacts;
 		EBookClient *book_client = NULL;
 		GHook *hook_stop;
@@ -620,7 +628,7 @@ search_address_in_addressbooks (const gchar *address,
 	mail_cancel_hook_remove (hook_cancellable);
 	g_object_unref (cancellable);
 
-	g_slist_free_full (addr_sources, (GDestroyNotify) g_object_unref);
+	g_list_free_full (addr_sources, (GDestroyNotify) g_object_unref);
 
 	g_free (query);
 
@@ -637,16 +645,20 @@ search_address_in_addressbooks (const gchar *address,
 }
 
 gboolean
-em_utils_in_addressbook (CamelInternetAddress *iaddr,
+em_utils_in_addressbook (ESourceRegistry *registry,
+                         CamelInternetAddress *iaddr,
                          gboolean local_only)
 {
 	const gchar *addr;
 
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
+
 	/* TODO: check all addresses? */
 	if (iaddr == NULL || !camel_internet_address_get (iaddr, 0, NULL, &addr))
 		return FALSE;
 
-	return search_address_in_addressbooks (addr, local_only, NULL, NULL);
+	return search_address_in_addressbooks (
+		registry, addr, local_only, NULL, NULL);
 }
 
 static gboolean
@@ -687,7 +699,8 @@ G_LOCK_DEFINE_STATIC (photos_cache);
 static GSList *photos_cache = NULL; /* list of PhotoInfo-s */
 
 CamelMimePart *
-em_utils_contact_photo (CamelInternetAddress *cia,
+em_utils_contact_photo (ESourceRegistry *registry,
+                        CamelInternetAddress *cia,
                         gboolean local_only)
 {
 	const gchar *addr = NULL;
@@ -696,6 +709,8 @@ em_utils_contact_photo (CamelInternetAddress *cia,
 	GSList *p, *last = NULL;
 	gint cache_len;
 
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	if (cia == NULL || !camel_internet_address_get (cia, 0, NULL, &addr) || !addr) {
 		return NULL;
 	}
@@ -722,7 +737,8 @@ em_utils_contact_photo (CamelInternetAddress *cia,
 
 	/* !p means the address had not been found in the cache */
 	if (!p && search_address_in_addressbooks (
-			addr, local_only, extract_photo_data, &photo)) {
+		registry, addr, local_only, extract_photo_data, &photo)) {
+
 		PhotoInfo *pi;
 
 		/* keep only up to 10 photos in memory */
@@ -838,11 +854,6 @@ emu_free_mail_cache (void)
 		emu_broken_books_hash = NULL;
 	}
 
-	if (emu_books_source_list) {
-		g_object_unref (emu_books_source_list);
-		emu_books_source_list = NULL;
-	}
-
 	if (contact_cache) {
 		g_hash_table_destroy (contact_cache);
 		contact_cache = NULL;
@@ -859,70 +870,197 @@ emu_free_mail_cache (void)
 	G_UNLOCK (photos_cache);
 }
 
-static EAccount *
-guess_account_from_folder (CamelFolder *folder)
+static ESource *
+guess_mail_account_from_folder (ESourceRegistry *registry,
+                                CamelFolder *folder)
 {
+	ESource *source;
 	CamelStore *store;
 	const gchar *uid;
 
+	/* Lookup an ESource by CamelStore UID. */
 	store = camel_folder_get_parent_store (folder);
 	uid = camel_service_get_uid (CAMEL_SERVICE (store));
+	source = e_source_registry_ref_source (registry, uid);
+
+	/* If we found an ESource, make sure it's a mail account. */
+	if (source != NULL) {
+		const gchar *extension_name;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+		if (!e_source_has_extension (source, extension_name)) {
+			g_object_unref (source);
+			source = NULL;
+		}
+	}
 
-	return e_get_account_by_uid (uid);
+	return source;
 }
 
-static EAccount *
-guess_account_from_message (CamelMimeMessage *message)
+static ESource *
+guess_mail_account_from_message (ESourceRegistry *registry,
+                                 CamelMimeMessage *message)
 {
+	ESource *source = NULL;
 	const gchar *uid;
 
+	/* Lookup an ESource by 'X-Evolution-Source' header. */
 	uid = camel_mime_message_get_source (message);
+	if (uid != NULL)
+		source = e_source_registry_ref_source (registry, uid);
 
-	return (uid != NULL) ? e_get_account_by_uid (uid) : NULL;
+	/* If we found an ESource, make sure it's a mail account. */
+	if (source != NULL) {
+		const gchar *extension_name;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+		if (!e_source_has_extension (source, extension_name)) {
+			g_object_unref (source);
+			source = NULL;
+		}
+	}
+
+	return source;
 }
 
-EAccount *
-em_utils_guess_account (CamelMimeMessage *message,
-                        CamelFolder *folder)
+ESource *
+em_utils_guess_mail_account (ESourceRegistry *registry,
+                             CamelMimeMessage *message,
+                             CamelFolder *folder)
 {
-	EAccount *account = NULL;
+	ESource *source = NULL;
+	const gchar *newsgroups;
 
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
 
 	if (folder != NULL)
 		g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
 
 	/* check for newsgroup header */
-	if (folder != NULL
-	    && camel_medium_get_header (CAMEL_MEDIUM (message), "Newsgroups"))
-		account = guess_account_from_folder (folder);
+	newsgroups = camel_medium_get_header (
+		CAMEL_MEDIUM (message), "Newsgroups");
+	if (folder != NULL && newsgroups != NULL)
+		source = guess_mail_account_from_folder (registry, folder);
 
 	/* check for source folder */
-	if (account == NULL && folder != NULL)
-		account = guess_account_from_folder (folder);
+	if (source == NULL && folder != NULL)
+		source = guess_mail_account_from_folder (registry, folder);
 
 	/* then message source */
-	if (account == NULL)
-		account = guess_account_from_message (message);
+	if (source == NULL)
+		source = guess_mail_account_from_message (registry, message);
+
+	return source;
+}
+
+ESource *
+em_utils_guess_mail_identity (ESourceRegistry *registry,
+                              CamelMimeMessage *message,
+                              CamelFolder *folder)
+{
+	ESource *source;
+	ESourceExtension *extension;
+	const gchar *extension_name;
+	const gchar *uid;
+
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+	if (folder != NULL)
+		g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+
+	source = em_utils_guess_mail_account (registry, message, folder);
+
+	if (source == NULL)
+		return NULL;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+
+	uid = e_source_mail_account_get_identity_uid (
+		E_SOURCE_MAIL_ACCOUNT (extension));
+	if (uid == NULL)
+		return NULL;
+
+	source = e_source_registry_ref_source (registry, uid);
+	if (source == NULL)
+		return NULL;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	if (!e_source_has_extension (source, extension_name)) {
+		g_object_unref (source);
+		return NULL;
+	}
+
+	return source;
+}
+
+static gboolean
+mail_account_in_recipients (ESourceRegistry *registry,
+                            ESource *source,
+                            GHashTable *recipients)
+{
+	ESourceExtension *extension;
+	const gchar *extension_name;
+	const gchar *uid;
+	gboolean match = FALSE;
+	gchar *address;
+
+	/* Disregard disabled mail accounts. */
+	if (!e_source_get_enabled (source))
+		return FALSE;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+
+	uid = e_source_mail_account_get_identity_uid (
+		E_SOURCE_MAIL_ACCOUNT (extension));
+	if (uid == NULL)
+		return FALSE;
+
+	source = e_source_registry_ref_source (registry, uid);
+	if (source == NULL)
+		return FALSE;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	if (!e_source_has_extension (source, extension_name)) {
+		g_object_unref (source);
+		return FALSE;
+	}
+
+	extension = e_source_get_extension (source, extension_name);
 
-	return account;
+	address = e_source_mail_identity_dup_address (
+		E_SOURCE_MAIL_IDENTITY (extension));
+
+	g_object_unref (source);
+
+	if (address != NULL) {
+		match = (g_hash_table_lookup (recipients, address) != NULL);
+		g_free (address);
+	}
+
+	return match;
 }
 
-EAccount *
-em_utils_guess_account_with_recipients (CamelMimeMessage *message,
-                                        CamelFolder *folder)
+ESource *
+em_utils_guess_mail_account_with_recipients (ESourceRegistry *registry,
+                                             CamelMimeMessage *message,
+                                             CamelFolder *folder)
 {
-	EAccount *account = NULL;
-	EAccountList *account_list;
+	ESource *source = NULL;
 	GHashTable *recipients;
-	EIterator *iterator;
 	CamelInternetAddress *addr;
+	GList *list, *iter;
+	const gchar *extension_name;
 	const gchar *type;
 	const gchar *key;
 
 	/* This policy is subject to debate and tweaking,
 	 * but please also document the rational here. */
 
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
 
 	/* Build a set of email addresses in which to test for membership.
@@ -952,53 +1090,126 @@ em_utils_guess_account_with_recipients (CamelMimeMessage *message,
 	}
 
 	/* First Preference: We were given a folder that maps to an
-	 * enabled account, and that account's email address appears
+	 * enabled mail account, and that account's address appears
 	 * in the list of To: or Cc: recipients. */
 
 	if (folder != NULL)
-		account = guess_account_from_folder (folder);
-
-	if (account == NULL || !account->enabled)
-		goto second_preference;
+		source = guess_mail_account_from_folder (registry, folder);
 
-	if ((key = account->id->address) == NULL)
+	if (source == NULL)
 		goto second_preference;
 
-	if (g_hash_table_lookup (recipients, key) != NULL)
+	if (mail_account_in_recipients (registry, source, recipients))
 		goto exit;
 
 second_preference:
 
-	/* Second Preference: Choose any enabled account whose email
+	/* Second Preference: Choose any enabled mail account whose
 	 * address appears in the list to To: or Cc: recipients. */
 
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
+	if (source != NULL) {
+		g_object_unref (source);
+		source = NULL;
+	}
 
-	while (e_iterator_is_valid (iterator)) {
-		account = (EAccount *) e_iterator_get (iterator);
-		e_iterator_next (iterator);
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-		if (account == NULL || !account->enabled)
-			continue;
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		ESource *temp = E_SOURCE (iter->data);
 
-		if ((key = account->id->address) == NULL)
-			continue;
-
-		if (g_hash_table_lookup (recipients, key) != NULL) {
-			g_object_unref (iterator);
-			goto exit;
+		if (mail_account_in_recipients (registry, temp, recipients)) {
+			source = g_object_ref (temp);
+			break;
 		}
 	}
-	g_object_unref (iterator);
 
-	/* Last Preference: Defer to em_utils_guess_account(). */
-	account = em_utils_guess_account (message, folder);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	if (source != NULL)
+		goto exit;
+
+	/* Last Preference: Defer to em_utils_guess_mail_account(). */
+	source = em_utils_guess_mail_account (registry, message, folder);
 
 exit:
 	g_hash_table_destroy (recipients);
 
-	return account;
+	return source;
+}
+
+ESource *
+em_utils_guess_mail_identity_with_recipients (ESourceRegistry *registry,
+                                              CamelMimeMessage *message,
+                                              CamelFolder *folder)
+{
+	ESource *source;
+	ESourceExtension *extension;
+	const gchar *extension_name;
+	const gchar *uid;
+
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+	source = em_utils_guess_mail_account_with_recipients (
+		registry, message, folder);
+
+	if (source == NULL)
+		return NULL;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+
+	uid = e_source_mail_account_get_identity_uid (
+		E_SOURCE_MAIL_ACCOUNT (extension));
+	if (uid == NULL)
+		return NULL;
+
+	source = e_source_registry_ref_source (registry, uid);
+	if (source == NULL)
+		return NULL;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	if (!e_source_has_extension (source, extension_name)) {
+		g_object_unref (source);
+		return NULL;
+	}
+
+	return source;
+}
+
+ESource *
+em_utils_ref_mail_identity_for_store (ESourceRegistry *registry,
+                                      CamelStore *store)
+{
+	ESourceMailAccount *extension;
+	ESource *source;
+	const gchar *extension_name;
+	const gchar *store_uid;
+	gchar *identity_uid;
+
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+	g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+
+	store_uid = camel_service_get_uid (CAMEL_SERVICE (store));
+	g_return_val_if_fail (store_uid != NULL, NULL);
+
+	source = e_source_registry_ref_source (registry, store_uid);
+	g_return_val_if_fail (source != NULL, NULL);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+	identity_uid = e_source_mail_account_dup_identity_uid (extension);
+
+	g_object_unref (source);
+	source = NULL;
+
+	if (identity_uid != NULL) {
+		source = e_source_registry_ref_source (registry, identity_uid);
+		g_free (identity_uid);
+	}
+
+	return source;
 }
 
 /**
diff --git a/libemail-engine/e-mail-utils.h b/libemail-engine/e-mail-utils.h
index ca8ed01..b378287 100644
--- a/libemail-engine/e-mail-utils.h
+++ b/libemail-engine/e-mail-utils.h
@@ -23,21 +23,39 @@
 #define E_MAIL_UTILS_H
 
 #include <camel/camel.h>
-#include <libedataserver/e-account.h>
+#include <libedataserver/e-source-registry.h>
 
-gboolean	em_utils_folder_is_drafts	(CamelFolder *folder);
-gboolean	em_utils_folder_is_templates	(CamelFolder *folder);
-gboolean	em_utils_folder_is_sent		(CamelFolder *folder);
-gboolean	em_utils_folder_is_outbox	(CamelFolder *folder);
-gboolean	em_utils_in_addressbook		(CamelInternetAddress *addr,
+gboolean	em_utils_folder_is_drafts	(ESourceRegistry *registry,
+						 CamelFolder *folder);
+gboolean	em_utils_folder_is_templates	(ESourceRegistry *registry,
+						 CamelFolder *folder);
+gboolean	em_utils_folder_is_sent		(ESourceRegistry *registry,
+						 CamelFolder *folder);
+gboolean	em_utils_folder_is_outbox	(ESourceRegistry *registry,
+						 CamelFolder *folder);
+gboolean	em_utils_in_addressbook		(ESourceRegistry *registry,
+						 CamelInternetAddress *addr,
 						 gboolean local_only);
-CamelMimePart *	em_utils_contact_photo		(CamelInternetAddress *addr,
+CamelMimePart *	em_utils_contact_photo		(ESourceRegistry *registry,
+						 CamelInternetAddress *addr,
 						 gboolean local);
-EAccount *	em_utils_guess_account		(CamelMimeMessage *message,
+ESource *	em_utils_guess_mail_account	(ESourceRegistry *registry,
+						 CamelMimeMessage *message,
+						 CamelFolder *folder);
+ESource *	em_utils_guess_mail_identity	(ESourceRegistry *registry,
+						 CamelMimeMessage *message,
+						 CamelFolder *folder);
+ESource *	em_utils_guess_mail_account_with_recipients
+						(ESourceRegistry *registry,
+						 CamelMimeMessage *message,
 						 CamelFolder *folder);
-EAccount *	em_utils_guess_account_with_recipients
-						(CamelMimeMessage *message,
+ESource *	em_utils_guess_mail_identity_with_recipients
+						(ESourceRegistry *registry,
+						 CamelMimeMessage *message,
 						 CamelFolder *folder);
+ESource *	em_utils_ref_mail_identity_for_store
+						(ESourceRegistry *registry,
+						 CamelStore *store);
 void		emu_remove_from_mail_cache	(const GSList *addresses);
 void		emu_remove_from_mail_cache_1	(const gchar *address);
 void		emu_free_mail_cache		(void);
diff --git a/libemail-engine/mail-config.c b/libemail-engine/mail-config.c
index 09f0332..af193f5 100644
--- a/libemail-engine/mail-config.c
+++ b/libemail-engine/mail-config.c
@@ -31,9 +31,6 @@
 
 #include <libedataserver/e-data-server-util.h>
 
-#include <libemail-utils/e-account-utils.h>
-#include <libemail-utils/e-signature-utils.h>
-
 #include "e-mail-folder-utils.h"
 #include "mail-config.h"
 #include "mail-tools.h"
@@ -137,24 +134,6 @@ settings_int_value_changed (GSettings *settings,
 	*save_location = g_settings_get_int (settings, key);
 }
 
-void
-mail_config_write (void)
-{
-	EAccountList *account_list;
-	ESignatureList *signature_list;
-
-	if (!config)
-		return;
-
-	account_list = e_get_account_list ();
-	signature_list = e_get_signature_list ();
-
-	e_account_list_save (account_list);
-	e_signature_list_save (signature_list);
-
-	g_settings_sync ();
-}
-
 gint
 mail_config_get_address_count (void)
 {
diff --git a/libemail-engine/mail-config.h b/libemail-engine/mail-config.h
index 0a1c618..cc836ac 100644
--- a/libemail-engine/mail-config.h
+++ b/libemail-engine/mail-config.h
@@ -29,7 +29,6 @@ G_BEGIN_DECLS
 
 /* Configuration */
 void		mail_config_init		(EMailSession *session);
-void		mail_config_write		(void);
 
 /* General Accessor functions */
 
diff --git a/libemail-engine/mail-folder-cache.c b/libemail-engine/mail-folder-cache.c
index 32a4b99..ebc392f 100644
--- a/libemail-engine/mail-folder-cache.c
+++ b/libemail-engine/mail-folder-cache.c
@@ -341,11 +341,16 @@ update_1folder (MailFolderCache *cache,
                 const gchar *msg_subject,
                 CamelFolderInfo *info)
 {
+	EMailSession *session;
+	ESourceRegistry *registry;
 	struct _folder_update *up;
 	CamelFolder *folder;
 	gint unread = -1;
 	gint deleted;
 
+	session = mail_folder_cache_get_session (cache);
+	registry = e_mail_session_get_registry (session);
+
 	folder = mfi->folder;
 	if (folder) {
 		gboolean folder_is_sent;
@@ -354,9 +359,9 @@ update_1folder (MailFolderCache *cache,
 		gboolean folder_is_vtrash;
 		gboolean special_case;
 
-		folder_is_sent = em_utils_folder_is_sent (folder);
-		folder_is_drafts = em_utils_folder_is_drafts (folder);
-		folder_is_outbox = em_utils_folder_is_outbox (folder);
+		folder_is_sent = em_utils_folder_is_sent (registry, folder);
+		folder_is_drafts = em_utils_folder_is_drafts (registry, folder);
+		folder_is_outbox = em_utils_folder_is_outbox (registry, folder);
 		folder_is_vtrash = CAMEL_IS_VTRASH_FOLDER (folder);
 
 		special_case =
diff --git a/libemail-engine/mail-ops.c b/libemail-engine/mail-ops.c
index 217f75d..91e424b 100644
--- a/libemail-engine/mail-ops.c
+++ b/libemail-engine/mail-ops.c
@@ -35,8 +35,9 @@
 #include <glib/gi18n.h>
 
 #include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-submission.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-utils/mail-mt.h>
 
 #include "e-mail-utils.h"
@@ -222,12 +223,20 @@ fetch_mail_exec (struct _fetch_mail_msg *m,
                  GError **error)
 {
 	struct _filter_mail_msg *fm = (struct _filter_mail_msg *) m;
+	GObjectClass *class;
 	CamelFolder *folder = NULL;
 	CamelService *service;
 	CamelSession *session;
+	CamelSettings *settings;
+	CamelStore *parent_store;
+	CamelUIDCache *cache = NULL;
 	CamelURL *url;
+	gboolean keep;
+	gboolean delete_fetched;
 	gboolean is_local_delivery = FALSE;
 	const gchar *uid = NULL;
+	const gchar *data_dir;
+	gchar *cachename;
 	gint i;
 
 	service = CAMEL_SERVICE (m->store);
@@ -239,6 +248,18 @@ fetch_mail_exec (struct _fetch_mail_msg *m,
 		goto exit;
 	g_object_ref (fm->destination);
 
+	service = CAMEL_SERVICE (m->store);
+	uid = camel_service_get_uid (service);
+	settings = camel_service_get_settings (service);
+
+	/* XXX This is a POP3-specific setting. */
+	class = G_OBJECT_GET_CLASS (settings);
+	if (g_object_class_find_property (class, "keep-on-server") != NULL)
+		g_object_get (settings, "keep-on-server", &keep, NULL);
+
+	/* Just for readability. */
+	delete_fetched = !keep;
+
 	url = camel_service_new_camel_url (service);
 	is_local_delivery = em_utils_is_local_delivery_mbox_file (url);
 
@@ -276,32 +297,26 @@ fetch_mail_exec (struct _fetch_mail_msg *m,
 
 	camel_url_free (url);
 
-	if (folder != NULL) {
-		/* This handles 'keep on server' stuff, if we have any new
-		 * uid's to copy across, we need to copy them to a new array
-		 * 'cause of the way fetch_mail_free works. */
-		CamelUIDCache *cache = NULL;
-		CamelStore *parent_store;
-		CamelService *service;
-		const gchar *data_dir;
-		gchar *cachename;
+	if (folder == NULL)
+		goto exit;
 
-		parent_store = camel_folder_get_parent_store (folder);
+	parent_store = camel_folder_get_parent_store (folder);
 
-		if (m->fetch_count > 0) {
-			/* We probably should fetch some old messages first. */
-			m->still_more = camel_folder_fetch_messages_sync (folder, m->fetch_type,
-					m->fetch_count, cancellable, error) ? 1 : 0;
-		}
-		service = CAMEL_SERVICE (parent_store);
-		data_dir = camel_service_get_user_data_dir (service);
+	if (m->fetch_count > 0) {
+		/* We probably should fetch some old messages first. */
+		m->still_more = camel_folder_fetch_messages_sync (folder, m->fetch_type,
+				m->fetch_count, cancellable, error) ? 1 : 0;
+	}
+
+	service = CAMEL_SERVICE (parent_store);
+	data_dir = camel_service_get_user_data_dir (service);
 
-		cachename = g_build_filename (data_dir, "uid-cache", NULL);
-		cache = camel_uid_cache_new (cachename);
-		g_free (cachename);
+	cachename = g_build_filename (data_dir, "uid-cache", NULL);
+	cache = camel_uid_cache_new (cachename);
+	g_free (cachename);
 
-		if (cache) {
-			GPtrArray *folder_uids, *cache_uids, *uids;
+	if (cache) {
+		GPtrArray *folder_uids, *cache_uids, *uids;
 
 			if (m->provider_fetch_inbox) {
 				g_object_unref (fm->destination);
@@ -325,46 +340,48 @@ fetch_mail_exec (struct _fetch_mail_msg *m,
 
 				camel_uid_cache_free_uids (cache_uids);
 
-				fm->cache = cache;
-				em_filter_folder_element_exec (fm, cancellable, error);
+			fm->cache = cache;
 
-				/* need to uncancel so writes/etc. don't fail */
-				if (g_cancellable_is_cancelled (m->cancellable))
-					g_cancellable_reset (m->cancellable);
+			/* FIXME Should return a success/failure flag. */
+			em_filter_folder_element_exec (fm, cancellable, error);
 
-				/* save the cache of uids that we've just downloaded */
-				camel_uid_cache_save (cache);
-			}
+			/* need to uncancel so writes/etc. don't fail */
+			if (g_cancellable_is_cancelled (m->cancellable))
+				g_cancellable_reset (m->cancellable);
 
-			if (fm->delete && (!error || !*error)) {
-				/* not keep on server - just delete all
-				 * the actual messages on the server */
-				for (i = 0; i < folder_uids->len; i++) {
-					camel_folder_delete_message (
-						folder, folder_uids->pdata[i]);
-				}
-			}
+			/* save the cache of uids that we've just downloaded */
+			camel_uid_cache_save (cache);
+		}
 
-			if ((fm->delete || cache_uids) && (!error || !*error)) {
-				/* expunge messages (downloaded so far) */
-				/* FIXME Not passing a GCancellable or GError here. */
-				camel_folder_synchronize_sync (
-					folder, fm->delete, NULL, NULL);
+		if (delete_fetched && (!error || !*error)) {
+			/* not keep on server - just delete all
+			 * the actual messages on the server */
+			for (i = 0; i < folder_uids->len; i++) {
+				camel_folder_delete_message (
+					folder, folder_uids->pdata[i]);
 			}
+		}
 
-			camel_uid_cache_destroy (cache);
-			camel_folder_free_uids (folder, folder_uids);
-		} else {
-			em_filter_folder_element_exec (fm, cancellable, error);
+		if ((delete_fetched || cache_uids) && (!error || !*error)) {
+			/* expunge messages (downloaded so far) */
+			/* FIXME Not passing a GCancellable or GError here. */
+			camel_folder_synchronize_sync (
+				folder, delete_fetched, NULL, NULL);
 		}
 
-		/* we unref the source folder here since we
-		 * may now block in finalize (we try to
-		 * disconnect cleanly) */
-		g_object_unref (fm->source_folder);
-		fm->source_folder = NULL;
+		camel_uid_cache_destroy (cache);
+		camel_folder_free_uids (folder, folder_uids);
+	} else {
+		/* FIXME Should return a success/failure flag. */
+		em_filter_folder_element_exec (fm, cancellable, error);
 	}
 
+	/* we unref the source folder here since we
+	 * may now block in finalize (we try to
+	 * disconnect cleanly) */
+	g_object_unref (fm->source_folder);
+	fm->source_folder = NULL;
+
 exit:
 	if (!is_local_delivery && m->provider_unlock)
 		m->provider_unlock (uid);
@@ -414,8 +431,7 @@ static MailMsgInfo fetch_mail_info = {
 /* ouch, a 'do everything' interface ... */
 void
 mail_fetch_mail (CamelStore *store,
-                 gint keep,
-                 CamelFetchType fetch_type,
+                 CamelFetchType fetch_type, 
                  gint fetch_count,
                  const gchar *type,
                  MailProviderFetchLockFunc lock_func,
@@ -442,7 +458,6 @@ mail_fetch_mail (CamelStore *store,
 	fm = (struct _filter_mail_msg *) m;
 	fm->session = g_object_ref (session);
 	m->store = g_object_ref (store);
-	fm->delete = !keep;
 	fm->cache = NULL;
 	if (cancellable)
 		m->cancellable = g_object_ref (cancellable);
@@ -504,6 +519,44 @@ static void	report_status		(struct _send_queue_msg *m,
 					 const gchar *desc,
 					 ...);
 
+static gboolean
+get_submission_details_from_identity (EMailSession *session,
+                                      const gchar *identity_uid,
+                                      gchar **out_transport_uid,
+                                      gchar **out_sent_folder_uri)
+{
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceExtension *extension;
+	const gchar *extension_name;
+
+	registry = e_mail_session_get_registry (session);
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	source = e_source_registry_ref_source (registry, identity_uid);
+
+	if (source == NULL)
+		return FALSE;
+
+	if (!e_source_has_extension (source, extension_name)) {
+		g_object_unref (source);
+		return FALSE;
+	}
+
+	extension = e_source_get_extension (source, extension_name);
+
+	*out_sent_folder_uri =
+		e_source_mail_submission_dup_sent_folder (
+		E_SOURCE_MAIL_SUBMISSION (extension));
+
+	*out_transport_uid =
+		e_source_mail_submission_dup_transport_uid (
+		E_SOURCE_MAIL_SUBMISSION (extension));
+
+	g_object_unref (source);
+
+	return TRUE;
+}
+
 /* send 1 message to a specific transport */
 static void
 mail_send_message (struct _send_queue_msg *m,
@@ -514,11 +567,11 @@ mail_send_message (struct _send_queue_msg *m,
                    GCancellable *cancellable,
                    GError **error)
 {
-	EAccount *account = NULL;
+	CamelService *service;
 	const CamelInternetAddress *iaddr;
 	CamelAddress *from, *recipients;
 	CamelMessageInfo *info = NULL;
-	CamelProvider *provider;
+	CamelProvider *provider = NULL;
 	gchar *transport_uid = NULL;
 	gchar *sent_folder_uri = NULL;
 	const gchar *resent_from, *tmp;
@@ -539,48 +592,31 @@ mail_send_message (struct _send_queue_msg *m,
 	err = g_string_new ("");
 	xev = mail_tool_remove_xevolution_headers (message);
 
-	tmp = camel_header_raw_find (&xev, "X-Evolution-Account", NULL);
+	tmp = camel_header_raw_find (&xev, "X-Evolution-Identity", NULL);
 	if (tmp != NULL) {
-		gchar *name;
-
-		name = g_strstrip (g_strdup (tmp));
-		if ((account = e_get_account_by_uid (name))
-		    /* 'old' x-evolution-account stored the name, how silly */
-		    || (account = e_get_account_by_name (name))) {
-			if (account->transport) {
-				CamelService *service;
-				gchar *transport_uid;
-
-				transport_uid = g_strconcat (
-					account->uid, "-transport", NULL);
-				service = camel_session_get_service (
-					CAMEL_SESSION (m->session),
-					transport_uid);
-				g_free (transport_uid);
-
-				if (CAMEL_IS_TRANSPORT (service))
-					transport = CAMEL_TRANSPORT (service);
-			}
+		gchar *identity_uid;
 
-			sent_folder_uri = g_strdup (account->sent_folder_uri);
-		}
-		g_free (name);
+		identity_uid = g_strstrip (g_strdup (tmp));
+		get_submission_details_from_identity (
+			m->session, identity_uid,
+			&transport_uid, &sent_folder_uri);
+		g_free (identity_uid);
 	}
 
-	if (!account) {
-		/* default back to these headers */
-		tmp = camel_header_raw_find(&xev, "X-Evolution-Transport", NULL);
-		if (tmp)
-			transport_uid = g_strstrip (g_strdup (tmp));
+	tmp = camel_header_raw_find (&xev, "X-Evolution-Transport", NULL);
+	if (transport_uid == NULL && tmp != NULL)
+		transport_uid = g_strstrip (g_strdup (tmp));
 
-		tmp = camel_header_raw_find(&xev, "X-Evolution-Fcc", NULL);
-		if (tmp)
-			sent_folder_uri = g_strstrip (g_strdup (tmp));
-	}
+	tmp = camel_header_raw_find (&xev, "X-Evolution-Fcc", NULL);
+	if (sent_folder_uri == NULL && tmp != NULL)
+		sent_folder_uri = g_strstrip (g_strdup (tmp));
 
-	if (transport != NULL) {
-		const gchar *uid;
+	service = camel_session_get_service (
+		CAMEL_SESSION (m->session), transport_uid);
+	if (service != NULL)
+		provider = camel_service_get_provider (service);
 
+	if (CAMEL_IS_TRANSPORT (service)) {
 		/* Let the dialog know the right account it is using. */
 		uid = camel_service_get_uid (CAMEL_SERVICE (transport));
 		report_status (m, CAMEL_FILTER_STATUS_ACTION, 0, uid);
@@ -607,12 +643,12 @@ mail_send_message (struct _send_queue_msg *m,
 
 	if (camel_address_length (recipients) > 0) {
 		if (!camel_service_connect_sync (
-			CAMEL_SERVICE (transport), cancellable, error))
+			service, cancellable, error))
 			goto exit;
 
 		if (!camel_transport_send_to_sync (
-			transport, message, from,
-			recipients, cancellable, error))
+			CAMEL_TRANSPORT (service), message,
+			from, recipients, cancellable, error))
 			goto exit;
 	}
 
@@ -663,8 +699,6 @@ mail_send_message (struct _send_queue_msg *m,
 		}
 	}
 
-	provider = camel_service_get_provider (CAMEL_SERVICE (transport));
-
 	if (provider == NULL
 	    || !(provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)) {
 		GError *local_error = NULL;
@@ -1362,9 +1396,10 @@ expunge_pop3_stores (CamelFolder *expunging,
 	CamelStore *parent_store;
 	CamelService *service;
 	CamelSession *session;
+	ESourceRegistry *registry;
 	GPtrArray *uids;
-	EAccount *account;
-	EIterator *iter;
+	GList *list, *link;
+	const gchar *extension_name;
 	gboolean success = TRUE;
 	guint ii;
 
@@ -1372,6 +1407,7 @@ expunge_pop3_stores (CamelFolder *expunging,
 
 	service = CAMEL_SERVICE (parent_store);
 	session = camel_service_get_session (service);
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
 
 	uids = camel_folder_get_uids (expunging);
 
@@ -1432,79 +1468,89 @@ expunge_pop3_stores (CamelFolder *expunging,
 		return TRUE;
 	}
 
-	for (iter = e_list_get_iterator ((EList *) e_get_account_list ());
-	     e_iterator_is_valid (iter); e_iterator_next (iter)) {
-		account = (EAccount *) e_iterator_get (iter);
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-		if (account->enabled &&
-		    account->source && account->source->url &&
-		    g_str_has_prefix (account->source->url, "pop://")) {
-			CamelFolder *folder;
-			CamelService *service;
-			CamelSettings *settings;
-			gboolean any_found = FALSE;
-			gboolean delete_expunged = FALSE;
-			gboolean keep_on_server = FALSE;
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceBackend *extension;
+		CamelFolder *folder;
+		CamelService *service;
+		CamelSettings *settings;
+		const gchar *backend_name;
+		const gchar *source_uid;
+		gboolean any_found = FALSE;
+		gboolean delete_expunged = FALSE;
+		gboolean keep_on_server = FALSE;
+		gboolean enabled;
 
-			service = camel_session_get_service (session, account->uid);
+		source_uid = e_source_get_uid (source);
+		enabled = e_source_get_enabled (source);
 
-			if (!CAMEL_IS_STORE (service))
-				continue;
+		extension = e_source_get_extension (source, extension_name);
+		backend_name = e_source_backend_get_backend_name (extension);
 
-			settings = camel_service_get_settings (service);
-			if (!settings)
-				continue;
+		if (!enabled || g_strcmp0 (backend_name, "pop") != 0)
+			continue;
 
-			g_object_get (
-				settings,
-				"delete-expunged", &delete_expunged,
-				"keep-on-server", &keep_on_server,
-				NULL);
+		service = camel_session_get_service (
+			CAMEL_SESSION (session), source_uid);
 
-			if (!keep_on_server || !delete_expunged)
-				continue;
+		settings = camel_service_get_settings (service);
 
-			folder = e_mail_session_get_inbox_sync (
-				E_MAIL_SESSION (session),
-				account->uid, cancellable, error);
+		g_object_get (
+			settings,
+			"delete-expunged", &delete_expunged,
+			"keep-on-server", &keep_on_server,
+			NULL);
 
-			/* Abort the loop on error. */
-			if (folder == NULL) {
-				success = FALSE;
-				break;
-			}
+		if (!keep_on_server || !delete_expunged)
+			continue;
 
-			uids = camel_folder_get_uids (folder);
-			if (uids) {
-				for (ii = 0; ii < uids->len; ii++) {
-					/* ensure the ID is from this account,
-					 * as it's generated by evolution */
-					const gchar *source_uid;
-
-					source_uid = g_hash_table_lookup (
-						expunging_uids, uids->pdata[ii]);
-					if (folder_is_from_source_uid (folder, source_uid)) {
-						any_found = TRUE;
-						camel_folder_delete_message (folder, uids->pdata[ii]);
-					}
-				}
-				camel_folder_free_uids (folder, uids);
-			}
+		folder = camel_store_get_inbox_folder_sync (
+			CAMEL_STORE (service), cancellable, error);
 
-			if (any_found)
-				success = camel_folder_synchronize_sync (
-					folder, TRUE, cancellable, error);
+		/* Abort the loop on error. */
+		if (folder == NULL) {
+			success = FALSE;
+			break;
+		}
+
+		uids = camel_folder_get_uids (folder);
 
+		if (uids == NULL) {
 			g_object_unref (folder);
+			continue;
+		}
 
-			/* Abort the loop on error. */
-			if (!success)
-				break;
+		for (ii = 0; ii < uids->len; ii++) {
+			/* ensure the ID is from this account,
+			 * as it's generated by evolution */
+			const gchar *source_uid;
+
+			source_uid = g_hash_table_lookup (
+				expunging_uids, uids->pdata[ii]);
+			if (folder_is_from_source_uid (folder, source_uid)) {
+				any_found = TRUE;
+				camel_folder_delete_message (
+					folder, uids->pdata[ii]);
+			}
 		}
+
+		camel_folder_free_uids (folder, uids);
+
+		if (any_found)
+			success = camel_folder_synchronize_sync (
+				folder, TRUE, cancellable, error);
+
+		g_object_unref (folder);
+
+		/* Abort the loop on error. */
+		if (!success)
+			break;
 	}
 
-	if (iter)
-		g_object_unref (iter);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
 	g_hash_table_destroy (expunging_uids);
 
diff --git a/libemail-engine/mail-ops.h b/libemail-engine/mail-ops.h
index d42268d..7ec9b14 100644
--- a/libemail-engine/mail-ops.h
+++ b/libemail-engine/mail-ops.h
@@ -79,7 +79,6 @@ typedef CamelFolder *
 						 GError **error);
 
 void		mail_fetch_mail			(CamelStore *store,
-						 gint keep,
 						 CamelFetchType fetch_type,
 						 gint fetch_count,
 						 const gchar *type,
diff --git a/libemail-utils/Makefile.am b/libemail-utils/Makefile.am
index a856df6..18e9926 100644
--- a/libemail-utils/Makefile.am
+++ b/libemail-utils/Makefile.am
@@ -13,10 +13,6 @@ libemail_utils_la_CPPFLAGS = \
 
 libmailutilsincludedir = $(privincludedir)/libemail-utils
 libmailutilsinclude_HEADERS = \
-	e-account-utils.h \
-	e-signature-list.h \
-	e-signature-utils.h \
-	e-signature.h \
 	em-filter-folder-element.h \
 	em-vfolder-context.h \
 	em-vfolder-rule.h \
@@ -25,10 +21,6 @@ libmailutilsinclude_HEADERS = \
 
 libemail_utils_la_SOURCES = \
 	$(libmailutilsinclude_HEADERS) \
-	e-account-utils.c \
-	e-signature-list.c \
-	e-signature-utils.c \
-	e-signature.c \
 	em-filter-folder-element.c \
 	em-vfolder-context.c \
 	em-vfolder-rule.c \
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 7358f35..d1c4fdd 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -45,8 +45,28 @@ mailinclude_HEADERS =					\
 	e-mail-account-store.h				\
 	e-mail-account-tree-view.h			\
 	e-mail-attachment-bar.h				\
+	e-mail-autoconfig.h				\
 	e-mail-backend.h				\
 	e-mail-browser.h				\
+	e-mail-config-assistant.h			\
+	e-mail-config-auth-check.h			\
+	e-mail-config-confirm-page.h			\
+	e-mail-config-defaults-page.h			\
+	e-mail-config-identity-page.h			\
+	e-mail-config-lookup-page.h			\
+	e-mail-config-notebook.h			\
+	e-mail-config-page.h				\
+	e-mail-config-provider-page.h			\
+	e-mail-config-receiving-page.h			\
+	e-mail-config-security-page.h			\
+	e-mail-config-sending-page.h			\
+	e-mail-config-service-backend.h			\
+	e-mail-config-service-notebook.h		\
+	e-mail-config-service-page.h			\
+	e-mail-config-sidebar.h				\
+	e-mail-config-summary-page.h			\
+	e-mail-config-welcome-page.h			\
+	e-mail-config-window.h				\
 	e-mail-display.h				\
 	e-mail-folder-pane.h				\
 	e-mail-junk-options.h				\
@@ -67,7 +87,6 @@ mailinclude_HEADERS =					\
 	e-mail-tag-editor.h				\
 	e-mail-ui-session.h				\
 	e-mail-view.h					\
-	em-account-editor.h				\
 	em-composer-utils.h				\
 	em-config.h					\
 	em-event.h					\
@@ -111,8 +130,28 @@ libevolution_mail_la_SOURCES =				\
 	e-mail-account-store.c				\
 	e-mail-account-tree-view.c			\
 	e-mail-attachment-bar.c				\
+	e-mail-autoconfig.c				\
 	e-mail-backend.c				\
 	e-mail-browser.c				\
+	e-mail-config-assistant.c			\
+	e-mail-config-auth-check.c			\
+	e-mail-config-confirm-page.c			\
+	e-mail-config-defaults-page.c			\
+	e-mail-config-identity-page.c			\
+	e-mail-config-lookup-page.c			\
+	e-mail-config-notebook.c			\
+	e-mail-config-page.c				\
+	e-mail-config-provider-page.c			\
+	e-mail-config-receiving-page.c			\
+	e-mail-config-security-page.c			\
+	e-mail-config-sending-page.c			\
+	e-mail-config-service-backend.c			\
+	e-mail-config-service-notebook.c		\
+	e-mail-config-service-page.c			\
+	e-mail-config-sidebar.c				\
+	e-mail-config-summary-page.c			\
+	e-mail-config-welcome-page.c			\
+	e-mail-config-window.c				\
 	e-mail-display.c				\
 	e-mail-folder-pane.c				\
 	e-mail-junk-options.c				\
@@ -133,7 +172,6 @@ libevolution_mail_la_SOURCES =				\
 	e-mail-tag-editor.c				\
 	e-mail-ui-session.c				\
 	e-mail-view.c					\
-	em-account-editor.c				\
 	em-composer-utils.c				\
 	em-config.c					\
 	em-event.c					\
@@ -202,12 +240,29 @@ libevolution_mail_la_LIBADD =				\
 	$(E_WIDGETS_LIBS)				\
 	$(SMIME_LIBS)					\
 	$(LIBSOUP_LIBS)					\
-	$(GNOME_PLATFORM_LIBS)
+	-lresolv
 
 libevolution_mail_la_LDFLAGS = -avoid-version $(NO_UNDEFINED)
 
 libevolution_mail_la_DEPENDENCIES = em-filter-i18n.h
 
+noinst_PROGRAMS = test-mail-autoconfig
+
+test_mail_autoconfig_CPPFLAGS = \
+	$(AM_CPPFLAGS)					\
+	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
+	$(GNOME_PLATFORM_CFLAGS)
+
+test_mail_autoconfig_SOURCES = \
+	e-mail-autoconfig.c				\
+	e-mail-autoconfig.h				\
+	test-mail-autoconfig.c
+
+test_mail_autoconfig_LDADD = \
+	$(EVOLUTION_DATA_SERVER_LIBS)			\
+	$(GNOME_PLATFORM_LIBS)				\
+	-lresolv
+
 # Misc data to install
 filterdir = $(privdatadir)
 filter_DATA = filtertypes.xml vfoldertypes.xml searchtypes.xml
diff --git a/mail/e-mail-account-manager.c b/mail/e-mail-account-manager.c
index 86a0bf5..5cf6012 100644
--- a/mail/e-mail-account-manager.c
+++ b/mail/e-mail-account-manager.c
@@ -22,6 +22,8 @@
 #include <glib/gi18n-lib.h>
 #include <gdk/gdkkeysyms.h>
 
+#include <libedataserver/e-source-collection.h>
+
 #include <libemail-engine/e-mail-session.h>
 #include <mail/e-mail-account-tree-view.h>
 
@@ -70,18 +72,27 @@ static void
 mail_account_manager_edit_cb (EMailAccountManager *manager)
 {
 	EMailAccountTreeView *tree_view;
-	EAccount *account;
+	EMailAccountStore *store;
+	ESourceRegistry *registry;
+	EMailSession *session;
 	CamelService *service;
+	ESource *source;
 	const gchar *uid;
 
+	store = e_mail_account_manager_get_store (manager);
+	session = e_mail_account_store_get_session (store);
+	registry = e_mail_session_get_registry (session);
+
 	tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
 	service = e_mail_account_tree_view_get_selected_service (tree_view);
 
 	uid = camel_service_get_uid (service);
-	account = e_get_account_by_uid (uid);
-	g_return_if_fail (account != NULL);
+	source = e_source_registry_ref_source (registry, uid);
+	g_return_if_fail (source != NULL);
 
-	e_mail_account_manager_edit_account (manager, account);
+	e_mail_account_manager_edit_account (manager, source);
+
+	g_object_unref (source);
 }
 
 static void
@@ -209,6 +220,7 @@ mail_account_manager_selection_changed_cb (EMailAccountManager *manager,
 	gboolean builtin;
 	gboolean sensitive;
 	gboolean not_default;
+	gboolean removable;
 
 	add_button = manager->priv->add_button;
 	edit_button = manager->priv->edit_button;
@@ -221,9 +233,11 @@ mail_account_manager_selection_changed_cb (EMailAccountManager *manager,
 			E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service,
 			E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, &builtin,
 			-1);
+		removable = !builtin;
 	} else {
 		service = NULL;
 		builtin = FALSE;
+		removable = FALSE;
 	}
 
 	store = e_mail_account_manager_get_store (manager);
@@ -232,11 +246,40 @@ mail_account_manager_selection_changed_cb (EMailAccountManager *manager,
 
 	if (service == NULL)
 		gtk_widget_grab_focus (add_button);
+	else {
+		ESource *source;
+		EMailSession *session;
+		ESourceRegistry *registry;
+		const gchar *uid;
+
+		session = e_mail_account_store_get_session (store);
+		registry = e_mail_session_get_registry (session);
+
+		uid = camel_service_get_uid (service);
+		source = e_source_registry_ref_source (registry, uid);
+
+		if (source != NULL) {
+			ESource *collection;
+			const gchar *extension_name;
+
+			extension_name = E_SOURCE_EXTENSION_COLLECTION;
+			collection = e_source_registry_find_extension (
+				registry, source, extension_name);
+			if (collection != NULL) {
+				g_object_unref (source);
+				source = collection;
+			}
+
+			removable = e_source_get_removable (source);
+
+			g_object_unref (source);
+		}
+	}
 
 	sensitive = (service != NULL && !builtin);
 	gtk_widget_set_sensitive (edit_button, sensitive);
 
-	sensitive = (service != NULL && !builtin);
+	sensitive = (service != NULL && removable);
 	gtk_widget_set_sensitive (delete_button, sensitive);
 
 	sensitive = (service != NULL && !builtin && not_default);
@@ -519,7 +562,7 @@ e_mail_account_manager_class_init (EMailAccountManagerClass *class)
 		NULL, NULL,
 		g_cclosure_marshal_VOID__OBJECT,
 		G_TYPE_NONE, 1,
-		E_TYPE_ACCOUNT);
+		E_TYPE_SOURCE);
 }
 
 static void
@@ -556,11 +599,11 @@ e_mail_account_manager_add_account (EMailAccountManager *manager)
 
 void
 e_mail_account_manager_edit_account (EMailAccountManager *manager,
-                                     EAccount *account)
+                                     ESource *source)
 {
 	g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager));
-	g_return_if_fail (E_IS_ACCOUNT (account));
+	g_return_if_fail (E_IS_SOURCE (source));
 
-	g_signal_emit (manager, signals[EDIT_ACCOUNT], 0, account);
+	g_signal_emit (manager, signals[EDIT_ACCOUNT], 0, source);
 }
 
diff --git a/mail/e-mail-account-manager.h b/mail/e-mail-account-manager.h
index 63e52b4..a17ff2a 100644
--- a/mail/e-mail-account-manager.h
+++ b/mail/e-mail-account-manager.h
@@ -20,8 +20,8 @@
 #define E_MAIL_ACCOUNT_MANAGER_H
 
 #include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
 #include <mail/e-mail-account-store.h>
-#include <libemail-utils/e-account-utils.h>
 
 /* Standard GObject macros */
 #define E_TYPE_MAIL_ACCOUNT_MANAGER \
@@ -59,7 +59,7 @@ struct _EMailAccountManagerClass {
 	/* Signals */
 	void		(*add_account)		(EMailAccountManager *manager);
 	void		(*edit_account)		(EMailAccountManager *manager,
-						 EAccount *account);
+						 ESource *source);
 };
 
 GType		e_mail_account_manager_get_type	(void) G_GNUC_CONST;
@@ -71,7 +71,7 @@ void		e_mail_account_manager_add_account
 						(EMailAccountManager *manager);
 void		e_mail_account_manager_edit_account
 						(EMailAccountManager *manager,
-						 EAccount *account);
+						 ESource *source);
 
 G_END_DECLS
 
diff --git a/mail/e-mail-account-store.c b/mail/e-mail-account-store.c
index 2dac692..1c5dedf 100644
--- a/mail/e-mail-account-store.c
+++ b/mail/e-mail-account-store.c
@@ -23,11 +23,11 @@
 #include <glib/gi18n-lib.h>
 
 #include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-collection.h>
 
 #include <e-util/e-marshal.h>
 #include <libevolution-utils/e-alert-dialog.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-engine/mail-ops.h>
 
 #include <mail/mail-vfolder-ui.h>
@@ -101,24 +101,6 @@ index_item_free (IndexItem *item)
 	g_slice_free (IndexItem, item);
 }
 
-static void
-mail_account_store_save_default (EMailAccountStore *store)
-{
-	EAccountList *account_list;
-	EAccount *account;
-	CamelService *service;
-	const gchar *uid;
-
-	service = e_mail_account_store_get_default_service (store);
-
-	account_list = e_get_account_list ();
-	uid = camel_service_get_uid (service);
-	account = e_get_account_by_uid (uid);
-	g_return_if_fail (account != NULL);
-
-	e_account_list_set_default (account_list, account);
-}
-
 static gboolean
 mail_account_store_get_iter (EMailAccountStore *store,
                              CamelService *service,
@@ -238,6 +220,46 @@ mail_account_store_service_notify_cb (CamelService *service,
 }
 
 static void
+mail_account_store_remove_source_cb (ESource *source,
+                                     GAsyncResult *result,
+                                     EMailAccountStore *store)
+{
+	GError *error = NULL;
+
+	/* FIXME EMailAccountStore should implement EAlertSink. */
+	if (!e_source_remove_finish (source, result, &error)) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+	}
+
+	g_return_if_fail (store->priv->busy_count > 0);
+	store->priv->busy_count--;
+	g_object_notify (G_OBJECT (store), "busy");
+
+	g_object_unref (store);
+}
+
+static void
+mail_account_store_write_source_cb (ESource *source,
+                                    GAsyncResult *result,
+                                    EMailAccountStore *store)
+{
+	GError *error = NULL;
+
+	/* FIXME EMailAccountStore should implement EAlertSink. */
+	if (!e_source_write_finish (source, result, &error)) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+	}
+
+	g_return_if_fail (store->priv->busy_count > 0);
+	store->priv->busy_count--;
+	g_object_notify (G_OBJECT (store), "busy");
+
+	g_object_unref (store);
+}
+
+static void
 mail_account_store_clean_index (EMailAccountStore *store)
 {
 	GQueue trash = G_QUEUE_INIT;
@@ -427,23 +449,34 @@ static void
 mail_account_store_constructed (GObject *object)
 {
 	EMailAccountStore *store;
+	EMailSession *session;
+	ESourceRegistry *registry;
 	const gchar *config_dir;
 
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (e_mail_account_store_parent_class)->constructed (object);
 
 	store = E_MAIL_ACCOUNT_STORE (object);
+	session = e_mail_account_store_get_session (store);
+	registry = e_mail_session_get_registry (session);
+
+	/* Bind the default mail account ESource to our default
+	 * CamelService, with help from some transform functions. */
+	g_object_bind_property_full (
+		registry, "default-mail-account",
+		store, "default-service",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		e_binding_transform_source_to_service,
+		e_binding_transform_service_to_source,
+		session, (GDestroyNotify) NULL);
+
 	config_dir = mail_session_get_config_dir ();
 
 	/* XXX Should we take the filename as a constructor property? */
 	store->priv->sort_order_filename = g_build_filename (
 		config_dir, "sortorder.ini", NULL);
 
-	/* XXX This is kinda lame, but should work until EAccount dies. */
-	g_signal_connect (
-		object, "notify::default-service",
-		G_CALLBACK (mail_account_store_save_default), NULL);
-
 	e_extensible_load_extensions (E_EXTENSIBLE (object));
 }
 
@@ -458,94 +491,73 @@ static void
 mail_account_store_service_removed (EMailAccountStore *store,
                                     CamelService *service)
 {
-	/* XXX On the account-mgmt branch this operation is asynchronous.
-	 *     The 'busy_count' is bumped until changes are written back
-	 *     to the D-Bus service.  For now I guess we'll just block. */
-
-	EAccountList *account_list;
-	EAccount *account;
 	EMailSession *session;
-	MailFolderCache *cache;
-	CamelProvider *provider;
+	ESourceRegistry *registry;
+	ESource *source;
 	const gchar *uid;
 
 	session = e_mail_account_store_get_session (store);
-	cache = e_mail_session_get_folder_cache (session);
+	registry = e_mail_session_get_registry (session);
 
-	mail_folder_cache_service_removed (cache, service);
-
-	account_list = e_get_account_list ();
 	uid = camel_service_get_uid (service);
-	account = e_get_account_by_uid (uid);
-	g_return_if_fail (account != NULL);
-
-	/* no change */
-	if (!account->enabled)
-		return;
-
-	provider = camel_service_get_provider (service);
-	g_return_if_fail (provider != NULL);
-
-	if (provider->flags & CAMEL_PROVIDER_IS_STORAGE)
-		mail_disconnect_store (CAMEL_STORE (service));
+	source = e_source_registry_ref_source (registry, uid);
+
+	/* If this ESource is part of a collection, we need to remove
+	 * the entire collection.  Check the ESource and its ancestors
+	 * for a collection extension and remove the containing source. */
+	if (source != NULL) {
+		ESource *collection;
+
+		collection = e_source_registry_find_extension (
+			registry, source, E_SOURCE_EXTENSION_COLLECTION);
+		if (collection != NULL) {
+			g_object_unref (source);
+			source = collection;
+		}
+	}
 
-	/* Remove all the proxies the account has created.
-	 * FIXME This proxy stuff belongs in evolution-groupwise. */
-	e_account_list_remove_account_proxies (account_list, account);
+	if (source != NULL) {
+		store->priv->busy_count++;
+		g_object_notify (G_OBJECT (store), "busy");
 
-	e_account_list_remove (account_list, account);
+		/* XXX Should this be cancellable? */
+		e_source_remove (
+			source, NULL, (GAsyncReadyCallback)
+			mail_account_store_remove_source_cb,
+			g_object_ref (store));
 
-	e_account_list_save (account_list);
+		g_object_unref (source);
+	}
 }
 
 static void
 mail_account_store_service_enabled (EMailAccountStore *store,
                                     CamelService *service)
 {
-	/* XXX On the account-mgmt branch this operation is asynchronous.
-	 *     The 'busy_count' is bumped until changes are written back
-	 *     to the D-Bus service.  For now I guess we'll just block. */
-
 	EMailSession *session;
-	MailFolderCache *cache;
-	GSettings *settings;
+	ESourceRegistry *registry;
+	ESource *source;
 	const gchar *uid;
 
 	session = e_mail_account_store_get_session (store);
-	cache = e_mail_session_get_folder_cache (session);
-
-	mail_folder_cache_service_enabled (cache, service);
+	registry = e_mail_session_get_registry (session);
 
 	uid = camel_service_get_uid (service);
+	source = e_source_registry_ref_source (registry, uid);
 
-	/* Handle built-in services that don't have an EAccount. */
+	if (source != NULL) {
+		e_source_set_enabled (source, TRUE);
 
-	if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) {
-		settings = g_settings_new ("org.gnome.evolution.mail");
-		g_settings_set_boolean (settings, "enable-local", TRUE);
-		g_object_unref (settings);
-
-	} else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) {
-		settings = g_settings_new ("org.gnome.evolution.mail");
-		g_settings_set_boolean (settings, "enable-vfolders", TRUE);
-		g_object_unref (settings);
-
-	} else {
-		EAccountList *account_list;
-		EAccount *account;
-
-		account_list = e_get_account_list ();
-		account = e_get_account_by_uid (uid);
-		g_return_if_fail (account != NULL);
-
-		/* no change */
-		if (account->enabled)
-			return;
+		store->priv->busy_count++;
+		g_object_notify (G_OBJECT (store), "busy");
 
-		account->enabled = TRUE;
+		/* XXX Should this be cancellable? */
+		e_source_write (
+			source, NULL, (GAsyncReadyCallback)
+			mail_account_store_write_source_cb,
+			g_object_ref (store));
 
-		e_account_list_change (account_list, account);
-		e_account_list_save (account_list);
+		g_object_unref (source);
 	}
 }
 
@@ -553,63 +565,30 @@ static void
 mail_account_store_service_disabled (EMailAccountStore *store,
                                      CamelService *service)
 {
-	/* XXX On the account-mgmt branch this operation is asynchronous.
-	 *     The 'busy_count' is bumped until changes are written back
-	 *     to the D-Bus service.  For now I guess we'll just block. */
-
 	EMailSession *session;
-	MailFolderCache *cache;
-	GSettings *settings;
+	ESourceRegistry *registry;
+	ESource *source;
 	const gchar *uid;
 
 	session = e_mail_account_store_get_session (store);
-	cache = e_mail_session_get_folder_cache (session);
-
-	mail_folder_cache_service_disabled (cache, service);
+	registry = e_mail_session_get_registry (session);
 
 	uid = camel_service_get_uid (service);
+	source = e_source_registry_ref_source (registry, uid);
 
-	/* Handle built-in services that don't have an EAccount. */
+	if (source != NULL) {
+		e_source_set_enabled (source, FALSE);
 
-	if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) {
-		settings = g_settings_new ("org.gnome.evolution.mail");
-		g_settings_set_boolean (settings, "enable-local", FALSE);
-		g_object_unref (settings);
-
-	} else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) {
-		settings = g_settings_new ("org.gnome.evolution.mail");
-		g_settings_set_boolean (settings, "enable-vfolders", FALSE);
-		g_object_unref (settings);
-
-	} else {
-		EAccountList *account_list;
-		EAccount *account;
-		CamelProvider *provider;
+		store->priv->busy_count++;
+		g_object_notify (G_OBJECT (store), "busy");
 
-		account_list = e_get_account_list ();
-		account = e_get_account_by_uid (uid);
-		g_return_if_fail (account != NULL);
+		/* XXX Should this be cancellable? */
+		e_source_write (
+			source, NULL, (GAsyncReadyCallback)
+			mail_account_store_write_source_cb,
+			g_object_ref (store));
 
-		/* no change */
-		if (!account->enabled)
-			return;
-
-		account->enabled = FALSE;
-
-		provider = camel_service_get_provider (service);
-		g_return_if_fail (provider != NULL);
-
-		if (provider->flags & CAMEL_PROVIDER_IS_STORAGE)
-			mail_disconnect_store (CAMEL_STORE (service));
-
-		/* FIXME This proxy stuff belongs in evolution-groupwise. */
-		e_account_list_remove_account_proxies (account_list, account);
-
-		if (account->parent_uid != NULL)
-			e_account_list_remove (account_list, account);
-
-		e_account_list_change (account_list, account);
-		e_account_list_save (account_list);
+		g_object_unref (source);
 	}
 }
 
@@ -643,25 +622,14 @@ mail_account_store_remove_requested (EMailAccountStore *store,
                                      GtkWindow *parent_window,
                                      CamelService *service)
 {
-	EAccountList *account_list;
-	EAccount *account;
-	const gchar *alert;
-	const gchar *uid;
 	gint response;
 
-	account_list = e_get_account_list ();
-	uid = camel_service_get_uid (service);
-	account = e_get_account_by_uid (uid);
-
-	g_return_val_if_fail (account != NULL, FALSE);
+	/* FIXME Need to use "mail:ask-delete-account-with-proxies" if the
+	 *       mail account has proxies.  But this is groupwise-specific
+	 *       and doesn't belong here anyway.  Think of a better idea. */
 
-	/* FIXME This proxy stuff belongs in evolution-groupwise. */
-	if (e_account_list_account_has_proxies (account_list, account))
-		alert = "mail:ask-delete-account-with-proxies";
-	else
-		alert = "mail:ask-delete-account";
-
-	response = e_alert_run_dialog_for_args (parent_window, alert, NULL);
+	response = e_alert_run_dialog_for_args (
+		parent_window, "mail:ask-delete-account", NULL);
 
 	return (response == GTK_RESPONSE_YES);
 }
@@ -679,34 +647,12 @@ mail_account_store_disable_requested (EMailAccountStore *store,
                                       GtkWindow *parent_window,
                                       CamelService *service)
 {
-	EAccountList *account_list;
-	EAccount *account;
-	const gchar *uid;
-	gint response;
-
-	account_list = e_get_account_list ();
-	uid = camel_service_get_uid (service);
-	account = e_get_account_by_uid (uid);
-
-	/* "On This Computer" and "Search Folders" do not have
-	 * EAccounts, so just silently return TRUE if we failed
-	 * to find a matching EAccount for the CamelService. */
-
-	/* Silently return TRUE if we failed to find a matching
-	 * EAccount since "On This Computer" and "Search Folders"
-	 * do not have EAccounts. */
-	if (account == NULL)
-		return TRUE;
+	/* FIXME Need to check whether the account has proxies and run a
+	 *       "mail:ask-delete-proxy-accounts" alert dialog, but this
+	 *       is groupwise-specific and doesn't belong here anyway.
+	 *       Think of a better idea. */
 
-	/* FIXME This proxy stuff belongs in evolution-groupwise. */
-	if (e_account_list_account_has_proxies (account_list, account))
-		response = e_alert_run_dialog_for_args (
-			parent_window,
-			"mail:ask-delete-proxy-accounts", NULL);
-	else
-		response = GTK_RESPONSE_YES;
-
-	return (response == GTK_RESPONSE_YES);
+	return TRUE;
 }
 
 static void
@@ -1086,13 +1032,20 @@ e_mail_account_store_add_service (EMailAccountStore *store,
 		g_object_unref (settings);
 
 	} else {
-		EAccount *account;
+		EMailSession *session;
+		ESourceRegistry *registry;
+		ESource *source;
+
+		session = e_mail_account_store_get_session (store);
 
-		account = e_get_account_by_uid (uid);
-		g_return_if_fail (account != NULL);
+		registry = e_mail_session_get_registry (session);
+		source = e_source_registry_ref_source (registry, uid);
+		g_return_if_fail (source != NULL);
 
 		builtin = FALSE;
-		enabled = account->enabled;
+		enabled = e_source_get_enabled (source);
+
+		g_object_unref (source);
 	}
 
 	/* Where do we insert new services now that accounts can be
diff --git a/mail/e-mail-autoconfig.c b/mail/e-mail-autoconfig.c
new file mode 100644
index 0000000..e3588a8
--- /dev/null
+++ b/mail/e-mail-autoconfig.c
@@ -0,0 +1,883 @@
+/*
+ * e-mail-autoconfig.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-autoconfig.h"
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+/* Stuff for DNS querying and message parsing. */
+#include <netdb.h>
+#include <netinet/in.h>
+#include <resolv.h>
+#include <arpa/nameser.h>
+#if defined(HAVE_ARPA_NAMESER_COMPAT_H) && !defined(GETSHORT)
+#include <arpa/nameser_compat.h>
+#endif
+
+/* For error codes. */
+#include <libsoup/soup.h>
+
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-transport.h>
+
+#define E_MAIL_AUTOCONFIG_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfigPrivate))
+
+#define AUTOCONFIG_BASE_URI \
+	"http://api.gnome.org/evolution/autoconfig/1.1/";
+
+/* XXX g_file_load_contents() on an "http://"; URI returns error codes
+ *     in the SOUP_HTTP_ERROR domain instead of the G_IO_ERROR domain.
+ *     That is both undocumented and unexpected. */
+#define ERROR_IS_NOT_FOUND(error) \
+	(g_error_matches ((error), SOUP_HTTP_ERROR, SOUP_STATUS_NOT_FOUND))
+
+typedef struct _ParserClosure ParserClosure;
+typedef struct _ResolverClosure ResolverClosure;
+
+struct _EMailAutoconfigPrivate {
+	gchar *email_address;
+	gchar *email_local_part;
+	gchar *email_domain_part;
+	gchar *markup_content;
+};
+
+struct _ParserClosure {
+	CamelNetworkSettings *network_settings;
+	const gchar *expected_type;
+	const gchar *email_address;
+	const gchar *email_local_part;
+	const gchar *email_domain_part;
+	gboolean in_server_element;
+	gboolean settings_modified;
+};
+
+struct _ResolverClosure {
+	volatile gint ref_count;
+	GMainContext *main_context;
+	GMainLoop *main_loop;
+	gchar *domain_name;
+	gchar *name_server;
+	GError *error;
+};
+
+enum {
+	PROP_0,
+	PROP_EMAIL_ADDRESS
+};
+
+/* Forward Declarations */
+static void	e_mail_autoconfig_initable_init	(GInitableIface *interface);
+
+/* By default, the GAsyncInitable interface calls GInitable.init()
+ * from a separate thread, so we only have to override GInitable. */
+G_DEFINE_TYPE_WITH_CODE (
+	EMailAutoconfig,
+	e_mail_autoconfig,
+	G_TYPE_OBJECT,
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_INITABLE, e_mail_autoconfig_initable_init)
+	G_IMPLEMENT_INTERFACE (
+		G_TYPE_ASYNC_INITABLE, NULL))
+
+static ResolverClosure *
+resolver_closure_new (const gchar *domain_name)
+{
+	ResolverClosure *closure;
+
+	closure = g_slice_new0 (ResolverClosure);
+	closure->domain_name = g_strdup (domain_name);
+	closure->main_context = g_main_context_new ();
+	closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
+	closure->ref_count = 1;
+
+	return closure;
+}
+
+static ResolverClosure *
+resolver_closure_ref (ResolverClosure *closure)
+{
+	g_return_val_if_fail (closure != NULL, NULL);
+	g_return_val_if_fail (closure->ref_count > 0, NULL);
+
+	g_atomic_int_inc (&closure->ref_count);
+
+	return closure;
+}
+
+static void
+resolver_closure_unref (ResolverClosure *closure)
+{
+	g_return_if_fail (closure != NULL);
+	g_return_if_fail (closure->ref_count > 0);
+
+	if (g_atomic_int_dec_and_test (&closure->ref_count)) {
+		g_main_context_unref (closure->main_context);
+		g_main_loop_unref (closure->main_loop);
+		g_free (closure->domain_name);
+		g_free (closure->name_server);
+		g_clear_error (&closure->error);
+		g_slice_free (ResolverClosure, closure);
+	}
+}
+
+static gboolean
+mail_autoconfig_resolver_idle_quit (gpointer user_data)
+{
+	GMainLoop *main_loop = user_data;
+
+	g_main_loop_quit (main_loop);
+
+	return FALSE;
+}
+
+static void
+mail_autoconfig_resolver_cancelled (GCancellable *cancellable,
+                                    ResolverClosure *closure)
+{
+	GSource *source;
+
+	source = g_idle_source_new ();
+	g_source_set_callback (
+		source,
+		mail_autoconfig_resolver_idle_quit,
+		g_main_loop_ref (closure->main_loop),
+		(GDestroyNotify) g_main_loop_unref);
+	g_source_attach (source, closure->main_context);
+	g_source_unref (source);
+}
+
+static gpointer
+mail_autoconfig_resolver_thread (gpointer user_data)
+{
+	ResolverClosure *closure = user_data;
+	HEADER *header;
+	guchar answer[1024];
+	gchar namebuf[1024];
+	guchar *end, *cp;
+	gint count;
+	gint length;
+	gint herr;
+
+	/* Query DNS for the MX record for the domain name given in the
+	 * email address.  We need an authoritative name server for it. */
+
+	length = res_query (
+		closure->domain_name, C_IN, T_MX,
+		answer, sizeof (answer));
+	herr = h_errno;  /* h_errno is defined in <netdb.h> */
+
+	/* Based heavily on _g_resolver_targets_from_res_query().
+	 * The binary DNS message format is described in RFC 1035. */
+
+	if (length <= 0) {
+		if (length == 0 || herr == HOST_NOT_FOUND || herr == NO_DATA)
+			g_set_error (
+				&closure->error,
+				G_RESOLVER_ERROR,
+				G_RESOLVER_ERROR_NOT_FOUND,
+				_("No mail exchanger record for '%s'"),
+				closure->domain_name);
+		else if (herr == TRY_AGAIN)
+			g_set_error (
+				&closure->error,
+				G_RESOLVER_ERROR,
+				G_RESOLVER_ERROR_TEMPORARY_FAILURE,
+				_("Temporarily unable to resolve '%s'"),
+				closure->domain_name);
+		else
+			g_set_error (
+				&closure->error,
+				G_RESOLVER_ERROR,
+				G_RESOLVER_ERROR_INTERNAL,
+				_("Error resolving '%s'"),
+				closure->domain_name);
+		goto exit;
+	}
+
+	header = (HEADER *) answer;
+	cp = answer + sizeof (HEADER);
+	end = answer + length;
+
+	/* Skip the 'question' section. */
+	count = ntohs (header->qdcount);
+	while (count-- && cp < end) {
+		cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf));
+		cp += 2;			/* skip QTYPE */
+		cp += 2;			/* skip QCLASS */
+	}
+
+	/* Skip the 'answers' section. */
+	count = ntohs (header->ancount);
+	while (count-- && cp < end) {
+		guint16 rdlength;
+		cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf));
+		cp += 2;			/* skip TYPE */
+		cp += 2;			/* skip CLASS */
+		cp += 4;			/* skip TTL */
+		GETSHORT (rdlength, cp);	/* read RDLENGTH */
+		cp += rdlength;			/* skip RDATA */
+	}
+
+	/* Read the 'authority' section. */
+	count = ntohs (header->nscount);
+	while (count-- && cp < end) {
+		guint16 type, qclass, rdlength;
+		cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf));
+		GETSHORT (type, cp);
+		GETSHORT (qclass, cp);
+		cp += 4;			/* skip TTL */
+		GETSHORT (rdlength, cp);
+
+		if (type != T_NS || qclass != C_IN) {
+			cp += rdlength;
+			continue;
+		}
+
+		cp += dn_expand (answer, end, cp, namebuf, sizeof (namebuf));
+
+		/* Pick the first T_NS record we find. */
+		closure->name_server = g_strdup (namebuf);
+		break;
+	}
+
+	if (closure->name_server == NULL)
+		g_set_error (
+			&closure->error,
+			G_RESOLVER_ERROR,
+			G_RESOLVER_ERROR_NOT_FOUND,
+			_("No authoritative name server for '%s'"),
+			closure->domain_name);
+
+exit:
+	g_main_loop_quit (closure->main_loop);
+	resolver_closure_unref (closure);
+
+	return NULL;  /* return value is not used */
+}
+
+static gchar *
+mail_autoconfig_resolve_authority (const gchar *domain,
+                                   GCancellable *cancellable,
+                                   GError **error)
+{
+	ResolverClosure *closure;
+	GThread *resolver_thread;
+	gchar *name_server = NULL;
+	gulong cancel_id = 0;
+
+	closure = resolver_closure_new (domain);
+
+	/* DNS record lookup is not cancellable, so we run it in a
+	 * separate thread.  We don't join with the thread, however,
+	 * because if we get cancelled we want to return immediately.
+	 * So use a reference count on the thread closure and always
+	 * let the thread run to completion even if we're not around
+	 * any longer to pick up the result. */
+	resolver_thread = g_thread_create (
+		mail_autoconfig_resolver_thread,
+		resolver_closure_ref (closure),
+		FALSE /* not joinable */, error);
+
+	if (resolver_thread == NULL)
+		return FALSE;
+
+	if (G_IS_CANCELLABLE (cancellable))
+		cancel_id = g_cancellable_connect (
+			cancellable,
+			G_CALLBACK (mail_autoconfig_resolver_cancelled),
+			resolver_closure_ref (closure),
+			(GDestroyNotify) resolver_closure_unref);
+
+	g_main_loop_run (closure->main_loop);
+
+	if (cancel_id > 0)
+		g_cancellable_disconnect (cancellable, cancel_id);
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+		/* do nothing */
+
+	} else if (closure->error != NULL) {
+		g_warn_if_fail (closure->name_server == NULL);
+		g_propagate_error (error, closure->error);
+		closure->error = NULL;
+
+	} else {
+		g_warn_if_fail (closure->name_server != NULL);
+		name_server = closure->name_server;
+		closure->name_server = NULL;
+	}
+
+	resolver_closure_unref (closure);
+
+	return name_server;
+}
+
+static gboolean
+mail_autoconfig_lookup (EMailAutoconfig *autoconfig,
+                        const gchar *domain,
+                        GCancellable *cancellable,
+                        GError **error)
+{
+	GFile *file;
+	gchar *uri;
+	gboolean success;
+
+	uri = g_strconcat (AUTOCONFIG_BASE_URI, domain, NULL);
+	file = g_file_new_for_uri (uri);
+	g_free (uri);
+
+	/* Just to make sure we don't leak. */
+	g_free (autoconfig->priv->markup_content);
+	autoconfig->priv->markup_content = NULL;
+
+	success = g_file_load_contents (
+		file, cancellable,
+		&autoconfig->priv->markup_content,
+		NULL, NULL, error);
+
+	g_object_unref (file);
+
+	return success;
+}
+
+static void
+mail_autoconfig_parse_start_element (GMarkupParseContext *context,
+                                     const gchar *element_name,
+                                     const gchar **attribute_names,
+                                     const gchar **attribute_values,
+                                     gpointer user_data,
+                                     GError **error)
+{
+	ParserClosure *closure = user_data;
+	gboolean is_incoming_server;
+	gboolean is_outgoing_server;
+
+	is_incoming_server = g_str_equal (element_name, "incomingServer");
+	is_outgoing_server = g_str_equal (element_name, "outgoingServer");
+
+	if (is_incoming_server || is_outgoing_server) {
+		const gchar *type = NULL;
+
+		g_markup_collect_attributes (
+			element_name,
+			attribute_names,
+			attribute_values,
+			error,
+			G_MARKUP_COLLECT_STRING,
+			"type", &type,
+			G_MARKUP_COLLECT_INVALID);
+
+		closure->in_server_element =
+			(g_strcmp0 (type, closure->expected_type) == 0);
+	}
+}
+
+static void
+mail_autoconfig_parse_end_element (GMarkupParseContext *context,
+                                   const gchar *element_name,
+                                   gpointer user_data,
+                                   GError **error)
+{
+	ParserClosure *closure = user_data;
+	gboolean is_incoming_server;
+	gboolean is_outgoing_server;
+
+	is_incoming_server = g_str_equal (element_name, "incomingServer");
+	is_outgoing_server = g_str_equal (element_name, "outgoingServer");
+
+	if (is_incoming_server || is_outgoing_server)
+		closure->in_server_element = FALSE;
+}
+
+static void
+mail_autoconfig_parse_text (GMarkupParseContext *context,
+                            const gchar *text,
+                            gsize text_length,
+                            gpointer user_data,
+                            GError **error)
+{
+	ParserClosure *closure = user_data;
+	const gchar *element_name;
+	GString *string;
+
+	if (!closure->in_server_element)
+		return;
+
+	/* Perform the following text substitutions:
+	 *
+	 * %EMAILADDRESS%    :  closure->email_address
+	 * %EMAILLOCALPART%  :  closure->email_local_part
+	 * %EMAILDOMAIN%     :  closure->email_domain_part
+	 */
+	if (strchr (text, '%') == NULL)
+		string = g_string_new (text);
+	else {
+		const gchar *cp = text;
+
+		string = g_string_sized_new (256);
+		while (*cp != '\0') {
+			const gchar *variable;
+			const gchar *substitute;
+
+			if (*cp != '%') {
+				g_string_append_c (string, *cp++);
+				continue;
+			}
+
+			variable = "%EMAILADDRESS%";
+			substitute = closure->email_address;
+
+			if (strncmp (cp, variable, strlen (variable)) == 0) {
+				g_string_append (string, substitute);
+				cp += strlen (variable);
+				continue;
+			}
+
+			variable = "%EMAILLOCALPART%";
+			substitute = closure->email_local_part;
+
+			if (strncmp (cp, variable, strlen (variable)) == 0) {
+				g_string_append (string, substitute);
+				cp += strlen (variable);
+				continue;
+			}
+
+			variable = "%EMAILDOMAIN%";
+			substitute = closure->email_domain_part;
+
+			if (strncmp (cp, variable, strlen (variable)) == 0) {
+				g_string_append (string, substitute);
+				cp += strlen (variable);
+				continue;
+			}
+
+			g_string_append_c (string, *cp++);
+		}
+	}
+
+	element_name = g_markup_parse_context_get_element (context);
+
+	if (g_str_equal (element_name, "hostname")) {
+		camel_network_settings_set_host (
+			closure->network_settings, string->str);
+		closure->settings_modified = TRUE;
+
+	} else if (g_str_equal (element_name, "username")) {
+		camel_network_settings_set_user (
+			closure->network_settings, string->str);
+		closure->settings_modified = TRUE;
+
+	} else if (g_str_equal (element_name, "port")) {
+		glong port = strtol (string->str, NULL, 10);
+		if (port == CLAMP (port, 1, G_MAXUINT16)) {
+			camel_network_settings_set_port (
+				closure->network_settings, (guint16) port);
+			closure->settings_modified = TRUE;
+		}
+
+	} else if (g_str_equal (element_name, "socketType")) {
+		if (g_str_equal (string->str, "plain")) {
+			camel_network_settings_set_security_method (
+				closure->network_settings,
+				CAMEL_NETWORK_SECURITY_METHOD_NONE);
+			closure->settings_modified = TRUE;
+		} else if (g_str_equal (string->str, "SSL")) {
+			camel_network_settings_set_security_method (
+				closure->network_settings,
+				CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT);
+			closure->settings_modified = TRUE;
+		} else if (g_str_equal (string->str, "STARTTLS")) {
+			camel_network_settings_set_security_method (
+				closure->network_settings,
+				CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT);
+			closure->settings_modified = TRUE;
+		}
+	}
+
+	/* FIXME Not handling <authentication> elements.
+	 *       Unclear how some map to SASL mechanisms. */
+
+	g_string_free (string, TRUE);
+}
+
+static GMarkupParser mail_autoconfig_parser = {
+	mail_autoconfig_parse_start_element,
+	mail_autoconfig_parse_end_element,
+	mail_autoconfig_parse_text
+};
+
+static gboolean
+mail_autoconfig_set_details (EMailAutoconfig *autoconfig,
+                             const gchar *expected_type,
+                             ESource *source,
+                             const gchar *extension_name)
+{
+	GMarkupParseContext *context;
+	ESourceCamel *camel_ext;
+	ESourceBackend *backend_ext;
+	CamelSettings *settings;
+	ParserClosure closure;
+	const gchar *backend_name;
+	const gchar *markup_content;
+	gboolean success;
+
+	if (!e_source_has_extension (source, extension_name))
+		return FALSE;
+
+	backend_ext = e_source_get_extension (source, extension_name);
+	backend_name = e_source_backend_get_backend_name (backend_ext);
+	extension_name = e_source_camel_get_extension_name (backend_name);
+	camel_ext = e_source_get_extension (source, extension_name);
+
+	settings = e_source_camel_get_settings (camel_ext);
+	g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), FALSE);
+
+	markup_content = e_mail_autoconfig_get_markup_content (autoconfig);
+	g_return_val_if_fail (markup_content != NULL, FALSE);
+
+	closure.network_settings = CAMEL_NETWORK_SETTINGS (settings);
+	closure.expected_type = expected_type;
+	closure.in_server_element = FALSE;
+	closure.settings_modified = FALSE;
+
+	/* These are used for text substitutions. */
+	closure.email_address = autoconfig->priv->email_address;
+	closure.email_local_part = autoconfig->priv->email_local_part;
+	closure.email_domain_part = autoconfig->priv->email_domain_part;
+
+	context = g_markup_parse_context_new (
+		&mail_autoconfig_parser, 0, &closure, (GDestroyNotify) NULL);
+
+	success = g_markup_parse_context_parse (
+		context, markup_content, strlen (markup_content), NULL);
+
+	success &= g_markup_parse_context_end_parse (context, NULL);
+
+	/* Did we actually configure anything? */
+	success &= closure.settings_modified;
+
+	g_markup_parse_context_free (context);
+
+	return success;
+}
+
+static void
+mail_autoconfig_set_email_address (EMailAutoconfig *autoconfig,
+                                   const gchar *email_address)
+{
+	g_return_if_fail (email_address != NULL);
+	g_return_if_fail (autoconfig->priv->email_address == NULL);
+
+	autoconfig->priv->email_address = g_strdup (email_address);
+}
+
+static void
+mail_autoconfig_set_property (GObject *object,
+                              guint property_id,
+                              const GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_EMAIL_ADDRESS:
+			mail_autoconfig_set_email_address (
+				E_MAIL_AUTOCONFIG (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_autoconfig_get_property (GObject *object,
+                              guint property_id,
+                              GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_EMAIL_ADDRESS:
+			g_value_set_string (
+				value,
+				e_mail_autoconfig_get_email_address (
+				E_MAIL_AUTOCONFIG (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_autoconfig_finalize (GObject *object)
+{
+	EMailAutoconfigPrivate *priv;
+
+	priv = E_MAIL_AUTOCONFIG_GET_PRIVATE (object);
+
+	g_free (priv->email_address);
+	g_free (priv->email_local_part);
+	g_free (priv->email_domain_part);
+	g_free (priv->markup_content);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_autoconfig_parent_class)->finalize (object);
+}
+
+static gboolean
+mail_autoconfig_initable_init (GInitable *initable,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+	EMailAutoconfig *autoconfig;
+	const gchar *email_address;
+	const gchar *domain;
+	const gchar *cp;
+	gchar *name_server;
+	gboolean success = FALSE;
+	GError *local_error = NULL;
+
+	autoconfig = E_MAIL_AUTOCONFIG (initable);
+	email_address = e_mail_autoconfig_get_email_address (autoconfig);
+
+	if (email_address == NULL) {
+		g_set_error_literal (
+			error, G_IO_ERROR,
+			G_IO_ERROR_INVALID_ARGUMENT,
+			_("No email address provided"));
+		return FALSE;
+	}
+
+	cp = strchr (email_address, '@');
+	if (cp == NULL) {
+		g_set_error_literal (
+			error, G_IO_ERROR,
+			G_IO_ERROR_INVALID_ARGUMENT,
+			_("Missing domain in email address"));
+		return FALSE;
+	}
+
+	domain = cp + 1;
+
+	autoconfig->priv->email_local_part =
+		g_strndup (email_address, cp - email_address);
+	autoconfig->priv->email_domain_part = g_strdup (domain);
+
+	/* First try the email address domain verbatim. */
+	success = mail_autoconfig_lookup (
+		autoconfig, domain, cancellable, &local_error);
+
+	g_warn_if_fail (
+		(success && local_error == NULL) ||
+		(!success && local_error != NULL));
+
+	if (success)
+		return TRUE;
+
+	/* "404 Not Found" errors are non-fatal this time around. */
+	if (ERROR_IS_NOT_FOUND (local_error)) {
+		g_clear_error (&local_error);
+	} else {
+		g_propagate_error (error, local_error);
+		return FALSE;
+	}
+
+	/* Look up an authoritative name server for the email address
+	 * domain according to its "mail exchanger" (MX) DNS record. */
+	name_server = mail_autoconfig_resolve_authority (
+		domain, cancellable, error);
+
+	if (name_server == NULL)
+		return FALSE;
+
+	/* Widdle away segments of the name server domain until
+	 * we find a match, or until we widdle down to nothing. */
+
+	cp = name_server;
+	while (cp != NULL && strchr (cp, '.') != NULL) {
+		g_clear_error (&local_error);
+
+		success = mail_autoconfig_lookup (
+			autoconfig, cp, cancellable, &local_error);
+
+		g_warn_if_fail (
+			(success && local_error == NULL) ||
+			(!success && local_error != NULL));
+
+		if (success || !ERROR_IS_NOT_FOUND (local_error))
+			break;
+
+		cp = strchr (cp, '.');
+		if (cp != NULL)
+			cp++;
+	}
+
+	if (local_error != NULL)
+		g_propagate_error (error, local_error);
+
+	g_free (name_server);
+
+	return success;
+}
+
+static void
+e_mail_autoconfig_class_init (EMailAutoconfigClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailAutoconfigPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_autoconfig_set_property;
+	object_class->get_property = mail_autoconfig_get_property;
+	object_class->finalize = mail_autoconfig_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_EMAIL_ADDRESS,
+		g_param_spec_string (
+			"email-address",
+			"Email Address",
+			"The address from which to query config data",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_autoconfig_initable_init (GInitableIface *interface)
+{
+	interface->init = mail_autoconfig_initable_init;
+}
+
+static void
+e_mail_autoconfig_init (EMailAutoconfig *autoconfig)
+{
+	autoconfig->priv = E_MAIL_AUTOCONFIG_GET_PRIVATE (autoconfig);
+}
+
+EMailAutoconfig *
+e_mail_autoconfig_new_sync (const gchar *email_address,
+                            GCancellable *cancellable,
+                            GError **error)
+{
+	g_return_val_if_fail (email_address != NULL, NULL);
+
+	return g_initable_new (
+		E_TYPE_MAIL_AUTOCONFIG,
+		cancellable, error,
+		"email-address", email_address,
+		NULL);
+}
+
+void
+e_mail_autoconfig_new (const gchar *email_address,
+                       gint io_priority,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
+{
+	g_return_if_fail (email_address != NULL);
+
+	g_async_initable_new_async (
+		E_TYPE_MAIL_AUTOCONFIG,
+		io_priority, cancellable,
+		callback, user_data,
+		"email-address", email_address,
+		NULL);
+}
+
+EMailAutoconfig *
+e_mail_autoconfig_finish (GAsyncResult *result,
+                          GError **error)
+{
+	GObject *source_object;
+	GObject *autoconfig;
+
+	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+	source_object = g_async_result_get_source_object (result);
+	g_return_val_if_fail (source_object != NULL, NULL);
+
+	autoconfig = g_async_initable_new_finish (
+		G_ASYNC_INITABLE (source_object), result, error);
+
+	g_object_unref (source_object);
+
+	if (autoconfig == NULL)
+		return NULL;
+
+	return E_MAIL_AUTOCONFIG (autoconfig);
+}
+
+const gchar *
+e_mail_autoconfig_get_email_address (EMailAutoconfig *autoconfig)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), NULL);
+
+	return autoconfig->priv->email_address;
+}
+
+const gchar *
+e_mail_autoconfig_get_markup_content (EMailAutoconfig *autoconfig)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), NULL);
+
+	return autoconfig->priv->markup_content;
+}
+
+gboolean
+e_mail_autoconfig_set_imap_details (EMailAutoconfig *autoconfig,
+                                    ESource *imap_source)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE);
+	g_return_val_if_fail (E_IS_SOURCE (imap_source), FALSE);
+
+	return mail_autoconfig_set_details (
+		autoconfig, "imap", imap_source,
+		E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+}
+
+gboolean
+e_mail_autoconfig_set_pop3_details (EMailAutoconfig *autoconfig,
+                                    ESource *pop3_source)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE);
+	g_return_val_if_fail (E_IS_SOURCE (pop3_source), FALSE);
+
+	return mail_autoconfig_set_details (
+		autoconfig, "pop3", pop3_source,
+		E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+}
+
+gboolean
+e_mail_autoconfig_set_smtp_details (EMailAutoconfig *autoconfig,
+                                    ESource *smtp_source)
+{
+	g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE);
+	g_return_val_if_fail (E_IS_SOURCE (smtp_source), FALSE);
+
+	return mail_autoconfig_set_details (
+		autoconfig, "smtp", smtp_source,
+		E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+}
+
diff --git a/mail/e-mail-autoconfig.h b/mail/e-mail-autoconfig.h
new file mode 100644
index 0000000..5b03ace
--- /dev/null
+++ b/mail/e-mail-autoconfig.h
@@ -0,0 +1,89 @@
+/*
+ * e-mail-autoconfig.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_AUTOCONFIG_H
+#define E_MAIL_AUTOCONFIG_H
+
+#include <gio/gio.h>
+#include <libedataserver/e-source.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_AUTOCONFIG \
+	(e_mail_autoconfig_get_type ())
+#define E_MAIL_AUTOCONFIG(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfig))
+#define E_MAIL_AUTOCONFIG_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfigClass))
+#define E_IS_MAIL_AUTOCONFIG(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_AUTOCONFIG))
+#define E_IS_MAIL_AUTOCONFIG_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_AUTOCONFIG))
+#define E_MAIL_AUTOCONFIG_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_AUTOCONFIG, EMailAutoconfigClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAutoconfig EMailAutoconfig;
+typedef struct _EMailAutoconfigClass EMailAutoconfigClass;
+typedef struct _EMailAutoconfigPrivate EMailAutoconfigPrivate;
+
+struct _EMailAutoconfig {
+	GObject parent;
+	EMailAutoconfigPrivate *priv;
+};
+
+struct _EMailAutoconfigClass {
+	GObjectClass parent_class;
+};
+
+GType		e_mail_autoconfig_get_type	(void) G_GNUC_CONST;
+EMailAutoconfig *
+		e_mail_autoconfig_new_sync	(const gchar *email_address,
+						 GCancellable *cancellable,
+						 GError **error);
+void		e_mail_autoconfig_new		(const gchar *email_address,
+						 gint io_priority,
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+EMailAutoconfig *
+		e_mail_autoconfig_finish	(GAsyncResult *result,
+						 GError **error);
+const gchar *	e_mail_autoconfig_get_email_address
+						(EMailAutoconfig *autoconfig);
+const gchar *	e_mail_autoconfig_get_markup_content
+						(EMailAutoconfig *autoconfig);
+gboolean	e_mail_autoconfig_set_imap_details
+						(EMailAutoconfig *autoconfig,
+						 ESource *imap_source);
+gboolean	e_mail_autoconfig_set_pop3_details
+						(EMailAutoconfig *autoconfig,
+						 ESource *pop3_source);
+gboolean	e_mail_autoconfig_set_smtp_details
+						(EMailAutoconfig *autoconfig,
+						 ESource *smtp_source);
+
+G_END_DECLS
+
+#endif /* E_MAIL_AUTOCONFIG_H */
+
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index c350bd7..60e506d 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -32,15 +32,15 @@
 #include <glib/gstdio.h>
 #include <glib/gi18n-lib.h>
 #include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-submission.h>
 
 #include <shell/e-shell.h>
 
 #include <libevolution-utils/e-alert-dialog.h>
 #include <libevolution-utils/e-alert-sink.h>
 
-#include <misc/e-account-combo-box.h>
-
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-engine/e-mail-folder-utils.h>
 #include <libemail-engine/e-mail-session.h>
 #include <libemail-engine/e-mail-store-utils.h>
@@ -141,11 +141,14 @@ mail_backend_prepare_for_offline_cb (EShell *shell,
 {
 	GtkWindow *window;
 	EMailSession *session;
+	ESourceRegistry *registry;
 	GList *list, *link;
+	const gchar *extension_name;
 	gboolean synchronize = FALSE;
 
 	window = e_shell_get_active_window (shell);
 	session = e_mail_backend_get_session (backend);
+	registry = e_mail_session_get_registry (session);
 
 	if (e_shell_get_network_available (shell) &&
 		e_shell_backend_is_started (E_SHELL_BACKEND (backend)))
@@ -158,12 +161,17 @@ mail_backend_prepare_for_offline_cb (EShell *shell,
 			CAMEL_SESSION (session), FALSE);
 	}
 
-	list = camel_session_list_services (CAMEL_SESSION (session));
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
 
 	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
 		CamelService *service;
+		const gchar *uid;
 
-		service = CAMEL_SERVICE (link->data);
+		uid = e_source_get_uid (source);
+		service = camel_session_get_service (
+			CAMEL_SESSION (session), uid);
 
 		if (!CAMEL_IS_STORE (service))
 			continue;
@@ -176,7 +184,7 @@ mail_backend_prepare_for_offline_cb (EShell *shell,
 			g_object_ref (activity));
 	}
 
-	g_list_free (list);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 }
 
 static void
@@ -185,27 +193,31 @@ mail_backend_prepare_for_online_cb (EShell *shell,
                                     EMailBackend *backend)
 {
 	EMailSession *session;
+	ESourceRegistry *registry;
 	GList *list, *link;
+	const gchar *extension_name;
 
 	session = e_mail_backend_get_session (backend);
+	registry = e_mail_session_get_registry (session);
+
 	camel_session_set_online (CAMEL_SESSION (session), TRUE);
 
-	list = camel_session_list_services (CAMEL_SESSION (session));
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
 
 	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
 		CamelService *service;
-		EAccount *account;
 		const gchar *uid;
 
-		service = CAMEL_SERVICE (link->data);
-
-		if (!CAMEL_IS_STORE (service))
+		if (!e_source_get_enabled (source))
 			continue;
 
-		uid = camel_service_get_uid (service);
-		account = e_get_account_by_uid (uid);
+		uid = e_source_get_uid (source);
+		service = camel_session_get_service (
+			CAMEL_SESSION (session), uid);
 
-		if (account != NULL && !account->enabled)
+		if (!CAMEL_IS_STORE (service))
 			continue;
 
 		/* FIXME Not passing a GCancellable. */
@@ -216,7 +228,7 @@ mail_backend_prepare_for_online_cb (EShell *shell,
 			g_object_ref (activity));
 	}
 
-	g_list_free (link);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 }
 
 /* Helper for mail_backend_prepare_for_quit_cb() */
@@ -273,7 +285,6 @@ mail_backend_prepare_for_quit_cb (EShell *shell,
                                   EActivity *activity,
                                   EMailBackend *backend)
 {
-	EAccountList *account_list;
 	EMailSession *session;
 	GList *list, *link;
 	gboolean delete_junk;
@@ -286,9 +297,6 @@ mail_backend_prepare_for_quit_cb (EShell *shell,
 
 	camel_application_is_exiting = TRUE;
 
-	account_list = e_get_account_list ();
-	e_account_list_prune_proxies (account_list);
-
 	mail_vfolder_shutdown ();
 
 	/* Cancel all pending activities. */
@@ -399,20 +407,26 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache,
                                 const gchar *folder_name,
                                 EMailBackend *backend)
 {
+	EShell *shell;
 	CamelStoreClass *class;
-	EAccountList *account_list;
-	EIterator *iterator;
+	ESourceRegistry *registry;
+	EShellBackend *shell_backend;
 	EMailSession *session;
 	EAlertSink *alert_sink;
+	GList *list, *link;
+	const gchar *extension_name;
 	const gchar *local_drafts_folder_uri;
 	const gchar *local_sent_folder_uri;
-	gboolean write_config = FALSE;
 	gchar *uri;
 
 	/* Check whether the deleted folder was a designated Drafts or
 	 * Sent folder for any mail account, and if so revert the setting
 	 * to the equivalent local folder, which is always present. */
 
+	shell_backend = E_SHELL_BACKEND (backend);
+	shell = e_shell_backend_get_shell (shell_backend);
+	registry = e_shell_get_registry (shell);
+
 	class = CAMEL_STORE_GET_CLASS (store);
 	g_return_if_fail (class->compare_folder_name != NULL);
 
@@ -429,51 +443,69 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache,
 
 	uri = e_mail_folder_uri_build (store, folder_name);
 
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-	while (e_iterator_is_valid (iterator)) {
-		EAccount *account;
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *drafts_folder_uri;
+
+		extension = e_source_get_extension (source, extension_name);
 
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iterator);
+		drafts_folder_uri =
+			e_source_mail_composition_get_drafts_folder (
+			E_SOURCE_MAIL_COMPOSITION (extension));
 
-		if (account->sent_folder_uri != NULL) {
-			gboolean match;
+		if (class->compare_folder_name (drafts_folder_uri, uri)) {
+			GError *error = NULL;
 
-			match = class->compare_folder_name (
-				account->sent_folder_uri, uri);
+			e_source_mail_composition_set_drafts_folder (
+				E_SOURCE_MAIL_COMPOSITION (extension),
+				local_drafts_folder_uri);
 
-			if (match) {
-				g_free (account->sent_folder_uri);
-				account->sent_folder_uri =
-					g_strdup (local_sent_folder_uri);
-				write_config = TRUE;
+			/* FIXME This is a blocking D-Bus method call. */
+			if (!e_source_write_sync (source, NULL, &error)) {
+				g_warning ("%s", error->message);
+				g_error_free (error);
 			}
 		}
+	}
 
-		if (account->drafts_folder_uri != NULL) {
-			gboolean match;
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
-			match = class->compare_folder_name (
-				account->drafts_folder_uri, uri);
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-			if (match) {
-				g_free (account->drafts_folder_uri);
-				account->drafts_folder_uri =
-					g_strdup (local_drafts_folder_uri);
-				write_config = TRUE;
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *sent_folder_uri;
+
+		extension = e_source_get_extension (source, extension_name);
+
+		sent_folder_uri =
+			e_source_mail_submission_get_sent_folder (
+			E_SOURCE_MAIL_SUBMISSION (extension));
+
+		if (class->compare_folder_name (sent_folder_uri, uri)) {
+			GError *error = NULL;
+
+			e_source_mail_submission_set_sent_folder (
+				E_SOURCE_MAIL_SUBMISSION (extension),
+				local_sent_folder_uri);
+
+			/* FIXME This is a blocking D-Bus method call. */
+			if (!e_source_write_sync (source, NULL, &error)) {
+				g_warning ("%s", error->message);
+				g_error_free (error);
 			}
 		}
-
-		e_iterator_next (iterator);
 	}
 
-	g_object_unref (iterator);
-	g_free (uri);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
-	if (write_config)
-		mail_config_write ();
+	g_free (uri);
 
 	/* This does something completely different.
 	 * XXX Make it a separate signal handler? */
@@ -487,10 +519,12 @@ mail_backend_folder_renamed_cb (MailFolderCache *folder_cache,
                                 const gchar *new_folder_name,
                                 EMailBackend *backend)
 {
+	EShell *shell;
 	CamelStoreClass *class;
-	EAccountList *account_list;
-	EIterator *iterator;
-	gboolean write_config = FALSE;
+	ESourceRegistry *registry;
+	EShellBackend *shell_backend;
+	GList *list, *link;
+	const gchar *extension_name;
 	gchar *old_uri;
 	gchar *new_uri;
 	gint ii;
@@ -500,54 +534,84 @@ mail_backend_folder_renamed_cb (MailFolderCache *folder_cache,
 		"views/custom_view-"
 	};
 
+	/* Check whether the renamed folder was a designated Drafts or
+	 * Sent folder for any mail account, and if so update the setting
+	 * to the new folder name. */
+
+	shell_backend = E_SHELL_BACKEND (backend);
+	shell = e_shell_backend_get_shell (shell_backend);
+	registry = e_shell_get_registry (shell);
+
 	class = CAMEL_STORE_GET_CLASS (store);
 	g_return_if_fail (class->compare_folder_name != NULL);
 
 	old_uri = e_mail_folder_uri_build (store, old_folder_name);
 	new_uri = e_mail_folder_uri_build (store, new_folder_name);
 
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *drafts_folder_uri;
 
-	while (e_iterator_is_valid (iterator)) {
-		EAccount *account;
+		extension = e_source_get_extension (source, extension_name);
 
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iterator);
+		drafts_folder_uri =
+			e_source_mail_composition_get_drafts_folder (
+			E_SOURCE_MAIL_COMPOSITION (extension));
 
-		if (account->sent_folder_uri != NULL) {
-			gboolean match;
+		if (class->compare_folder_name (drafts_folder_uri, old_uri)) {
+			GError *error = NULL;
 
-			match = class->compare_folder_name (
-				account->sent_folder_uri, old_uri);
+			e_source_mail_composition_set_drafts_folder (
+				E_SOURCE_MAIL_COMPOSITION (extension),
+				new_uri);
 
-			if (match) {
-				g_free (account->sent_folder_uri);
-				account->sent_folder_uri = g_strdup (new_uri);
-				write_config = TRUE;
+			/* FIXME This is a blocking D-Bus method call. */
+			if (!e_source_write_sync (source, NULL, &error)) {
+				g_warning ("%s", error->message);
+				g_error_free (error);
 			}
 		}
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
-		if (account->drafts_folder_uri != NULL) {
-			gboolean match;
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	list = e_source_registry_list_sources (registry, extension_name);
 
-			match = class->compare_folder_name (
-				account->drafts_folder_uri, old_uri);
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceExtension *extension;
+		const gchar *sent_folder_uri;
 
-			if (match) {
-				g_free (account->drafts_folder_uri);
-				account->drafts_folder_uri = g_strdup (new_uri);
-				write_config = TRUE;
+		extension = e_source_get_extension (source, extension_name);
+
+		sent_folder_uri =
+			e_source_mail_submission_get_sent_folder (
+			E_SOURCE_MAIL_SUBMISSION (extension));
+
+		if (class->compare_folder_name (sent_folder_uri, old_uri)) {
+			GError *error = NULL;
+
+			e_source_mail_submission_set_sent_folder (
+				E_SOURCE_MAIL_SUBMISSION (extension),
+				new_uri);
+
+			/* FIXME This is a blocking D-Bus method call. */
+			if (!e_source_write_sync (source, NULL, &error)) {
+				g_warning ("%s", error->message);
+				g_error_free (error);
 			}
 		}
-
-		e_iterator_next (iterator);
 	}
 
-	g_object_unref (iterator);
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
-	if (write_config)
-		mail_config_write ();
+	g_free (old_uri);
+	g_free (new_uri);
 
 	/* Rename GalView files. */
 
@@ -565,9 +629,6 @@ mail_backend_folder_renamed_cb (MailFolderCache *folder_cache,
 		g_free (newname);
 	}
 
-	g_free (old_uri);
-	g_free (new_uri);
-
 	/* This does something completely different.
 	 * XXX Make it a separate signal handler? */
 	mail_filter_rename_folder (
@@ -606,10 +667,8 @@ mail_backend_folder_changed_cb (MailFolderCache *folder_cache,
 			g_object_unref (folder);
 	}
 
-	g_free (folder_uri);
-
 	target = em_event_target_new_folder (
-		event, store, folder_name, new_messages,
+		event, store, folder_uri, new_messages,
 		msg_uid, msg_sender, msg_subject);
 
 	folder_type = (flags & CAMEL_FOLDER_TYPE_MASK);
@@ -939,6 +998,7 @@ mail_backend_constructed (GObject *object)
 	EShell *shell;
 	EShellBackend *shell_backend;
 	MailFolderCache *folder_cache;
+	ESourceRegistry *registry;
 
 	priv = E_MAIL_BACKEND_GET_PRIVATE (object);
 
@@ -948,9 +1008,8 @@ mail_backend_constructed (GObject *object)
 	if (camel_init (e_get_user_data_dir (), TRUE) != 0)
 		exit (0);
 
-	camel_provider_init ();
-
-	priv->session = e_mail_ui_session_new ();
+	registry = e_shell_get_registry (shell);
+	priv->session = e_mail_ui_session_new (registry);
 
 	g_signal_connect (
 		priv->session, "flush-outbox",
@@ -978,10 +1037,6 @@ mail_backend_constructed (GObject *object)
 		G_CALLBACK (mail_backend_job_finished_cb),
 		shell_backend);
 
-	/* FIXME This is an evil hack that needs to die.
-	 *       Give EAccountComboBox a CamelSession property. */
-	e_account_combo_box_set_session (CAMEL_SESSION (priv->session));
-
 	g_signal_connect (
 		priv->session, "store-added",
 		G_CALLBACK (mail_backend_add_store),
@@ -1029,7 +1084,6 @@ mail_backend_constructed (GObject *object)
 		G_CALLBACK (mail_backend_folder_changed_cb), shell_backend);
 
 	mail_config_init (priv->session);
-	mail_msg_init ();
 
 	mail_msg_register_activities (
 		mail_mt_create_activity,
diff --git a/mail/e-mail-config-assistant.c b/mail/e-mail-config-assistant.c
new file mode 100644
index 0000000..e81a198
--- /dev/null
+++ b/mail/e-mail-config-assistant.c
@@ -0,0 +1,1157 @@
+/*
+ * e-mail-config-assistant.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-assistant.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-mail-transport.h>
+
+#include <libevolution-utils/e-alert-sink.h>
+
+#include <mail/e-mail-config-confirm-page.h>
+#include <mail/e-mail-config-identity-page.h>
+#include <mail/e-mail-config-lookup-page.h>
+#include <mail/e-mail-config-provider-page.h>
+#include <mail/e-mail-config-receiving-page.h>
+#include <mail/e-mail-config-sending-page.h>
+#include <mail/e-mail-config-summary-page.h>
+#include <mail/e-mail-config-welcome-page.h>
+
+#define E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistantPrivate))
+
+struct _EMailConfigAssistantPrivate {
+	EMailSession *session;
+	ESource *identity_source;
+	GPtrArray *account_sources;
+	GPtrArray *transport_sources;
+	EMailConfigServicePage *receiving_page;
+	EMailConfigServicePage *sending_page;
+	EMailConfigSummaryPage *summary_page;
+	EMailConfigPage *lookup_page;
+	GHashTable *visited_pages;
+	gboolean auto_configure_done;
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT_BACKEND,
+	PROP_ACCOUNT_SOURCE,
+	PROP_IDENTITY_SOURCE,
+	PROP_SESSION,
+	PROP_TRANSPORT_BACKEND,
+	PROP_TRANSPORT_SOURCE
+};
+
+/* XXX We implement EAlertSink but don't implement a custom submit_alert()
+ *     method.  So any alert results in a pop-up message dialog, which is a
+ *     fashion faux pas these days.  But it's only used when submitting the
+ *     the newly-configured account fails, so should rarely be seen. */
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigAssistant,
+	e_mail_config_assistant,
+	GTK_TYPE_ASSISTANT,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_ALERT_SINK, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL))
+
+static gint
+mail_config_assistant_provider_compare (gconstpointer data1,
+                                        gconstpointer data2)
+{
+	const CamelProvider *provider1 = data1;
+	const CamelProvider *provider2 = data2;
+
+	/* The "none" provider comes first. */
+	if (g_strcmp0 (provider1->protocol, "none") == 0)
+		return -1;
+	if (g_strcmp0 (provider2->protocol, "none") == 0)
+		return 1;
+
+	/* Then sort remote providers before local providers. */
+	if (provider1->flags & CAMEL_PROVIDER_IS_REMOTE) {
+		if (provider2->flags & CAMEL_PROVIDER_IS_REMOTE)
+			return 0;
+		else
+			return -1;
+	} else {
+		if (provider2->flags & CAMEL_PROVIDER_IS_REMOTE)
+			return 1;
+		else
+			return 0;
+	}
+}
+
+static GList *
+mail_config_assistant_list_providers (void)
+{
+	GList *list, *link;
+	GQueue trash = G_QUEUE_INIT;
+
+	list = camel_provider_list (TRUE);
+	list = g_list_sort (list, mail_config_assistant_provider_compare);
+
+	/* Keep only providers with a "mail" or "news" domain. */
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		CamelProvider *provider = link->data;
+		gboolean mail_or_news_domain;
+
+		mail_or_news_domain =
+			(g_strcmp0 (provider->domain, "mail") == 0) ||
+			(g_strcmp0 (provider->domain, "news") == 0);
+
+		if (mail_or_news_domain)
+			continue;
+
+		g_queue_push_tail (&trash, link);
+	}
+
+	while ((link = g_queue_pop_head (&trash)) != NULL)
+		list = g_list_remove_link (list, link);
+
+	return list;
+}
+
+static void
+mail_config_assistant_notify_account_backend (EMailConfigServicePage *page,
+                                              GParamSpec *pspec,
+                                              EMailConfigAssistant *assistant)
+{
+	EMailConfigServiceBackend *backend;
+	EMailConfigServicePage *sending_page;
+	EMailConfigServicePageClass *page_class;
+	CamelProvider *provider;
+
+	backend = e_mail_config_service_page_get_active_backend (page);
+
+	/* The Receiving Page combo box may not have an active item. */
+	if (backend == NULL)
+		goto notify;
+
+	/* The Sending Page may not have been created yet. */
+	if (assistant->priv->sending_page == NULL)
+		goto notify;
+
+	provider = e_mail_config_service_backend_get_provider (backend);
+
+	/* XXX This should never fail, but the Camel macro below does
+	 *     not check for NULL so better to malfunction than crash. */
+	g_return_if_fail (provider != NULL);
+
+	sending_page = assistant->priv->sending_page;
+	page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (sending_page);
+
+	/* The Sending Page is invisible when the CamelProvider for the
+	 * receiving type defines both a storage and transport service.
+	 * This is common in CamelProviders for groupware products like
+	 * Microsoft Exchange and Novell GroupWise. */
+	if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) {
+		backend = e_mail_config_service_page_lookup_backend (
+			sending_page, provider->protocol);
+		gtk_widget_hide (GTK_WIDGET (sending_page));
+	} else {
+		backend = e_mail_config_service_page_lookup_backend (
+			sending_page, page_class->default_backend_name);
+		gtk_widget_show (GTK_WIDGET (sending_page));
+	}
+
+	e_mail_config_service_page_set_active_backend (sending_page, backend);
+
+notify:
+	g_object_freeze_notify (G_OBJECT (assistant));
+
+	g_object_notify (G_OBJECT (assistant), "account-backend");
+	g_object_notify (G_OBJECT (assistant), "account-source");
+
+	g_object_thaw_notify (G_OBJECT (assistant));
+}
+
+static void
+mail_config_assistant_notify_transport_backend (EMailConfigServicePage *page,
+                                                GParamSpec *pspec,
+                                                EMailConfigAssistant *assistant)
+{
+	g_object_freeze_notify (G_OBJECT (assistant));
+
+	g_object_notify (G_OBJECT (assistant), "transport-backend");
+	g_object_notify (G_OBJECT (assistant), "transport-source");
+
+	g_object_thaw_notify (G_OBJECT (assistant));
+}
+
+static void
+mail_config_assistant_page_changed (EMailConfigPage *page,
+                                    EMailConfigAssistant *assistant)
+{
+	gtk_assistant_set_page_complete (
+		GTK_ASSISTANT (assistant), GTK_WIDGET (page),
+		e_mail_config_page_check_complete (page));
+}
+
+static void
+mail_config_assistant_autoconfigure_cb (GObject *source_object,
+                                        GAsyncResult *result,
+                                        gpointer user_data)
+{
+	EMailConfigAssistantPrivate *priv;
+	GtkAssistant *assistant;
+	EMailAutoconfig *autoconfig;
+	const gchar *email_address;
+	gint n_pages, ii;
+	GError *error = NULL;
+
+	assistant = GTK_ASSISTANT (user_data);
+	priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (assistant);
+
+	/* Whether it works or not, we only do this once. */
+	priv->auto_configure_done = TRUE;
+
+	autoconfig = e_mail_autoconfig_finish (result, &error);
+
+	/* We don't really care about errors, we only capture the GError
+	 * as a debugging aid.  If this doesn't work we simply proceed to
+	 * the Receiving Email page. */
+	if (error != NULL) {
+		gtk_assistant_next_page (assistant);
+		g_error_free (error);
+		goto exit;
+	}
+
+	g_return_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig));
+
+	/* Autoconfiguration worked!  Feed the results to the
+	 * service pages and then skip to the Summary page. */
+
+	e_mail_config_service_page_auto_configure (
+		priv->receiving_page, autoconfig);
+
+	e_mail_config_service_page_auto_configure (
+		priv->sending_page, autoconfig);
+
+	/* Also set the initial account name to the email address
+	 * given so the user can just click past the Summary page. */
+	email_address = e_mail_autoconfig_get_email_address (autoconfig);
+	e_mail_config_summary_page_set_account_name (
+		priv->summary_page, email_address);
+
+	/* XXX Can't find a better way to learn the page number of
+	 *     the summary page.  Oh my god this API is horrible. */
+	n_pages = gtk_assistant_get_n_pages (assistant);
+	for (ii = 0; ii < n_pages; ii++) {
+		GtkWidget *nth_page;
+
+		nth_page = gtk_assistant_get_nth_page (assistant, ii);
+		if (E_IS_MAIL_CONFIG_SUMMARY_PAGE (nth_page))
+			break;
+	}
+
+	g_warn_if_fail (ii < n_pages);
+	gtk_assistant_set_current_page (assistant, ii);
+
+exit:
+	/* Set the page invisible so we never revisit it. */
+	gtk_widget_set_visible (GTK_WIDGET (priv->lookup_page), FALSE);
+
+	g_object_unref (assistant);
+}
+
+static gboolean
+mail_config_assistant_provider_page_visible (GBinding *binding,
+                                             const GValue *source_value,
+                                             GValue *target_value,
+                                             gpointer unused)
+{
+	EMailConfigServiceBackend *active_backend;
+	EMailConfigServiceBackend *page_backend;
+	EMailConfigProviderPage *page;
+	GObject *target_object;
+	gboolean visible;
+
+	target_object = g_binding_get_target (binding);
+	page = E_MAIL_CONFIG_PROVIDER_PAGE (target_object);
+	page_backend = e_mail_config_provider_page_get_backend (page);
+
+	active_backend = g_value_get_object (source_value);
+	visible = (page_backend == active_backend);
+	g_value_set_boolean (target_value, visible);
+
+	return TRUE;
+}
+
+static void
+mail_config_assistant_close_cb (GObject *object,
+                                GAsyncResult *result,
+                                gpointer user_data)
+{
+	EMailConfigAssistant *assistant;
+	GdkWindow *gdk_window;
+	GError *error = NULL;
+
+	assistant = E_MAIL_CONFIG_ASSISTANT (object);
+
+	/* Set the cursor back to normal. */
+	gdk_window = gtk_widget_get_window (GTK_WIDGET (assistant));
+	gdk_window_set_cursor (gdk_window, NULL);
+
+	/* Allow user interaction with window content. */
+	gtk_widget_set_sensitive (GTK_WIDGET (assistant), TRUE);
+
+	e_mail_config_assistant_commit_finish (assistant, result, &error);
+
+	/* Ignore cancellations. */
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		g_error_free (error);
+
+	} else if (error != NULL) {
+		e_alert_submit (
+			E_ALERT_SINK (assistant),
+			"mail:session-message-error",
+			error->message, NULL);
+		g_error_free (error);
+
+	} else {
+		gtk_widget_destroy (GTK_WIDGET (assistant));
+	}
+}
+
+static void
+mail_config_assistant_set_session (EMailConfigAssistant *assistant,
+                                   EMailSession *session)
+{
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
+	g_return_if_fail (assistant->priv->session == NULL);
+
+	assistant->priv->session = g_object_ref (session);
+}
+
+static void
+mail_config_assistant_set_property (GObject *object,
+                                    guint property_id,
+                                    const GValue *value,
+                                    GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SESSION:
+			mail_config_assistant_set_session (
+				E_MAIL_CONFIG_ASSISTANT (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_assistant_get_property (GObject *object,
+                                    guint property_id,
+                                    GValue *value,
+                                    GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_assistant_get_account_backend (
+				E_MAIL_CONFIG_ASSISTANT (object)));
+			return;
+
+		case PROP_ACCOUNT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_assistant_get_account_source (
+				E_MAIL_CONFIG_ASSISTANT (object)));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_assistant_get_identity_source (
+				E_MAIL_CONFIG_ASSISTANT (object)));
+			return;
+
+		case PROP_SESSION:
+			g_value_set_object (
+				value,
+				e_mail_config_assistant_get_session (
+				E_MAIL_CONFIG_ASSISTANT (object)));
+			return;
+
+		case PROP_TRANSPORT_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_assistant_get_transport_backend (
+				E_MAIL_CONFIG_ASSISTANT (object)));
+			return;
+
+		case PROP_TRANSPORT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_assistant_get_transport_source (
+				E_MAIL_CONFIG_ASSISTANT (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_assistant_dispose (GObject *object)
+{
+	EMailConfigAssistantPrivate *priv;
+
+	priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (object);
+
+	if (priv->session != NULL) {
+		g_object_unref (priv->session);
+		priv->session = NULL;
+	}
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->receiving_page != NULL) {
+		g_object_unref (priv->receiving_page);
+		priv->receiving_page = NULL;
+	}
+
+	if (priv->sending_page != NULL) {
+		g_object_unref (priv->sending_page);
+		priv->sending_page = NULL;
+	}
+
+	if (priv->summary_page != NULL) {
+		g_object_unref (priv->summary_page);
+		priv->summary_page = NULL;
+	}
+
+	if (priv->lookup_page != NULL) {
+		g_object_unref (priv->lookup_page);
+		priv->lookup_page = NULL;
+	}
+
+	g_ptr_array_set_size (priv->account_sources, 0);
+	g_ptr_array_set_size (priv->transport_sources, 0);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_assistant_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_assistant_finalize (GObject *object)
+{
+	EMailConfigAssistantPrivate *priv;
+
+	priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (object);
+
+	g_ptr_array_free (priv->account_sources, TRUE);
+	g_ptr_array_free (priv->transport_sources, TRUE);
+
+	g_hash_table_destroy (priv->visited_pages);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_assistant_parent_class)->
+		finalize (object);
+}
+
+static void
+mail_config_assistant_constructed (GObject *object)
+{
+	EMailConfigAssistant *assistant;
+	ESource *identity_source;
+	ESourceRegistry *registry;
+	ESourceExtension *extension;
+	ESourceMailComposition *mail_composition_extension;
+	ESourceMailIdentity *mail_identity_extension;
+	ESourceMailSubmission *mail_submission_extension;
+	EMailSession *session;
+	EMailConfigPage *page;
+	GList *list, *link;
+	const gchar *extension_name;
+	const gchar *title;
+
+	assistant = E_MAIL_CONFIG_ASSISTANT (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_assistant_parent_class)->
+		constructed (object);
+
+	title = _("Evolution Account Assistant");
+	gtk_window_set_title (GTK_WINDOW (assistant), title);
+	gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER);
+
+	session = e_mail_config_assistant_get_session (assistant);
+	registry = e_mail_session_get_registry (session);
+
+	/* Configure a new identity source. */
+
+	identity_source = e_source_new (NULL, NULL, NULL);
+	assistant->priv->identity_source = identity_source;
+	session = e_mail_config_assistant_get_session (assistant);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	extension = e_source_get_extension (identity_source, extension_name);
+	mail_composition_extension = E_SOURCE_MAIL_COMPOSITION (extension);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	extension = e_source_get_extension (identity_source, extension_name);
+	mail_identity_extension = E_SOURCE_MAIL_IDENTITY (extension);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	extension = e_source_get_extension (identity_source, extension_name);
+	mail_submission_extension = E_SOURCE_MAIL_SUBMISSION (extension);
+
+	e_source_mail_composition_set_drafts_folder (
+		mail_composition_extension,
+		e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_DRAFTS));
+
+	e_source_mail_composition_set_templates_folder (
+		mail_composition_extension,
+		e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_TEMPLATES));
+
+	e_source_mail_submission_set_sent_folder (
+		mail_submission_extension,
+		e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_SENT));
+
+	/*** Welcome Page ***/
+
+	page = e_mail_config_welcome_page_new ();
+	e_mail_config_assistant_add_page (assistant, page);
+
+	/*** Identity Page ***/
+
+	page = e_mail_config_identity_page_new (registry, identity_source);
+	e_mail_config_identity_page_set_show_account_info (
+		E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
+	e_mail_config_identity_page_set_show_signatures (
+		E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
+	e_mail_config_assistant_add_page (assistant, page);
+
+	/*** Lookup Page ***/
+
+	page = e_mail_config_lookup_page_new ();
+	e_mail_config_assistant_add_page (assistant, page);
+	assistant->priv->lookup_page = g_object_ref (page);
+
+	/*** Receiving Page ***/
+
+	page = e_mail_config_receiving_page_new (registry);
+	e_mail_config_assistant_add_page (assistant, page);
+	assistant->priv->receiving_page = g_object_ref (page);
+
+	g_object_bind_property (
+		mail_identity_extension, "address",
+		page, "email-address",
+		G_BINDING_SYNC_CREATE);
+
+	g_signal_connect (
+		page, "notify::active-backend",
+		G_CALLBACK (mail_config_assistant_notify_account_backend),
+		assistant);
+
+	/*** Receiving Options (multiple) ***/
+
+	/* Populate the Receiving Email page while at the same time
+	 * adding a Receiving Options page for each account type. */
+
+	list = mail_config_assistant_list_providers ();
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		EMailConfigServiceBackend *backend;
+		CamelProvider *provider = link->data;
+		ESourceBackend *backend_extension;
+		ESource *scratch_source;
+		const gchar *backend_name;
+
+		if (provider->object_types[CAMEL_PROVIDER_STORE] == 0)
+			continue;
+
+		/* ESource uses "backend_name" and CamelProvider
+		 * uses "protocol", but the terms are synonymous. */
+		backend_name = provider->protocol;
+
+		scratch_source = e_source_new (NULL, NULL, NULL);
+		backend_extension = e_source_get_extension (
+			scratch_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+		e_source_backend_set_backend_name (
+			backend_extension, backend_name);
+
+		/* We always pass NULL for the collection argument.
+		 * The backend generates its own scratch collection
+		 * source if implements the new_collection() method. */
+		backend = e_mail_config_service_page_add_scratch_source (
+			assistant->priv->receiving_page, scratch_source, NULL);
+
+		g_object_unref (scratch_source);
+
+		page = e_mail_config_provider_page_new (backend);
+
+		/* Note: We exclude this page if it has no options,
+		 *       but we don't know that until we create it. */
+		if (e_mail_config_provider_page_is_empty (
+				E_MAIL_CONFIG_PROVIDER_PAGE (page))) {
+			g_object_unref (g_object_ref_sink (page));
+			continue;
+		} else {
+			e_mail_config_assistant_add_page (assistant, page);
+		}
+
+		/* Each Receiving Options page is only visible when its
+		 * service backend is active on the Receiving Email page. */
+		g_object_bind_property_full (
+			assistant->priv->receiving_page, "active-backend",
+			page, "visible",
+			G_BINDING_SYNC_CREATE,
+			mail_config_assistant_provider_page_visible,
+			NULL,
+			NULL, (GDestroyNotify) NULL);
+	}
+
+	g_list_free (list);
+
+	/*** Sending Page ***/
+
+	page = e_mail_config_sending_page_new (registry);
+	e_mail_config_assistant_add_page (assistant, page);
+	assistant->priv->sending_page = g_object_ref (page);
+
+	g_object_bind_property (
+		mail_identity_extension, "address",
+		page, "email-address",
+		G_BINDING_SYNC_CREATE);
+
+	g_signal_connect (
+		page, "notify::active-backend",
+		G_CALLBACK (mail_config_assistant_notify_transport_backend),
+		assistant);
+
+	list = mail_config_assistant_list_providers ();
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		CamelProvider *provider = link->data;
+		ESourceBackend *backend_extension;
+		ESource *scratch_source;
+		const gchar *backend_name;
+
+		if (provider->object_types[CAMEL_PROVIDER_TRANSPORT] == 0)
+			continue;
+
+		/* ESource uses "backend_name" and CamelProvider
+		 * uses "protocol", but the terms are synonymous. */
+		backend_name = provider->protocol;
+
+		scratch_source = e_source_new (NULL, NULL, NULL);
+		backend_extension = e_source_get_extension (
+			scratch_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+		e_source_backend_set_backend_name (
+			backend_extension, backend_name);
+
+		/* We always pass NULL for the collection argument.
+		 * The backend generates its own scratch collection
+		 * source if implements the new_collection() method. */
+		e_mail_config_service_page_add_scratch_source (
+			assistant->priv->sending_page, scratch_source, NULL);
+
+		g_object_unref (scratch_source);
+	}
+
+	g_list_free (list);
+
+	/*** Summary Page ***/
+
+	page = e_mail_config_summary_page_new ();
+	e_mail_config_assistant_add_page (assistant, page);
+	assistant->priv->summary_page = g_object_ref (page);
+
+	g_object_bind_property (
+		assistant, "account-backend",
+		page, "account-backend",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		assistant, "identity-source",
+		page, "identity-source",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		assistant, "transport-backend",
+		page, "transport-backend",
+		G_BINDING_SYNC_CREATE);
+
+	/*** Confirm Page ***/
+
+	page = e_mail_config_confirm_page_new ();
+	e_mail_config_assistant_add_page (assistant, page);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (assistant));
+}
+
+static void
+mail_config_assistant_remove (GtkContainer *container,
+                              GtkWidget *widget)
+{
+	if (E_IS_MAIL_CONFIG_PAGE (widget))
+		g_signal_handlers_disconnect_by_func (
+			widget, mail_config_assistant_page_changed,
+			E_MAIL_CONFIG_ASSISTANT (container));
+
+	/* Chain up to parent's remove() method. */
+	GTK_CONTAINER_CLASS (e_mail_config_assistant_parent_class)->
+		remove (container, widget);
+}
+
+static void
+mail_config_assistant_prepare (GtkAssistant *assistant,
+                               GtkWidget *page)
+{
+	EMailConfigAssistantPrivate *priv;
+
+	priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (assistant);
+
+	/* Only setup defaults the first time a page is visited. */
+	if (!g_hash_table_contains (priv->visited_pages, page)) {
+		if (E_IS_MAIL_CONFIG_PAGE (page))
+			e_mail_config_page_setup_defaults (
+				E_MAIL_CONFIG_PAGE (page));
+		g_hash_table_add (priv->visited_pages, page);
+	}
+
+	if (E_IS_MAIL_CONFIG_LOOKUP_PAGE (page)) {
+		ESource *source;
+		ESourceMailIdentity *extension;
+		const gchar *email_address;
+		const gchar *extension_name;
+
+		source = priv->identity_source;
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		extension = e_source_get_extension (source, extension_name);
+		email_address = e_source_mail_identity_get_address (extension);
+
+		/* XXX This operation is not cancellable. */
+		e_mail_autoconfig_new (
+			email_address, G_PRIORITY_DEFAULT, NULL,
+			mail_config_assistant_autoconfigure_cb,
+			g_object_ref (assistant));
+	}
+}
+
+static void
+mail_config_assistant_close (GtkAssistant *assistant)
+{
+	GdkCursor *gdk_cursor;
+	GdkWindow *gdk_window;
+
+	/* Do not chain up.  GtkAssistant does not implement this method. */
+
+	/* Make the cursor appear busy. */
+	gdk_cursor = gdk_cursor_new (GDK_WATCH);
+	gdk_window = gtk_widget_get_window (GTK_WIDGET (assistant));
+	gdk_window_set_cursor (gdk_window, gdk_cursor);
+	g_object_unref (gdk_cursor);
+
+	/* Prevent user interaction with window content. */
+	gtk_widget_set_sensitive (GTK_WIDGET (assistant), FALSE);
+
+	/* XXX This operation is not cancellable. */
+	e_mail_config_assistant_commit (
+		E_MAIL_CONFIG_ASSISTANT (assistant),
+		NULL, mail_config_assistant_close_cb, NULL);
+}
+
+static void
+mail_config_assistant_cancel (GtkAssistant *assistant)
+{
+	/* Do not chain up.  GtkAssistant does not implement this method. */
+
+	gtk_widget_destroy (GTK_WIDGET (assistant));
+}
+
+static void
+e_mail_config_assistant_class_init (EMailConfigAssistantClass *class)
+{
+	GObjectClass *object_class;
+	GtkContainerClass *container_class;
+	GtkAssistantClass *assistant_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigAssistantPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_assistant_set_property;
+	object_class->get_property = mail_config_assistant_get_property;
+	object_class->dispose = mail_config_assistant_dispose;
+	object_class->finalize = mail_config_assistant_finalize;
+	object_class->constructed = mail_config_assistant_constructed;
+
+	container_class = GTK_CONTAINER_CLASS (class);
+	container_class->remove = mail_config_assistant_remove;
+
+	assistant_class = GTK_ASSISTANT_CLASS (class);
+	assistant_class->prepare = mail_config_assistant_prepare;
+	assistant_class->close = mail_config_assistant_close;
+	assistant_class->cancel = mail_config_assistant_cancel;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_BACKEND,
+		g_param_spec_object (
+			"account-backend",
+			"Account Backend",
+			"Active mail account service backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_SOURCE,
+		g_param_spec_object (
+			"account-source",
+			"Account Source",
+			"Mail account source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SESSION,
+		g_param_spec_object (
+			"session",
+			"Session",
+			"Mail session",
+			E_TYPE_MAIL_SESSION,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TRANSPORT_BACKEND,
+		g_param_spec_object (
+			"transport-backend",
+			"Transport Backend",
+			"Active mail transport service backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TRANSPORT_SOURCE,
+		g_param_spec_object (
+			"transport-source",
+			"Transport Source",
+			"Mail transport source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_assistant_init (EMailConfigAssistant *assistant)
+{
+	assistant->priv = E_MAIL_CONFIG_ASSISTANT_GET_PRIVATE (assistant);
+
+	assistant->priv->account_sources =
+		g_ptr_array_new_with_free_func (
+		(GDestroyNotify) g_object_unref);
+
+	assistant->priv->transport_sources =
+		g_ptr_array_new_with_free_func (
+		(GDestroyNotify) g_object_unref);
+
+	assistant->priv->visited_pages = g_hash_table_new (NULL, NULL);
+}
+
+GtkWidget *
+e_mail_config_assistant_new (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_ASSISTANT,
+		"session", session, NULL);
+}
+
+EMailSession *
+e_mail_config_assistant_get_session (EMailConfigAssistant *assistant)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL);
+
+	return assistant->priv->session;
+}
+
+EMailConfigServiceBackend *
+e_mail_config_assistant_get_account_backend (EMailConfigAssistant *assistant)
+{
+	EMailConfigServicePage *page;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL);
+
+	page = assistant->priv->receiving_page;
+
+	return e_mail_config_service_page_get_active_backend (page);
+}
+
+ESource *
+e_mail_config_assistant_get_account_source (EMailConfigAssistant *assistant)
+{
+	EMailConfigServiceBackend *backend;
+	ESource *source = NULL;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL);
+
+	backend = e_mail_config_assistant_get_account_backend (assistant);
+
+	if (backend != NULL)
+		source = e_mail_config_service_backend_get_source (backend);
+
+	return source;
+}
+
+ESource *
+e_mail_config_assistant_get_identity_source (EMailConfigAssistant *assistant)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL);
+
+	return assistant->priv->identity_source;
+}
+
+EMailConfigServiceBackend *
+e_mail_config_assistant_get_transport_backend (EMailConfigAssistant *assistant)
+{
+	EMailConfigServicePage *page;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL);
+
+	page = assistant->priv->sending_page;
+
+	return e_mail_config_service_page_get_active_backend (page);
+}
+
+ESource *
+e_mail_config_assistant_get_transport_source (EMailConfigAssistant *assistant)
+{
+	EMailConfigServiceBackend *backend;
+	ESource *source = NULL;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant), NULL);
+
+	backend = e_mail_config_assistant_get_transport_backend (assistant);
+
+	if (backend != NULL)
+		source = e_mail_config_service_backend_get_source (backend);
+
+	return source;
+}
+
+void
+e_mail_config_assistant_add_page (EMailConfigAssistant *assistant,
+                                  EMailConfigPage *page)
+{
+	EMailConfigPageInterface *page_interface;
+	GtkAssistantPageType page_type;
+	GtkWidget *page_widget;
+	gint n_pages, position;
+	const gchar *page_title;
+	gboolean complete;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant));
+	g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page));
+
+	page_widget = GTK_WIDGET (page);
+	page_interface = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page);
+	page_type = page_interface->page_type;
+	page_title = page_interface->title;
+
+	/* Determine the position to insert the page. */
+	n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (assistant));
+	for (position = 0; position < n_pages; position++) {
+		GtkWidget *nth_page;
+
+		nth_page = gtk_assistant_get_nth_page (
+			GTK_ASSISTANT (assistant), position);
+		if (e_mail_config_page_compare (page_widget, nth_page) < 0)
+			break;
+	}
+
+	gtk_widget_show (page_widget);
+
+	/* Some pages can be clicked through unchanged. */
+	complete = e_mail_config_page_check_complete (page);
+
+	gtk_assistant_insert_page (
+		GTK_ASSISTANT (assistant), page_widget, position);
+	gtk_assistant_set_page_type (
+		GTK_ASSISTANT (assistant), page_widget, page_type);
+	gtk_assistant_set_page_title (
+		GTK_ASSISTANT (assistant), page_widget, page_title);
+	gtk_assistant_set_page_complete (
+		GTK_ASSISTANT (assistant), page_widget, complete);
+
+	/* XXX GtkAssistant has no equivalent to GtkNotebook's
+	 *     "page-added" and "page-removed" signals.  Fortunately
+	 *     removing a page does trigger GtkContainer::remove, so
+	 *     we can override that method and disconnect our signal
+	 *     handler before chaining up.  But I don't see any way
+	 *     for a subclass to intercept GtkAssistant pages being
+	 *     added, so we have to connect our signal handler here.
+	 *     Not really an issue, I'm just being pedantic. */
+
+	g_signal_connect (
+		page, "changed",
+		G_CALLBACK (mail_config_assistant_page_changed),
+		assistant);
+}
+
+/********************* e_mail_config_assistant_commit() **********************/
+
+static void
+mail_config_assistant_commit_cb (GObject *object,
+                                 GAsyncResult *result,
+                                 gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+	e_source_registry_create_sources_finish (
+		E_SOURCE_REGISTRY (object), result, &error);
+
+	if (error != NULL)
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+
+	g_object_unref (simple);
+}
+
+void
+e_mail_config_assistant_commit (EMailConfigAssistant *assistant,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+	EMailConfigServiceBackend *backend;
+	GSimpleAsyncResult *simple;
+	ESourceRegistry *registry;
+	EMailSession *session;
+	ESource *source;
+	GQueue *queue;
+	gint n_pages, ii;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_ASSISTANT (assistant));
+
+	session = e_mail_config_assistant_get_session (assistant);
+	registry = e_mail_session_get_registry (session);
+
+	queue = g_queue_new ();
+
+	/* Queue the collection data source if one is defined. */
+	backend = e_mail_config_assistant_get_account_backend (assistant);
+	source = e_mail_config_service_backend_get_collection (backend);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+
+	/* Queue the mail-related data sources for the account. */
+	source = e_mail_config_assistant_get_account_source (assistant);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+	source = e_mail_config_assistant_get_identity_source (assistant);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+	source = e_mail_config_assistant_get_transport_source (assistant);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+
+	n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT (assistant));
+
+	/* Tell all EMailConfigPages to commit their UI state to their
+	 * scratch ESources and push any additional data sources on to
+	 * the given source queue, such as calendars or address books
+	 * to be bundled with the mail account. */
+	for (ii = 0; ii < n_pages; ii++) {
+		GtkWidget *widget;
+
+		widget = gtk_assistant_get_nth_page (
+			GTK_ASSISTANT (assistant), ii);
+
+		if (E_IS_MAIL_CONFIG_PAGE (widget)) {
+			EMailConfigPage *page;
+			page = E_MAIL_CONFIG_PAGE (widget);
+			e_mail_config_page_commit_changes (page, queue);
+		}
+	}
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (assistant), callback, user_data,
+		e_mail_config_assistant_commit);
+
+	e_source_registry_create_sources (
+		registry, g_queue_peek_head_link (queue),
+		cancellable, mail_config_assistant_commit_cb, simple);
+
+	g_queue_free_full (queue, (GDestroyNotify) g_object_unref);
+}
+
+gboolean
+e_mail_config_assistant_commit_finish (EMailConfigAssistant *assistant,
+                                       GAsyncResult *result,
+                                       GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (assistant),
+		e_mail_config_assistant_commit), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	/* Assume success unless a GError is set. */
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
diff --git a/mail/e-mail-config-assistant.h b/mail/e-mail-config-assistant.h
new file mode 100644
index 0000000..de225af
--- /dev/null
+++ b/mail/e-mail-config-assistant.h
@@ -0,0 +1,96 @@
+/*
+ * e-mail-config-assistant.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_ASSISTANT_H
+#define E_MAIL_CONFIG_ASSISTANT_H
+
+#include <gtk/gtk.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-service-backend.h>
+#include <libemail-engine/e-mail-session.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_ASSISTANT \
+	(e_mail_config_assistant_get_type ())
+#define E_MAIL_CONFIG_ASSISTANT(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistant))
+#define E_MAIL_CONFIG_ASSISTANT_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistantClass))
+#define E_IS_MAIL_CONFIG_ASSISTANT(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_ASSISTANT))
+#define E_IS_MAIL_CONFIG_ASSISTANT_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_ASSISTANT))
+#define E_MAIL_CONFIG_ASSISTANT_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_ASSISTANT, EMailConfigAssistantClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigAssistant EMailConfigAssistant;
+typedef struct _EMailConfigAssistantClass EMailConfigAssistantClass;
+typedef struct _EMailConfigAssistantPrivate EMailConfigAssistantPrivate;
+
+struct _EMailConfigAssistant {
+	GtkAssistant parent;
+	EMailConfigAssistantPrivate *priv;
+};
+
+struct _EMailConfigAssistantClass {
+	GtkAssistantClass parent_class;
+};
+
+GType		e_mail_config_assistant_get_type
+					(void) G_GNUC_CONST;
+GtkWidget *	e_mail_config_assistant_new
+					(EMailSession *session);
+EMailSession *	e_mail_config_assistant_get_session
+					(EMailConfigAssistant *assistant);
+EMailConfigServiceBackend *
+		e_mail_config_assistant_get_account_backend
+					(EMailConfigAssistant *assistant);
+ESource *	e_mail_config_assistant_get_account_source
+					(EMailConfigAssistant *assistant);
+ESource *	e_mail_config_assistant_get_identity_source
+					(EMailConfigAssistant *assistant);
+EMailConfigServiceBackend *
+		e_mail_config_assistant_get_transport_backend
+					(EMailConfigAssistant *assistant);
+ESource *	e_mail_config_assistant_get_transport_source
+					(EMailConfigAssistant *assistant);
+void		e_mail_config_assistant_add_page
+					(EMailConfigAssistant *assistant,
+					 EMailConfigPage *page);
+void		e_mail_config_assistant_commit
+					(EMailConfigAssistant *assistant,
+					 GCancellable *cancellable,
+					 GAsyncReadyCallback callback,
+					 gpointer user_data);
+gboolean	e_mail_config_assistant_commit_finish
+					(EMailConfigAssistant *assistant,
+					 GAsyncResult *result,
+					 GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_ASSISTANT_H */
+
diff --git a/mail/e-mail-config-auth-check.c b/mail/e-mail-config-auth-check.c
new file mode 100644
index 0000000..22523e5
--- /dev/null
+++ b/mail/e-mail-config-auth-check.c
@@ -0,0 +1,446 @@
+/*
+ * e-mail-config-auth-check.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-auth-check.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libevolution-utils/e-alert.h>
+#include <e-util/e-mktemp.h>
+#include <misc/e-auth-combo-box.h>
+#include <mail/e-mail-config-service-page.h>
+
+#define E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckPrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailConfigAuthCheckPrivate {
+	EMailConfigServiceBackend *backend;
+	gchar *active_mechanism;
+
+	GtkWidget *combo_box;  /* not referenced */
+};
+
+struct _AsyncContext {
+	EMailConfigAuthCheck *auth_check;
+	CamelSession *temporary_session;
+	EActivity *activity;
+};
+
+enum {
+	PROP_0,
+	PROP_ACTIVE_MECHANISM,
+	PROP_BACKEND
+};
+
+G_DEFINE_TYPE (
+	EMailConfigAuthCheck,
+	e_mail_config_auth_check,
+	GTK_TYPE_BOX)
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+	if (async_context->auth_check != NULL)
+		g_object_unref (async_context->auth_check);
+
+	if (async_context->temporary_session != NULL)
+		g_object_unref (async_context->temporary_session);
+
+	if (async_context->activity != NULL)
+		g_object_unref (async_context->activity);
+
+	g_slice_free (AsyncContext, async_context);
+}
+
+static void
+mail_config_auth_check_update_done_cb (GObject *source_object,
+                                       GAsyncResult *result,
+                                       gpointer user_data)
+{
+	AsyncContext *async_context = user_data;
+	EMailConfigAuthCheck *auth_check;
+	EAlertSink *alert_sink;
+	GList *available_authtypes;
+	GError *error = NULL;
+
+	auth_check = async_context->auth_check;
+	alert_sink = e_activity_get_alert_sink (async_context->activity);
+
+	available_authtypes = camel_service_query_auth_types_finish (
+		CAMEL_SERVICE (source_object), result, &error);
+
+	if (e_activity_handle_cancellation (async_context->activity, error)) {
+		g_warn_if_fail (available_authtypes == NULL);
+		g_error_free (error);
+
+	} else if (error != NULL) {
+		g_warn_if_fail (available_authtypes == NULL);
+		e_alert_submit (
+			alert_sink,
+			"mail:checking-service-error",
+			error->message, NULL);
+		g_error_free (error);
+
+	} else {
+		e_auth_combo_box_update_available (
+			E_AUTH_COMBO_BOX (auth_check->priv->combo_box),
+			available_authtypes);
+		g_list_free (available_authtypes);
+	}
+
+	gtk_widget_set_sensitive (GTK_WIDGET (auth_check), TRUE);
+
+	async_context_free (async_context);
+}
+
+static void
+mail_config_auth_check_update (EMailConfigAuthCheck *auth_check)
+{
+	EActivity *activity;
+	EMailConfigServicePage *page;
+	EMailConfigServiceBackend *backend;
+	EMailConfigServicePageClass *page_class;
+	EMailConfigServiceBackendClass *backend_class;
+	CamelService *service;
+	CamelSession *session;
+	CamelSettings *settings;
+	GCancellable *cancellable;
+	AsyncContext *async_context;
+	gchar *temp_dir;
+	GError *error = NULL;
+
+	backend = e_mail_config_auth_check_get_backend (auth_check);
+	page = e_mail_config_service_backend_get_page (backend);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page);
+	backend_class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+
+	temp_dir = e_mkdtemp ("evolution-auth-check-XXXXXX");
+
+	/* Create a temporary session for our temporary service.
+	 * Use the same temporary directory for "user-data-dir" and
+	 * "user-cache-dir".  For our purposes it shouldn't matter. */
+	session = g_object_new (
+		CAMEL_TYPE_SESSION,
+		"user-data-dir", temp_dir,
+		"user-cache-dir", temp_dir,
+		NULL);
+
+	/* This returns a BORROWED reference to the CamelService. */
+	service = camel_session_add_service (
+		session, "fake-uid",
+		backend_class->backend_name,
+		page_class->provider_type, &error);
+
+	g_free (temp_dir);
+
+	if (error != NULL) {
+		g_warn_if_fail (service == NULL);
+		e_alert_submit (
+			E_ALERT_SINK (page),
+			"mail:checking-service-error",
+			error->message, NULL);
+		g_error_free (error);
+		return;
+	}
+
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	camel_service_set_settings (service, settings);
+
+	activity = e_mail_config_service_page_new_activity (page);
+	cancellable = e_activity_get_cancellable (activity);
+
+	gtk_widget_set_sensitive (GTK_WIDGET (auth_check), FALSE);
+
+	async_context = g_slice_new (AsyncContext);
+	async_context->auth_check = g_object_ref (auth_check);
+	async_context->temporary_session = session;  /* takes ownership */
+	async_context->activity = activity;          /* takes ownership */
+
+	camel_service_query_auth_types (
+		service, G_PRIORITY_DEFAULT, cancellable,
+		mail_config_auth_check_update_done_cb, async_context);
+}
+
+static void
+mail_config_auth_check_clicked_cb (GtkButton *button,
+                                   EMailConfigAuthCheck *auth_check)
+{
+	mail_config_auth_check_update (auth_check);
+}
+
+static void
+mail_config_auth_check_init_mechanism (EMailConfigAuthCheck *auth_check)
+{
+	EMailConfigServiceBackend *backend;
+	CamelProvider *provider;
+	CamelSettings *settings;
+	const gchar *auth_mechanism = NULL;
+
+	/* Pick an initial active mechanism name by examining both
+	 * the corresponding CamelNetworkSettings and CamelProvider. */
+
+	backend = e_mail_config_auth_check_get_backend (auth_check);
+	provider = e_mail_config_service_backend_get_provider (backend);
+	settings = e_mail_config_service_backend_get_settings (backend);
+	g_return_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings));
+
+	auth_mechanism =
+		camel_network_settings_get_auth_mechanism (
+		CAMEL_NETWORK_SETTINGS (settings));
+
+	/* If CamelNetworkSettings does not have a mechanism name set,
+	 * choose from the CamelProvider's list of supported mechanisms. */
+	if (auth_mechanism == NULL && provider != NULL) {
+		if (provider->authtypes != NULL) {
+			CamelServiceAuthType *auth_type;
+			auth_type = provider->authtypes->data;
+			auth_mechanism = auth_type->authproto;
+		}
+	}
+
+	if (auth_mechanism != NULL)
+		e_mail_config_auth_check_set_active_mechanism (
+			auth_check, auth_mechanism);
+}
+
+static void
+mail_config_auth_check_set_backend (EMailConfigAuthCheck *auth_check,
+                                    EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+	g_return_if_fail (auth_check->priv->backend == NULL);
+
+	auth_check->priv->backend = g_object_ref (backend);
+}
+
+static void
+mail_config_auth_check_set_property (GObject *object,
+                                     guint property_id,
+                                     const GValue *value,
+                                     GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE_MECHANISM:
+			e_mail_config_auth_check_set_active_mechanism (
+				E_MAIL_CONFIG_AUTH_CHECK (object),
+				g_value_get_string (value));
+			return;
+
+		case PROP_BACKEND:
+			mail_config_auth_check_set_backend (
+				E_MAIL_CONFIG_AUTH_CHECK (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_auth_check_get_property (GObject *object,
+                                     guint property_id,
+                                     GValue *value,
+                                     GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE_MECHANISM:
+			g_value_set_string (
+				value,
+				e_mail_config_auth_check_get_active_mechanism (
+				E_MAIL_CONFIG_AUTH_CHECK (object)));
+			return;
+
+		case PROP_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_auth_check_get_backend (
+				E_MAIL_CONFIG_AUTH_CHECK (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_auth_check_dispose (GObject *object)
+{
+	EMailConfigAuthCheckPrivate *priv;
+
+	priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (object);
+
+	if (priv->backend != NULL) {
+		g_object_unref (priv->backend);
+		priv->backend = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_auth_check_finalize (GObject *object)
+{
+	EMailConfigAuthCheckPrivate *priv;
+
+	priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (object);
+
+	g_free (priv->active_mechanism);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)->
+		finalize (object);
+}
+
+static void
+mail_config_auth_check_constructed (GObject *object)
+{
+	EMailConfigAuthCheck *auth_check;
+	EMailConfigServiceBackend *backend;
+	CamelProvider *provider;
+	GtkWidget *widget;
+	const gchar *text;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)->
+		constructed (object);
+
+	auth_check = E_MAIL_CONFIG_AUTH_CHECK (object);
+	backend = e_mail_config_auth_check_get_backend (auth_check);
+	provider = e_mail_config_service_backend_get_provider (backend);
+
+	widget = e_auth_combo_box_new ();
+	e_auth_combo_box_set_provider (E_AUTH_COMBO_BOX (widget), provider);
+	gtk_box_pack_start (GTK_BOX (object), widget, FALSE, FALSE, 0);
+	auth_check->priv->combo_box = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		widget, "active-id",
+		auth_check, "active-mechanism",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	text = _("Check for Supported Types");
+	widget = gtk_button_new_with_label (text);
+	gtk_box_pack_start (GTK_BOX (object), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_auth_check_clicked_cb),
+		auth_check);
+
+	mail_config_auth_check_init_mechanism (auth_check);
+}
+
+static void
+e_mail_config_auth_check_class_init (EMailConfigAuthCheckClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigAuthCheckPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_auth_check_set_property;
+	object_class->get_property = mail_config_auth_check_get_property;
+	object_class->dispose = mail_config_auth_check_dispose;
+	object_class->finalize = mail_config_auth_check_finalize;
+	object_class->constructed = mail_config_auth_check_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACTIVE_MECHANISM,
+		g_param_spec_string (
+			"active-mechanism",
+			"Active Mechanism",
+			"Active authentication mechanism",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_BACKEND,
+		g_param_spec_object (
+			"backend",
+			"Backend",
+			"Mail configuration backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_auth_check_init (EMailConfigAuthCheck *auth_check)
+{
+	auth_check->priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (auth_check);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (auth_check),
+		GTK_ORIENTATION_HORIZONTAL);
+
+	gtk_box_set_spacing (GTK_BOX (auth_check), 6);
+}
+
+GtkWidget *
+e_mail_config_auth_check_new (EMailConfigServiceBackend *backend)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_AUTH_CHECK,
+		"backend", backend, NULL);
+}
+
+EMailConfigServiceBackend *
+e_mail_config_auth_check_get_backend (EMailConfigAuthCheck *auth_check)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check), NULL);
+
+	return auth_check->priv->backend;
+}
+
+const gchar *
+e_mail_config_auth_check_get_active_mechanism (EMailConfigAuthCheck *auth_check)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check), NULL);
+
+	return auth_check->priv->active_mechanism;
+}
+
+void
+e_mail_config_auth_check_set_active_mechanism (EMailConfigAuthCheck *auth_check,
+                                               const gchar *active_mechanism)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check));
+
+	g_free (auth_check->priv->active_mechanism);
+	auth_check->priv->active_mechanism = g_strdup (active_mechanism);
+
+	g_object_notify (G_OBJECT (auth_check), "active-mechanism");
+}
+
diff --git a/mail/e-mail-config-auth-check.h b/mail/e-mail-config-auth-check.h
new file mode 100644
index 0000000..c7bf759
--- /dev/null
+++ b/mail/e-mail-config-auth-check.h
@@ -0,0 +1,73 @@
+/*
+ * e-mail-config-auth-check.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_AUTH_CHECK_H
+#define E_MAIL_CONFIG_AUTH_CHECK_H
+
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_AUTH_CHECK \
+	(e_mail_config_auth_check_get_type ())
+#define E_MAIL_CONFIG_AUTH_CHECK(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheck))
+#define E_MAIL_CONFIG_AUTH_CHECK_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckClass))
+#define E_IS_MAIL_CONFIG_AUTH_CHECK(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK))
+#define E_IS_MAIL_CONFIG_AUTH_CHECK_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_AUTH_CHECK))
+#define E_MAIL_CONFIG_AUTH_CHECK_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigAuthCheck EMailConfigAuthCheck;
+typedef struct _EMailConfigAuthCheckClass EMailConfigAuthCheckClass;
+typedef struct _EMailConfigAuthCheckPrivate EMailConfigAuthCheckPrivate;
+
+struct _EMailConfigAuthCheck {
+	GtkBox parent;
+	EMailConfigAuthCheckPrivate *priv;
+};
+
+struct _EMailConfigAuthCheckClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_auth_check_get_type
+					(void) G_GNUC_CONST;
+GtkWidget *	e_mail_config_auth_check_new
+					(EMailConfigServiceBackend *backend);
+EMailConfigServiceBackend *
+		e_mail_config_auth_check_get_backend
+					(EMailConfigAuthCheck *auth_check);
+const gchar *	e_mail_config_auth_check_get_active_mechanism
+					(EMailConfigAuthCheck *auth_check);
+void		e_mail_config_auth_check_set_active_mechanism
+					(EMailConfigAuthCheck *auth_check,
+					 const gchar *active_mechanism);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_AUTH_CHECK_H */
diff --git a/mail/e-mail-config-confirm-page.c b/mail/e-mail-config-confirm-page.c
new file mode 100644
index 0000000..f58da03
--- /dev/null
+++ b/mail/e-mail-config-confirm-page.c
@@ -0,0 +1,205 @@
+/*
+ * e-mail-config-confirm-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-confirm-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+
+#define E_MAIL_CONFIG_CONFIRM_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPagePrivate))
+
+struct _EMailConfigConfirmPagePrivate {
+	gchar *text;
+};
+
+enum {
+	PROP_0,
+	PROP_TEXT
+};
+
+/* Forward Declarations */
+static void	e_mail_config_confirm_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigConfirmPage,
+	e_mail_config_confirm_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_confirm_page_interface_init))
+
+static void
+mail_config_confirm_page_set_property (GObject *object,
+                                       guint property_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_TEXT:
+			e_mail_config_confirm_page_set_text (
+				E_MAIL_CONFIG_CONFIRM_PAGE (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_confirm_page_get_property (GObject *object,
+                                       guint property_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_TEXT:
+			g_value_set_string (
+				value,
+				e_mail_config_confirm_page_get_text (
+				E_MAIL_CONFIG_CONFIRM_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_confirm_page_finalize (GObject *object)
+{
+	EMailConfigConfirmPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_CONFIRM_PAGE_GET_PRIVATE (object);
+
+	g_free (priv->text);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_confirm_page_parent_class)->
+		finalize (object);
+}
+
+static void
+mail_config_confirm_page_constructed (GObject *object)
+{
+	EMailConfigConfirmPage *page;
+	GtkWidget *widget;
+
+	page = E_MAIL_CONFIG_CONFIRM_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_confirm_page_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_CENTER);
+
+	widget = gtk_label_new (NULL);
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		page, "text",
+		widget, "label",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+e_mail_config_confirm_page_class_init (EMailConfigConfirmPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigConfirmPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_confirm_page_set_property;
+	object_class->get_property = mail_config_confirm_page_get_property;
+	object_class->finalize = mail_config_confirm_page_finalize;
+	object_class->constructed = mail_config_confirm_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TEXT,
+		g_param_spec_string (
+			"text",
+			"Text",
+			"Confirmation message",
+			_("Congratulations, your mail configuration is "
+			  "complete.\n\nYou are now ready to send and "
+			  "receive email using Evolution.\n\nClick "
+			  "\"Apply\" to save your settings."),
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_confirm_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Done");
+	interface->page_type = GTK_ASSISTANT_PAGE_CONFIRM;
+	interface->sort_order = E_MAIL_CONFIG_CONFIRM_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_confirm_page_init (EMailConfigConfirmPage *page)
+{
+	page->priv = E_MAIL_CONFIG_CONFIRM_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_confirm_page_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, NULL);
+}
+
+const gchar *
+e_mail_config_confirm_page_get_text (EMailConfigConfirmPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_CONFIRM_PAGE (page), NULL);
+
+	return page->priv->text;
+}
+
+void
+e_mail_config_confirm_page_set_text (EMailConfigConfirmPage *page,
+                                     const gchar *text)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_CONFIRM_PAGE (page));
+
+	g_free (page->priv->text);
+	page->priv->text = g_strdup ((text != NULL) ? text : "");
+
+	g_object_notify (G_OBJECT (page), "text");
+}
+
diff --git a/mail/e-mail-config-confirm-page.h b/mail/e-mail-config-confirm-page.h
new file mode 100644
index 0000000..d4bae94
--- /dev/null
+++ b/mail/e-mail-config-confirm-page.h
@@ -0,0 +1,75 @@
+/*
+ * e-mail-config-confirm-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_CONFIRM_PAGE_H
+#define E_MAIL_CONFIG_CONFIRM_PAGE_H
+
+#include <gtk/gtk.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_CONFIRM_PAGE \
+	(e_mail_config_confirm_page_get_type ())
+#define E_MAIL_CONFIG_CONFIRM_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPage))
+#define E_MAIL_CONFIG_CONFIRM_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPageClass))
+#define E_IS_MAIL_CONFIG_CONFIRM_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE))
+#define E_IS_MAIL_CONFIG_CONFIRM_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE))
+#define E_MAIL_CONFIG_CONFIRM_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_CONFIRM_PAGE, EMailConfigConfirmPageClass))
+
+#define E_MAIL_CONFIG_CONFIRM_PAGE_SORT_ORDER (600)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigConfirmPage EMailConfigConfirmPage;
+typedef struct _EMailConfigConfirmPageClass EMailConfigConfirmPageClass;
+typedef struct _EMailConfigConfirmPagePrivate EMailConfigConfirmPagePrivate;
+
+struct _EMailConfigConfirmPage {
+	GtkBox parent;
+	EMailConfigConfirmPagePrivate *priv;
+};
+
+struct _EMailConfigConfirmPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_confirm_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_confirm_page_new	(void);
+const gchar *	e_mail_config_confirm_page_get_text
+						(EMailConfigConfirmPage *page);
+void		e_mail_config_confirm_page_set_text
+						(EMailConfigConfirmPage *page,
+						 const gchar *text);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_CONFIRM_PAGE_H */
+
diff --git a/mail/e-mail-config-defaults-page.c b/mail/e-mail-config-defaults-page.c
new file mode 100644
index 0000000..d815f05
--- /dev/null
+++ b/mail/e-mail-config-defaults-page.c
@@ -0,0 +1,868 @@
+/*
+ * e-mail-config-defaults-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-defaults-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-enumtypes.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-mdn.h>
+#include <libedataserver/e-data-server-util.h>
+
+#include <libemail-engine/e-mail-folder-utils.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/em-folder-selection-button.h>
+
+#define E_MAIL_CONFIG_DEFAULTS_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPagePrivate))
+
+struct _EMailConfigDefaultsPagePrivate {
+	EMailSession *session;
+	ESource *account_source;
+	ESource *identity_source;
+
+	GtkWidget *drafts_button;  /* not referenced */
+	GtkWidget *sent_button;    /* not referenced */
+	GtkWidget *trash_toggle;   /* not referenced */
+	GtkWidget *junk_toggle;    /* not referenced */
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT_SOURCE,
+	PROP_IDENTITY_SOURCE,
+	PROP_SESSION
+};
+
+/* Forward Declarations */
+static void	e_mail_config_defaults_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigDefaultsPage,
+	e_mail_config_defaults_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_defaults_page_interface_init))
+
+static CamelSettings *
+mail_config_defaults_page_maybe_get_settings (EMailConfigDefaultsPage *page)
+{
+	ESource *source;
+	ESourceCamel *camel_ext;
+	ESourceBackend *backend_ext;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	source = e_mail_config_defaults_page_get_account_source (page);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	backend_ext = e_source_get_extension (source, extension_name);
+	backend_name = e_source_backend_get_backend_name (backend_ext);
+	extension_name = e_source_camel_get_extension_name (backend_name);
+
+	/* Avoid accidentally creating a backend-specific extension
+	 * in the mail account source if the mail account source is
+	 * part of a collection, in which case the backend-specific
+	 * extension is kept in the top-level collection source. */
+	if (!e_source_has_extension (source, extension_name))
+		return NULL;
+
+	camel_ext = e_source_get_extension (source, extension_name);
+
+	return e_source_camel_get_settings (camel_ext);
+}
+
+static CamelStore *
+mail_config_defaults_page_get_store (EMailConfigDefaultsPage *page)
+{
+	ESource *source;
+	EMailSession *session;
+	CamelService *service;
+	const gchar *uid;
+
+	session = e_mail_config_defaults_page_get_session (page);
+	source = e_mail_config_defaults_page_get_account_source (page);
+
+	uid = e_source_get_uid (source);
+	service = camel_session_get_service (CAMEL_SESSION (session), uid);
+
+	return CAMEL_IS_STORE (service) ? CAMEL_STORE (service) : NULL;
+}
+
+static gboolean
+mail_config_defaults_page_addrs_to_string (GBinding *binding,
+                                           const GValue *source_value,
+                                           GValue *target_value,
+                                           gpointer unused)
+{
+	gchar **strv;
+
+	strv = g_value_dup_boxed (source_value);
+
+	if (strv != NULL) {
+		gchar *string = g_strjoinv ("; ", strv);
+		g_value_set_string (target_value, string);
+		g_free (string);
+	} else {
+		g_value_set_string (target_value, "");
+	}
+
+	g_strfreev (strv);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_defaults_page_string_to_addrs (GBinding *binding,
+                                           const GValue *source_value,
+                                           GValue *target_value,
+                                           gpointer unused)
+{
+	CamelInternetAddress *address;
+	const gchar *string;
+	gchar **strv;
+	gint n_addresses, ii;
+
+	string = g_value_get_string (source_value);
+
+	address = camel_internet_address_new ();
+	n_addresses = camel_address_decode (CAMEL_ADDRESS (address), string);
+
+	if (n_addresses < 0) {
+		g_object_unref (address);
+		return FALSE;
+
+	} else if (n_addresses == 0) {
+		g_value_set_boxed (target_value, NULL);
+		g_object_unref (address);
+		return TRUE;
+	}
+
+	strv = g_new0 (gchar *, n_addresses + 1);
+
+	for (ii = 0; ii < n_addresses; ii++) {
+		const gchar *name = NULL;
+		const gchar *addr = NULL;
+
+		camel_internet_address_get (address, ii, &name, &addr);
+		strv[ii] = camel_internet_address_format_address (name, addr);
+	}
+
+	g_value_take_boxed (target_value, strv);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_defaults_page_folder_name_to_uri (GBinding *binding,
+                                              const GValue *source_value,
+                                              GValue *target_value,
+                                              gpointer data)
+{
+	EMailConfigDefaultsPage *page;
+	CamelStore *store;
+	const gchar *folder_name;
+	gchar *folder_uri = NULL;
+
+	page = E_MAIL_CONFIG_DEFAULTS_PAGE (data);
+	store = mail_config_defaults_page_get_store (page);
+	g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+
+	folder_name = g_value_get_string (source_value);
+
+	if (folder_name != NULL)
+		folder_uri = e_mail_folder_uri_build (store, folder_name);
+
+	g_value_set_string (target_value, folder_uri);
+
+	g_free (folder_uri);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_defaults_page_folder_uri_to_name (GBinding *binding,
+                                              const GValue *source_value,
+                                              GValue *target_value,
+                                              gpointer data)
+{
+	EMailConfigDefaultsPage *page;
+	EMailSession *session;
+	const gchar *folder_uri;
+	gchar *folder_name = NULL;
+	GError *error = NULL;
+
+	page = E_MAIL_CONFIG_DEFAULTS_PAGE (data);
+	session = e_mail_config_defaults_page_get_session (page);
+
+	folder_uri = g_value_get_string (source_value);
+
+	if (folder_uri == NULL) {
+		g_value_set_string (target_value, NULL);
+		return TRUE;
+	}
+
+	e_mail_folder_uri_parse (
+		CAMEL_SESSION (session), folder_uri,
+		NULL, &folder_name, &error);
+
+	if (error != NULL) {
+		g_warn_if_fail (folder_name == NULL);
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	g_return_val_if_fail (folder_name != NULL, FALSE);
+
+	g_value_set_string (target_value, folder_name);
+
+	g_free (folder_name);
+
+	return TRUE;
+}
+
+static void
+mail_config_defaults_page_restore_folders (EMailConfigDefaultsPage *page)
+{
+	EMFolderSelectionButton *button;
+	EMailSession *session;
+	EMailLocalFolder type;
+	const gchar *folder_uri;
+
+	session = e_mail_config_defaults_page_get_session (page);
+
+	type = E_MAIL_LOCAL_FOLDER_DRAFTS;
+	button = EM_FOLDER_SELECTION_BUTTON (page->priv->drafts_button);
+	folder_uri = e_mail_session_get_local_folder_uri (session, type);
+	em_folder_selection_button_set_folder_uri (button, folder_uri);
+
+	type = E_MAIL_LOCAL_FOLDER_SENT;
+	button = EM_FOLDER_SELECTION_BUTTON (page->priv->sent_button);
+	folder_uri = e_mail_session_get_local_folder_uri (session, type);
+	em_folder_selection_button_set_folder_uri (button, folder_uri);
+}
+
+static void
+mail_config_defaults_page_restore_real_folder (GtkToggleButton *toggle_button)
+{
+	gtk_toggle_button_set_active (toggle_button, FALSE);
+}
+
+static GtkWidget *
+mail_config_defaults_page_add_real_folder (EMailConfigDefaultsPage *page,
+                                           GtkSizeGroup *size_group,
+                                           GtkButton *revert_button,
+                                           const gchar *toggle_label,
+                                           const gchar *dialog_caption,
+                                           const gchar *property_name,
+                                           const gchar *use_property_name)
+{
+	GtkWidget *box;
+	GtkWidget *check_button;
+	GtkWidget *folder_button;
+	EMailSession *session;
+	CamelSettings *settings;
+	CamelStore *store;
+	GObjectClass *class;
+
+	store = mail_config_defaults_page_get_store (page);
+	g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+
+	session = e_mail_config_defaults_page_get_session (page);
+	settings = mail_config_defaults_page_maybe_get_settings (page);
+
+	if (settings == NULL)
+		return NULL;
+
+	/* These folder settings are backend-specific, so check if
+	 * the CamelSettings class has the property names we need. */
+
+	class = G_OBJECT_GET_CLASS (settings);
+
+	if (g_object_class_find_property (class, property_name) == NULL)
+		return NULL;
+
+	if (g_object_class_find_property (class, use_property_name) == NULL)
+		return NULL;
+
+	/* We're good to go. */
+
+	box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+	check_button = gtk_check_button_new_with_mnemonic (toggle_label);
+	g_object_set (check_button, "xalign", 1.0, NULL);
+	gtk_size_group_add_widget (size_group, check_button);
+	gtk_box_pack_start (GTK_BOX (box), check_button, FALSE, FALSE, 0);
+	gtk_widget_show (check_button);
+
+	g_object_bind_property (
+		settings, use_property_name,
+		check_button, "active",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	folder_button = em_folder_selection_button_new (
+		session, "", dialog_caption);
+	em_folder_selection_button_set_store (
+		EM_FOLDER_SELECTION_BUTTON (folder_button), store);
+	gtk_box_pack_start (GTK_BOX (box), folder_button, TRUE, TRUE, 0);
+	gtk_widget_show (folder_button);
+
+	/* XXX CamelSettings only stores the folder's path name, but the
+	 *     EMFolderSelectionButton requires a full folder URI, so we
+	 *     have to do some fancy transforms for the binding to work. */
+	g_object_bind_property_full (
+		settings, property_name,
+		folder_button, "folder-uri",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		mail_config_defaults_page_folder_name_to_uri,
+		mail_config_defaults_page_folder_uri_to_name,
+		g_object_ref (page),
+		(GDestroyNotify) g_object_unref);
+
+	g_object_bind_property (
+		check_button, "active",
+		folder_button, "sensitive",
+		G_BINDING_SYNC_CREATE);
+
+	g_signal_connect_swapped (
+		revert_button, "clicked",
+		G_CALLBACK (mail_config_defaults_page_restore_real_folder),
+		check_button);
+
+	return box;
+}
+
+static void
+mail_config_defaults_page_set_account_source (EMailConfigDefaultsPage *page,
+                                              ESource *account_source)
+{
+	g_return_if_fail (E_IS_SOURCE (account_source));
+	g_return_if_fail (page->priv->account_source == NULL);
+
+	page->priv->account_source = g_object_ref (account_source);
+}
+
+static void
+mail_config_defaults_page_set_identity_source (EMailConfigDefaultsPage *page,
+                                               ESource *identity_source)
+{
+	g_return_if_fail (E_IS_SOURCE (identity_source));
+	g_return_if_fail (page->priv->identity_source == NULL);
+
+	page->priv->identity_source = g_object_ref (identity_source);
+}
+
+static void
+mail_config_defaults_page_set_session (EMailConfigDefaultsPage *page,
+                                       EMailSession *session)
+{
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
+	g_return_if_fail (page->priv->session == NULL);
+
+	page->priv->session = g_object_ref (session);
+}
+
+static void
+mail_config_defaults_page_set_property (GObject *object,
+                                        guint property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			mail_config_defaults_page_set_account_source (
+				E_MAIL_CONFIG_DEFAULTS_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			mail_config_defaults_page_set_identity_source (
+				E_MAIL_CONFIG_DEFAULTS_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SESSION:
+			mail_config_defaults_page_set_session (
+				E_MAIL_CONFIG_DEFAULTS_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_defaults_page_get_property (GObject *object,
+                                        guint property_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_defaults_page_get_account_source (
+				E_MAIL_CONFIG_DEFAULTS_PAGE (object)));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_defaults_page_get_identity_source (
+				E_MAIL_CONFIG_DEFAULTS_PAGE (object)));
+			return;
+
+		case PROP_SESSION:
+			g_value_set_object (
+				value,
+				e_mail_config_defaults_page_get_session (
+				E_MAIL_CONFIG_DEFAULTS_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_defaults_page_dispose (GObject *object)
+{
+	EMailConfigDefaultsPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_DEFAULTS_PAGE_GET_PRIVATE (object);
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->session != NULL) {
+		g_object_unref (priv->session);
+		priv->session = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_defaults_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_defaults_page_constructed (GObject *object)
+{
+	EMailConfigDefaultsPage *page;
+	EMailSession *session;
+	ESource *source;
+	ESourceMailComposition *composition_ext;
+	ESourceMailSubmission *submission_ext;
+	ESourceMDN *mdn_ext;
+	GtkLabel *label;
+	GtkButton *button;
+	GtkWidget *widget;
+	GtkWidget *container;
+	GtkSizeGroup *size_group;
+	GEnumClass *enum_class;
+	GEnumValue *enum_value;
+	EMdnResponsePolicy policy;
+	const gchar *extension_name;
+	const gchar *text;
+	gchar *markup;
+
+	page = E_MAIL_CONFIG_DEFAULTS_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_defaults_page_parent_class)->
+		constructed (object);
+
+	session = e_mail_config_defaults_page_get_session (page);
+	source = e_mail_config_defaults_page_get_identity_source (page);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	composition_ext = e_source_get_extension (source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	submission_ext = e_source_get_extension (source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_MDN;
+	mdn_ext = e_source_get_extension (source, extension_name);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+	/*** Special Folders ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Special Folders");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Draft Messages _Folder:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	text = _("Choose a folder for saving draft messages.");
+	widget = em_folder_selection_button_new (session, "", text);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+	page->priv->drafts_button = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		composition_ext, "drafts-folder",
+		widget, "folder-uri",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	text = _("Sent _Messages Folder:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	text = _("Choose a folder for saving sent messages.");
+	widget = em_folder_selection_button_new (session, "", text);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+	page->priv->sent_button = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		submission_ext, "sent-folder",
+		widget, "folder-uri",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	widget = gtk_button_new_with_mnemonic (_("_Restore Defaults"));
+	gtk_widget_set_halign (widget, GTK_ALIGN_START);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 5, 1, 1);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_config_defaults_page_restore_folders),
+		page);
+
+	button = GTK_BUTTON (widget);
+
+	widget = mail_config_defaults_page_add_real_folder (
+		page, size_group, button,
+		_("Use a Real Folder for _Trash:"),
+		_("Choose a folder for deleted messages."),
+		"real-trash-path", "use-real-trash-path");
+	if (widget != NULL) {
+		gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 2, 1);
+		gtk_widget_show (widget);
+	}
+
+	widget = mail_config_defaults_page_add_real_folder (
+		page, size_group, button,
+		_("Use a Real Folder for _Junk:"),
+		_("Choose a folder for junk messages."),
+		"real-junk-path", "use-real-junk-path");
+	if (widget != NULL) {
+		gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 2, 1);
+		gtk_widget_show (widget);
+	}
+
+	/*** Composing Messages ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Composing Messages");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Alway_s carbon-copy (cc) to:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property_full (
+		composition_ext, "cc",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		mail_config_defaults_page_addrs_to_string,
+		mail_config_defaults_page_string_to_addrs,
+		NULL, (GDestroyNotify) NULL);
+
+	text = _("Always _blind carbon-copy (bcc) to:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property_full (
+		composition_ext, "bcc",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		mail_config_defaults_page_addrs_to_string,
+		mail_config_defaults_page_string_to_addrs,
+		NULL, (GDestroyNotify) NULL);
+
+	/*** Message Receipts ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Message Receipts");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("S_end message receipts:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_combo_box_text_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	/* XXX This is a pain in the butt, but we want to avoid hard-coding
+	 *     string values from the EMdnResponsePolicy enum class in case
+	 *     they change in the future. */
+	enum_class = g_type_class_ref (E_TYPE_MDN_RESPONSE_POLICY);
+	policy = E_MDN_RESPONSE_POLICY_NEVER;
+	enum_value = g_enum_get_value (enum_class, policy);
+	g_return_if_fail (enum_value != NULL);
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		enum_value->value_nick, _("Never"));
+	policy = E_MDN_RESPONSE_POLICY_ALWAYS;
+	enum_value = g_enum_get_value (enum_class, policy);
+	g_return_if_fail (enum_value != NULL);
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		enum_value->value_nick, _("Always"));
+	policy = E_MDN_RESPONSE_POLICY_ASK;
+	enum_value = g_enum_get_value (enum_class, policy);
+	g_return_if_fail (enum_value != NULL);
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		enum_value->value_nick, _("Ask for each message"));
+	g_type_class_unref (enum_class);
+
+	g_object_bind_property_full (
+		mdn_ext, "response-policy",
+		widget, "active-id",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		e_binding_transform_enum_value_to_nick,
+		e_binding_transform_enum_nick_to_value,
+		NULL, (GDestroyNotify) NULL);
+
+	g_object_unref (size_group);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+e_mail_config_defaults_page_class_init (EMailConfigDefaultsPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigDefaultsPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_defaults_page_set_property;
+	object_class->get_property = mail_config_defaults_page_get_property;
+	object_class->dispose = mail_config_defaults_page_dispose;
+	object_class->constructed = mail_config_defaults_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_SOURCE,
+		g_param_spec_object (
+			"account-source",
+			"Account Source",
+			"Mail account source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SESSION,
+		g_param_spec_object (
+			"session",
+			"Session",
+			"Mail session",
+			E_TYPE_MAIL_SESSION,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_defaults_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Defaults");
+	interface->sort_order = E_MAIL_CONFIG_DEFAULTS_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_defaults_page_init (EMailConfigDefaultsPage *page)
+{
+	page->priv = E_MAIL_CONFIG_DEFAULTS_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_defaults_page_new (EMailSession *session,
+                                 ESource *account_source,
+                                 ESource *identity_source)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (account_source), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE,
+		"account-source", account_source,
+		"identity-source", identity_source,
+		"session", session, NULL);
+}
+
+EMailSession *
+e_mail_config_defaults_page_get_session (EMailConfigDefaultsPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_DEFAULTS_PAGE (page), NULL);
+
+	return page->priv->session;
+}
+
+ESource *
+e_mail_config_defaults_page_get_account_source (EMailConfigDefaultsPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_DEFAULTS_PAGE (page), NULL);
+
+	return page->priv->account_source;
+}
+
+ESource *
+e_mail_config_defaults_page_get_identity_source (EMailConfigDefaultsPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_DEFAULTS_PAGE (page), NULL);
+
+	return page->priv->identity_source;
+}
+
diff --git a/mail/e-mail-config-defaults-page.h b/mail/e-mail-config-defaults-page.h
new file mode 100644
index 0000000..0f6371c
--- /dev/null
+++ b/mail/e-mail-config-defaults-page.h
@@ -0,0 +1,79 @@
+/*
+ * e-mail-config-defaults-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_DEFAULTS_PAGE_H
+#define E_MAIL_CONFIG_DEFAULTS_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libemail-engine/e-mail-session.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE \
+	(e_mail_config_defaults_page_get_type ())
+#define E_MAIL_CONFIG_DEFAULTS_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPage))
+#define E_MAIL_CONFIG_DEFAULT_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPageClass))
+#define E_IS_MAIL_CONFIG_DEFAULTS_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE))
+#define E_IS_MAIL_CONFIG_DEFAULTS_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE))
+#define E_MAIL_CONFIG_DEFAULTS_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPageClass))
+
+#define E_MAIL_CONFIG_DEFAULTS_PAGE_SORT_ORDER (500)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigDefaultsPage EMailConfigDefaultsPage;
+typedef struct _EMailConfigDefaultsPageClass EMailConfigDefaultsPageClass;
+typedef struct _EMailConfigDefaultsPagePrivate EMailConfigDefaultsPagePrivate;
+
+struct _EMailConfigDefaultsPage {
+	GtkBox parent;
+	EMailConfigDefaultsPagePrivate *priv;
+};
+
+struct _EMailConfigDefaultsPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_defaults_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_defaults_page_new	(EMailSession *session,
+						 ESource *account_source,
+						 ESource *identity_source);
+EMailSession *	e_mail_config_defaults_page_get_session
+						(EMailConfigDefaultsPage *page);
+ESource *	e_mail_config_defaults_page_get_account_source
+						(EMailConfigDefaultsPage *page);
+ESource *	e_mail_config_defaults_page_get_identity_source
+						(EMailConfigDefaultsPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_DEFAULTS_PAGE_H */
+
diff --git a/mail/e-mail-config-identity-page.c b/mail/e-mail-config-identity-page.c
new file mode 100644
index 0000000..a0920ab
--- /dev/null
+++ b/mail/e-mail-config-identity-page.c
@@ -0,0 +1,738 @@
+/*
+ * e-mail-config-identity-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-identity-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-mail-identity.h>
+
+#include <e-util/e-marshal.h>
+#include <misc/e-mail-signature-combo-box.h>
+#include <misc/e-mail-signature-editor.h>
+
+#define E_MAIL_CONFIG_IDENTITY_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPagePrivate))
+
+struct _EMailConfigIdentityPagePrivate {
+	ESource *identity_source;
+	ESourceRegistry *registry;
+	gboolean show_account_info;
+	gboolean show_instructions;
+	gboolean show_signatures;
+};
+
+enum {
+	PROP_0,
+	PROP_IDENTITY_SOURCE,
+	PROP_REGISTRY,
+	PROP_SHOW_ACCOUNT_INFO,
+	PROP_SHOW_INSTRUCTIONS,
+	PROP_SHOW_SIGNATURES
+};
+
+/* Forward Declarations */
+static void	e_mail_config_identity_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigIdentityPage,
+	e_mail_config_identity_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_identity_page_interface_init))
+
+static gboolean
+mail_config_identity_page_is_email (const gchar *email_address)
+{
+	const gchar *cp;
+
+	/* Make sure we have a '@' between a name and domain part. */
+	cp = strchr (email_address, '@');
+
+	return (cp != NULL && cp != email_address && *(cp + 1) != '\0');
+}
+
+static void
+mail_config_identity_page_add_signature_cb (GtkButton *button,
+                                            EMailConfigIdentityPage *page)
+{
+	ESourceRegistry *registry;
+	GtkWidget *editor;
+
+	registry = e_mail_config_identity_page_get_registry (page);
+
+	editor = e_mail_signature_editor_new (registry, NULL);
+	gtk_window_set_position (GTK_WINDOW (editor), GTK_WIN_POS_CENTER);
+	gtk_widget_show (editor);
+}
+
+static void
+mail_config_identity_page_set_registry (EMailConfigIdentityPage *page,
+                                        ESourceRegistry *registry)
+{
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+	g_return_if_fail (page->priv->registry == NULL);
+
+	page->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_config_identity_page_set_identity_source (EMailConfigIdentityPage *page,
+                                               ESource *identity_source)
+{
+	g_return_if_fail (E_IS_SOURCE (identity_source));
+	g_return_if_fail (page->priv->identity_source == NULL);
+
+	page->priv->identity_source = g_object_ref (identity_source);
+}
+
+static void
+mail_config_identity_page_set_property (GObject *object,
+                                        guint property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_IDENTITY_SOURCE:
+			mail_config_identity_page_set_identity_source (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_REGISTRY:
+			mail_config_identity_page_set_registry (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SHOW_ACCOUNT_INFO:
+			e_mail_config_identity_page_set_show_account_info (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_SHOW_INSTRUCTIONS:
+			e_mail_config_identity_page_set_show_instructions (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_SHOW_SIGNATURES:
+			e_mail_config_identity_page_set_show_signatures (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object),
+				g_value_get_boolean (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_identity_page_get_property (GObject *object,
+                                        guint property_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_identity_page_get_identity_source (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object)));
+			return;
+
+		case PROP_REGISTRY:
+			g_value_set_object (
+				value,
+				e_mail_config_identity_page_get_registry (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object)));
+			return;
+
+		case PROP_SHOW_ACCOUNT_INFO:
+			g_value_set_boolean (
+				value,
+				e_mail_config_identity_page_get_show_account_info (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object)));
+			return;
+
+		case PROP_SHOW_INSTRUCTIONS:
+			g_value_set_boolean (
+				value,
+				e_mail_config_identity_page_get_show_instructions (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object)));
+			return;
+
+		case PROP_SHOW_SIGNATURES:
+			g_value_set_boolean (
+				value,
+				e_mail_config_identity_page_get_show_signatures (
+				E_MAIL_CONFIG_IDENTITY_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_identity_page_dispose (GObject *object)
+{
+	EMailConfigIdentityPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_IDENTITY_PAGE_GET_PRIVATE (object);
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->registry != NULL) {
+		g_object_unref (priv->registry);
+		priv->registry = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_identity_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_identity_page_constructed (GObject *object)
+{
+	EMailConfigIdentityPage *page;
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceMailIdentity *extension;
+	GtkLabel *label;
+	GtkWidget *widget;
+	GtkWidget *container;
+	GtkSizeGroup *size_group;
+	const gchar *extension_name;
+	const gchar *text;
+	gchar *markup;
+
+	page = E_MAIL_CONFIG_IDENTITY_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_identity_page_parent_class)->
+		constructed (object);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	registry = e_mail_config_identity_page_get_registry (page);
+	source = e_mail_config_identity_page_get_identity_source (page);
+	extension = e_source_get_extension (source, extension_name);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	/* This keeps all mnemonic labels the same width. */
+	size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+	gtk_size_group_set_ignore_hidden (size_group, TRUE);
+
+	text = _("Please enter your name and email address below. "
+		 "The \"optional\" fields below do not need to be filled "
+		 "in, unless you wish to include this information in email "
+		 "you send.");
+	widget = gtk_label_new (text);
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+
+	g_object_bind_property (
+		page, "show-instructions",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	/*** Account Information ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+
+	g_object_bind_property (
+		page, "show-account-info",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	container = widget;
+
+	text = _("Account Information");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Type the name by which you would like to refer to "
+		 "this account.\nFor example, \"Work\" or \"Personal\".");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 2, 1);
+	gtk_widget_show (widget);
+
+	text = _("_Name:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		source, "display-name",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/* This entry affects the "check-complete" result. */
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	/*** Required Information ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Required Information");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Full Nam_e:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		extension, "name",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/* This entry affects the "check-complete" result. */
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	text = _("Email _Address:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		extension, "address",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/* This entry affects the "check-complete" result. */
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	/*** Optional Information ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Optional Information");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 3, 1);
+	gtk_widget_show (widget);
+
+	text = _("Re_ply-To:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 2, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		extension, "reply-to",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/* This entry affects the "check-complete" result. */
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	text = _("Or_ganization:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 2, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		extension, "organization",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	text = _("Si_gnature:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		page, "show-signatures",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	label = GTK_LABEL (widget);
+
+	widget = e_mail_signature_combo_box_new (registry);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_halign (widget, GTK_ALIGN_START);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		extension, "signature-uid",
+		widget, "active-id",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		page, "show-signatures",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	text = _("Add Ne_w Signature...");
+	widget = gtk_button_new_with_mnemonic (text);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 3, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		page, "show-signatures",
+		widget, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_identity_page_add_signature_cb), page);
+
+	g_object_unref (size_group);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static gboolean
+mail_config_identity_page_check_complete (EMailConfigPage *page)
+{
+	EMailConfigIdentityPage *id_page;
+	ESource *source;
+	ESourceMailIdentity *extension;
+	const gchar *extension_name;
+	const gchar *name;
+	const gchar *address;
+	const gchar *reply_to;
+	const gchar *display_name;
+
+	id_page = E_MAIL_CONFIG_IDENTITY_PAGE (page);
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	source = e_mail_config_identity_page_get_identity_source (id_page);
+	extension = e_source_get_extension (source, extension_name);
+
+	name = e_source_mail_identity_get_name (extension);
+	address = e_source_mail_identity_get_address (extension);
+	reply_to = e_source_mail_identity_get_reply_to (extension);
+
+	display_name = e_source_get_display_name (source);
+
+	if (name == NULL)
+		return FALSE;
+
+	if (address == NULL)
+		return FALSE;
+
+	if (!mail_config_identity_page_is_email (address))
+		return FALSE;
+
+	/* A NULL reply_to string is allowed. */
+	if (reply_to != NULL && !mail_config_identity_page_is_email (reply_to))
+		return FALSE;
+
+	/* Only enforce when account information is visible. */
+	if (e_mail_config_identity_page_get_show_account_info (id_page))
+		if (display_name == NULL || *display_name == '\0')
+			return FALSE;
+
+	return TRUE;
+}
+
+static void
+e_mail_config_identity_page_class_init (EMailConfigIdentityPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigIdentityPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_identity_page_set_property;
+	object_class->get_property = mail_config_identity_page_get_property;
+	object_class->dispose = mail_config_identity_page_dispose;
+	object_class->constructed = mail_config_identity_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_REGISTRY,
+		g_param_spec_object (
+			"registry",
+			"Registry",
+			"Registry of data sources",
+			E_TYPE_SOURCE_REGISTRY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SHOW_ACCOUNT_INFO,
+		g_param_spec_boolean (
+			"show-account-info",
+			"Show Account Info",
+			"Show the \"Account Information\" section",
+			TRUE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SHOW_INSTRUCTIONS,
+		g_param_spec_boolean (
+			"show-instructions",
+			"Show Instructions",
+			"Show helpful instructions",
+			TRUE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SHOW_SIGNATURES,
+		g_param_spec_boolean (
+			"show-signatures",
+			"Show Signatures",
+			"Show mail signature options",
+			TRUE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_identity_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Identity");
+	interface->sort_order = E_MAIL_CONFIG_IDENTITY_PAGE_SORT_ORDER;
+	interface->check_complete = mail_config_identity_page_check_complete;
+}
+
+static void
+e_mail_config_identity_page_init (EMailConfigIdentityPage *page)
+{
+	page->priv = E_MAIL_CONFIG_IDENTITY_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_identity_page_new (ESourceRegistry *registry,
+                                 ESource *identity_source)
+{
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_IDENTITY_PAGE,
+		"registry", registry,
+		"identity-source", identity_source,
+		NULL);
+}
+
+ESourceRegistry *
+e_mail_config_identity_page_get_registry (EMailConfigIdentityPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), NULL);
+
+	return page->priv->registry;
+}
+
+ESource *
+e_mail_config_identity_page_get_identity_source (EMailConfigIdentityPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), NULL);
+
+	return page->priv->identity_source;
+}
+
+gboolean
+e_mail_config_identity_page_get_show_account_info (EMailConfigIdentityPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
+
+	return page->priv->show_account_info;
+}
+
+void
+e_mail_config_identity_page_set_show_account_info (EMailConfigIdentityPage *page,
+                                                   gboolean show_account_info)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page));
+
+	page->priv->show_account_info = show_account_info;
+
+	g_object_notify (G_OBJECT (page), "show-account-info");
+}
+
+gboolean
+e_mail_config_identity_page_get_show_instructions (EMailConfigIdentityPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
+
+	return page->priv->show_instructions;
+}
+
+void
+e_mail_config_identity_page_set_show_instructions (EMailConfigIdentityPage *page,
+                                                   gboolean show_instructions)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page));
+
+	page->priv->show_instructions = show_instructions;
+
+	g_object_notify (G_OBJECT (page), "show-instructions");
+}
+
+gboolean
+e_mail_config_identity_page_get_show_signatures (EMailConfigIdentityPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
+
+	return page->priv->show_signatures;
+}
+
+void
+e_mail_config_identity_page_set_show_signatures (EMailConfigIdentityPage *page,
+                                                 gboolean show_signatures)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_IDENTITY_PAGE (page));
+
+	page->priv->show_signatures = show_signatures;
+
+	g_object_notify (G_OBJECT (page), "show-signatures");
+}
+
diff --git a/mail/e-mail-config-identity-page.h b/mail/e-mail-config-identity-page.h
new file mode 100644
index 0000000..51d879e
--- /dev/null
+++ b/mail/e-mail-config-identity-page.h
@@ -0,0 +1,91 @@
+/*
+ * e-mail-config-identity-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_IDENTITY_PAGE_H
+#define E_MAIL_CONFIG_IDENTITY_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source-registry.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_IDENTITY_PAGE \
+	(e_mail_config_identity_page_get_type ())
+#define E_MAIL_CONFIG_IDENTITY_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPage))
+#define E_MAIL_CONFIG_IDENTITY_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPageClass))
+#define E_IS_MAIL_CONFIG_IDENTITY_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE))
+#define E_IS_MAIL_CONFIG_IDENTITY_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE))
+#define E_MAIL_CONFIG_IDENTITY_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_IDENTITY_PAGE, EMailConfigIdentityPageClass))
+
+#define E_MAIL_CONFIG_IDENTITY_PAGE_SORT_ORDER (100)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigIdentityPage EMailConfigIdentityPage;
+typedef struct _EMailConfigIdentityPageClass EMailConfigIdentityPageClass;
+typedef struct _EMailConfigIdentityPagePrivate EMailConfigIdentityPagePrivate;
+
+struct _EMailConfigIdentityPage {
+	GtkBox parent;
+	EMailConfigIdentityPagePrivate *priv;
+};
+
+struct _EMailConfigIdentityPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_identity_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_identity_page_new	(ESourceRegistry *registry,
+						 ESource *identity_source);
+ESourceRegistry *
+		e_mail_config_identity_page_get_registry
+						(EMailConfigIdentityPage *page);
+ESource *	e_mail_config_identity_page_get_identity_source
+						(EMailConfigIdentityPage *page);
+gboolean	e_mail_config_identity_page_get_show_account_info
+						(EMailConfigIdentityPage *page);
+void		e_mail_config_identity_page_set_show_account_info
+						(EMailConfigIdentityPage *page,
+						 gboolean show_account_info);
+gboolean	e_mail_config_identity_page_get_show_instructions
+						(EMailConfigIdentityPage *page);
+void		e_mail_config_identity_page_set_show_instructions
+						(EMailConfigIdentityPage *page,
+						 gboolean show_instructions);
+gboolean	e_mail_config_identity_page_get_show_signatures
+						(EMailConfigIdentityPage *page);
+void		e_mail_config_identity_page_set_show_signatures
+						(EMailConfigIdentityPage *page,
+						 gboolean show_signatures);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_IDENTITY_PAGE_H */
diff --git a/mail/e-mail-config-lookup-page.c b/mail/e-mail-config-lookup-page.c
new file mode 100644
index 0000000..0154a05
--- /dev/null
+++ b/mail/e-mail-config-lookup-page.c
@@ -0,0 +1,109 @@
+/*
+ * e-mail-config-lookup-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-lookup-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+/* Forward Declarations */
+static void	e_mail_config_lookup_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigLookupPage,
+	e_mail_config_lookup_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE(
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_lookup_page_interface_init))
+
+static void
+mail_config_lookup_page_constructed (GObject *object)
+{
+	EMailConfigLookupPage *page;
+	GtkWidget *container;
+	GtkWidget *widget;
+	const gchar *text;
+
+	page = E_MAIL_CONFIG_LOOKUP_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_lookup_page_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_FILL);
+
+	widget = gtk_alignment_new (0.5, 0.5, 0.5, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_spinner_new ();
+	gtk_spinner_start (GTK_SPINNER (widget));
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	gtk_widget_show (widget);
+
+	text = _("Looking up account details...");
+	widget = gtk_label_new (text);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+}
+
+static gboolean
+mail_config_lookup_page_check_complete (EMailConfigPage *page)
+{
+	return FALSE;
+}
+
+static void
+e_mail_config_lookup_page_class_init (EMailConfigLookupPageClass *class)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = mail_config_lookup_page_constructed;
+}
+
+static void
+e_mail_config_lookup_page_interface_init (EMailConfigPageInterface *interface)
+{
+	/* Do not set a title.  We don't want this
+	 * page listed in a GtkAssistant sidebar. */
+	interface->title = "";
+	interface->sort_order = E_MAIL_CONFIG_LOOKUP_PAGE_SORT_ORDER;
+	interface->page_type = GTK_ASSISTANT_PAGE_CUSTOM;
+	interface->check_complete = mail_config_lookup_page_check_complete;
+}
+
+static void
+e_mail_config_lookup_page_init (EMailConfigLookupPage *page)
+{
+}
+
+EMailConfigPage *
+e_mail_config_lookup_page_new ()
+{
+	return g_object_new (E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, NULL);
+}
diff --git a/mail/e-mail-config-lookup-page.h b/mail/e-mail-config-lookup-page.h
new file mode 100644
index 0000000..bbf9db3
--- /dev/null
+++ b/mail/e-mail-config-lookup-page.h
@@ -0,0 +1,73 @@
+/*
+ * e-mail-config-lookup-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_LOOKUP_PAGE_H
+#define E_MAIL_CONFIG_LOOKUP_PAGE_H
+
+#include <gtk/gtk.h>
+
+#include <mail/e-mail-config-identity-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_LOOKUP_PAGE \
+	(e_mail_config_lookup_page_get_type ())
+#define E_MAIL_CONFIG_LOOKUP_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, EMailConfigLookupPage))
+#define E_MAIL_CONFIG_LOOKUP_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, EMailConfigLookupPageClass))
+#define E_IS_MAIL_CONFIG_LOOKUP_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE))
+#define E_IS_MAIL_CONFIG_LOOKUP_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE))
+#define E_MAIL_CONFIG_LOOKUP_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_LOOKUP_PAGE, EMailConfigLookupPageClass))
+
+/* Since this is a transient page we define the sort order
+ * as the previous page's sort order plus a small offset. */
+#define E_MAIL_CONFIG_LOOKUP_PAGE_SORT_ORDER \
+	(E_MAIL_CONFIG_IDENTITY_PAGE_SORT_ORDER + 10)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigLookupPage EMailConfigLookupPage;
+typedef struct _EMailConfigLookupPageClass EMailConfigLookupPageClass;
+typedef struct _EMailConfigLookupPagePrivate EMailConfigLookupPagePrivate;
+
+struct _EMailConfigLookupPage {
+	GtkBox parent;
+	EMailConfigLookupPagePrivate *priv;
+};
+
+struct _EMailConfigLookupPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_lookup_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_lookup_page_new	(void);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_LOOKUP_PAGE_H */
+
diff --git a/mail/e-mail-config-notebook.c b/mail/e-mail-config-notebook.c
new file mode 100644
index 0000000..982427f
--- /dev/null
+++ b/mail/e-mail-config-notebook.c
@@ -0,0 +1,764 @@
+/*
+ * e-mail-config-notebook.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-notebook.h"
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-mail-identity.h>
+
+#include <mail/e-mail-config-defaults-page.h>
+#include <mail/e-mail-config-identity-page.h>
+#include <mail/e-mail-config-provider-page.h>
+#include <mail/e-mail-config-receiving-page.h>
+#include <mail/e-mail-config-security-page.h>
+#include <mail/e-mail-config-sending-page.h>
+
+#define E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookPrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailConfigNotebookPrivate {
+	EMailSession *session;
+	ESource *account_source;
+	ESource *identity_source;
+	ESource *transport_source;
+	ESource *collection_source;
+};
+
+struct _AsyncContext {
+	ESourceRegistry *registry;
+	GCancellable *cancellable;
+	GQueue *source_queue;
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT_SOURCE,
+	PROP_COLLECTION_SOURCE,
+	PROP_COMPLETE,
+	PROP_IDENTITY_SOURCE,
+	PROP_SESSION,
+	PROP_TRANSPORT_SOURCE
+};
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigNotebook,
+	e_mail_config_notebook,
+	GTK_TYPE_NOTEBOOK,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL))
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+	if (async_context->registry != NULL)
+		g_object_unref (async_context->registry);
+
+	if (async_context->cancellable != NULL)
+		g_object_unref (async_context->cancellable);
+
+	g_queue_free_full (
+		async_context->source_queue,
+		(GDestroyNotify) g_object_unref);
+
+	g_slice_free (AsyncContext, async_context);
+}
+
+static void
+mail_config_notebook_sort_pages (EMailConfigNotebook *notebook)
+{
+	GList *list, *link;
+	gint ii = 0;
+
+	list = g_list_sort (
+		gtk_container_get_children (GTK_CONTAINER (notebook)),
+		(GCompareFunc) e_mail_config_page_compare);
+
+	for (link = list; link != NULL; link = g_list_next (link))
+		gtk_notebook_reorder_child (
+			GTK_NOTEBOOK (notebook),
+			GTK_WIDGET (link->data), ii++);
+
+	g_list_free (list);
+}
+
+static void
+mail_config_notebook_page_changed (EMailConfigPage *page,
+                                   EMailConfigNotebook *notebook)
+{
+	g_object_notify (G_OBJECT (notebook), "complete");
+}
+
+static void
+mail_config_notebook_set_account_source (EMailConfigNotebook *notebook,
+                                         ESource *account_source)
+{
+	g_return_if_fail (E_IS_SOURCE (account_source));
+	g_return_if_fail (notebook->priv->account_source == NULL);
+
+	notebook->priv->account_source = g_object_ref (account_source);
+}
+
+static void
+mail_config_notebook_set_collection_source (EMailConfigNotebook *notebook,
+                                            ESource *collection_source)
+{
+	g_return_if_fail (notebook->priv->collection_source == NULL);
+
+	if (collection_source != NULL) {
+		g_return_if_fail (E_IS_SOURCE (collection_source));
+		g_object_ref (collection_source);
+	}
+
+	notebook->priv->collection_source = collection_source;
+}
+
+static void
+mail_config_notebook_set_identity_source (EMailConfigNotebook *notebook,
+                                          ESource *identity_source)
+{
+	g_return_if_fail (E_IS_SOURCE (identity_source));
+	g_return_if_fail (notebook->priv->identity_source == NULL);
+
+	notebook->priv->identity_source = g_object_ref (identity_source);
+}
+
+static void
+mail_config_notebook_set_session (EMailConfigNotebook *notebook,
+                                  EMailSession *session)
+{
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
+	g_return_if_fail (notebook->priv->session == NULL);
+
+	notebook->priv->session = g_object_ref (session);
+}
+
+static void
+mail_config_notebook_set_transport_source (EMailConfigNotebook *notebook,
+                                           ESource *transport_source)
+{
+	g_return_if_fail (E_IS_SOURCE (transport_source));
+	g_return_if_fail (notebook->priv->transport_source == NULL);
+
+	notebook->priv->transport_source = g_object_ref (transport_source);
+}
+
+static void
+mail_config_notebook_set_property (GObject *object,
+                                   guint property_id,
+                                   const GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			mail_config_notebook_set_account_source (
+				E_MAIL_CONFIG_NOTEBOOK (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_COLLECTION_SOURCE:
+			mail_config_notebook_set_collection_source (
+				E_MAIL_CONFIG_NOTEBOOK (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			mail_config_notebook_set_identity_source (
+				E_MAIL_CONFIG_NOTEBOOK (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SESSION:
+			mail_config_notebook_set_session (
+				E_MAIL_CONFIG_NOTEBOOK (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_TRANSPORT_SOURCE:
+			mail_config_notebook_set_transport_source (
+				E_MAIL_CONFIG_NOTEBOOK (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_notebook_get_property (GObject *object,
+                                   guint property_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_notebook_get_account_source (
+				E_MAIL_CONFIG_NOTEBOOK (object)));
+			return;
+
+		case PROP_COLLECTION_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_notebook_get_collection_source (
+				E_MAIL_CONFIG_NOTEBOOK (object)));
+			return;
+
+		case PROP_COMPLETE:
+			g_value_set_boolean (
+				value,
+				e_mail_config_notebook_check_complete (
+				E_MAIL_CONFIG_NOTEBOOK (object)));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_notebook_get_identity_source (
+				E_MAIL_CONFIG_NOTEBOOK (object)));
+			return;
+
+		case PROP_SESSION:
+			g_value_set_object (
+				value,
+				e_mail_config_notebook_get_session (
+				E_MAIL_CONFIG_NOTEBOOK (object)));
+			return;
+
+		case PROP_TRANSPORT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_notebook_get_transport_source (
+				E_MAIL_CONFIG_NOTEBOOK (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_notebook_dispose (GObject *object)
+{
+	EMailConfigNotebookPrivate *priv;
+
+	priv = E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE (object);
+
+	if (priv->session != NULL) {
+		g_object_ref (priv->session);
+		priv->session = NULL;
+	}
+
+	if (priv->account_source != NULL) {
+		g_object_ref (priv->account_source);
+		priv->account_source = NULL;
+	}
+
+	if (priv->identity_source != NULL) {
+		g_object_ref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->transport_source != NULL) {
+		g_object_ref (priv->transport_source);
+		priv->transport_source = NULL;
+	}
+
+	if (priv->collection_source != NULL) {
+		g_object_ref (priv->collection_source);
+		priv->collection_source = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_notebook_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_notebook_constructed (GObject *object)
+{
+	EMailConfigNotebook *notebook;
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceExtension *extension;
+	ESourceMailIdentity *mail_identity_extension;
+	EMailConfigServiceBackend *backend;
+	CamelProvider *provider;
+	EMailSession *session;
+	EMailConfigPage *page;
+	const gchar *extension_name;
+
+	notebook = E_MAIL_CONFIG_NOTEBOOK (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_notebook_parent_class)->
+		constructed (object);
+
+	session = e_mail_config_notebook_get_session (notebook);
+	registry = e_mail_session_get_registry (session);
+
+	source = notebook->priv->identity_source;
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	extension = e_source_get_extension (source, extension_name);
+	mail_identity_extension = E_SOURCE_MAIL_IDENTITY (extension);
+
+	/*** Identity Page ***/
+
+	page = e_mail_config_identity_page_new (
+		registry, notebook->priv->identity_source);
+	e_mail_config_identity_page_set_show_instructions (
+		E_MAIL_CONFIG_IDENTITY_PAGE (page), FALSE);
+	e_mail_config_notebook_add_page (notebook, page);
+
+	/*** Receiving Page ***/
+
+	page = e_mail_config_receiving_page_new (registry);
+	backend = e_mail_config_service_page_add_scratch_source (
+		E_MAIL_CONFIG_SERVICE_PAGE (page),
+		notebook->priv->account_source,
+		notebook->priv->collection_source);
+	e_mail_config_notebook_add_page (notebook, page);
+
+	g_object_bind_property (
+		mail_identity_extension, "address",
+		page, "email-address",
+		G_BINDING_SYNC_CREATE);
+
+	provider = e_mail_config_service_backend_get_provider (backend);
+
+	/*** Receiving Options (conditional) ***/
+
+	/* Note: We exclude this page if it has no options,
+	 *       but we don't know that until we create it. */
+	page = e_mail_config_provider_page_new (backend);
+	if (e_mail_config_provider_page_is_empty (
+			E_MAIL_CONFIG_PROVIDER_PAGE (page))) {
+		g_object_unref (g_object_ref_sink (page));
+	} else {
+		e_mail_config_notebook_add_page (notebook, page);
+	}
+
+	/*** Sending Page (conditional) ***/
+
+	if (!CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) {
+		page = e_mail_config_sending_page_new (registry);
+		e_mail_config_service_page_add_scratch_source (
+			E_MAIL_CONFIG_SERVICE_PAGE (page),
+			notebook->priv->transport_source,
+			notebook->priv->collection_source);
+		e_mail_config_notebook_add_page (notebook, page);
+
+		g_object_bind_property (
+			mail_identity_extension, "address",
+			page, "email-address",
+			G_BINDING_SYNC_CREATE);
+	}
+
+	/*** Defaults Page ***/
+
+	page = e_mail_config_defaults_page_new (
+		session,
+		notebook->priv->account_source,
+		notebook->priv->identity_source);
+	e_mail_config_notebook_add_page (notebook, page);
+
+	/*** Security Page ***/
+
+	page = e_mail_config_security_page_new (
+		notebook->priv->identity_source);
+	e_mail_config_notebook_add_page (notebook, page);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (notebook));
+}
+
+static void
+mail_config_notebook_page_removed (GtkNotebook *notebook,
+                                   GtkWidget *child,
+                                   guint page_num)
+{
+	/* Do not chain up.  GtkNotebook does not implement this method. */
+
+	if (E_IS_MAIL_CONFIG_PAGE (child))
+		g_signal_handlers_disconnect_by_func (
+			child, mail_config_notebook_page_changed,
+			E_MAIL_CONFIG_NOTEBOOK (notebook));
+}
+
+static void
+mail_config_notebook_page_added (GtkNotebook *notebook,
+                                 GtkWidget *child,
+                                 guint page_num)
+{
+	/* Do not chain up.  GtkNotebook does not implement this method. */
+
+	if (E_IS_MAIL_CONFIG_PAGE (child))
+		g_signal_connect (
+			child, "changed",
+			G_CALLBACK (mail_config_notebook_page_changed),
+			E_MAIL_CONFIG_NOTEBOOK (notebook));
+}
+
+static void
+e_mail_config_notebook_class_init (EMailConfigNotebookClass *class)
+{
+	GObjectClass *object_class;
+	GtkNotebookClass *notebook_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigNotebookPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_notebook_set_property;
+	object_class->get_property = mail_config_notebook_get_property;
+	object_class->dispose = mail_config_notebook_dispose;
+	object_class->constructed = mail_config_notebook_constructed;
+
+	notebook_class = GTK_NOTEBOOK_CLASS (class);
+	notebook_class->page_removed = mail_config_notebook_page_removed;
+	notebook_class->page_added = mail_config_notebook_page_added;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_SOURCE,
+		g_param_spec_object (
+			"account-source",
+			"Account Source",
+			"Mail account source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_COLLECTION_SOURCE,
+		g_param_spec_object (
+			"collection-source",
+			"Collection Source",
+			"Optional collection source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_COMPLETE,
+		g_param_spec_boolean (
+			"complete",
+			"Complete",
+			"Whether all required fields are complete",
+			FALSE,  /* default is not used */
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SESSION,
+		g_param_spec_object (
+			"session",
+			"Session",
+			"Mail session",
+			E_TYPE_MAIL_SESSION,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TRANSPORT_SOURCE,
+		g_param_spec_object (
+			"transport-source",
+			"Transport Source",
+			"Mail transport source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_notebook_init (EMailConfigNotebook *notebook)
+{
+	notebook->priv = E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE (notebook);
+}
+
+GtkWidget *
+e_mail_config_notebook_new (EMailSession *session,
+                            ESource *account_source,
+                            ESource *identity_source,
+                            ESource *transport_source,
+                            ESource *collection_source)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (account_source), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (transport_source), NULL);
+
+	/* A collection source is optional. */
+	if (collection_source != NULL)
+		g_return_val_if_fail (E_IS_SOURCE (collection_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_NOTEBOOK,
+		"session", session,
+		"account-source", account_source,
+		"identity-source", identity_source,
+		"transport-source", transport_source,
+		"collection-source", collection_source,
+		NULL);
+}
+
+EMailSession *
+e_mail_config_notebook_get_session (EMailConfigNotebook *notebook)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
+
+	return notebook->priv->session;
+}
+
+ESource *
+e_mail_config_notebook_get_account_source (EMailConfigNotebook *notebook)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
+
+	return notebook->priv->account_source;
+}
+
+ESource *
+e_mail_config_notebook_get_identity_source (EMailConfigNotebook *notebook)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
+
+	return notebook->priv->identity_source;
+}
+
+ESource *
+e_mail_config_notebook_get_transport_source (EMailConfigNotebook *notebook)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
+
+	return notebook->priv->transport_source;
+}
+
+ESource *
+e_mail_config_notebook_get_collection_source (EMailConfigNotebook *notebook)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
+
+	return notebook->priv->collection_source;
+}
+
+void
+e_mail_config_notebook_add_page (EMailConfigNotebook *notebook,
+                                 EMailConfigPage *page)
+{
+	EMailConfigPageInterface *page_interface;
+	GtkWidget *tab_label;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook));
+	g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page));
+
+	page_interface = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page);
+	tab_label = gtk_label_new (page_interface->title);
+
+	gtk_widget_show (GTK_WIDGET (page));
+
+	gtk_notebook_append_page (
+		GTK_NOTEBOOK (notebook),
+		GTK_WIDGET (page), tab_label);
+
+	mail_config_notebook_sort_pages (notebook);
+}
+
+gboolean
+e_mail_config_notebook_check_complete (EMailConfigNotebook *notebook)
+{
+	GList *list, *link;
+	gboolean complete = TRUE;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), FALSE);
+
+	list = gtk_container_get_children (GTK_CONTAINER (notebook));
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		if (E_IS_MAIL_CONFIG_PAGE (link->data)) {
+			EMailConfigPage *page;
+			page = E_MAIL_CONFIG_PAGE (link->data);
+			complete = e_mail_config_page_check_complete (page);
+
+			if (!complete)
+				break;
+		}
+	}
+
+	g_list_free (list);
+
+	return complete;
+}
+
+/********************** e_mail_config_notebook_commit() **********************/
+
+static void
+mail_config_notebook_commit_cb (GObject *object,
+                                GAsyncResult *result,
+                                gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	AsyncContext *async_context;
+	ESource *next_source;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+	async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+	e_source_registry_commit_source_finish (
+		E_SOURCE_REGISTRY (object), result, &error);
+
+	if (error != NULL) {
+		g_simple_async_result_take_error (simple, error);
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+		return;
+	}
+
+	next_source = g_queue_pop_head (async_context->source_queue);
+
+	if (next_source == NULL) {
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+		return;
+	}
+
+	e_source_registry_commit_source (
+		async_context->registry, next_source,
+		async_context->cancellable,
+		mail_config_notebook_commit_cb, simple);
+
+	g_object_unref (next_source);
+}
+
+void
+e_mail_config_notebook_commit (EMailConfigNotebook *notebook,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	AsyncContext *async_context;
+	ESourceRegistry *registry;
+	EMailSession *session;
+	ESource *source;
+	GList *list, *link;
+	GQueue *queue;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook));
+
+	session = e_mail_config_notebook_get_session (notebook);
+	registry = e_mail_session_get_registry (session);
+
+	queue = g_queue_new ();
+
+	/* Queue the collection data source if one is defined. */
+	source = e_mail_config_notebook_get_collection_source (notebook);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+
+	/* Queue the mail-related data sources for the account. */
+	source = e_mail_config_notebook_get_account_source (notebook);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+	source = e_mail_config_notebook_get_identity_source (notebook);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+	source = e_mail_config_notebook_get_transport_source (notebook);
+	if (source != NULL)
+		g_queue_push_tail (queue, g_object_ref (source));
+
+	list = gtk_container_get_children (GTK_CONTAINER (notebook));
+
+	/* Tell all EMailConfigPages to commit their UI state to their
+	 * scratch ESources and push any additional data sources on to
+	 * the given source queue, such as calendars or address books
+	 * to be bundled with the mail account. */
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		if (E_IS_MAIL_CONFIG_PAGE (link->data)) {
+			EMailConfigPage *page;
+			page = E_MAIL_CONFIG_PAGE (link->data);
+			e_mail_config_page_commit_changes (page, queue);
+		}
+	}
+
+	g_list_free (list);
+
+	async_context = g_slice_new0 (AsyncContext);
+	async_context->registry = g_object_ref (registry);
+	async_context->source_queue = queue;  /* takes ownership */
+
+	if (G_IS_CANCELLABLE (cancellable))
+		async_context->cancellable = g_object_ref (cancellable);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (notebook), callback, user_data,
+		e_mail_config_notebook_commit);
+
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_context, (GDestroyNotify) async_context_free);
+
+	source = g_queue_pop_head (async_context->source_queue);
+	g_return_if_fail (E_IS_SOURCE (source));
+
+	e_source_registry_commit_source (
+		async_context->registry, source,
+		async_context->cancellable,
+		mail_config_notebook_commit_cb, simple);
+
+	g_object_unref (source);
+}
+
+gboolean
+e_mail_config_notebook_commit_finish (EMailConfigNotebook *notebook,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (notebook),
+		e_mail_config_notebook_commit), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	/* Assume success unless a GError is set. */
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
diff --git a/mail/e-mail-config-notebook.h b/mail/e-mail-config-notebook.h
new file mode 100644
index 0000000..3e816c6
--- /dev/null
+++ b/mail/e-mail-config-notebook.h
@@ -0,0 +1,98 @@
+/*
+ * e-mail-config-notebook.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_NOTEBOOK_H
+#define E_MAIL_CONFIG_NOTEBOOK_H
+
+#include <gtk/gtk.h>
+
+#include <libemail-engine/e-mail-session.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_NOTEBOOK \
+	(e_mail_config_notebook_get_type ())
+#define E_MAIL_CONFIG_NOTEBOOK(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebook))
+#define E_MAIL_CONFIG_NOTEBOOK_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookClass))
+#define E_IS_MAIL_CONFIG_NOTEBOOK(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK))
+#define E_IS_MAIL_CONFIG_NOTEBOOK_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_NOTEBOOK))
+#define E_MAIL_CONFIG_NOTEBOOK_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_NOTEBOOK, EMailConfigNotebookClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigNotebook EMailConfigNotebook;
+typedef struct _EMailConfigNotebookClass EMailConfigNotebookClass;
+typedef struct _EMailConfigNotebookPrivate EMailConfigNotebookPrivate;
+
+struct _EMailConfigNotebook {
+	GtkNotebook parent;
+	EMailConfigNotebookPrivate *priv;
+};
+
+struct _EMailConfigNotebookClass {
+	GtkNotebookClass parent_class;
+};
+
+GType		e_mail_config_notebook_get_type
+					(void) G_GNUC_CONST;
+GtkWidget *	e_mail_config_notebook_new
+					(EMailSession *session,
+					 ESource *account_source,
+					 ESource *identity_source,
+					 ESource *transport_source,
+					 ESource *collection_source);
+EMailSession *	e_mail_config_notebook_get_session
+					(EMailConfigNotebook *notebook);
+ESource *	e_mail_config_notebook_get_account_source
+					(EMailConfigNotebook *notebook);
+ESource *	e_mail_config_notebook_get_identity_source
+					(EMailConfigNotebook *notebook);
+ESource *	e_mail_config_notebook_get_transport_source
+					(EMailConfigNotebook *notebook);
+ESource *	e_mail_config_notebook_get_collection_source
+					(EMailConfigNotebook *notebook);
+void		e_mail_config_notebook_add_page
+					(EMailConfigNotebook *notebook,
+					 EMailConfigPage *page);
+gboolean	e_mail_config_notebook_check_complete
+					(EMailConfigNotebook *notebook);
+void		e_mail_config_notebook_commit
+					(EMailConfigNotebook *notebook,
+					 GCancellable *cancellable,
+					 GAsyncReadyCallback callback,
+					 gpointer user_data);
+gboolean	e_mail_config_notebook_commit_finish
+					(EMailConfigNotebook *notebook,
+					 GAsyncResult *result,
+					 GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_NOTEBOOK_H */
+
diff --git a/mail/e-mail-config-page.c b/mail/e-mail-config-page.c
new file mode 100644
index 0000000..29d18e8
--- /dev/null
+++ b/mail/e-mail-config-page.c
@@ -0,0 +1,176 @@
+/*
+ * e-mail-config-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <e-util/e-marshal.h>
+
+enum {
+	CHANGED,
+	SETUP_DEFAULTS,
+	CHECK_COMPLETE,
+	COMMIT_CHANGES,
+	LAST_SIGNAL
+};
+
+static gulong signals[LAST_SIGNAL];
+
+G_DEFINE_INTERFACE (
+	EMailConfigPage,
+	e_mail_config_page,
+	GTK_TYPE_WIDGET)
+
+static gboolean
+mail_config_page_check_complete (EMailConfigPage *page)
+{
+	return TRUE;
+}
+
+static gboolean
+mail_config_page_check_complete_accumulator (GSignalInvocationHint *ihint,
+                                             GValue *return_accu,
+                                             const GValue *handler_return,
+                                             gpointer unused)
+{
+	gboolean v_boolean;
+
+	/* Abort emission if a handler returns FALSE. */
+	v_boolean = g_value_get_boolean (handler_return);
+	g_value_set_boolean (return_accu, v_boolean);
+
+	return v_boolean;
+}
+
+static void
+e_mail_config_page_default_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Untitled");
+	interface->page_type = GTK_ASSISTANT_PAGE_CONTENT;
+
+	interface->check_complete = mail_config_page_check_complete;
+
+	signals[CHANGED] = g_signal_new (
+		"changed",
+		G_TYPE_FROM_INTERFACE (interface),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailConfigPageInterface, changed),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[SETUP_DEFAULTS] = g_signal_new (
+		"setup-defaults",
+		G_TYPE_FROM_INTERFACE (interface),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailConfigPageInterface, setup_defaults),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[CHECK_COMPLETE] = g_signal_new (
+		"check-complete",
+		G_TYPE_FROM_INTERFACE (interface),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailConfigPageInterface, check_complete),
+		mail_config_page_check_complete_accumulator, NULL,
+		e_marshal_BOOLEAN__VOID,
+		G_TYPE_BOOLEAN, 0);
+
+	signals[COMMIT_CHANGES] = g_signal_new (
+		"commit-changes",
+		G_TYPE_FROM_INTERFACE (interface),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailConfigPageInterface, commit_changes),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__POINTER,
+		G_TYPE_NONE, 1,
+		G_TYPE_POINTER);
+}
+
+void
+e_mail_config_page_changed (EMailConfigPage *page)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page));
+
+	g_signal_emit (page, signals[CHANGED], 0);
+}
+
+void
+e_mail_config_page_setup_defaults (EMailConfigPage *page)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page));
+
+	g_signal_emit (page, signals[SETUP_DEFAULTS], 0);
+}
+
+gboolean
+e_mail_config_page_check_complete (EMailConfigPage *page)
+{
+	gboolean complete;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_PAGE (page), FALSE);
+
+	g_signal_emit (page, signals[CHECK_COMPLETE], 0, &complete);
+
+	return complete;
+}
+
+void
+e_mail_config_page_commit_changes (EMailConfigPage *page,
+                                   GQueue *source_queue)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_PAGE (page));
+	g_return_if_fail (source_queue != NULL);
+
+	g_signal_emit (page, signals[COMMIT_CHANGES], 0, source_queue);
+}
+
+gint
+e_mail_config_page_compare (GtkWidget *page_a,
+                            GtkWidget *page_b)
+{
+	EMailConfigPageInterface *interface_a = NULL;
+	EMailConfigPageInterface *interface_b = NULL;
+
+	if (E_IS_MAIL_CONFIG_PAGE (page_a))
+		interface_a = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page_a);
+
+	if (E_IS_MAIL_CONFIG_PAGE (page_b))
+		interface_b = E_MAIL_CONFIG_PAGE_GET_INTERFACE (page_b);
+
+	if (interface_a == interface_b)
+		return 0;
+
+	if (interface_a != NULL && interface_b == NULL)
+		return -1;
+
+	if (interface_a == NULL && interface_b != NULL)
+		return 1;
+
+	if (interface_a->sort_order < interface_b->sort_order)
+		return -1;
+
+	if (interface_a->sort_order > interface_b->sort_order)
+		return 1;
+
+	return 0;
+}
+
diff --git a/mail/e-mail-config-page.h b/mail/e-mail-config-page.h
new file mode 100644
index 0000000..40a949a
--- /dev/null
+++ b/mail/e-mail-config-page.h
@@ -0,0 +1,72 @@
+/*
+ * e-mail-config-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_PAGE_H
+#define E_MAIL_CONFIG_PAGE_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_PAGE \
+	(e_mail_config_page_get_type ())
+#define E_MAIL_CONFIG_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_PAGE, EMailConfigPage))
+#define E_IS_MAIL_CONFIG_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_PAGE))
+#define E_MAIL_CONFIG_PAGE_GET_INTERFACE(obj) \
+	(G_TYPE_INSTANCE_GET_INTERFACE \
+	((obj), E_TYPE_MAIL_CONFIG_PAGE, EMailConfigPageInterface))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigPage EMailConfigPage;
+typedef struct _EMailConfigPageInterface EMailConfigPageInterface;
+
+struct _EMailConfigPageInterface {
+	GTypeInterface parent_interface;
+
+	gint sort_order;
+	const gchar *title;
+	GtkAssistantPageType page_type;
+
+	/* Signals */
+	void		(*changed)		(EMailConfigPage *page);
+	void		(*setup_defaults)	(EMailConfigPage *page);
+	gboolean	(*check_complete)	(EMailConfigPage *page);
+	void		(*commit_changes)	(EMailConfigPage *page,
+						 GQueue *source_queue);
+};
+
+GType		e_mail_config_page_get_type	(void) G_GNUC_CONST;
+void		e_mail_config_page_changed	(EMailConfigPage *page);
+void		e_mail_config_page_setup_defaults
+						(EMailConfigPage *page);
+gboolean	e_mail_config_page_check_complete
+						(EMailConfigPage *page);
+void		e_mail_config_page_commit_changes
+						(EMailConfigPage *page,
+						 GQueue *source_queue);
+gint		e_mail_config_page_compare	(GtkWidget *page_a,
+						 GtkWidget *page_b);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_PAGE_H */
+
diff --git a/mail/e-mail-config-provider-page.c b/mail/e-mail-config-provider-page.c
new file mode 100644
index 0000000..1474ff3
--- /dev/null
+++ b/mail/e-mail-config-provider-page.c
@@ -0,0 +1,774 @@
+/*
+ * e-mail-config-provider-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-provider-page.h"
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-data-server-util.h>
+
+#include <libevolution-utils/e-alert-sink.h>
+#include <libevolution-utils/e-alert-dialog.h>
+#include <misc/e-activity-bar.h>
+#include <misc/e-alert-bar.h>
+
+#define E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPagePrivate))
+
+#define STANDARD_MARGIN   12
+#define DEPENDENCY_MARGIN 24
+
+struct _EMailConfigProviderPagePrivate {
+	EMailConfigServiceBackend *backend;
+	gboolean is_empty;
+
+	GtkWidget *activity_bar;
+	GtkWidget *alert_bar;
+};
+
+enum {
+	PROP_0,
+	PROP_BACKEND
+};
+
+/* Forward Declarations */
+static void	e_mail_config_provider_page_alert_sink_init
+					(EAlertSinkInterface *interface);
+static void	e_mail_config_provider_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigProviderPage,
+	e_mail_config_provider_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_ALERT_SINK,
+		e_mail_config_provider_page_alert_sink_init)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_provider_page_interface_init))
+
+static void
+mail_config_provider_page_handle_dependency (EMailConfigProviderPage *page,
+                                             CamelProviderConfEntry *entry,
+                                             GtkWidget *widget)
+{
+	EMailConfigServiceBackend *backend;
+	CamelSettings *settings;
+	GBindingFlags binding_flags = G_BINDING_SYNC_CREATE;
+	const gchar *depname = entry->depname;
+	gint margin;
+
+	if (depname == NULL)
+		return;
+
+	if (*depname == '!') {
+		binding_flags |= G_BINDING_INVERT_BOOLEAN;
+		depname++;
+	}
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	g_object_bind_property (
+		settings, depname,
+		widget, "sensitive",
+		binding_flags);
+
+	/* Further indent the widget to show its dependency. */
+	margin = gtk_widget_get_margin_left (widget);
+	gtk_widget_set_margin_left (widget, margin + DEPENDENCY_MARGIN);
+}
+
+static void
+mail_config_provider_page_add_section (EMailConfigProviderPage *page,
+                                       CamelProviderConfEntry *entry)
+{
+	EMailConfigServiceBackend *backend;
+	CamelProvider *provider;
+	GtkWidget *widget;
+	gchar *markup;
+
+	g_return_if_fail (entry->text != NULL);
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	provider = e_mail_config_service_backend_get_provider (backend);
+
+	markup = g_markup_printf_escaped ("<b>%s</b>", entry->text);
+
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	/* Skip the top margin if this is the first entry. */
+	if (entry != provider->extra_conf)
+		gtk_widget_set_margin_top (widget, 6);
+
+	g_free (markup);
+}
+
+static void
+mail_config_provider_page_add_checkbox (EMailConfigProviderPage *page,
+                                        CamelProviderConfEntry *entry)
+{
+	EMailConfigServiceBackend *backend;
+	CamelSettings *settings;
+	GtkWidget *widget;
+
+	g_return_if_fail (entry->text != NULL);
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	widget = gtk_check_button_new_with_mnemonic (entry->text);
+	gtk_widget_set_margin_left (widget, STANDARD_MARGIN);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		settings, entry->name,
+		widget, "active",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	mail_config_provider_page_handle_dependency (page, entry, widget);
+}
+
+static void
+mail_config_provider_page_add_checkspin (EMailConfigProviderPage *page,
+                                         CamelProviderConfEntry *entry)
+{
+	EMailConfigServiceBackend *backend;
+	CamelSettings *settings;
+	GObjectClass *class;
+	GParamSpec *pspec;
+	GParamSpec *use_pspec;
+	GtkAdjustment *adjustment;
+	GtkWidget *hbox, *spin;
+	GtkWidget *prefix;
+	gchar *use_property_name;
+	gchar *pre, *post;
+
+	g_return_if_fail (entry->text != NULL);
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	/* The entry->name property (e.g. "foo") should be numeric for the
+	 * spin button.  If a "use" boolean property exists (e.g. "use-foo")
+	 * then a checkbox is also shown. */
+
+	class = G_OBJECT_GET_CLASS (settings);
+	pspec = g_object_class_find_property (class, entry->name);
+	g_return_if_fail (pspec != NULL);
+
+	use_property_name = g_strconcat ("use-", entry->name, NULL);
+	use_pspec = g_object_class_find_property (class, use_property_name);
+	if (use_pspec != NULL && use_pspec->value_type != G_TYPE_BOOLEAN)
+		use_pspec = NULL;
+	g_free (use_property_name);
+
+	/* Make sure we can convert to and from doubles. */
+	g_return_if_fail (
+		g_value_type_transformable (
+		pspec->value_type, G_TYPE_DOUBLE));
+	g_return_if_fail (
+		g_value_type_transformable (
+		G_TYPE_DOUBLE, pspec->value_type));
+
+	if (G_IS_PARAM_SPEC_CHAR (pspec)) {
+		GParamSpecChar *pspec_char;
+		pspec_char = G_PARAM_SPEC_CHAR (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_char->default_value,
+			(gdouble) pspec_char->minimum,
+			(gdouble) pspec_char->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_UCHAR (pspec)) {
+		GParamSpecUChar *pspec_uchar;
+		pspec_uchar = G_PARAM_SPEC_UCHAR (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_uchar->default_value,
+			(gdouble) pspec_uchar->minimum,
+			(gdouble) pspec_uchar->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_INT (pspec)) {
+		GParamSpecInt *pspec_int;
+		pspec_int = G_PARAM_SPEC_INT (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_int->default_value,
+			(gdouble) pspec_int->minimum,
+			(gdouble) pspec_int->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_UINT (pspec)) {
+		GParamSpecUInt *pspec_uint;
+		pspec_uint = G_PARAM_SPEC_UINT (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_uint->default_value,
+			(gdouble) pspec_uint->minimum,
+			(gdouble) pspec_uint->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_LONG (pspec)) {
+		GParamSpecLong *pspec_long;
+		pspec_long = G_PARAM_SPEC_LONG (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_long->default_value,
+			(gdouble) pspec_long->minimum,
+			(gdouble) pspec_long->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_ULONG (pspec)) {
+		GParamSpecULong *pspec_ulong;
+		pspec_ulong = G_PARAM_SPEC_ULONG (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_ulong->default_value,
+			(gdouble) pspec_ulong->minimum,
+			(gdouble) pspec_ulong->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_FLOAT (pspec)) {
+		GParamSpecFloat *pspec_float;
+		pspec_float = G_PARAM_SPEC_FLOAT (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_float->default_value,
+			(gdouble) pspec_float->minimum,
+			(gdouble) pspec_float->maximum,
+			1.0, 1.0, 0.0);
+
+	} else if (G_IS_PARAM_SPEC_DOUBLE (pspec)) {
+		GParamSpecDouble *pspec_double;
+		pspec_double = G_PARAM_SPEC_DOUBLE (pspec);
+		adjustment = gtk_adjustment_new (
+			(gdouble) pspec_double->default_value,
+			(gdouble) pspec_double->minimum,
+			(gdouble) pspec_double->maximum,
+			1.0, 1.0, 0.0);
+
+	} else
+		g_return_if_reached ();
+
+	pre = g_alloca (strlen (entry->text) + 1);
+	strcpy (pre, entry->text);
+	post = strstr (pre, "%s");
+	if (post != NULL) {
+		*post = '\0';
+		post += 2;
+	}
+
+	hbox = gtk_hbox_new (FALSE, 3);
+	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
+	gtk_box_pack_start (GTK_BOX (page), hbox, FALSE, FALSE, 0);
+	gtk_widget_show (hbox);
+
+	if (use_pspec != NULL) {
+		prefix = gtk_check_button_new_with_mnemonic (pre);
+
+		g_object_bind_property (
+			settings, use_pspec->name,
+			prefix, "active",
+			G_BINDING_BIDIRECTIONAL |
+			G_BINDING_SYNC_CREATE);
+	} else {
+		prefix = gtk_label_new_with_mnemonic (pre);
+	}
+	gtk_box_pack_start (GTK_BOX (hbox), prefix, FALSE, TRUE, 0);
+	gtk_widget_show (prefix);
+
+	spin = gtk_spin_button_new (adjustment, 1.0, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, TRUE, 0);
+	gtk_widget_show (spin);
+
+	g_object_bind_property (
+		settings, entry->name,
+		spin, "value",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	if (use_pspec != NULL)
+		g_object_bind_property (
+			prefix, "active",
+			spin, "sensitive",
+			G_BINDING_SYNC_CREATE);
+
+	if (post != NULL) {
+		GtkWidget *label = gtk_label_new_with_mnemonic (post);
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), prefix);
+		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+		gtk_widget_show (label);
+	}
+
+	mail_config_provider_page_handle_dependency (page, entry, hbox);
+}
+
+static void
+mail_config_provider_page_add_entry (EMailConfigProviderPage *page,
+                                     CamelProviderConfEntry *entry)
+{
+	EMailConfigServiceBackend *backend;
+	CamelSettings *settings;
+	GtkWidget *hbox;
+	GtkWidget *input;
+	GtkWidget *label;
+
+	g_return_if_fail (entry->text != NULL);
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	hbox = gtk_hbox_new (FALSE, 0);
+	gtk_box_set_spacing (GTK_BOX (hbox), 6);
+	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
+	gtk_box_pack_start (GTK_BOX (page), hbox, FALSE, FALSE, 0);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new_with_mnemonic (entry->text);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+	gtk_widget_show (label);
+
+	input = gtk_entry_new ();
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), input);
+	gtk_box_pack_start (GTK_BOX (hbox), input, TRUE, TRUE, 0);
+	gtk_widget_show (input);
+
+	g_object_bind_property (
+		settings, entry->name,
+		input, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		input, "sensitive",
+		label, "sensitive",
+		G_BINDING_SYNC_CREATE);
+
+	mail_config_provider_page_handle_dependency (page, entry, hbox);
+}
+
+static void
+mail_config_provider_page_add_options (EMailConfigProviderPage *page,
+                                       CamelProviderConfEntry *entry)
+{
+	EMailConfigServiceBackend *backend;
+	CamelProvider *provider;
+	CamelSettings *settings;
+	GtkCellRenderer *renderer;
+	GtkListStore *store;
+	GtkWidget *hbox;
+	GtkWidget *combo;
+	GtkWidget *label;
+	gchar **tokens;
+	guint length, ii;
+
+	/* The 'value' string is of the format:
+	 *
+	 *   'nick0:caption0:nick1:caption1:...nickN:captionN'
+	 *
+	 * where 'nick' is the nickname a GEnumValue and 'caption'
+	 * is the localized combo box item displayed to the user. */
+
+	g_return_if_fail (entry->text != NULL);
+	g_return_if_fail (entry->value != NULL);
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	provider = e_mail_config_service_backend_get_provider (backend);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	hbox = gtk_hbox_new (FALSE, 0);
+	gtk_box_set_spacing (GTK_BOX (hbox), 6);
+	gtk_widget_set_margin_left (hbox, STANDARD_MARGIN);
+	gtk_box_pack_start (GTK_BOX (page), hbox, FALSE, FALSE, 0);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new_with_mnemonic (entry->text);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+	gtk_widget_show (label);
+
+	/* 0: 'nick', 1: caption */
+	store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+
+	tokens = g_strsplit (entry->value, ":", -1);
+	length = g_strv_length (tokens);
+
+	/* Take the strings two at a time. */
+	for (ii = 0; ii + 1 < length; ii += 2) {
+		GtkTreeIter iter;
+		const gchar *nick;
+		const gchar *caption;
+
+		nick = tokens[ii + 0];
+		caption = tokens[ii + 1];
+
+		/* Localize the caption. */
+		caption = dgettext (provider->translation_domain, caption);
+
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter, 0, nick, 1, caption, -1);
+	}
+
+	g_strfreev (tokens);
+
+	combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+	gtk_combo_box_set_id_column (GTK_COMBO_BOX (combo), 0);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+	gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
+	gtk_widget_show (combo);
+
+	g_object_bind_property_full (
+		settings, entry->name,
+		combo, "active-id",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		e_binding_transform_enum_value_to_nick,
+		e_binding_transform_enum_nick_to_value,
+		NULL, (GDestroyNotify) NULL);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+	gtk_cell_layout_set_attributes (
+		GTK_CELL_LAYOUT (combo), renderer, "text", 1, NULL);
+
+	mail_config_provider_page_handle_dependency (page, entry, hbox);
+}
+
+static void
+mail_config_provider_page_add_widgets (EMailConfigProviderPage *page)
+{
+	EMailConfigServiceBackend *backend;
+	CamelProviderConfEntry *entries;
+	CamelProvider *provider;
+	GtkWidget *frame;
+	GtkWidget *widget;
+	gint ii;
+
+	/* Note the "text" member of each CamelProviderConfEntry is
+	 * already localized, so we can use it directly in widgets. */
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	provider = e_mail_config_service_backend_get_provider (backend);
+	g_return_if_fail (provider != NULL);
+
+	entries = provider->extra_conf;
+
+	/* Loop until we see CAMEL_PROVIDER_CONF_END. */
+	for (ii = 0; entries[ii].type != CAMEL_PROVIDER_CONF_END; ii++) {
+
+		/* Skip entries with no name. */
+		if (entries[ii].name == NULL)
+			continue;
+
+		switch (entries[ii].type) {
+			case CAMEL_PROVIDER_CONF_SECTION_START:
+				mail_config_provider_page_add_section (
+					page, &entries[ii]);
+				break;
+
+			case CAMEL_PROVIDER_CONF_CHECKBOX:
+				mail_config_provider_page_add_checkbox (
+					page, &entries[ii]);
+				break;
+
+			case CAMEL_PROVIDER_CONF_CHECKSPIN:
+				mail_config_provider_page_add_checkspin (
+					page, &entries[ii]);
+				break;
+
+			case CAMEL_PROVIDER_CONF_ENTRY:
+				mail_config_provider_page_add_entry (
+					page, &entries[ii]);
+				break;
+
+			case CAMEL_PROVIDER_CONF_OPTIONS:
+				mail_config_provider_page_add_options (
+					page, &entries[ii]);
+				break;
+
+			default:
+				break;  /* skip it */
+		}
+	}
+
+	/* So far only Evolution-EWS uses the activity and alert
+	 * bars, but other packages may someday find it handy. */
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_box_pack_end (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	/* Visibility is bound to the EActivityBar. */
+
+	frame = widget;
+
+	widget = e_activity_bar_new ();
+	gtk_container_add (GTK_CONTAINER (frame), widget);
+	page->priv->activity_bar = widget;  /* not referenced */
+	/* EActivity controls its own visibility. */
+
+	g_object_bind_property (
+		widget, "visible",
+		frame, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_box_pack_end (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	/* Visibility is bound to the EAlertBar. */
+
+	frame = widget;
+
+	widget = e_alert_bar_new ();
+	gtk_container_add (GTK_CONTAINER (frame), widget);
+	page->priv->alert_bar = widget;  /* not referenced */
+	/* EAlertBar controls its own visibility. */
+
+	g_object_bind_property (
+		widget, "visible",
+		frame, "visible",
+		G_BINDING_SYNC_CREATE);
+}
+
+static void
+mail_config_provider_page_set_backend (EMailConfigProviderPage *page,
+                                       EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+	g_return_if_fail (page->priv->backend == NULL);
+
+	page->priv->backend = g_object_ref (backend);
+}
+
+static void
+mail_config_provider_page_set_property (GObject *object,
+                                        guint property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			mail_config_provider_page_set_backend (
+				E_MAIL_CONFIG_PROVIDER_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_provider_page_get_property (GObject *object,
+                                        guint property_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_provider_page_get_backend (
+				E_MAIL_CONFIG_PROVIDER_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_provider_page_dispose (GObject *object)
+{
+	EMailConfigProviderPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (object);
+
+	if (priv->backend != NULL) {
+		g_object_unref (priv->backend);
+		priv->backend = NULL;
+	}
+
+	/* Chain up parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_provider_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_provider_page_constructed (GObject *object)
+{
+	EMailConfigProviderPage *page;
+	EMailConfigServiceBackend *backend;
+	CamelProvider *provider;
+
+	page = E_MAIL_CONFIG_PROVIDER_PAGE (object);
+
+	/* Chain up parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_provider_page_parent_class)->
+		constructed (object);
+
+	gtk_box_set_spacing (GTK_BOX (object), 6);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (object), GTK_ORIENTATION_VERTICAL);
+
+	backend = e_mail_config_provider_page_get_backend (page);
+	provider = e_mail_config_service_backend_get_provider (backend);
+
+	if (provider != NULL && provider->extra_conf != NULL)
+		mail_config_provider_page_add_widgets (page);
+	else
+		page->priv->is_empty = TRUE;
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+mail_config_provider_page_submit_alert (EAlertSink *alert_sink,
+                                        EAlert *alert)
+{
+	EMailConfigProviderPagePrivate *priv;
+	EAlertBar *alert_bar;
+	GtkWidget *dialog;
+	gpointer parent;
+
+	priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (alert_sink);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (alert_sink));
+	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+	switch (e_alert_get_message_type (alert)) {
+		case GTK_MESSAGE_INFO:
+		case GTK_MESSAGE_WARNING:
+		case GTK_MESSAGE_ERROR:
+			alert_bar = E_ALERT_BAR (priv->alert_bar);
+			e_alert_bar_add_alert (alert_bar, alert);
+			break;
+
+		default:
+			dialog = e_alert_dialog_new (parent, alert);
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+			break;
+	}
+}
+
+static void
+e_mail_config_provider_page_class_init (EMailConfigProviderPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigProviderPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_provider_page_set_property;
+	object_class->get_property = mail_config_provider_page_get_property;
+	object_class->dispose = mail_config_provider_page_dispose;
+	object_class->constructed = mail_config_provider_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_BACKEND,
+		g_param_spec_object (
+			"backend",
+			"Backend",
+			"Service backend to generate options from",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_provider_page_alert_sink_init (EAlertSinkInterface *interface)
+{
+	interface->submit_alert = mail_config_provider_page_submit_alert;
+}
+
+static void
+e_mail_config_provider_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Receiving Options");
+	interface->sort_order = E_MAIL_CONFIG_PROVIDER_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_provider_page_init (EMailConfigProviderPage *page)
+{
+	page->priv = E_MAIL_CONFIG_PROVIDER_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_provider_page_new (EMailConfigServiceBackend *backend)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_PROVIDER_PAGE,
+		"backend", backend, NULL);
+}
+
+gboolean
+e_mail_config_provider_page_is_empty (EMailConfigProviderPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), TRUE);
+
+	return page->priv->is_empty;
+}
+
+EMailConfigServiceBackend *
+e_mail_config_provider_page_get_backend (EMailConfigProviderPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), NULL);
+
+	return page->priv->backend;
+}
+
+EActivity *
+e_mail_config_provider_page_new_activity (EMailConfigProviderPage *page)
+{
+	EActivity *activity;
+	EActivityBar *activity_bar;
+	GCancellable *cancellable;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_PROVIDER_PAGE (page), NULL);
+
+	/* Clear any previous alerts. */
+	e_alert_bar_clear (E_ALERT_BAR (page->priv->alert_bar));
+
+	activity = e_activity_new ();
+
+	e_activity_set_alert_sink (activity, E_ALERT_SINK (page));
+
+	cancellable = camel_operation_new ();
+	e_activity_set_cancellable (activity, cancellable);
+	g_object_unref (cancellable);
+
+	activity_bar = E_ACTIVITY_BAR (page->priv->activity_bar);
+	e_activity_bar_set_activity (activity_bar, activity);
+
+	return activity;
+}
+
diff --git a/mail/e-mail-config-provider-page.h b/mail/e-mail-config-provider-page.h
new file mode 100644
index 0000000..fbbdf7f
--- /dev/null
+++ b/mail/e-mail-config-provider-page.h
@@ -0,0 +1,81 @@
+/*
+ * e-mail-config-provider-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_PROVIDER_PAGE_H
+#define E_MAIL_CONFIG_PROVIDER_PAGE_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+#include <libedataserver/e-source-registry.h>
+
+#include <e-util/e-activity.h>
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_PROVIDER_PAGE \
+	(e_mail_config_provider_page_get_type ())
+#define E_MAIL_CONFIG_PROVIDER_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPage))
+#define E_MAIL_CONFIG_PROVIDER_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPageClass))
+#define E_IS_MAIL_CONFIG_PROVIDER_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE))
+#define E_IS_MAIL_CONFIG_PROVIDER_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE))
+#define E_MAIL_CONFIG_PROVIDER_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_PROVIDER_PAGE, EMailConfigProviderPageClass))
+
+#define E_MAIL_CONFIG_PROVIDER_PAGE_SORT_ORDER (300)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigProviderPage EMailConfigProviderPage;
+typedef struct _EMailConfigProviderPageClass EMailConfigProviderPageClass;
+typedef struct _EMailConfigProviderPagePrivate EMailConfigProviderPagePrivate;
+
+struct _EMailConfigProviderPage {
+	GtkBox parent;
+	EMailConfigProviderPagePrivate *priv;
+};
+
+struct _EMailConfigProviderPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_provider_page_get_type
+					(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_provider_page_new
+					(EMailConfigServiceBackend *backend);
+gboolean	e_mail_config_provider_page_is_empty
+					(EMailConfigProviderPage *page);
+EMailConfigServiceBackend *
+		e_mail_config_provider_page_get_backend
+					(EMailConfigProviderPage *page);
+EActivity *	e_mail_config_provider_page_new_activity
+					(EMailConfigProviderPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_PROVIDER_PAGE_H */
diff --git a/mail/e-mail-config-receiving-page.c b/mail/e-mail-config-receiving-page.c
new file mode 100644
index 0000000..7106f20
--- /dev/null
+++ b/mail/e-mail-config-receiving-page.c
@@ -0,0 +1,70 @@
+/*
+ * e-mail-config-receiving-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-receiving-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-mail-account.h>
+
+/* Forward Declarations */
+static void	e_mail_config_receiving_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigReceivingPage,
+	e_mail_config_receiving_page,
+	E_TYPE_MAIL_CONFIG_SERVICE_PAGE,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_receiving_page_interface_init))
+
+static void
+e_mail_config_receiving_page_class_init (EMailConfigReceivingPageClass *class)
+{
+	EMailConfigServicePageClass *service_page_class;
+
+	service_page_class = E_MAIL_CONFIG_SERVICE_PAGE_CLASS (class);
+	service_page_class->extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	service_page_class->provider_type = CAMEL_PROVIDER_STORE;
+	service_page_class->default_backend_name = "imapx";
+}
+
+static void
+e_mail_config_receiving_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Receiving Email");
+	interface->sort_order = E_MAIL_CONFIG_RECEIVING_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_receiving_page_init (EMailConfigReceivingPage *page)
+{
+}
+
+EMailConfigPage *
+e_mail_config_receiving_page_new (ESourceRegistry *registry)
+{
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_RECEIVING_PAGE,
+		"registry", registry, NULL);
+}
+
diff --git a/mail/e-mail-config-receiving-page.h b/mail/e-mail-config-receiving-page.h
new file mode 100644
index 0000000..626da30
--- /dev/null
+++ b/mail/e-mail-config-receiving-page.h
@@ -0,0 +1,69 @@
+/*
+ * e-mail-config-receiving-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_RECEIVING_PAGE_H
+#define E_MAIL_CONFIG_RECEIVING_PAGE_H
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-service-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_RECEIVING_PAGE \
+	(e_mail_config_receiving_page_get_type ())
+#define E_MAIL_CONFIG_RECEIVING_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, EMailConfigReceivingPage))
+#define E_MAIL_CONFIG_RECEIVING_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, EMailConfigReceivingPageClass))
+#define E_IS_MAIL_CONFIG_RECEIVING_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE))
+#define E_IS_MAIL_CONFIG_RECEIVING_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE))
+#define E_MAIL_CONFIG_RECEIVING_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_RECEIVING_PAGE, EMailConfigReceivingPageClass))
+
+#define E_MAIL_CONFIG_RECEIVING_PAGE_SORT_ORDER (200)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigReceivingPage EMailConfigReceivingPage;
+typedef struct _EMailConfigReceivingPageClass EMailConfigReceivingPageClass;
+typedef struct _EMailConfigReceivingPagePrivate EMailConfigReceivingPagePrivate;
+
+struct _EMailConfigReceivingPage {
+	EMailConfigServicePage parent;
+};
+
+struct _EMailConfigReceivingPageClass {
+	EMailConfigServicePageClass parent_class;
+};
+
+GType		e_mail_config_receiving_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_receiving_page_new
+						(ESourceRegistry *registry);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_RECEIVING_PAGE_H */
+
diff --git a/mail/e-mail-config-security-page.c b/mail/e-mail-config-security-page.c
new file mode 100644
index 0000000..911e40b
--- /dev/null
+++ b/mail/e-mail-config-security-page.c
@@ -0,0 +1,672 @@
+/*
+ * e-mail-config-security-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-security-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-openpgp.h>
+#include <libedataserver/e-source-smime.h>
+
+#if defined (HAVE_NSS)
+#include <smime/gui/e-cert-selector.h>
+#endif /* HAVE_NSS */
+
+#define E_MAIL_CONFIG_SECURITY_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPagePrivate))
+
+struct _EMailConfigSecurityPagePrivate {
+	ESource *identity_source;
+};
+
+enum {
+	PROP_0,
+	PROP_IDENTITY_SOURCE
+};
+
+/* Forward Declarations */
+static void	e_mail_config_security_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigSecurityPage,
+	e_mail_config_security_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_security_page_interface_init))
+
+static gboolean
+mail_config_security_page_string_has_text (GBinding *binding,
+                                           const GValue *source_value,
+                                           GValue *target_value,
+                                           gpointer unused)
+{
+	const gchar *string;
+	gchar *stripped;
+
+	string = g_value_get_string (source_value);
+
+	if (string == NULL)
+		string = "";
+
+	stripped = g_strstrip (g_strdup (string));
+	g_value_set_boolean (target_value, *stripped != '\0');
+	g_free (stripped);
+
+	return TRUE;
+}
+
+static void
+mail_config_security_page_cert_selected (ECertSelector *selector,
+                                         const gchar *key,
+                                         GtkEntry *entry)
+{
+	if (key != NULL)
+		gtk_entry_set_text (entry, key);
+
+	gtk_widget_destroy (GTK_WIDGET (selector));
+}
+
+static void
+mail_config_security_page_select_encrypt_cert (GtkButton *button,
+                                               GtkEntry *entry)
+{
+	GtkWidget *selector;
+	gpointer parent;
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
+	parent = GTK_IS_WIDGET (parent) ? parent : NULL;
+
+	selector = e_cert_selector_new (
+		E_CERT_SELECTOR_RECIPIENT,
+		gtk_entry_get_text (entry));
+	gtk_window_set_transient_for (
+		GTK_WINDOW (selector), parent);
+	gtk_widget_show (selector);
+
+	g_signal_connect (
+		selector, "selected",
+		G_CALLBACK (mail_config_security_page_cert_selected),
+		entry);
+}
+
+static void
+mail_config_security_page_select_sign_cert (GtkButton *button,
+                                            GtkEntry *entry)
+{
+	GtkWidget *selector;
+	gpointer parent;
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
+	parent = GTK_IS_WIDGET (parent) ? parent : NULL;
+
+	selector = e_cert_selector_new (
+		E_CERT_SELECTOR_SIGNER,
+		gtk_entry_get_text (entry));
+	gtk_window_set_transient_for (
+		GTK_WINDOW (selector), parent);
+	gtk_widget_show (selector);
+
+	g_signal_connect (
+		selector, "selected",
+		G_CALLBACK (mail_config_security_page_cert_selected),
+		entry);
+}
+
+static void
+mail_config_security_page_clear_cert (GtkButton *button,
+                                      GtkEntry *entry)
+{
+	gtk_entry_set_text (entry, "");
+}
+
+static void
+mail_config_security_page_set_identity_source (EMailConfigSecurityPage *page,
+                                               ESource *identity_source)
+{
+	g_return_if_fail (E_IS_SOURCE (identity_source));
+	g_return_if_fail (page->priv->identity_source == NULL);
+
+	page->priv->identity_source = g_object_ref (identity_source);
+}
+
+static void
+mail_config_security_page_set_property (GObject *object,
+                                        guint property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_IDENTITY_SOURCE:
+			mail_config_security_page_set_identity_source (
+				E_MAIL_CONFIG_SECURITY_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_security_page_get_property (GObject *object,
+                                        guint property_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_security_page_get_identity_source (
+				E_MAIL_CONFIG_SECURITY_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_security_page_dispose (GObject *object)
+{
+	EMailConfigSecurityPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_SECURITY_PAGE_GET_PRIVATE (object);
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_security_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_security_page_constructed (GObject *object)
+{
+	EMailConfigSecurityPage *page;
+	ESource *source;
+	ESourceMailComposition *composition_ext;
+	ESourceOpenPGP *openpgp_ext;
+	GtkEntry *entry;
+	GtkLabel *label;
+	GtkWidget *widget;
+	GtkWidget *container;
+	GtkSizeGroup *size_group;
+	const gchar *extension_name;
+	const gchar *text;
+	gchar *markup;
+
+#if defined (HAVE_NSS)
+	ESourceSMIME *smime_ext;
+#endif /* HAVE_NSS */
+
+	page = E_MAIL_CONFIG_SECURITY_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_security_page_parent_class)->
+		constructed (object);
+
+	source = e_mail_config_security_page_get_identity_source (page);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	composition_ext = e_source_get_extension (source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_OPENPGP;
+	openpgp_ext = e_source_get_extension (source, extension_name);
+
+#if defined (HAVE_NSS)
+	extension_name = E_SOURCE_EXTENSION_SMIME;
+	smime_ext = e_source_get_extension (source, extension_name);
+#endif /* HAVE_NSS */
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+	/*** General ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("General");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	gtk_widget_show (widget);
+
+	text = _("_Do not sign meeting requests (for Outlook compatibility)");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		composition_ext, "sign-imip",
+		widget, "active",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/*** Pretty Good Privacy (OpenPGP) ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Pretty Good Privacy (OpenPGP)");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	gtk_widget_show (widget);
+
+	text = _("OpenPGP _Key ID:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		openpgp_ext, "key-id",
+		widget, "text",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	text = _("Si_gning algorithm:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_combo_box_text_new ();
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"", _("Default"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha1", _("SHA1"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha256", _("SHA256"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha384", _("SHA384"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha512", _("SHA512"));
+	gtk_widget_set_halign (widget, GTK_ALIGN_START);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		openpgp_ext, "signing-algorithm",
+		widget, "active-id",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	/* Make sure the combo box has an active item. */
+	if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget)) == NULL)
+		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
+	text = _("Al_ways sign outgoing messages when using this account");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 2, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		openpgp_ext, "sign-by-default",
+		widget, "active",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	text = _("Always encrypt to _myself when sending encrypted messages");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 2, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		openpgp_ext, "encrypt-to-self",
+		widget, "active",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	text = _("Always _trust keys in my keyring when encrypting");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 2, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		openpgp_ext, "always-trust",
+		widget, "active",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+#if defined (HAVE_NSS)
+
+	/*** Security MIME (S/MIME) ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Secure MIME (S/MIME)");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 4, 1);
+	gtk_widget_show (widget);
+
+	text = _("Sig_ning certificate:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		smime_ext, "signing-certificate",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	entry = GTK_ENTRY (widget);
+
+	widget = gtk_button_new_with_label (_("Select"));
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_security_page_select_sign_cert),
+		entry);
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_CLEAR);
+	gtk_grid_attach (GTK_GRID (container), widget, 3, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_security_page_clear_cert),
+		entry);
+
+	text = _("Signing _algorithm:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_combo_box_text_new ();
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"", _("Default"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha1", _("SHA1"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha256", _("SHA256"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha384", _("SHA384"));
+	gtk_combo_box_text_append (
+		GTK_COMBO_BOX_TEXT (widget),
+		"sha512", _("SHA512"));
+	gtk_widget_set_halign (widget, GTK_ALIGN_START);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		smime_ext, "signing-algorithm",
+		widget, "active-id",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	/* Make sure the combo box has an active item. */
+	if (gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget)) == NULL)
+		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
+	text = _("Always sign outgoing messages when using this account");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 4, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		smime_ext, "sign-by-default",
+		widget, "active",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	g_object_bind_property_full (
+		smime_ext, "signing-certificate",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE,
+		mail_config_security_page_string_has_text,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	/* Add extra padding between signing stuff and encryption stuff. */
+	gtk_widget_set_margin_bottom (widget, 6);
+
+	text = _("Encryption certificate:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		smime_ext, "encryption-certificate",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	entry = GTK_ENTRY (widget);
+
+	widget = gtk_button_new_with_label (_("Select"));
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_security_page_select_encrypt_cert),
+		entry);
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_CLEAR);
+	gtk_grid_attach (GTK_GRID (container), widget, 3, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_security_page_clear_cert),
+		entry);
+
+	text = _("Always encrypt outgoing messages when using this account");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 4, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		smime_ext, "encrypt-by-default",
+		widget, "active",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	g_object_bind_property_full (
+		smime_ext, "encryption-certificate",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE,
+		mail_config_security_page_string_has_text,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	text = _("Always encrypt to myself when sending encrypted messages");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 6, 4, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		smime_ext, "encrypt-to-self",
+		widget, "active",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL);
+
+	g_object_bind_property_full (
+		smime_ext, "encryption-certificate",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE,
+		mail_config_security_page_string_has_text,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+#endif /* HAVE_NSS */
+
+	g_object_unref (size_group);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+e_mail_config_security_page_class_init (EMailConfigSecurityPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigSecurityPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_security_page_set_property;
+	object_class->get_property = mail_config_security_page_get_property;
+	object_class->dispose = mail_config_security_page_dispose;
+	object_class->constructed = mail_config_security_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_security_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Security");
+	interface->sort_order = E_MAIL_CONFIG_SECURITY_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_security_page_init (EMailConfigSecurityPage *page)
+{
+	page->priv = E_MAIL_CONFIG_SECURITY_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_security_page_new (ESource *identity_source)
+{
+	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_SECURITY_PAGE,
+		"identity-source", identity_source, NULL);
+}
+
+ESource *
+e_mail_config_security_page_get_identity_source (EMailConfigSecurityPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SECURITY_PAGE (page), NULL);
+
+	return page->priv->identity_source;
+}
+
diff --git a/mail/e-mail-config-security-page.h b/mail/e-mail-config-security-page.h
new file mode 100644
index 0000000..79174ea
--- /dev/null
+++ b/mail/e-mail-config-security-page.h
@@ -0,0 +1,73 @@
+/*
+ * e-mail-config-security-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_SECURITY_PAGE_H
+#define E_MAIL_CONFIG_SECURITY_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SECURITY_PAGE \
+	(e_mail_config_security_page_get_type ())
+#define E_MAIL_CONFIG_SECURITY_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPage))
+#define E_MAIL_CONFIG_SECURITY_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPageClass))
+#define E_IS_MAIL_CONFIG_SECURITY_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE))
+#define E_IS_MAIL_CONFIG_SECURITY_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SECURITY_PAGE))
+#define E_MAIL_CONFIG_SECURITY_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SECURITY_PAGE, EMailConfigSecurityPageClass))
+
+#define E_MAIL_CONFIG_SECURITY_PAGE_SORT_ORDER (600)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigSecurityPage EMailConfigSecurityPage;
+typedef struct _EMailConfigSecurityPageClass EMailConfigSecurityPageClass;
+typedef struct _EMailConfigSecurityPagePrivate EMailConfigSecurityPagePrivate;
+
+struct _EMailConfigSecurityPage {
+	GtkBox parent;
+	EMailConfigSecurityPagePrivate *priv;
+};
+
+struct _EMailConfigSecurityPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_security_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_security_page_new	(ESource *identity_source);
+ESource *	e_mail_config_security_page_get_identity_source
+						(EMailConfigSecurityPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_SECURITY_PAGE_H */
+
diff --git a/mail/e-mail-config-sending-page.c b/mail/e-mail-config-sending-page.c
new file mode 100644
index 0000000..198a3ea
--- /dev/null
+++ b/mail/e-mail-config-sending-page.c
@@ -0,0 +1,70 @@
+/*
+ * e-mail-config-sending-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-sending-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-mail-transport.h>
+
+/* Forward Declarations */
+static void	e_mail_config_sending_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigSendingPage,
+	e_mail_config_sending_page,
+	E_TYPE_MAIL_CONFIG_SERVICE_PAGE,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_sending_page_interface_init))
+
+static void
+e_mail_config_sending_page_class_init (EMailConfigSendingPageClass *class)
+{
+	EMailConfigServicePageClass *service_page_class;
+
+	service_page_class = E_MAIL_CONFIG_SERVICE_PAGE_CLASS (class);
+	service_page_class->extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+	service_page_class->provider_type = CAMEL_PROVIDER_TRANSPORT;
+	service_page_class->default_backend_name = "smtp";
+}
+
+static void
+e_mail_config_sending_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Sending Email");
+	interface->sort_order = E_MAIL_CONFIG_SENDING_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_sending_page_init (EMailConfigSendingPage *page)
+{
+}
+
+EMailConfigPage *
+e_mail_config_sending_page_new (ESourceRegistry *registry)
+{
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_SENDING_PAGE,
+		"registry", registry, NULL);
+}
+
diff --git a/mail/e-mail-config-sending-page.h b/mail/e-mail-config-sending-page.h
new file mode 100644
index 0000000..4727602
--- /dev/null
+++ b/mail/e-mail-config-sending-page.h
@@ -0,0 +1,68 @@
+/*
+ * e-mail-config-sending-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_SENDING_PAGE_H
+#define E_MAIL_CONFIG_SENDING_PAGE_H
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-service-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SENDING_PAGE \
+	(e_mail_config_sending_page_get_type ())
+#define E_MAIL_CONFIG_SENDING_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SENDING_PAGE, EMailConfigSendingPage))
+#define E_MAIL_CONFIG_SENDING_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SENDING_PAGE, EMailConfigSendingPageClass))
+#define E_IS_MAIL_CONFIG_SENDING_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SENDING_PAGE))
+#define E_IS_MAIL_CONFIG_SENDING_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SENDING_PAGE))
+#define E_MAIL_CONFIG_SENDING_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SENDING_PAGE, EMailConfigSendingPageClass))
+
+#define E_MAIL_CONFIG_SENDING_PAGE_SORT_ORDER (400)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigSendingPage EMailConfigSendingPage;
+typedef struct _EMailConfigSendingPageClass EMailConfigSendingPageClass;
+typedef struct _EMailConfigSendingPagePrivate EMailConfigSendingPagePrivate;
+
+struct _EMailConfigSendingPage {
+	EMailConfigServicePage parent;
+};
+
+struct _EMailConfigSendingPageClass {
+	EMailConfigServicePageClass parent_class;
+};
+
+GType		e_mail_config_sending_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_sending_page_new	(ESourceRegistry *registry);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_SENDING_PAGE_H */
+
diff --git a/mail/e-mail-config-service-backend.c b/mail/e-mail-config-service-backend.c
new file mode 100644
index 0000000..fb86db2
--- /dev/null
+++ b/mail/e-mail-config-service-backend.c
@@ -0,0 +1,477 @@
+/*
+ * e-mail-config-service-backend.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-service-backend.h"
+
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-backend.h>
+#include <libedataserver/e-source-collection.h>
+
+#include <mail/e-mail-config-receiving-page.h>
+#include <mail/e-mail-config-sending-page.h>
+
+#define E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendPrivate))
+
+struct _EMailConfigServiceBackendPrivate {
+	ESource *source;
+	ESource *collection;
+};
+
+enum {
+	PROP_0,
+	PROP_COLLECTION,
+	PROP_SELECTABLE,
+	PROP_SOURCE
+};
+
+G_DEFINE_ABSTRACT_TYPE (
+	EMailConfigServiceBackend,
+	e_mail_config_service_backend,
+	E_TYPE_EXTENSION)
+
+static void
+mail_config_service_backend_init_collection (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+
+	/* Use the new_collection() method to initialize the "collection"
+	 * property.  This assumes we're editing a new account.  If we're
+	 * editing an existing account, the initial "collection" property
+	 * value should be overridden with the existing collection source. */
+
+	g_return_if_fail (backend->priv->collection == NULL);
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_if_fail (class->new_collection != NULL);
+
+	backend->priv->collection = class->new_collection (backend);
+}
+
+static void
+mail_config_service_backend_set_property (GObject *object,
+                                          guint property_id,
+                                          const GValue *value,
+                                          GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_COLLECTION:
+			e_mail_config_service_backend_set_collection (
+				E_MAIL_CONFIG_SERVICE_BACKEND (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SOURCE:
+			e_mail_config_service_backend_set_source (
+				E_MAIL_CONFIG_SERVICE_BACKEND (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_service_backend_get_property (GObject *object,
+                                          guint property_id,
+                                          GValue *value,
+                                          GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_COLLECTION:
+			g_value_set_object (
+				value,
+				e_mail_config_service_backend_get_collection (
+				E_MAIL_CONFIG_SERVICE_BACKEND (object)));
+			return;
+
+		case PROP_SELECTABLE:
+			g_value_set_boolean (
+				value,
+				e_mail_config_service_backend_get_selectable (
+				E_MAIL_CONFIG_SERVICE_BACKEND (object)));
+			return;
+
+		case PROP_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_service_backend_get_source (
+				E_MAIL_CONFIG_SERVICE_BACKEND (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_service_backend_dispose (GObject *object)
+{
+	EMailConfigServiceBackendPrivate *priv;
+
+	priv = E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE (object);
+
+	if (priv->source != NULL) {
+		g_object_unref (priv->source);
+		priv->source = NULL;
+	}
+
+	if (priv->collection != NULL) {
+		g_object_unref (priv->collection);
+		priv->collection = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_service_backend_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_service_backend_constructed (GObject *object)
+{
+	EMailConfigServiceBackend *backend;
+
+	backend = E_MAIL_CONFIG_SERVICE_BACKEND (object);
+	mail_config_service_backend_init_collection (backend);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_service_backend_parent_class)->
+		constructed (object);
+}
+
+static gboolean
+mail_config_service_backend_get_selectable (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServicePage *page;
+	CamelProvider *provider;
+	gboolean selectable = TRUE;
+
+	page = e_mail_config_service_backend_get_page (backend);
+	provider = e_mail_config_service_backend_get_provider (backend);
+
+	if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider))
+		selectable = E_IS_MAIL_CONFIG_RECEIVING_PAGE (page);
+
+	return selectable;
+}
+
+static ESource *
+mail_config_service_backend_new_collection (EMailConfigServiceBackend *backend)
+{
+	/* This is typically only used for groupware backends. */
+	return NULL;
+}
+
+static void
+mail_config_service_backend_insert_widgets (EMailConfigServiceBackend *backend,
+                                            GtkBox *parent)
+{
+	/* does nothing */
+}
+
+static void
+mail_config_service_backend_setup_defaults (EMailConfigServiceBackend *backend)
+{
+	/* does nothing */
+}
+
+static gboolean
+mail_config_service_backend_auto_configure (EMailConfigServiceBackend *backend,
+                                            EMailAutoconfig *autoconfig)
+{
+	return FALSE;
+}
+
+static gboolean
+mail_config_service_backend_check_complete (EMailConfigServiceBackend *backend)
+{
+	return TRUE;
+}
+
+static void
+mail_config_service_backend_commit_changes (EMailConfigServiceBackend *backend)
+{
+	/* does nothing */
+}
+
+static void
+e_mail_config_service_backend_class_init (EMailConfigServiceBackendClass *class)
+{
+	GObjectClass *object_class;
+	EExtensionClass *extension_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigServiceBackendPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_service_backend_set_property;
+	object_class->get_property = mail_config_service_backend_get_property;
+	object_class->dispose = mail_config_service_backend_dispose;
+	object_class->constructed = mail_config_service_backend_constructed;
+
+	extension_class = E_EXTENSION_CLASS (class);
+	extension_class->extensible_type = E_TYPE_MAIL_CONFIG_SERVICE_PAGE;
+
+	class->get_selectable = mail_config_service_backend_get_selectable;
+	class->new_collection = mail_config_service_backend_new_collection;
+	class->insert_widgets = mail_config_service_backend_insert_widgets;
+	class->setup_defaults = mail_config_service_backend_setup_defaults;
+	class->auto_configure = mail_config_service_backend_auto_configure;
+	class->check_complete = mail_config_service_backend_check_complete;
+	class->commit_changes = mail_config_service_backend_commit_changes;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_COLLECTION,
+		g_param_spec_object (
+			"collection",
+			"Collection",
+			"Optional collection ESource",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SELECTABLE,
+		g_param_spec_boolean (
+			"selectable",
+			"Selectable",
+			"Whether the backend is user selectable",
+			TRUE,  /* not applied */
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SOURCE,
+		g_param_spec_object (
+			"source",
+			"Source",
+			"The ESource being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_service_backend_init (EMailConfigServiceBackend *backend)
+{
+	backend->priv = E_MAIL_CONFIG_SERVICE_BACKEND_GET_PRIVATE (backend);
+}
+
+EMailConfigServicePage *
+e_mail_config_service_backend_get_page (EMailConfigServiceBackend *backend)
+{
+	EExtensible *extensible;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	extensible = e_extension_get_extensible (E_EXTENSION (backend));
+
+	return E_MAIL_CONFIG_SERVICE_PAGE (extensible);
+}
+
+ESource *
+e_mail_config_service_backend_get_source (EMailConfigServiceBackend *backend)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	return backend->priv->source;
+}
+
+void
+e_mail_config_service_backend_set_source (EMailConfigServiceBackend *backend,
+                                          ESource *source)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+
+	if (source != NULL) {
+		g_return_if_fail (E_IS_SOURCE (source));
+		g_object_ref (source);
+	}
+
+	if (backend->priv->source != NULL)
+		g_object_unref (backend->priv->source);
+
+	backend->priv->source = source;
+
+	g_object_notify (G_OBJECT (backend), "source");
+}
+
+ESource *
+e_mail_config_service_backend_get_collection (EMailConfigServiceBackend *backend)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	return backend->priv->collection;
+}
+
+void
+e_mail_config_service_backend_set_collection (EMailConfigServiceBackend *backend,
+                                              ESource *collection)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+
+	if (collection != NULL) {
+		g_return_if_fail (E_IS_SOURCE (collection));
+		g_object_ref (collection);
+	}
+
+	if (backend->priv->collection != NULL)
+		g_object_unref (backend->priv->collection);
+
+	backend->priv->collection = collection;
+
+	g_object_notify (G_OBJECT (backend), "collection");
+}
+
+CamelProvider *
+e_mail_config_service_backend_get_provider (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_val_if_fail (class->backend_name != NULL, NULL);
+
+	return camel_provider_get (class->backend_name, NULL);
+}
+
+CamelSettings *
+e_mail_config_service_backend_get_settings (EMailConfigServiceBackend *backend)
+{
+	ESource *source;
+	ESourceCamel *camel_extension;
+	ESourceBackend *backend_extension;
+	EMailConfigServicePage *page;
+	EMailConfigServicePageClass *page_class;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	source = e_mail_config_service_backend_get_source (backend);
+
+	page = e_mail_config_service_backend_get_page (backend);
+	page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page);
+
+	/* The provider-specific settings live in the collection source
+	 * if the service backend defines one, or else they live in the
+	 * scratch source we were given. */
+	source = e_mail_config_service_backend_get_collection (backend);
+	if (source != NULL) {
+		extension_name = E_SOURCE_EXTENSION_COLLECTION;
+	} else {
+		extension_name = page_class->extension_name;
+		source = e_mail_config_service_backend_get_source (backend);
+	}
+	g_return_val_if_fail (source != NULL, NULL);
+
+	backend_extension = e_source_get_extension (source, extension_name);
+	backend_name = e_source_backend_get_backend_name (backend_extension);
+
+	extension_name = e_source_camel_get_extension_name (backend_name);
+	camel_extension = e_source_get_extension (source, extension_name);
+
+	return e_source_camel_get_settings (camel_extension);
+}
+
+gboolean
+e_mail_config_service_backend_get_selectable (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_val_if_fail (class->get_selectable != NULL, FALSE);
+
+	return class->get_selectable (backend);
+}
+
+void
+e_mail_config_service_backend_insert_widgets (EMailConfigServiceBackend *backend,
+                                              GtkBox *parent)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+	g_return_if_fail (GTK_IS_BOX (parent));
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_if_fail (class->insert_widgets != NULL);
+
+	class->insert_widgets (backend, parent);
+}
+
+void
+e_mail_config_service_backend_setup_defaults (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_if_fail (class->setup_defaults != NULL);
+
+	return class->setup_defaults (backend);
+}
+
+gboolean
+e_mail_config_service_backend_auto_configure (EMailConfigServiceBackend *backend,
+                                              EMailAutoconfig *autoconfig)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
+	g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), FALSE);
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_val_if_fail (class->auto_configure != NULL, FALSE);
+
+	return class->auto_configure (backend, autoconfig);
+}
+
+gboolean
+e_mail_config_service_backend_check_complete (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), FALSE);
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_val_if_fail (class->check_complete != NULL, FALSE);
+
+	return class->check_complete (backend);
+}
+
+void
+e_mail_config_service_backend_commit_changes (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_return_if_fail (class->commit_changes != NULL);
+
+	class->commit_changes (backend);
+}
+
diff --git a/mail/e-mail-config-service-backend.h b/mail/e-mail-config-service-backend.h
new file mode 100644
index 0000000..6ba4ad3
--- /dev/null
+++ b/mail/e-mail-config-service-backend.h
@@ -0,0 +1,121 @@
+/*
+ * e-mail-config-service-backend.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_SERVICE_BACKEND_H
+#define E_MAIL_CONFIG_SERVICE_BACKEND_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+#include <libebackend/e-extension.h>
+#include <libedataserver/e-source.h>
+
+#include <mail/e-mail-autoconfig.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SERVICE_BACKEND \
+	(e_mail_config_service_backend_get_type ())
+#define E_MAIL_CONFIG_SERVICE_BACKEND(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackend))
+#define E_MAIL_CONFIG_SERVICE_BACKEND_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendClass))
+#define E_IS_MAIL_CONFIG_SERVICE_BACKEND(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND))
+#define E_IS_MAIL_CONFIG_SERVICE_BACKEND_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND))
+#define E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND, EMailConfigServiceBackendClass))
+
+G_BEGIN_DECLS
+
+struct _EMailConfigServicePage;
+
+typedef struct _EMailConfigServiceBackend EMailConfigServiceBackend;
+typedef struct _EMailConfigServiceBackendClass EMailConfigServiceBackendClass;
+typedef struct _EMailConfigServiceBackendPrivate EMailConfigServiceBackendPrivate;
+
+struct _EMailConfigServiceBackend {
+	EExtension parent;
+	EMailConfigServiceBackendPrivate *priv;
+};
+
+struct _EMailConfigServiceBackendClass {
+	EExtensionClass parent_class;
+
+	const gchar *backend_name;
+
+	gboolean	(*get_selectable)
+					(EMailConfigServiceBackend *backend);
+	ESource *	(*new_collection)
+					(EMailConfigServiceBackend *backend);
+	void		(*insert_widgets)
+					(EMailConfigServiceBackend *backend,
+					 GtkBox *parent);
+	void		(*setup_defaults)
+					(EMailConfigServiceBackend *backend);
+	gboolean	(*auto_configure)
+					(EMailConfigServiceBackend *backend,
+					 EMailAutoconfig *autoconfig);
+	gboolean	(*check_complete)
+					(EMailConfigServiceBackend *backend);
+	void		(*commit_changes)
+					(EMailConfigServiceBackend *backend);
+};
+
+GType		e_mail_config_service_backend_get_type
+					(void) G_GNUC_CONST;
+struct _EMailConfigServicePage *
+		e_mail_config_service_backend_get_page
+					(EMailConfigServiceBackend *backend);
+ESource *	e_mail_config_service_backend_get_source
+					(EMailConfigServiceBackend *backend);
+void		e_mail_config_service_backend_set_source
+					(EMailConfigServiceBackend *backend,
+					 ESource *source);
+ESource *	e_mail_config_service_backend_get_collection
+					(EMailConfigServiceBackend *backend);
+void		e_mail_config_service_backend_set_collection
+					(EMailConfigServiceBackend *backend,
+					 ESource *collection);
+CamelProvider *	e_mail_config_service_backend_get_provider
+					(EMailConfigServiceBackend *backend);
+CamelSettings *	e_mail_config_service_backend_get_settings
+					(EMailConfigServiceBackend *backend);
+gboolean	e_mail_config_service_backend_get_selectable
+					(EMailConfigServiceBackend *backend);
+void		e_mail_config_service_backend_insert_widgets
+					(EMailConfigServiceBackend *backend,
+					 GtkBox *parent);
+void		e_mail_config_service_backend_setup_defaults
+					(EMailConfigServiceBackend *backend);
+gboolean	e_mail_config_service_backend_auto_configure
+					(EMailConfigServiceBackend *backend,
+					 EMailAutoconfig *autoconfig);
+gboolean	e_mail_config_service_backend_check_complete
+					(EMailConfigServiceBackend *backend);
+void		e_mail_config_service_backend_commit_changes
+					(EMailConfigServiceBackend *backend);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_SERVICE_BACKEND_H */
+
diff --git a/mail/e-mail-config-service-notebook.c b/mail/e-mail-config-service-notebook.c
new file mode 100644
index 0000000..757cd90
--- /dev/null
+++ b/mail/e-mail-config-service-notebook.c
@@ -0,0 +1,365 @@
+/*
+ * e-mail-config-service-notebook.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-service-notebook.h"
+
+#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookPrivate))
+
+#define CHILD_BACKEND_KEY_FORMAT \
+	"__e_mail_config_service_notebook_%p_child_backend__"
+
+struct _EMailConfigServiceNotebookPrivate {
+	EMailConfigServiceBackend *active_backend;
+	gchar *child_backend_key;
+};
+
+enum {
+	PROP_0,
+	PROP_ACTIVE_BACKEND
+};
+
+enum {
+	PROP_CHILD_0,
+	PROP_CHILD_BACKEND
+};
+
+G_DEFINE_TYPE (
+	EMailConfigServiceNotebook,
+	e_mail_config_service_notebook,
+	GTK_TYPE_NOTEBOOK)
+
+static void
+mail_config_service_notebook_set_child_backend (EMailConfigServiceNotebook *notebook,
+                                                GtkWidget *child,
+                                                EMailConfigServiceBackend *backend)
+{
+	const gchar *key;
+
+	key = notebook->priv->child_backend_key;
+
+	if (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend))
+		g_object_set_data_full (
+			G_OBJECT (child), key,
+			g_object_ref (backend),
+			(GDestroyNotify) g_object_unref);
+}
+
+static EMailConfigServiceBackend *
+mail_config_service_notebook_get_child_backend (EMailConfigServiceNotebook *notebook,
+                                                GtkWidget *child)
+{
+	const gchar *key;
+
+	key = notebook->priv->child_backend_key;
+
+	return g_object_get_data (G_OBJECT (child), key);
+}
+
+static gboolean
+mail_config_service_notebook_page_num_to_backend (GBinding *binding,
+                                                  const GValue *source_value,
+                                                  GValue *target_value,
+                                                  gpointer user_data)
+{
+	EMailConfigServiceBackend *backend;
+	GtkNotebook *notebook;
+	GtkWidget *child;
+	gint page_num;
+
+	/* The binding's source and target are the same instance. */
+	notebook = GTK_NOTEBOOK (g_binding_get_source (binding));
+
+	page_num = g_value_get_int (source_value);
+	child = gtk_notebook_get_nth_page (notebook, page_num);
+
+	if (child != NULL)
+		backend = mail_config_service_notebook_get_child_backend (
+			E_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), child);
+	else
+		backend = NULL;
+
+	g_value_set_object (target_value, backend);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_service_notebook_backend_to_page_num (GBinding *binding,
+                                                  const GValue *source_value,
+                                                  GValue *target_value,
+                                                  gpointer user_data)
+{
+	EMailConfigServiceBackend *backend;
+	GtkNotebook *notebook;
+	gint n_pages, ii;
+
+	/* The binding's source and target are the same instance. */
+	notebook = GTK_NOTEBOOK (g_binding_get_source (binding));
+
+	backend = g_value_get_object (source_value);
+	n_pages = gtk_notebook_get_n_pages (notebook);
+
+	for (ii = 0; ii < n_pages; ii++) {
+		GtkWidget *child;
+		EMailConfigServiceBackend *candidate;
+
+		child = gtk_notebook_get_nth_page (notebook, ii);
+		candidate = mail_config_service_notebook_get_child_backend (
+			E_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), child);
+
+		if (backend == candidate) {
+			g_value_set_int (target_value, ii);
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static void
+mail_config_service_notebook_set_property (GObject *object,
+                                           guint property_id,
+                                           const GValue *value,
+                                           GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE_BACKEND:
+			e_mail_config_service_notebook_set_active_backend (
+				E_MAIL_CONFIG_SERVICE_NOTEBOOK (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_service_notebook_get_property (GObject *object,
+                                           guint property_id,
+                                           GValue *value,
+                                           GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_service_notebook_get_active_backend (
+				E_MAIL_CONFIG_SERVICE_NOTEBOOK (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_service_notebook_dispose (GObject *object)
+{
+	EMailConfigServiceNotebookPrivate *priv;
+
+	priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (object);
+
+	if (priv->active_backend != NULL) {
+		g_object_unref (priv->active_backend);
+		priv->active_backend = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_service_notebook_finalize (GObject *object)
+{
+	EMailConfigServiceNotebookPrivate *priv;
+
+	priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (object);
+
+	g_free (priv->child_backend_key);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)->
+		finalize (object);
+}
+
+static void
+mail_config_service_notebook_constructed (GObject *object)
+{
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_service_notebook_parent_class)->
+		constructed (object);
+
+	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (object), FALSE);
+
+	/* Current page is still -1 so skip G_BINDING_SYNC_CREATE. */
+	g_object_bind_property_full (
+		object, "page",
+		object, "active-backend",
+		G_BINDING_BIDIRECTIONAL,
+		mail_config_service_notebook_page_num_to_backend,
+		mail_config_service_notebook_backend_to_page_num,
+		NULL, (GDestroyNotify) NULL);
+}
+
+static void
+mail_config_service_notebook_set_child_property (GtkContainer *container,
+                                                 GtkWidget *child,
+                                                 guint property_id,
+                                                 const GValue *value,
+                                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CHILD_BACKEND:
+			mail_config_service_notebook_set_child_backend (
+				E_MAIL_CONFIG_SERVICE_NOTEBOOK (container),
+				child, g_value_get_object (value));
+			return;
+	}
+
+	GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (
+		container, property_id, pspec);
+}
+
+static void
+mail_config_service_notebook_get_child_property (GtkContainer *container,
+                                                 GtkWidget *child,
+                                                 guint property_id,
+                                                 GValue *value,
+                                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CHILD_BACKEND:
+			g_value_set_object (
+				value,
+				mail_config_service_notebook_get_child_backend (
+				E_MAIL_CONFIG_SERVICE_NOTEBOOK (container), child));
+			return;
+	}
+
+	GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (
+		container, property_id, pspec);
+}
+
+static void
+e_mail_config_service_notebook_class_init (EMailConfigServiceNotebookClass *class)
+{
+	GObjectClass *object_class;
+	GtkContainerClass *container_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigServiceNotebookPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_service_notebook_set_property;
+	object_class->get_property = mail_config_service_notebook_get_property;
+	object_class->dispose = mail_config_service_notebook_dispose;
+	object_class->finalize = mail_config_service_notebook_finalize;
+	object_class->constructed = mail_config_service_notebook_constructed;
+
+	container_class = GTK_CONTAINER_CLASS (class);
+	container_class->set_child_property = mail_config_service_notebook_set_child_property;
+	container_class->get_child_property = mail_config_service_notebook_get_child_property;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACTIVE_BACKEND,
+		g_param_spec_object (
+			"active-backend",
+			"Active Backend",
+			"The service backend for the current page",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	/* Child property for notebook pages. */
+	gtk_container_class_install_child_property (
+		container_class,
+		PROP_CHILD_BACKEND,
+		g_param_spec_object (
+			"backend",
+			"Backend",
+			"The service backend for this page",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_service_notebook_init (EMailConfigServiceNotebook *notebook)
+{
+	gchar *key;
+
+	notebook->priv = E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_PRIVATE (notebook);
+
+	key = g_strdup_printf (CHILD_BACKEND_KEY_FORMAT, notebook);
+	notebook->priv->child_backend_key = key;
+}
+
+GtkWidget *
+e_mail_config_service_notebook_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, NULL);
+}
+
+gint
+e_mail_config_service_notebook_add_page (EMailConfigServiceNotebook *notebook,
+                                         EMailConfigServiceBackend *backend,
+                                         GtkWidget *child)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), -1);
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), -1);
+	g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
+
+	gtk_widget_show (child);
+
+	mail_config_service_notebook_set_child_backend (
+		notebook, child, backend);
+
+	return gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, NULL);
+}
+
+EMailConfigServiceBackend *
+e_mail_config_service_notebook_get_active_backend (EMailConfigServiceNotebook *notebook)
+{
+	g_return_val_if_fail (
+		E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook), NULL);
+
+	return notebook->priv->active_backend;
+}
+
+void
+e_mail_config_service_notebook_set_active_backend (EMailConfigServiceNotebook *notebook,
+                                                   EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK (notebook));
+
+	if (backend != NULL) {
+		g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+		g_object_ref (backend);
+	}
+
+	if (notebook->priv->active_backend != NULL)
+		g_object_unref (notebook->priv->active_backend);
+
+	notebook->priv->active_backend = backend;
+
+	g_object_notify (G_OBJECT (notebook), "active-backend");
+}
+
diff --git a/mail/e-mail-config-service-notebook.h b/mail/e-mail-config-service-notebook.h
new file mode 100644
index 0000000..db339e9
--- /dev/null
+++ b/mail/e-mail-config-service-notebook.h
@@ -0,0 +1,77 @@
+/*
+ * e-mail-config-service-notebook.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_SERVICE_NOTEBOOK_H
+#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_H
+
+#include <gtk/gtk.h>
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK \
+	(e_mail_config_service_notebook_get_type ())
+#define E_MAIL_CONFIG_SERVICE_NOTEBOOK(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebook))
+#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookClass))
+#define E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK))
+#define E_IS_MAIL_CONFIG_SERVICE_NOTEBOOK_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK))
+#define E_MAIL_CONFIG_SERVICE_NOTEBOOK_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_NOTEBOOK, EMailConfigServiceNotebookClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigServiceNotebook EMailConfigServiceNotebook;
+typedef struct _EMailConfigServiceNotebookClass EMailConfigServiceNotebookClass;
+typedef struct _EMailConfigServiceNotebookPrivate EMailConfigServiceNotebookPrivate;
+
+struct _EMailConfigServiceNotebook {
+	GtkNotebook parent;
+	EMailConfigServiceNotebookPrivate *priv;
+};
+
+struct _EMailConfigServiceNotebookClass {
+	GtkNotebookClass parent_class;
+};
+
+GType		e_mail_config_service_notebook_get_type
+					(void) G_GNUC_CONST;
+GtkWidget *	e_mail_config_service_notebook_new
+					(void);
+gint		e_mail_config_service_notebook_add_page
+					(EMailConfigServiceNotebook *notebook,
+					 EMailConfigServiceBackend *backend,
+					 GtkWidget *child);
+EMailConfigServiceBackend *
+		e_mail_config_service_notebook_get_active_backend
+					(EMailConfigServiceNotebook *notebook);
+void		e_mail_config_service_notebook_set_active_backend
+					(EMailConfigServiceNotebook *notebook,
+					 EMailConfigServiceBackend *backend);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_SERVICE_NOTEBOOK_H */
+
diff --git a/mail/e-mail-config-service-page.c b/mail/e-mail-config-service-page.c
new file mode 100644
index 0000000..1f53ed5
--- /dev/null
+++ b/mail/e-mail-config-service-page.c
@@ -0,0 +1,1039 @@
+/*
+ * e-mail-config-service-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-service-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <camel/camel.h>
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-backend.h>
+
+#include <libevolution-utils/e-alert-sink.h>
+#include <libevolution-utils/e-alert-dialog.h>
+#include <misc/e-activity-bar.h>
+#include <misc/e-alert-bar.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-service-notebook.h>
+
+#define E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePagePrivate))
+
+/* Used for autoconfiguration. */
+#define POP3_BACKEND_NAME "pop"
+#define IMAP_BACKEND_NAME "imapx"
+#define SMTP_BACKEND_NAME "smtp"
+
+typedef struct _Candidate Candidate;
+
+struct _EMailConfigServicePagePrivate {
+	ESourceRegistry *registry;
+	EMailConfigServiceBackend *active_backend;
+	gchar *email_address;
+
+	GHashTable *backends;
+	GPtrArray *candidates;
+
+	/* Hidden candidates are not listed in the
+	 * combo box but can still be accessed through
+	 * e_mail_config_service_page_lookup_backend(). */
+	GPtrArray *hidden_candidates;
+
+	GtkWidget *type_combo;
+	GtkWidget *type_label;
+	GtkWidget *desc_label;
+	GtkWidget *notebook;
+	GtkWidget *activity_bar;
+	GtkWidget *alert_bar;
+
+	/* Combo box list store */
+	GtkListStore *list_store;
+};
+
+struct _Candidate {
+	gchar *name;
+	EMailConfigServiceBackend *backend;
+
+	CamelProvider *provider;
+	CamelSettings *settings;
+	gulong settings_notify_handler_id;
+
+	GtkWidget *widget;
+};
+
+enum {
+	PROP_0,
+	PROP_ACTIVE_BACKEND,
+	PROP_EMAIL_ADDRESS,
+	PROP_REGISTRY
+};
+
+enum {
+	COLUMN_BACKEND_NAME,
+	COLUMN_DISPLAY_NAME,
+	COLUMN_SELECTABLE,
+	NUM_COLUMNS
+};
+
+/* Forward Declarations */
+static void	e_mail_config_service_page_alert_sink_init
+					(EAlertSinkInterface *interface);
+static void	e_mail_config_service_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
+	EMailConfigServicePage,
+	e_mail_config_service_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_ALERT_SINK,
+		e_mail_config_service_page_alert_sink_init)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_service_page_interface_init))
+
+static void
+mail_config_service_page_settings_notify_cb (CamelSettings *settings,
+                                             GParamSpec *pspec,
+                                             EMailConfigPage *page)
+{
+	e_mail_config_page_changed (page);
+}
+
+static Candidate *
+mail_config_service_page_new_candidate (EMailConfigServicePage *page,
+                                        ESource *scratch_source,
+                                        ESource *opt_collection)
+{
+	Candidate *candidate;
+	CamelProvider *provider;
+	CamelSettings *settings;
+	ESourceBackend *extension;
+	EMailConfigServiceBackend *backend;
+	EMailConfigServicePageClass *class;
+	const gchar *extension_name;
+	const gchar *backend_name;
+	gulong handler_id;
+
+	/* Get the backend name for this scratch source. */
+	class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page);
+	extension_name = class->extension_name;
+	extension = e_source_get_extension (scratch_source, extension_name);
+	backend_name = e_source_backend_get_backend_name (extension);
+	g_return_val_if_fail (backend_name != NULL, NULL);
+
+	/* Make sure we have a corresponding EMailConfigServicePageBackend. */
+	backend = g_hash_table_lookup (page->priv->backends, backend_name);
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	/* Make sure we have a corresponding CamelProvider. */
+	provider = e_mail_config_service_backend_get_provider (backend);
+	g_return_val_if_fail (provider != NULL, NULL);
+
+	/* Need to give the backend a scratch source and (if provided) a
+	 * scratch collection source before we can extract a CamelSettings
+	 * instance, since the CamelSettings instance comes from either the
+	 * scratch collection source or else the scratch source. */
+	e_mail_config_service_backend_set_source (backend, scratch_source);
+	if (opt_collection != NULL)
+		e_mail_config_service_backend_set_collection (
+			backend, opt_collection);
+
+	/* Make sure we have a corresponding CamelSettings. */
+	settings = e_mail_config_service_backend_get_settings (backend);
+	g_return_val_if_fail (CAMEL_IS_SETTINGS (settings), NULL);
+
+	candidate = g_slice_new0 (Candidate);
+	candidate->name = g_strdup (backend_name);
+	candidate->backend = g_object_ref (backend);
+	candidate->provider = provider;
+	candidate->settings = g_object_ref (settings);
+
+	/* Remove the backend so it can't be reused.  If another scratch
+	 * source with the same backend name gets added, the hash table
+	 * lookup will fail and emit a runtime warning, which we want. */
+	g_hash_table_remove (page->priv->backends, backend_name);
+
+	/* Emit "changed" signals for subsequent CamelSettings changes. */
+	handler_id = g_signal_connect (
+		candidate->settings, "notify",
+		G_CALLBACK (mail_config_service_page_settings_notify_cb), page);
+	candidate->settings_notify_handler_id = handler_id;
+
+	return candidate;
+}
+
+static void
+mail_config_service_page_free_candidate (Candidate *candidate)
+{
+	g_free (candidate->name);
+
+	if (candidate->backend != NULL)
+		g_object_unref (candidate->backend);
+
+	if (candidate->settings != NULL) {
+		g_signal_handler_disconnect (
+			candidate->settings,
+			candidate->settings_notify_handler_id);
+		g_object_unref (candidate->settings);
+	}
+
+	if (candidate->widget != NULL)
+		g_object_unref (candidate->widget);
+
+	g_slice_free (Candidate, candidate);
+}
+
+static void
+mail_config_service_page_init_backends (EMailConfigServicePage *page)
+{
+	GList *list, *iter;
+
+	page->priv->backends = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) g_object_unref);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+
+	list = e_extensible_list_extensions (
+		E_EXTENSIBLE (page), E_TYPE_MAIL_CONFIG_SERVICE_BACKEND);
+
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		EMailConfigServiceBackend *backend;
+		EMailConfigServiceBackendClass *class;
+
+		backend = E_MAIL_CONFIG_SERVICE_BACKEND (iter->data);
+		class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+
+		if (class->backend_name != NULL)
+			g_hash_table_insert (
+				page->priv->backends,
+				g_strdup (class->backend_name),
+				g_object_ref (backend));
+	}
+
+	g_list_free (list);
+}
+
+static gboolean
+mail_config_service_page_backend_to_id (GBinding *binding,
+                                        const GValue *source_value,
+                                        GValue *target_value,
+                                        gpointer user_data)
+{
+	EMailConfigServiceBackend *backend;
+	EMailConfigServiceBackendClass *backend_class;
+
+	backend = g_value_get_object (source_value);
+	g_return_val_if_fail (backend != NULL, FALSE);
+
+	backend_class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+	g_value_set_string (target_value, backend_class->backend_name);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_service_page_id_to_backend (GBinding *binding,
+                                        const GValue *source_value,
+                                        GValue *target_value,
+                                        gpointer user_data)
+{
+	EMailConfigServiceBackend *backend = NULL;
+	GObject *source_object;
+	const gchar *backend_name;
+
+	source_object = g_binding_get_source (binding);
+	backend_name = g_value_get_string (source_value);
+
+	if (backend_name != NULL)
+		backend = e_mail_config_service_page_lookup_backend (
+			E_MAIL_CONFIG_SERVICE_PAGE (source_object),
+			backend_name);
+
+	g_value_set_object (target_value, backend);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_service_page_backend_name_to_description (GBinding *binding,
+                                                      const GValue *source_value,
+                                                      GValue *target_value,
+                                                      gpointer user_data)
+{
+	CamelProvider *provider;
+	const gchar *description;
+	const gchar *backend_name;
+
+	backend_name = g_value_get_string (source_value);
+
+	/* XXX Silly special case. */
+	if (backend_name == NULL)
+		backend_name = "none";
+
+	provider = camel_provider_get (backend_name, NULL);
+
+	if (provider != NULL && provider->description != NULL)
+		description = g_dgettext (
+			provider->translation_domain,
+			provider->description);
+	else
+		description = "";
+
+	g_value_set_string (target_value, description);
+
+	return TRUE;
+}
+
+static Candidate *
+mail_config_service_page_get_active_candidate (EMailConfigServicePage *page)
+{
+	GtkComboBox *combo_box;
+	gint active;
+
+	combo_box = GTK_COMBO_BOX (page->priv->type_combo);
+	active = gtk_combo_box_get_active (combo_box);
+	g_return_val_if_fail (active >= 0, NULL);
+
+	return g_ptr_array_index (page->priv->candidates, active);
+}
+
+static void
+mail_config_service_page_set_registry (EMailConfigServicePage *page,
+                                       ESourceRegistry *registry)
+{
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+	g_return_if_fail (page->priv->registry == NULL);
+
+	page->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_config_service_page_set_property (GObject *object,
+                                       guint property_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE_BACKEND:
+			e_mail_config_service_page_set_active_backend (
+				E_MAIL_CONFIG_SERVICE_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_EMAIL_ADDRESS:
+			e_mail_config_service_page_set_email_address (
+				E_MAIL_CONFIG_SERVICE_PAGE (object),
+				g_value_get_string (value));
+			return;
+
+		case PROP_REGISTRY:
+			mail_config_service_page_set_registry (
+				E_MAIL_CONFIG_SERVICE_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_service_page_get_property (GObject *object,
+                                       guint property_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_service_page_get_active_backend (
+				E_MAIL_CONFIG_SERVICE_PAGE (object)));
+			return;
+
+		case PROP_EMAIL_ADDRESS:
+			g_value_set_string (
+				value,
+				e_mail_config_service_page_get_email_address (
+				E_MAIL_CONFIG_SERVICE_PAGE (object)));
+			return;
+
+		case PROP_REGISTRY:
+			g_value_set_object (
+				value,
+				e_mail_config_service_page_get_registry (
+				E_MAIL_CONFIG_SERVICE_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_service_page_dispose (GObject *object)
+{
+	EMailConfigServicePagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (object);
+
+	if (priv->registry != NULL) {
+		g_object_unref (priv->registry);
+		priv->registry = NULL;
+	}
+
+	if (priv->active_backend != NULL) {
+		g_object_unref (priv->active_backend);
+		priv->active_backend = NULL;
+	}
+
+	g_hash_table_remove_all (priv->backends);
+	g_ptr_array_set_size (priv->candidates, 0);
+	g_ptr_array_set_size (priv->hidden_candidates, 0);
+
+	if (priv->list_store != NULL) {
+		g_object_unref (priv->list_store);
+		priv->list_store = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_service_page_parent_class)->dispose (object);
+}
+
+static void
+mail_config_service_page_finalize (GObject *object)
+{
+	EMailConfigServicePagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (object);
+
+	g_free (priv->email_address);
+	g_hash_table_destroy (priv->backends);
+	g_ptr_array_free (priv->candidates, TRUE);
+	g_ptr_array_free (priv->hidden_candidates, TRUE);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_service_page_parent_class)->finalize (object);
+}
+
+static void
+mail_config_service_page_constructed (GObject *object)
+{
+	EMailConfigServicePage *page;
+
+	page = E_MAIL_CONFIG_SERVICE_PAGE (object);
+
+	mail_config_service_page_init_backends (page);
+}
+
+static void
+mail_config_service_page_submit_alert (EAlertSink *alert_sink,
+                                       EAlert *alert)
+{
+	EMailConfigServicePagePrivate *priv;
+	EAlertBar *alert_bar;
+	GtkWidget *dialog;
+	gpointer parent;
+
+	priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (alert_sink);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (alert_sink));
+	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+	switch (e_alert_get_message_type (alert)) {
+		case GTK_MESSAGE_INFO:
+		case GTK_MESSAGE_WARNING:
+		case GTK_MESSAGE_ERROR:
+			alert_bar = E_ALERT_BAR (priv->alert_bar);
+			e_alert_bar_add_alert (alert_bar, alert);
+			break;
+
+		default:
+			dialog = e_alert_dialog_new (parent, alert);
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+			break;
+	}
+}
+
+static void
+mail_config_service_page_setup_defaults (EMailConfigPage *page)
+{
+	EMailConfigServicePageClass *class;
+	EMailConfigServicePagePrivate *priv;
+	guint ii;
+
+	class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page);
+	priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page);
+
+	for (ii = 0; ii < priv->candidates->len; ii++) {
+		Candidate *candidate;
+
+		candidate = priv->candidates->pdata[ii];
+		g_return_if_fail (candidate != NULL);
+
+		e_mail_config_service_backend_setup_defaults (
+			candidate->backend);
+	}
+
+	/* XXX Not sure if we need to call setup_defaults() for
+	 *     hidden candidates.  Hold off until a need arises. */
+
+	if (class->default_backend_name != NULL)
+		gtk_combo_box_set_active_id (
+			GTK_COMBO_BOX (priv->type_combo),
+			class->default_backend_name);
+}
+
+static gboolean
+mail_config_service_page_check_complete (EMailConfigPage *page)
+{
+	EMailConfigServicePagePrivate *priv;
+	Candidate *candidate;
+	GtkComboBox *type_combo;
+
+	priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page);
+
+	/* Make sure the combo box has an active item. */
+	type_combo = GTK_COMBO_BOX (priv->type_combo);
+	if (gtk_combo_box_get_active_id (type_combo) == NULL)
+		return FALSE;
+
+	candidate = mail_config_service_page_get_active_candidate (
+		E_MAIL_CONFIG_SERVICE_PAGE (page));
+	g_return_val_if_fail (candidate != NULL, FALSE);
+
+	return e_mail_config_service_backend_check_complete (
+		candidate->backend);
+}
+
+static void
+mail_config_service_page_commit_changes (EMailConfigPage *page,
+                                         GQueue *source_queue)
+{
+	Candidate *candidate;
+
+	candidate = mail_config_service_page_get_active_candidate (
+		E_MAIL_CONFIG_SERVICE_PAGE (page));
+	g_return_if_fail (candidate != NULL);
+
+	e_mail_config_service_backend_commit_changes (candidate->backend);
+}
+
+static void
+e_mail_config_service_page_class_init (EMailConfigServicePageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigServicePagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_service_page_set_property;
+	object_class->get_property = mail_config_service_page_get_property;
+	object_class->dispose = mail_config_service_page_dispose;
+	object_class->finalize = mail_config_service_page_finalize;
+	object_class->constructed = mail_config_service_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACTIVE_BACKEND,
+		g_param_spec_object (
+			"active-backend",
+			"Active Backend",
+			"The active service backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_EMAIL_ADDRESS,
+		g_param_spec_string (
+			"email-address",
+			"Email Address",
+			"The user's email address",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_REGISTRY,
+		g_param_spec_object (
+			"registry",
+			"Registry",
+			"Data source registry",
+			E_TYPE_SOURCE_REGISTRY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_service_page_alert_sink_init (EAlertSinkInterface *interface)
+{
+	interface->submit_alert = mail_config_service_page_submit_alert;
+}
+
+static void
+e_mail_config_service_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->setup_defaults = mail_config_service_page_setup_defaults;
+	interface->check_complete = mail_config_service_page_check_complete;
+	interface->commit_changes = mail_config_service_page_commit_changes;
+}
+
+static void
+e_mail_config_service_page_init (EMailConfigServicePage *page)
+{
+	GPtrArray *candidates;
+	GPtrArray *hidden_candidates;
+	PangoAttribute *attr;
+	PangoAttrList *attr_list;
+	GtkLabel *label;
+	GtkWidget *frame;
+	GtkWidget *widget;
+	GtkWidget *container;
+	GtkTreeModel *tree_model;
+	GtkCellRenderer *renderer;
+
+	/* The candidates array holds scratch ESources, one for each
+	 * item in the "type" combo box.  Scratch ESources are never
+	 * added to the registry, so backend extensions can make any
+	 * changes they want to them.  Whichever scratch ESource is
+	 * "active" (selected in the "type" combo box) when the user
+	 * clicks OK wins and is written to disk.  The others are
+	 * discarded. */
+	candidates = g_ptr_array_new_with_free_func (
+		(GDestroyNotify) mail_config_service_page_free_candidate);
+
+	/* Hidden candidates are not listed in the "type" combo box
+	 * but their scratch ESource can still be "active".  This is
+	 * a hack to accommodate groupware backends.  Usually when a
+	 * hidden candidate is active the service page will not be
+	 * visible anyway. */
+	hidden_candidates = g_ptr_array_new_with_free_func (
+		(GDestroyNotify) mail_config_service_page_free_candidate);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	page->priv = E_MAIL_CONFIG_SERVICE_PAGE_GET_PRIVATE (page);
+	page->priv->candidates = candidates;
+	page->priv->hidden_candidates = hidden_candidates;
+
+	/* Build a filtered model for the combo box, where row
+	 * visibility is determined by the "selectable" column. */
+
+	page->priv->list_store = gtk_list_store_new (
+		NUM_COLUMNS,
+		G_TYPE_STRING,		/* COLUMN_BACKEND_NAME */
+		G_TYPE_STRING,		/* COLUMN_DISPLAY_NAME */
+		G_TYPE_BOOLEAN);	/* COLUMN_SELECTABLE */
+
+	tree_model = gtk_tree_model_filter_new (
+		GTK_TREE_MODEL (page->priv->list_store), NULL);
+
+	gtk_tree_model_filter_set_visible_column (
+		GTK_TREE_MODEL_FILTER (tree_model), COLUMN_SELECTABLE);
+
+	/* Either the combo box or the label is shown, never both.
+	 * But we create both widgets and keep them both up-to-date
+	 * regardless just because it makes the logic simpler. */
+
+	container = GTK_WIDGET (page);
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 12);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	attr_list = pango_attr_list_new ();
+
+	attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+	pango_attr_list_insert (attr_list, attr);
+
+	widget = gtk_label_new_with_mnemonic (_("Server _Type:"));
+	gtk_widget_set_margin_right (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_combo_box_new_with_model (tree_model);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_combo_box_set_id_column (
+		GTK_COMBO_BOX (widget), COLUMN_BACKEND_NAME);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1);
+	page->priv->type_combo = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (
+		GTK_CELL_LAYOUT (widget), renderer, TRUE);
+	gtk_cell_layout_add_attribute (
+		GTK_CELL_LAYOUT (widget), renderer,
+		"text", COLUMN_DISPLAY_NAME);
+
+	widget = gtk_label_new (NULL);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_attributes (GTK_LABEL (widget), attr_list);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 0, 1, 1);
+	page->priv->type_label = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (_("Description:"));
+	gtk_widget_set_margin_right (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.0);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 2, 1);
+	page->priv->desc_label = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	pango_attr_list_unref (attr_list);
+
+	container = GTK_WIDGET (page);
+
+	widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = e_mail_config_service_notebook_new ();
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	page->priv->notebook = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	/* Visibility is bound to the EActivityBar. */
+
+	frame = widget;
+
+	widget = e_activity_bar_new ();
+	gtk_container_add (GTK_CONTAINER (frame), widget);
+	page->priv->activity_bar = widget;  /* not referenced */
+	/* EActivityBar controls its own visibility. */
+
+	g_object_bind_property (
+		widget, "visible",
+		frame, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	/* Visibility is bound to the EAlertBar. */
+
+	frame = widget;
+
+	widget = e_alert_bar_new ();
+	gtk_container_add (GTK_CONTAINER (frame), widget);
+	page->priv->alert_bar = widget;  /* not referenced */
+	/* EAlertBar controls its own visibility. */
+
+	g_object_bind_property (
+		widget, "visible",
+		frame, "visible",
+		G_BINDING_SYNC_CREATE);
+
+	/* Keep the notebook's active page number synchronized with our
+	 * own "active-backend" property.  Avoid G_BINDING_SYNC_CREATE
+	 * since we haven't added any notebook pages. */
+	g_object_bind_property (
+		page, "active-backend",
+		page->priv->notebook, "active-backend",
+		G_BINDING_BIDIRECTIONAL);
+
+	/* Keep the combo box's active row number synchronized with our
+	 * own "active-backend" property.  Avoid G_BINDING_SYNC_CREATE
+	 * since we haven't added any combo box rows. */
+	g_object_bind_property_full (
+		page, "active-backend",
+		page->priv->type_combo, "active-id",
+		G_BINDING_BIDIRECTIONAL,
+		mail_config_service_page_backend_to_id,
+		mail_config_service_page_id_to_backend,
+		NULL, (GDestroyNotify) NULL);
+
+	/* This keeps the description field up-to-date. */
+	g_object_bind_property_full (
+		page->priv->type_combo, "active-id",
+		page->priv->desc_label, "label",
+		G_BINDING_DEFAULT,
+		mail_config_service_page_backend_name_to_description,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	/* For the "Server Type", either the combo
+	 * box or the label is visible, never both. */
+	g_object_bind_property (
+		page->priv->type_combo, "visible",
+		page->priv->type_label, "visible",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_INVERT_BOOLEAN);
+
+	g_signal_connect_swapped (
+		page->priv->type_combo, "changed",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	g_object_unref (tree_model);
+}
+
+EMailConfigServiceBackend *
+e_mail_config_service_page_get_active_backend (EMailConfigServicePage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL);
+
+	return page->priv->active_backend;
+}
+
+void
+e_mail_config_service_page_set_active_backend (EMailConfigServicePage *page,
+                                               EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page));
+
+	if (backend != NULL) {
+		g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+		g_object_ref (backend);
+	}
+
+	if (page->priv->active_backend != NULL)
+		g_object_unref (page->priv->active_backend);
+
+	page->priv->active_backend = backend;
+
+	g_object_notify (G_OBJECT (page), "active-backend");
+}
+
+const gchar *
+e_mail_config_service_page_get_email_address (EMailConfigServicePage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL);
+
+	return page->priv->email_address;
+}
+
+void
+e_mail_config_service_page_set_email_address (EMailConfigServicePage *page,
+                                              const gchar *email_address)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page));
+
+	g_free (page->priv->email_address);
+	page->priv->email_address = g_strdup (email_address);
+
+	g_object_notify (G_OBJECT (page), "email-address");
+}
+
+ESourceRegistry *
+e_mail_config_service_page_get_registry (EMailConfigServicePage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL);
+
+	return page->priv->registry;
+}
+
+EMailConfigServiceBackend *
+e_mail_config_service_page_add_scratch_source (EMailConfigServicePage *page,
+                                               ESource *scratch_source,
+                                               ESource *opt_collection)
+{
+	GtkWidget *widget;
+	GtkLabel *type_label;
+	GtkComboBox *type_combo;
+	GtkTreeIter iter;
+	Candidate *candidate;
+	const gchar *display_name;
+	gboolean selectable;
+	gint page_num;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (scratch_source), NULL);
+
+	if (opt_collection != NULL)
+		g_return_val_if_fail (E_IS_SOURCE (opt_collection), NULL);
+
+	type_label = GTK_LABEL (page->priv->type_label);
+	type_combo = GTK_COMBO_BOX (page->priv->type_combo);
+
+	candidate = mail_config_service_page_new_candidate (
+		page, scratch_source, opt_collection);
+	g_return_val_if_fail (candidate != NULL, NULL);
+
+	widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+	e_mail_config_service_backend_insert_widgets (
+		candidate->backend, GTK_BOX (widget));
+	candidate->widget = g_object_ref_sink (widget);
+	gtk_widget_show (widget);
+
+	g_ptr_array_add (page->priv->candidates, candidate);
+
+	display_name = g_dgettext (
+		candidate->provider->translation_domain,
+		candidate->provider->name);
+
+	page_num = e_mail_config_service_notebook_add_page (
+		E_MAIL_CONFIG_SERVICE_NOTEBOOK (page->priv->notebook),
+		candidate->backend, widget);
+
+	selectable = e_mail_config_service_backend_get_selectable (
+		candidate->backend);
+
+	gtk_list_store_append (page->priv->list_store, &iter);
+
+	gtk_list_store_set (
+		page->priv->list_store, &iter,
+		COLUMN_BACKEND_NAME, candidate->name,
+		COLUMN_DISPLAY_NAME, display_name,
+		COLUMN_SELECTABLE, selectable,
+		-1);
+
+	/* The type label is only visible if we have one scratch source,
+	 * so just always set the label text to the most recently added
+	 * scratch source. */
+	gtk_label_set_text (type_label, display_name);
+
+	/* If no combo box row is active yet, choose the new row. */
+	if (gtk_combo_box_get_active_id (type_combo) == NULL)
+		gtk_combo_box_set_active_id (type_combo, candidate->name);
+
+	/* If the page number of the newly-added notebook page is zero,
+	 * show the "type" label.  Otherwise show the "type" combo box.
+	 * There's an inverted "visible" binding between the combo box
+	 * and label, so we only need to change one of the widgets. */
+	gtk_widget_set_visible (GTK_WIDGET (type_combo), page_num > 0);
+
+	return candidate->backend;
+}
+
+EMailConfigServiceBackend *
+e_mail_config_service_page_lookup_backend (EMailConfigServicePage *page,
+                                           const gchar *backend_name)
+{
+	guint index;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL);
+	g_return_val_if_fail (backend_name != NULL, NULL);
+
+	for (index = 0; index < page->priv->candidates->len; index++) {
+		Candidate *candidate;
+
+		candidate = page->priv->candidates->pdata[index];
+
+		if (g_strcmp0 (backend_name, candidate->name) == 0)
+			return candidate->backend;
+	}
+
+	return NULL;
+}
+
+EActivity *
+e_mail_config_service_page_new_activity (EMailConfigServicePage *page)
+{
+	EActivity *activity;
+	EActivityBar *activity_bar;
+	GCancellable *cancellable;
+
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page), NULL);
+
+	/* Clear any previous alerts. */
+	e_alert_bar_clear (E_ALERT_BAR (page->priv->alert_bar));
+
+	activity = e_activity_new ();
+
+	e_activity_set_alert_sink (activity, E_ALERT_SINK (page));
+
+	cancellable = camel_operation_new ();
+	e_activity_set_cancellable (activity, cancellable);
+	g_object_unref (cancellable);
+
+	activity_bar = E_ACTIVITY_BAR (page->priv->activity_bar);
+	e_activity_bar_set_activity (activity_bar, activity);
+
+	return activity;
+}
+
+void
+e_mail_config_service_page_auto_configure (EMailConfigServicePage *page,
+                                           EMailAutoconfig *autoconfig)
+{
+	EMailConfigServiceBackend *pop3 = NULL;
+	EMailConfigServiceBackend *imap = NULL;
+	EMailConfigServiceBackend *smtp = NULL;
+	guint ii;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_PAGE (page));
+	g_return_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig));
+
+	for (ii = 0; ii < page->priv->candidates->len; ii++) {
+		EMailConfigServiceBackendClass *class;
+		EMailConfigServiceBackend *backend;
+		Candidate *candidate;
+		gboolean configured;
+
+		candidate = page->priv->candidates->pdata[ii];
+
+		backend = candidate->backend;
+		class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+
+		configured = e_mail_config_service_backend_auto_configure (
+			backend, autoconfig);
+
+		/* XXX There's a few specific backends to check for.
+		 *     It requires that we know about these backends,
+		 *     which violates the abstraction, but we need to
+		 *     break our own rule to be practical here. */
+		if (g_strcmp0 (class->backend_name, POP3_BACKEND_NAME) == 0)
+			pop3 = configured ? backend : NULL;
+		if (g_strcmp0 (class->backend_name, IMAP_BACKEND_NAME) == 0)
+			imap = configured ? backend : NULL;
+		if (g_strcmp0 (class->backend_name, SMTP_BACKEND_NAME) == 0)
+			smtp = configured ? backend : NULL;
+	}
+
+	/* Select POP3 before IMAP.  If both are present we want IMAP. */
+	if (pop3 != NULL)
+		e_mail_config_service_page_set_active_backend (page, pop3);
+	if (imap != NULL)
+		e_mail_config_service_page_set_active_backend (page, imap);
+	if (smtp != NULL)
+		e_mail_config_service_page_set_active_backend (page, smtp);
+}
+
diff --git a/mail/e-mail-config-service-page.h b/mail/e-mail-config-service-page.h
new file mode 100644
index 0000000..3c5a40e
--- /dev/null
+++ b/mail/e-mail-config-service-page.h
@@ -0,0 +1,107 @@
+/*
+ * e-mail-config-service-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* XXX This is very similar to ESourceConfig for address books and
+ *     calendars, but not similar enough to easily unify the APIs.
+ *     Probably with more thought and effort it could be done. */
+
+#ifndef E_MAIL_CONFIG_SERVICE_PAGE_H
+#define E_MAIL_CONFIG_SERVICE_PAGE_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+#include <libedataserver/e-source-extension.h>
+#include <libedataserver/e-source-registry.h>
+
+#include <e-util/e-activity.h>
+#include <mail/e-mail-autoconfig.h>
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SERVICE_PAGE \
+	(e_mail_config_service_page_get_type ())
+#define E_MAIL_CONFIG_SERVICE_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePage))
+#define E_MAIL_CONFIG_SERVICE_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePageClass))
+#define E_IS_MAIL_CONFIG_SERVICE_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE))
+#define E_IS_MAIL_CONFIG_SERVICE_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SERVICE_PAGE))
+#define E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SERVICE_PAGE, EMailConfigServicePageClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigServicePage EMailConfigServicePage;
+typedef struct _EMailConfigServicePageClass EMailConfigServicePageClass;
+typedef struct _EMailConfigServicePagePrivate EMailConfigServicePagePrivate;
+
+struct _EMailConfigServicePage {
+	GtkBox parent;
+	EMailConfigServicePagePrivate *priv;
+};
+
+struct _EMailConfigServicePageClass {
+	GtkBoxClass parent_class;
+
+	const gchar *extension_name;
+	CamelProviderType provider_type;
+	const gchar *default_backend_name;
+};
+
+GType		e_mail_config_service_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigServiceBackend *
+		e_mail_config_service_page_get_active_backend
+						(EMailConfigServicePage *page);
+void		e_mail_config_service_page_set_active_backend
+						(EMailConfigServicePage *page,
+						 EMailConfigServiceBackend *backend);
+const gchar *	e_mail_config_service_page_get_email_address
+						(EMailConfigServicePage *page);
+void		e_mail_config_service_page_set_email_address
+						(EMailConfigServicePage *page,
+						 const gchar *email_address);
+ESourceRegistry *
+		e_mail_config_service_page_get_registry
+						(EMailConfigServicePage *page);
+EMailConfigServiceBackend *
+		e_mail_config_service_page_add_scratch_source
+						(EMailConfigServicePage *page,
+						 ESource *scratch_source,
+						 ESource *opt_collection);
+EMailConfigServiceBackend *
+		e_mail_config_service_page_lookup_backend
+						(EMailConfigServicePage *page,
+						 const gchar *backend_name);
+EActivity *	e_mail_config_service_page_new_activity
+						(EMailConfigServicePage *page);
+void		e_mail_config_service_page_auto_configure
+						(EMailConfigServicePage *page,
+						 EMailAutoconfig *autoconfig);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_SERVICE_PAGE_H */
+
diff --git a/mail/e-mail-config-sidebar.c b/mail/e-mail-config-sidebar.c
new file mode 100644
index 0000000..2d28ae8
--- /dev/null
+++ b/mail/e-mail-config-sidebar.c
@@ -0,0 +1,415 @@
+/*
+ * e-mail-config-sidebar.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-sidebar.h"
+
+#define E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebarPrivate))
+
+struct _EMailConfigSidebarPrivate {
+	EMailConfigNotebook *notebook;
+	gint active;
+
+	GHashTable *buttons_to_pages;
+	GHashTable *pages_to_buttons;
+
+	gulong page_added_handler_id;
+	gulong page_removed_handler_id;
+	gulong page_reordered_handler_id;
+};
+
+enum {
+	PROP_0,
+	PROP_ACTIVE,
+	PROP_NOTEBOOK
+};
+
+G_DEFINE_TYPE (
+	EMailConfigSidebar,
+	e_mail_config_sidebar,
+	GTK_TYPE_BUTTON_BOX)
+
+static void
+mail_config_sidebar_button_toggled (GtkToggleButton *button,
+                                    EMailConfigSidebar *sidebar)
+{
+	if (gtk_toggle_button_get_active (button)) {
+		GHashTable *hash_table;
+		GtkNotebook *notebook;
+		GtkWidget *page;
+		gint page_num;
+
+		hash_table = sidebar->priv->buttons_to_pages;
+		page = g_hash_table_lookup (hash_table, button);
+		g_return_if_fail (GTK_IS_WIDGET (page));
+
+		notebook = GTK_NOTEBOOK (sidebar->priv->notebook);
+		page_num = gtk_notebook_page_num (notebook, page);
+		e_mail_config_sidebar_set_active (sidebar, page_num);
+	}
+}
+
+static void
+mail_config_sidebar_notebook_page_added (GtkNotebook *notebook,
+                                         GtkWidget *page,
+                                         guint page_num,
+                                         EMailConfigSidebar *sidebar)
+{
+	GtkRadioButton *group_member;
+	GtkWidget *button;
+	GList *keys;
+	gchar *tab_label = NULL;
+
+	/* Grab another radio button if we have any. */
+	keys = g_hash_table_get_keys (sidebar->priv->buttons_to_pages);
+	group_member = (keys != NULL) ? GTK_RADIO_BUTTON (keys->data) : NULL;
+	g_list_free (keys);
+
+	gtk_container_child_get (
+		GTK_CONTAINER (notebook), page,
+		"tab-label", &tab_label, NULL);
+
+	button = gtk_radio_button_new_with_label_from_widget (
+		group_member, tab_label);
+	g_object_set (button, "draw-indicator", FALSE, NULL);
+	gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+	gtk_box_pack_start (GTK_BOX (sidebar), button, FALSE, FALSE, 0);
+	gtk_box_reorder_child (GTK_BOX (sidebar), button, page_num);
+	gtk_widget_show (button);
+
+	g_signal_connect (
+		button, "toggled",
+		G_CALLBACK (mail_config_sidebar_button_toggled), sidebar);
+
+	g_hash_table_insert (
+		sidebar->priv->pages_to_buttons,
+		g_object_ref (page), g_object_ref (button));
+
+	g_hash_table_insert (
+		sidebar->priv->buttons_to_pages,
+		g_object_ref (button), g_object_ref (page));
+}
+
+static void
+mail_config_sidebar_notebook_page_removed (GtkNotebook *notebook,
+                                           GtkWidget *page,
+                                           guint page_num,
+                                           EMailConfigSidebar *sidebar)
+{
+	GHashTable *hash_table;
+	GtkWidget *button;
+
+	hash_table = sidebar->priv->pages_to_buttons;
+	button = g_hash_table_lookup (hash_table, page);
+	g_return_if_fail (GTK_IS_WIDGET (button));
+
+	gtk_container_remove (GTK_CONTAINER (sidebar), button);
+
+	g_hash_table_remove (sidebar->priv->pages_to_buttons, page);
+	g_hash_table_remove (sidebar->priv->buttons_to_pages, button);
+}
+
+static void
+mail_config_sidebar_notebook_page_reordered (GtkNotebook *notebook,
+                                             GtkWidget *page,
+                                             guint page_num,
+                                             EMailConfigSidebar *sidebar)
+{
+	GHashTable *hash_table;
+	GtkWidget *button;
+
+	hash_table = sidebar->priv->pages_to_buttons;
+	button = g_hash_table_lookup (hash_table, page);
+	g_return_if_fail (GTK_IS_WIDGET (button));
+
+	gtk_box_reorder_child (GTK_BOX (sidebar), button, page_num);
+}
+
+static void
+mail_config_sidebar_set_notebook (EMailConfigSidebar *sidebar,
+                                  EMailConfigNotebook *notebook)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook));
+	g_return_if_fail (sidebar->priv->notebook == NULL);
+
+	sidebar->priv->notebook = g_object_ref (notebook);
+}
+
+static void
+mail_config_sidebar_set_property (GObject *object,
+                                  guint property_id,
+                                  const GValue *value,
+                                  GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE:
+			e_mail_config_sidebar_set_active (
+				E_MAIL_CONFIG_SIDEBAR (object),
+				g_value_get_int (value));
+			return;
+
+		case PROP_NOTEBOOK:
+			mail_config_sidebar_set_notebook (
+				E_MAIL_CONFIG_SIDEBAR (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_sidebar_get_property (GObject *object,
+                                  guint property_id,
+                                  GValue *value,
+                                  GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACTIVE:
+			g_value_set_int (
+				value,
+				e_mail_config_sidebar_get_active (
+				E_MAIL_CONFIG_SIDEBAR (object)));
+			return;
+
+		case PROP_NOTEBOOK:
+			g_value_set_object (
+				value,
+				e_mail_config_sidebar_get_notebook (
+				E_MAIL_CONFIG_SIDEBAR (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_sidebar_dispose (GObject *object)
+{
+	EMailConfigSidebarPrivate *priv;
+
+	priv = E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE (object);
+
+	if (priv->notebook != NULL) {
+		g_signal_handler_disconnect (
+			priv->notebook, priv->page_added_handler_id);
+		g_signal_handler_disconnect (
+			priv->notebook, priv->page_removed_handler_id);
+		g_signal_handler_disconnect (
+			priv->notebook, priv->page_reordered_handler_id);
+		g_object_unref (priv->notebook);
+		priv->notebook = NULL;
+	}
+
+	g_hash_table_remove_all (priv->buttons_to_pages);
+	g_hash_table_remove_all (priv->pages_to_buttons);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_sidebar_parent_class)->dispose (object);
+}
+
+static void
+mail_config_sidebar_finalize (GObject *object)
+{
+	EMailConfigSidebarPrivate *priv;
+
+	priv = E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE (object);
+
+	g_hash_table_destroy (priv->buttons_to_pages);
+	g_hash_table_destroy (priv->pages_to_buttons);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_sidebar_parent_class)->finalize (object);
+}
+
+static void
+mail_config_sidebar_constructed (GObject *object)
+{
+	EMailConfigSidebar *sidebar;
+	GtkNotebook *notebook;
+	gulong handler_id;
+	gint n_pages, ii;
+
+	sidebar = E_MAIL_CONFIG_SIDEBAR (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_sidebar_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (sidebar), GTK_ORIENTATION_VERTICAL);
+
+	gtk_button_box_set_layout (
+		GTK_BUTTON_BOX (sidebar), GTK_BUTTONBOX_START);
+
+	gtk_box_set_spacing (GTK_BOX (sidebar), 6);
+
+	/* Add buttons for existing notebook pages before
+	 * binding to properties or connecting to signals. */
+
+	notebook = GTK_NOTEBOOK (sidebar->priv->notebook);
+	n_pages = gtk_notebook_get_n_pages (notebook);
+
+	for (ii = 0; ii < n_pages; ii++) {
+		GtkWidget *page;
+
+		page = gtk_notebook_get_nth_page (notebook, ii);
+		mail_config_sidebar_notebook_page_added (
+			notebook, page, (guint) ii, sidebar);
+	}
+
+	g_object_bind_property (
+		sidebar, "active",
+		notebook, "page",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	handler_id = g_signal_connect (
+		notebook, "page-added",
+		G_CALLBACK (mail_config_sidebar_notebook_page_added),
+		sidebar);
+	sidebar->priv->page_added_handler_id = handler_id;
+
+	handler_id = g_signal_connect (
+		notebook, "page-removed",
+		G_CALLBACK (mail_config_sidebar_notebook_page_removed),
+		sidebar);
+	sidebar->priv->page_removed_handler_id = handler_id;
+
+	handler_id = g_signal_connect (
+		notebook, "page-reordered",
+		G_CALLBACK (mail_config_sidebar_notebook_page_reordered),
+		sidebar);
+	sidebar->priv->page_reordered_handler_id = handler_id;
+}
+
+static void
+e_mail_config_sidebar_class_init (EMailConfigSidebarClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigSidebarPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_sidebar_set_property;
+	object_class->get_property = mail_config_sidebar_get_property;
+	object_class->dispose = mail_config_sidebar_dispose;
+	object_class->finalize = mail_config_sidebar_finalize;
+	object_class->constructed = mail_config_sidebar_constructed;
+
+	/* Use the same constraints as GtkNotebook:page. */
+	g_object_class_install_property (
+		object_class,
+		PROP_ACTIVE,
+		g_param_spec_int (
+			"active",
+			"Active",
+			"Index of the currently active button",
+			-1, G_MAXINT, -1,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_NOTEBOOK,
+		g_param_spec_object (
+			"notebook",
+			"Notebook",
+			"Mail configuration notebook",
+			E_TYPE_MAIL_CONFIG_NOTEBOOK,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_sidebar_init (EMailConfigSidebar *sidebar)
+{
+	GHashTable *buttons_to_pages;
+	GHashTable *pages_to_buttons;
+
+	buttons_to_pages = g_hash_table_new_full (
+		(GHashFunc) g_direct_hash,
+		(GEqualFunc) g_direct_equal,
+		(GDestroyNotify) g_object_unref,
+		(GDestroyNotify) g_object_unref);
+
+	pages_to_buttons = g_hash_table_new_full (
+		(GHashFunc) g_direct_hash,
+		(GEqualFunc) g_direct_equal,
+		(GDestroyNotify) g_object_unref,
+		(GDestroyNotify) g_object_unref);
+
+	sidebar->priv = E_MAIL_CONFIG_SIDEBAR_GET_PRIVATE (sidebar);
+	sidebar->priv->buttons_to_pages = buttons_to_pages;
+	sidebar->priv->pages_to_buttons = pages_to_buttons;
+}
+
+GtkWidget *
+e_mail_config_sidebar_new (EMailConfigNotebook *notebook)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_NOTEBOOK (notebook), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_SIDEBAR,
+		"notebook", notebook, NULL);
+}
+
+gint
+e_mail_config_sidebar_get_active (EMailConfigSidebar *sidebar)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SIDEBAR (sidebar), -1);
+
+	return sidebar->priv->active;
+}
+
+void
+e_mail_config_sidebar_set_active (EMailConfigSidebar *sidebar,
+                                  gint active)
+{
+	GtkNotebook *notebook;
+	GtkWidget *page;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_SIDEBAR (sidebar));
+
+	notebook = GTK_NOTEBOOK (sidebar->priv->notebook);
+	page = gtk_notebook_get_nth_page (notebook, active);
+
+	sidebar->priv->active = (page != NULL) ? active : -1;
+
+	g_object_notify (G_OBJECT (sidebar), "active");
+
+	if (page != NULL) {
+		GHashTable *hash_table;
+		GtkToggleButton *button;
+
+		hash_table = sidebar->priv->pages_to_buttons;
+		button = g_hash_table_lookup (hash_table, page);
+		gtk_toggle_button_set_active (button, TRUE);
+	}
+}
+
+EMailConfigNotebook *
+e_mail_config_sidebar_get_notebook (EMailConfigSidebar *sidebar)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SIDEBAR (sidebar), NULL);
+
+	return sidebar->priv->notebook;
+}
+
diff --git a/mail/e-mail-config-sidebar.h b/mail/e-mail-config-sidebar.h
new file mode 100644
index 0000000..50f272e
--- /dev/null
+++ b/mail/e-mail-config-sidebar.h
@@ -0,0 +1,72 @@
+/*
+ * e-mail-config-sidebar.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_SIDEBAR_H
+#define E_MAIL_CONFIG_SIDEBAR_H
+
+#include <mail/e-mail-config-notebook.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SIDEBAR \
+	(e_mail_config_sidebar_get_type ())
+#define E_MAIL_CONFIG_SIDEBAR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebar))
+#define E_MAIL_CONFIG_SIDEBAR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebarClass))
+#define E_IS_MAIL_CONFIG_SIDEBAR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SIDEBAR))
+#define E_IS_MAIL_CONFIG_SIDEBAR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SIDEBAR))
+#define E_MAIL_CONFIG_SIDEBAR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SIDEBAR, EMailConfigSidebarClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigSidebar EMailConfigSidebar;
+typedef struct _EMailConfigSidebarClass EMailConfigSidebarClass;
+typedef struct _EMailConfigSidebarPrivate EMailConfigSidebarPrivate;
+
+struct _EMailConfigSidebar {
+	GtkButtonBox parent;
+	EMailConfigSidebarPrivate *priv;
+};
+
+struct _EMailConfigSidebarClass {
+	GtkButtonBoxClass parent_class;
+};
+
+GType		e_mail_config_sidebar_get_type	(void) G_GNUC_CONST;
+GtkWidget *	e_mail_config_sidebar_new	(EMailConfigNotebook *notebook);
+gint		e_mail_config_sidebar_get_active
+						(EMailConfigSidebar *sidebar);
+void		e_mail_config_sidebar_set_active
+						(EMailConfigSidebar *sidebar,
+						 gint active);
+EMailConfigNotebook *
+		e_mail_config_sidebar_get_notebook
+						(EMailConfigSidebar *sidebar);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_SIDEBAR_H */
+
diff --git a/mail/e-mail-config-summary-page.c b/mail/e-mail-config-summary-page.c
new file mode 100644
index 0000000..db6520a
--- /dev/null
+++ b/mail/e-mail-config-summary-page.c
@@ -0,0 +1,1064 @@
+/*
+ * e-mail-config-summary-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-summary-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <camel/camel.h>
+
+#include <libebackend/e-extensible.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-collection.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-mail-transport.h>
+#include <libedataserver/e-source-security.h>
+
+#define E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPagePrivate))
+
+struct _EMailConfigSummaryPagePrivate {
+	gchar *account_name;
+	ESource *account_source;
+	ESource *identity_source;
+	ESource *transport_source;
+	EMailConfigServiceBackend *account_backend;
+	EMailConfigServiceBackend *transport_backend;
+
+	gulong account_source_changed_id;
+	gulong identity_source_changed_id;
+	gulong transport_source_changed_id;
+
+	/* Widgets (not referenced) */
+	GtkLabel *name_label;
+	GtkLabel *address_label;
+	GtkLabel *recv_backend_label;
+	GtkLabel *recv_host_label;
+	GtkLabel *recv_user_label;
+	GtkLabel *recv_security_label;
+	GtkLabel *send_backend_label;
+	GtkLabel *send_host_label;
+	GtkLabel *send_user_label;
+	GtkLabel *send_security_label;
+	GtkEntry *account_name_entry;
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT_NAME,
+	PROP_ACCOUNT_BACKEND,
+	PROP_ACCOUNT_SOURCE,
+	PROP_IDENTITY_SOURCE,
+	PROP_TRANSPORT_BACKEND,
+	PROP_TRANSPORT_SOURCE
+};
+
+enum {
+	REFRESH,
+	LAST_SIGNAL
+};
+
+static gulong signals[LAST_SIGNAL];
+
+/* Forward Declarations */
+static void	e_mail_config_summary_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigSummaryPage,
+	e_mail_config_summary_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_summary_page_interface_init))
+
+/* Helper for mail_config_summary_page_refresh() */
+static void
+mail_config_summary_page_refresh_auth_labels (ESource *source,
+                                              GtkLabel *host_label,
+                                              GtkLabel *user_label)
+{
+	ESourceAuthentication *extension;
+	const gchar *extension_name;
+	const gchar *value;
+
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	if (!e_source_has_extension (source, extension_name))
+		return;
+
+	extension = e_source_get_extension (source, extension_name);
+
+	value = e_source_authentication_get_host (extension);
+	gtk_label_set_text (host_label, value);
+
+	value = e_source_authentication_get_user (extension);
+	gtk_label_set_text (user_label, value);
+}
+
+/* Helper for mail_config_summary_page_refresh() */
+static void
+mail_config_summary_page_refresh_security_label (ESource *source,
+                                                 GtkLabel *security_label)
+{
+	GEnumClass *enum_class;
+	GEnumValue *enum_value;
+	ESourceSecurity *extension;
+	const gchar *extension_name;
+	const gchar *value;
+
+	extension_name = E_SOURCE_EXTENSION_SECURITY;
+	if (!e_source_has_extension (source, extension_name))
+		return;
+
+	extension = e_source_get_extension (source, extension_name);
+
+	/* XXX This is a pain in the butt, but we want to avoid hard-coding
+	 *     string values from the CamelNetworkSecurityMethod enum class
+	 *     in case they change in the future. */
+	enum_class = g_type_class_ref (CAMEL_TYPE_NETWORK_SECURITY_METHOD);
+	value = e_source_security_get_method (extension);
+	if (value != NULL)
+		enum_value = g_enum_get_value_by_nick (enum_class, value);
+	else
+		enum_value = NULL;
+	if (enum_value == NULL) {
+		gtk_label_set_text (security_label, value);
+	} else switch ((CamelNetworkSecurityMethod) enum_value->value) {
+		case CAMEL_NETWORK_SECURITY_METHOD_NONE:
+			gtk_label_set_text (security_label, _("None"));
+			break;
+		case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT:
+			gtk_label_set_text (security_label, _("SSL"));
+			break;
+		case CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT:
+			gtk_label_set_text (security_label, _("TLS"));
+			break;
+	}
+	g_type_class_unref (enum_class);
+}
+
+static void
+mail_config_summary_page_source_changed (ESource *source,
+                                         EMailConfigSummaryPage *page)
+{
+	e_mail_config_summary_page_refresh (page);
+}
+
+static void
+mail_config_summary_page_set_property (GObject *object,
+                                       guint property_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_NAME:
+			e_mail_config_summary_page_set_account_name (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object),
+				g_value_get_string (value));
+			return;
+
+		case PROP_ACCOUNT_BACKEND:
+			e_mail_config_summary_page_set_account_backend (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			e_mail_config_summary_page_set_identity_source (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_TRANSPORT_BACKEND:
+			e_mail_config_summary_page_set_transport_backend (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_summary_page_get_property (GObject *object,
+                                       guint property_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_NAME:
+			g_value_set_string (
+				value,
+				e_mail_config_summary_page_get_account_name (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object)));
+			return;
+
+		case PROP_ACCOUNT_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_summary_page_get_account_backend (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object)));
+			return;
+
+		case PROP_ACCOUNT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_summary_page_get_account_source (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object)));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_summary_page_get_identity_source (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object)));
+			return;
+
+		case PROP_TRANSPORT_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_summary_page_get_transport_backend (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object)));
+			return;
+
+		case PROP_TRANSPORT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_summary_page_get_transport_source (
+				E_MAIL_CONFIG_SUMMARY_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_summary_page_dispose (GObject *object)
+{
+	EMailConfigSummaryPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (object);
+
+	if (priv->account_source != NULL) {
+		g_signal_handler_disconnect (
+			priv->account_source,
+			priv->account_source_changed_id);
+		g_object_unref (priv->account_source);
+		priv->account_source = NULL;
+		priv->account_source_changed_id = 0;
+	}
+
+	if (priv->identity_source != NULL) {
+		g_signal_handler_disconnect (
+			priv->identity_source,
+			priv->identity_source_changed_id);
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->transport_source != NULL) {
+		g_signal_handler_disconnect (
+			priv->transport_source,
+			priv->transport_source_changed_id);
+		g_object_unref (priv->transport_source);
+		priv->transport_source = NULL;
+		priv->transport_source_changed_id = 0;
+	}
+
+	if (priv->account_backend != NULL) {
+		g_object_unref (priv->account_backend);
+		priv->account_backend = NULL;
+	}
+
+	if (priv->transport_backend != NULL) {
+		g_object_unref (priv->transport_backend);
+		priv->transport_backend = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_summary_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_summary_page_finalize (GObject *object)
+{
+	EMailConfigSummaryPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (object);
+
+	g_free (priv->account_name);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_summary_page_parent_class)->
+		finalize (object);
+}
+
+static void
+mail_config_summary_page_constructed (GObject *object)
+{
+	EMailConfigSummaryPage *page;
+	GtkLabel *label;
+	GtkWidget *widget;
+	GtkWidget *container;
+	GtkSizeGroup *size_group;
+	const gchar *text;
+	gchar *markup;
+
+	page = E_MAIL_CONFIG_SUMMARY_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_summary_page_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	/* This page is dense with information,
+	 * so put extra space between sections. */
+	gtk_box_set_spacing (GTK_BOX (page), 24);
+
+	size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+	text = _("This is a summary of the settings which will be used "
+		 "to access your mail.");
+	widget = gtk_label_new (text);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	/*** Account Information ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Account Information");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Type the name by which you would like to refer to "
+		 "this account.\nFor example, \"Work\" or \"Personal\".");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 2, 1);
+	gtk_widget_show (widget);
+
+	text = _("_Name:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+	page->priv->account_name_entry = GTK_ENTRY (widget);
+	gtk_widget_show (widget);
+
+	/* This entry affects the "check-complete" result. */
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (e_mail_config_page_changed), page);
+
+	g_object_bind_property (
+		widget, "text",
+		page, "account-name",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/*** Details ***/
+
+	widget = gtk_grid_new ();
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 12);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("Personal Details");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 3, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Full Name:");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 2, 1);
+	page->priv->name_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	text = _("Email Address:");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 2, 1);
+	page->priv->address_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	text = _("Receiving");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_margin_top (widget, 6);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Sending");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_margin_top (widget, 6);
+	gtk_size_group_add_widget (size_group, widget);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 3, 1, 1);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	text = _("Server Type:");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 4, 1, 1);
+	page->priv->recv_backend_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 4, 1, 1);
+	page->priv->send_backend_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	text = _("Server:");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 5, 1, 1);
+	page->priv->recv_host_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 5, 1, 1);
+	page->priv->send_host_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	text = _("Username:");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 6, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 6, 1, 1);
+	page->priv->recv_user_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 6, 1, 1);
+	page->priv->send_user_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	text = _("Security:");
+	widget = gtk_label_new (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 7, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 7, 1, 1);
+	page->priv->recv_security_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 7, 1, 1);
+	page->priv->send_security_label = GTK_LABEL (widget);
+	gtk_widget_show (widget);
+
+	g_object_unref (size_group);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+mail_config_summary_page_refresh (EMailConfigSummaryPage *page)
+{
+	EMailConfigSummaryPagePrivate *priv;
+	ESource *source;
+	gboolean account_is_transport = FALSE;
+
+	priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page);
+
+	/* Clear all labels. */
+	gtk_label_set_text (priv->name_label, "");
+	gtk_label_set_text (priv->address_label, "");
+	gtk_label_set_text (priv->recv_backend_label, "");
+	gtk_label_set_text (priv->recv_host_label, "");
+	gtk_label_set_text (priv->recv_user_label, "");
+	gtk_label_set_text (priv->recv_security_label, "");
+	gtk_label_set_text (priv->send_backend_label, "");
+	gtk_label_set_text (priv->send_host_label, "");
+	gtk_label_set_text (priv->send_user_label, "");
+	gtk_label_set_text (priv->send_security_label, "");
+
+	source = e_mail_config_summary_page_get_identity_source (page);
+
+	if (source != NULL) {
+		ESourceMailIdentity *extension;
+		const gchar *extension_name;
+		const gchar *value;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		extension = e_source_get_extension (source, extension_name);
+
+		value = e_source_mail_identity_get_name (extension);
+		gtk_label_set_text (priv->name_label, value);
+
+		value = e_source_mail_identity_get_address (extension);
+		gtk_label_set_text (priv->address_label, value);
+	}
+
+	source = e_mail_config_summary_page_get_account_source (page);
+
+	if (source != NULL) {
+		ESourceBackend *extension;
+		const gchar *extension_name;
+		const gchar *value;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+		extension = e_source_get_extension (source, extension_name);
+
+		value = e_source_backend_get_backend_name (extension);
+		gtk_label_set_text (priv->recv_backend_label, value);
+
+		mail_config_summary_page_refresh_auth_labels (
+			source,
+			priv->recv_host_label,
+			priv->recv_user_label);
+
+		mail_config_summary_page_refresh_security_label (
+			source,
+			priv->recv_security_label);
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+		if (e_source_has_extension (source, extension_name))
+			account_is_transport = TRUE;
+	}
+
+	if (account_is_transport)
+		source = e_mail_config_summary_page_get_account_source (page);
+	else
+		source = e_mail_config_summary_page_get_transport_source (page);
+
+	if (source != NULL) {
+		ESourceBackend *extension;
+		const gchar *extension_name;
+		const gchar *value;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+		extension = e_source_get_extension (source, extension_name);
+
+		value = e_source_backend_get_backend_name (extension);
+		gtk_label_set_text (priv->send_backend_label, value);
+
+		mail_config_summary_page_refresh_auth_labels (
+			source,
+			priv->send_host_label,
+			priv->send_user_label);
+
+		mail_config_summary_page_refresh_security_label (
+			source,
+			priv->send_security_label);
+	}
+}
+
+static gboolean
+mail_config_summary_page_check_complete (EMailConfigPage *page)
+{
+	EMailConfigSummaryPagePrivate *priv;
+	gchar *stripped_text;
+	const gchar *text;
+	gboolean complete;
+
+	priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page);
+
+	/* Strip the account name of leading and trailing
+	 * whitespace as e_source_set_display_name() does. */
+	text = gtk_entry_get_text (priv->account_name_entry);
+	stripped_text = g_strstrip (g_strdup ((text != NULL) ? text : ""));
+	complete = (*stripped_text != '\0');
+	g_free (stripped_text);
+
+	return complete;
+}
+
+static void
+mail_config_summary_page_commit_changes (EMailConfigPage *page,
+                                         GQueue *source_queue)
+{
+	EMailConfigSummaryPagePrivate *priv;
+	EMailConfigServiceBackend *backend;
+	ESource *account_source;
+	ESource *identity_source;
+	ESource *transport_source;
+	ESource *collection_source;
+	ESourceExtension *extension;
+	const gchar *extension_name;
+	const gchar *parent_uid;
+	const gchar *text;
+
+	priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page);
+
+	backend = e_mail_config_summary_page_get_account_backend (
+		E_MAIL_CONFIG_SUMMARY_PAGE (page));
+	account_source =
+		e_mail_config_service_backend_get_source (backend);
+	collection_source =
+		e_mail_config_service_backend_get_collection (backend);
+
+	/* The transport backend is NULL when the Sending Page is hidden. */
+	backend = e_mail_config_summary_page_get_transport_backend (
+		E_MAIL_CONFIG_SUMMARY_PAGE (page));
+	transport_source = (backend != NULL) ?
+		e_mail_config_service_backend_get_source (backend) : NULL;
+
+	identity_source = e_mail_config_summary_page_get_identity_source (
+		E_MAIL_CONFIG_SUMMARY_PAGE (page));
+
+	text = gtk_entry_get_text (priv->account_name_entry);
+	e_source_set_display_name (account_source, text);
+	e_source_set_display_name (identity_source, text);
+	if (transport_source != NULL)
+		e_source_set_display_name (transport_source, text);
+	if (collection_source != NULL)
+		e_source_set_display_name (collection_source, text);
+
+	/* Setup parent/child relationships and cross-references. */
+
+	if (collection_source != NULL) {
+		parent_uid = e_source_get_uid (collection_source);
+		e_source_set_parent (account_source, parent_uid);
+		e_source_set_parent (identity_source, parent_uid);
+		if (transport_source != NULL)
+			e_source_set_parent (transport_source, parent_uid);
+	} else {
+		parent_uid = e_source_get_uid (account_source);
+		e_source_set_parent (identity_source, parent_uid);
+		if (transport_source != NULL)
+			e_source_set_parent (transport_source, parent_uid);
+	}
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (account_source, extension_name);
+	e_source_mail_account_set_identity_uid (
+		E_SOURCE_MAIL_ACCOUNT (extension),
+		e_source_get_uid (identity_source));
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	extension = e_source_get_extension (identity_source, extension_name);
+	if (transport_source != NULL)
+		e_source_mail_submission_set_transport_uid (
+			E_SOURCE_MAIL_SUBMISSION (extension),
+			e_source_get_uid (transport_source));
+}
+
+static void
+e_mail_config_summary_page_class_init (EMailConfigSummaryPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigSummaryPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_summary_page_set_property;
+	object_class->get_property = mail_config_summary_page_get_property;
+	object_class->dispose = mail_config_summary_page_dispose;
+	object_class->finalize = mail_config_summary_page_finalize;
+	object_class->constructed = mail_config_summary_page_constructed;
+
+	class->refresh = mail_config_summary_page_refresh;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_NAME,
+		g_param_spec_string (
+			"account-name",
+			"Account Name",
+			"Display name for the mail account",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_BACKEND,
+		g_param_spec_object (
+			"account-backend",
+			"Account Backend",
+			"Active mail account service backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_SOURCE,
+		g_param_spec_object (
+			"account-source",
+			"Account Source",
+			"Mail account source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TRANSPORT_BACKEND,
+		g_param_spec_object (
+			"transport-backend",
+			"Transport Backend",
+			"Active mail transport service backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TRANSPORT_SOURCE,
+		g_param_spec_object (
+			"transport-source",
+			"Transport Source",
+			"Mail transport source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	signals[REFRESH] = g_signal_new (
+		"refresh",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailConfigSummaryPageClass, refresh),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+}
+
+static void
+e_mail_config_summary_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Account Summary");
+	interface->sort_order = E_MAIL_CONFIG_SUMMARY_PAGE_SORT_ORDER;
+	interface->check_complete = mail_config_summary_page_check_complete;
+	interface->commit_changes = mail_config_summary_page_commit_changes;
+}
+
+static void
+e_mail_config_summary_page_init (EMailConfigSummaryPage *page)
+{
+	page->priv = E_MAIL_CONFIG_SUMMARY_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_summary_page_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, NULL);
+}
+
+void
+e_mail_config_summary_page_refresh (EMailConfigSummaryPage *page)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page));
+
+	g_signal_emit (page, signals[REFRESH], 0);
+}
+
+const gchar *
+e_mail_config_summary_page_get_account_name (EMailConfigSummaryPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL);
+
+	return page->priv->account_name;
+}
+
+void
+e_mail_config_summary_page_set_account_name (EMailConfigSummaryPage *page,
+                                             const gchar *account_name)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page));
+
+	if (account_name == NULL)
+		account_name = "";
+
+	g_free (page->priv->account_name);
+	page->priv->account_name = g_strdup (account_name);
+
+	g_object_notify (G_OBJECT (page), "account-name");
+}
+
+EMailConfigServiceBackend *
+e_mail_config_summary_page_get_account_backend (EMailConfigSummaryPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL);
+
+	return page->priv->account_backend;
+}
+
+void
+e_mail_config_summary_page_set_account_backend (EMailConfigSummaryPage *page,
+                                                EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page));
+
+	if (backend != NULL) {
+		g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+		g_object_ref (backend);
+	}
+
+	if (page->priv->account_backend != NULL)
+		g_object_unref (page->priv->account_backend);
+
+	page->priv->account_backend = backend;
+
+	if (page->priv->account_source != NULL) {
+		g_signal_handler_disconnect (
+			page->priv->account_source,
+			page->priv->account_source_changed_id);
+		g_object_unref (page->priv->account_source);
+		page->priv->account_source = NULL;
+		page->priv->account_source_changed_id = 0;
+	}
+
+	if (backend != NULL) {
+		ESource *source;
+		gulong handler_id;
+
+		source = e_mail_config_service_backend_get_source (backend);
+
+		handler_id = g_signal_connect (
+			source, "changed",
+			G_CALLBACK (mail_config_summary_page_source_changed),
+			page);
+
+		page->priv->account_source = g_object_ref (source);
+		page->priv->account_source_changed_id = handler_id;
+	}
+
+	g_object_freeze_notify (G_OBJECT (page));
+	g_object_notify (G_OBJECT (page), "account-backend");
+	g_object_notify (G_OBJECT (page), "account-source");
+	g_object_thaw_notify (G_OBJECT (page));
+
+	e_mail_config_summary_page_refresh (page);
+}
+
+ESource *
+e_mail_config_summary_page_get_account_source (EMailConfigSummaryPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL);
+
+	return page->priv->account_source;
+}
+
+ESource *
+e_mail_config_summary_page_get_identity_source (EMailConfigSummaryPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL);
+
+	return page->priv->identity_source;
+}
+
+void
+e_mail_config_summary_page_set_identity_source (EMailConfigSummaryPage *page,
+                                                ESource *identity_source)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page));
+
+	if (identity_source != NULL) {
+		g_return_if_fail (E_IS_SOURCE (identity_source));
+		g_object_ref (identity_source);
+	}
+
+	if (page->priv->identity_source != NULL) {
+		g_signal_handler_disconnect (
+			page->priv->identity_source,
+			page->priv->identity_source_changed_id);
+		g_object_unref (page->priv->identity_source);
+	}
+
+	page->priv->identity_source = identity_source;
+	page->priv->identity_source_changed_id = 0;
+
+	if (identity_source != NULL) {
+		gulong handler_id;
+
+		handler_id = g_signal_connect (
+			identity_source, "changed",
+			G_CALLBACK (mail_config_summary_page_source_changed),
+			page);
+
+		page->priv->identity_source_changed_id = handler_id;
+	}
+
+	g_object_notify (G_OBJECT (page), "identity-source");
+
+	e_mail_config_summary_page_refresh (page);
+}
+
+EMailConfigServiceBackend *
+e_mail_config_summary_page_get_transport_backend (EMailConfigSummaryPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL);
+
+	return page->priv->transport_backend;
+}
+
+void
+e_mail_config_summary_page_set_transport_backend (EMailConfigSummaryPage *page,
+                                                  EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page));
+
+	if (backend != NULL) {
+		g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+		g_object_ref (backend);
+	}
+
+	if (page->priv->transport_backend != NULL)
+		g_object_unref (page->priv->transport_backend);
+
+	page->priv->transport_backend = backend;
+
+	if (page->priv->transport_source != NULL) {
+		g_signal_handler_disconnect (
+			page->priv->transport_source,
+			page->priv->transport_source_changed_id);
+		g_object_unref (page->priv->transport_source);
+		page->priv->transport_source = NULL;
+		page->priv->transport_source_changed_id = 0;
+	}
+
+	if (backend != NULL) {
+		ESource *source;
+		gulong handler_id;
+
+		source = e_mail_config_service_backend_get_source (backend);
+
+		handler_id = g_signal_connect (
+			source, "changed",
+			G_CALLBACK (mail_config_summary_page_source_changed),
+			page);
+
+		page->priv->transport_source = g_object_ref (source);
+		page->priv->transport_source_changed_id = handler_id;
+	}
+
+	g_object_freeze_notify (G_OBJECT (page));
+	g_object_notify (G_OBJECT (page), "transport-backend");
+	g_object_notify (G_OBJECT (page), "transport-source");
+	g_object_thaw_notify (G_OBJECT (page));
+
+	e_mail_config_summary_page_refresh (page);
+}
+
+ESource *
+e_mail_config_summary_page_get_transport_source (EMailConfigSummaryPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SUMMARY_PAGE (page), NULL);
+
+	return page->priv->transport_source;
+}
+
diff --git a/mail/e-mail-config-summary-page.h b/mail/e-mail-config-summary-page.h
new file mode 100644
index 0000000..564207c
--- /dev/null
+++ b/mail/e-mail-config-summary-page.h
@@ -0,0 +1,101 @@
+/*
+ * e-mail-config-summary-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_SUMMARY_PAGE_H
+#define E_MAIL_CONFIG_SUMMARY_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_SUMMARY_PAGE \
+	(e_mail_config_summary_page_get_type ())
+#define E_MAIL_CONFIG_SUMMARY_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPage))
+#define E_MAIL_CONFIG_SUMMARY_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPageClass))
+#define E_IS_MAIL_CONFIG_SUMMARY_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE))
+#define E_IS_MAIL_CONFIG_SUMMARY_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE))
+#define E_MAIL_CONFIG_SUMMARY_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_SUMMARY_PAGE, EMailConfigSummaryPageClass))
+
+#define E_MAIL_CONFIG_SUMMARY_PAGE_SORT_ORDER (500)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigSummaryPage EMailConfigSummaryPage;
+typedef struct _EMailConfigSummaryPageClass EMailConfigSummaryPageClass;
+typedef struct _EMailConfigSummaryPagePrivate EMailConfigSummaryPagePrivate;
+
+struct _EMailConfigSummaryPage {
+	GtkBox parent;
+	EMailConfigSummaryPagePrivate *priv;
+};
+
+struct _EMailConfigSummaryPageClass {
+	GtkBoxClass parent_class;
+
+	/* Signals */
+	void		(*refresh)		(EMailConfigSummaryPage *page);
+};
+
+GType		e_mail_config_summary_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_summary_page_new	(void);
+void		e_mail_config_summary_page_refresh
+						(EMailConfigSummaryPage *page);
+const gchar *	e_mail_config_summary_page_get_account_name
+						(EMailConfigSummaryPage *page);
+void		e_mail_config_summary_page_set_account_name
+						(EMailConfigSummaryPage *page,
+						 const gchar *account_name);
+EMailConfigServiceBackend *
+		e_mail_config_summary_page_get_account_backend
+						(EMailConfigSummaryPage *page);
+void		e_mail_config_summary_page_set_account_backend
+						(EMailConfigSummaryPage *page,
+						 EMailConfigServiceBackend *backend);
+ESource *	e_mail_config_summary_page_get_account_source
+						(EMailConfigSummaryPage *page);
+ESource *	e_mail_config_summary_page_get_identity_source
+						(EMailConfigSummaryPage *page);
+void		e_mail_config_summary_page_set_identity_source
+						(EMailConfigSummaryPage *page,
+						 ESource *identity_source);
+EMailConfigServiceBackend *
+		e_mail_config_summary_page_get_transport_backend
+						(EMailConfigSummaryPage *page);
+void		e_mail_config_summary_page_set_transport_backend
+						(EMailConfigSummaryPage *page,
+						 EMailConfigServiceBackend *backend);
+ESource *	e_mail_config_summary_page_get_transport_source
+						(EMailConfigSummaryPage *page);
+
+#endif /* E_MAIL_CONFIG_SUMMARY_PAGE_H */
+
diff --git a/mail/e-mail-config-welcome-page.c b/mail/e-mail-config-welcome-page.c
new file mode 100644
index 0000000..6cb9fd1
--- /dev/null
+++ b/mail/e-mail-config-welcome-page.c
@@ -0,0 +1,203 @@
+/*
+ * e-mail-config-welcome-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-welcome-page.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+
+#define E_MAIL_CONFIG_WELCOME_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePagePrivate))
+
+struct _EMailConfigWelcomePagePrivate {
+	gchar *text;
+};
+
+enum {
+	PROP_0,
+	PROP_TEXT
+};
+
+/* Forward Declarations */
+static void	e_mail_config_welcome_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigWelcomePage,
+	e_mail_config_welcome_page,
+	GTK_TYPE_BOX,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_welcome_page_interface_init))
+
+static void
+mail_config_welcome_page_set_property (GObject *object,
+                                       guint property_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_TEXT:
+			e_mail_config_welcome_page_set_text (
+				E_MAIL_CONFIG_WELCOME_PAGE (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_welcome_page_get_property (GObject *object,
+                                       guint property_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_TEXT:
+			g_value_set_string (
+				value,
+				e_mail_config_welcome_page_get_text (
+				E_MAIL_CONFIG_WELCOME_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_welcome_page_finalize (GObject *object)
+{
+	EMailConfigWelcomePagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_WELCOME_PAGE_GET_PRIVATE (object);
+
+	g_free (priv->text);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_welcome_page_parent_class)->
+		finalize (object);
+}
+
+static void
+mail_config_welcome_page_constructed (GObject *object)
+{
+	EMailConfigWelcomePage *page;
+	GtkWidget *widget;
+
+	page = E_MAIL_CONFIG_WELCOME_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_welcome_page_parent_class)->
+		constructed (object);
+
+	gtk_orientable_set_orientation (
+		GTK_ORIENTABLE (page), GTK_ORIENTATION_VERTICAL);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	gtk_widget_set_valign (GTK_WIDGET (page), GTK_ALIGN_CENTER);
+
+	widget = gtk_label_new (NULL);
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		page, "text",
+		widget, "label",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+e_mail_config_welcome_page_class_init (EMailConfigWelcomePageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigWelcomePagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_welcome_page_set_property;
+	object_class->get_property = mail_config_welcome_page_get_property;
+	object_class->finalize = mail_config_welcome_page_finalize;
+	object_class->constructed = mail_config_welcome_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TEXT,
+		g_param_spec_string (
+			"text",
+			"Text",
+			"Welcome message",
+			_("Welcome to the Evolution Mail Configuration "
+			  "Assistant.\n\nClick \"Continue\" to begin."),
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_welcome_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Welcome");
+	interface->page_type = GTK_ASSISTANT_PAGE_INTRO;
+	interface->sort_order = E_MAIL_CONFIG_WELCOME_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_welcome_page_init (EMailConfigWelcomePage *page)
+{
+	page->priv = E_MAIL_CONFIG_WELCOME_PAGE_GET_PRIVATE (page);
+}
+
+EMailConfigPage *
+e_mail_config_welcome_page_new (void)
+{
+	return g_object_new (E_TYPE_MAIL_CONFIG_WELCOME_PAGE, NULL);
+}
+
+const gchar *
+e_mail_config_welcome_page_get_text (EMailConfigWelcomePage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_WELCOME_PAGE (page), NULL);
+
+	return page->priv->text;
+}
+
+void
+e_mail_config_welcome_page_set_text (EMailConfigWelcomePage *page,
+                                     const gchar *text)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_WELCOME_PAGE (page));
+
+	g_free (page->priv->text);
+	page->priv->text = g_strdup ((text != NULL) ? text : "");
+
+	g_object_notify (G_OBJECT (page), "text");
+}
+
diff --git a/mail/e-mail-config-welcome-page.h b/mail/e-mail-config-welcome-page.h
new file mode 100644
index 0000000..a7665ec
--- /dev/null
+++ b/mail/e-mail-config-welcome-page.h
@@ -0,0 +1,75 @@
+/*
+ * e-mail-config-welcome-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_WELCOME_PAGE_H
+#define E_MAIL_CONFIG_WELCOME_PAGE_H
+
+#include <gtk/gtk.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_WELCOME_PAGE \
+	(e_mail_config_welcome_page_get_type ())
+#define E_MAIL_CONFIG_WELCOME_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePage))
+#define E_MAIL_CONFIG_WELCOME_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePageClass))
+#define E_IS_MAIL_CONFIG_WELCOME_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE))
+#define E_IS_MAIL_CONFIG_WELCOME_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_WELCOME_PAGE))
+#define E_MAIL_CONFIG_WELCOME_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_WELCOME_PAGE, EMailConfigWelcomePageClass))
+
+#define E_MAIL_CONFIG_WELCOME_PAGE_SORT_ORDER (0)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigWelcomePage EMailConfigWelcomePage;
+typedef struct _EMailConfigWelcomePageClass EMailConfigWelcomePageClass;
+typedef struct _EMailConfigWelcomePagePrivate EMailConfigWelcomePagePrivate;
+
+struct _EMailConfigWelcomePage {
+	GtkBox parent;
+	EMailConfigWelcomePagePrivate *priv;
+};
+
+struct _EMailConfigWelcomePageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_welcome_page_get_type
+						(void) G_GNUC_CONST;
+EMailConfigPage *
+		e_mail_config_welcome_page_new	(void);
+const gchar *	e_mail_config_welcome_page_get_text
+						(EMailConfigWelcomePage *page);
+void		e_mail_config_welcome_page_set_text
+						(EMailConfigWelcomePage *page,
+						 const gchar *text);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_WELCOME_PAGE_H */
+
diff --git a/mail/e-mail-config-window.c b/mail/e-mail-config-window.c
new file mode 100644
index 0000000..fceb523
--- /dev/null
+++ b/mail/e-mail-config-window.c
@@ -0,0 +1,524 @@
+/*
+ * e-mail-config-window.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-window.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-collection.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-submission.h>
+
+#include <libevolution-utils/e-alert-dialog.h>
+#include <libevolution-utils/e-alert-sink.h>
+#include <misc/e-alert-bar.h>
+
+#include <mail/e-mail-config-notebook.h>
+#include <mail/e-mail-config-sidebar.h>
+
+#define E_MAIL_CONFIG_WINDOW_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindowPrivate))
+
+struct _EMailConfigWindowPrivate {
+	EMailSession *session;
+	ESource *original_source;
+
+	/* Scratch Sources */
+	ESource *account_source;
+	ESource *identity_source;
+	ESource *transport_source;
+	ESource *collection_source;  /* optional */
+
+	GtkWidget *notebook;  /* not referenced */
+	GtkWidget *alert_bar; /* not referenced */
+};
+
+enum {
+	PROP_0,
+	PROP_ORIGINAL_SOURCE,
+	PROP_SESSION
+};
+
+/* Forward Declarations */
+static void	e_mail_config_window_alert_sink_init
+					(EAlertSinkInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailConfigWindow,
+	e_mail_config_window,
+	GTK_TYPE_DIALOG,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_ALERT_SINK,
+		e_mail_config_window_alert_sink_init))
+
+static ESource *
+mail_config_window_clone_source (ESource *source)
+{
+	ESource *clone;
+	GDBusObject *dbus_object;
+
+	dbus_object = e_source_ref_dbus_object (source);
+
+	clone = e_source_new (dbus_object, NULL, NULL);
+
+	if (dbus_object != NULL)
+		g_object_unref (dbus_object);
+
+	return clone;
+}
+
+static void
+mail_config_window_setup_scratch_sources (EMailConfigWindow *window)
+{
+	ESource *source;
+	ESource *scratch_source;
+	ESourceRegistry *registry;
+	ESourceMailAccount *account_ext;
+	ESourceMailSubmission *submission_ext;
+	EMailSession *session;
+	const gchar *extension_name;
+	const gchar *uid;
+
+	session = e_mail_config_window_get_session (window);
+	registry = e_mail_session_get_registry (session);
+
+	source = window->priv->original_source;
+	scratch_source = mail_config_window_clone_source (source);
+	window->priv->account_source = scratch_source;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	account_ext = e_source_get_extension (source, extension_name);
+	uid = e_source_mail_account_get_identity_uid (account_ext);
+	source = e_source_registry_ref_source (registry, uid);
+	scratch_source = mail_config_window_clone_source (source);
+	window->priv->identity_source = scratch_source;
+	g_object_unref (source);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	submission_ext = e_source_get_extension (source, extension_name);
+	uid = e_source_mail_submission_get_transport_uid (submission_ext);
+	source = e_source_registry_ref_source (registry, uid);
+	scratch_source = mail_config_window_clone_source (source);
+	window->priv->transport_source = scratch_source;
+	g_object_unref (source);
+
+	extension_name = E_SOURCE_EXTENSION_COLLECTION;
+	source = e_source_registry_find_extension (
+		registry, window->priv->original_source, extension_name);
+	if (source != NULL) {
+		scratch_source = mail_config_window_clone_source (source);
+		window->priv->collection_source = scratch_source;
+		g_object_unref (source);
+	}
+}
+
+static void
+mail_config_window_commit_cb (GObject *object,
+                              GAsyncResult *result,
+                              gpointer user_data)
+{
+	EMailConfigWindow *window;
+	EMailConfigNotebook *notebook;
+	GdkWindow *gdk_window;
+	GError *error = NULL;
+
+	window = E_MAIL_CONFIG_WINDOW (user_data);
+	notebook = E_MAIL_CONFIG_NOTEBOOK (object);
+
+	/* Set the cursor back to normal. */
+	gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+	gdk_window_set_cursor (gdk_window, NULL);
+
+	/* Allow user interaction with window content. */
+	gtk_widget_set_sensitive (GTK_WIDGET (window), TRUE);
+
+	e_mail_config_notebook_commit_finish (notebook, result, &error);
+
+	/* Ignore cancellations. */
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		g_object_unref (window);
+		g_error_free (error);
+
+	} else if (error != NULL) {
+		e_alert_submit (
+			E_ALERT_SINK (window),
+			"mail:session-message-error",
+			error->message, NULL);
+		g_object_unref (window);
+		g_error_free (error);
+
+	} else {
+		gtk_widget_destroy (GTK_WIDGET (window));
+	}
+}
+
+static void
+mail_config_window_commit (EMailConfigWindow *window)
+{
+	GdkCursor *gdk_cursor;
+	GdkWindow *gdk_window;
+	EMailConfigNotebook *notebook;
+
+	notebook = E_MAIL_CONFIG_NOTEBOOK (window->priv->notebook);
+
+	/* Clear any previous alerts. */
+	e_alert_bar_clear (E_ALERT_BAR (window->priv->alert_bar));
+
+	/* Make the cursor appear busy. */
+	gdk_cursor = gdk_cursor_new (GDK_WATCH);
+	gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+	gdk_window_set_cursor (gdk_window, gdk_cursor);
+	g_object_unref (gdk_cursor);
+
+	/* Prevent user interaction with window content. */
+	gtk_widget_set_sensitive (GTK_WIDGET (window), FALSE);
+
+	/* XXX This operation is not cancellable. */
+	e_mail_config_notebook_commit (
+		notebook, NULL,
+		mail_config_window_commit_cb,
+		g_object_ref (window));
+}
+
+static void
+mail_config_window_set_original_source (EMailConfigWindow *window,
+                                        ESource *original_source)
+{
+	g_return_if_fail (E_IS_SOURCE (original_source));
+	g_return_if_fail (window->priv->original_source == NULL);
+
+	window->priv->original_source = g_object_ref (original_source);
+}
+
+static void
+mail_config_window_set_session (EMailConfigWindow *window,
+                                EMailSession *session)
+{
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
+	g_return_if_fail (window->priv->session == NULL);
+
+	window->priv->session = g_object_ref (session);
+}
+
+static void
+mail_config_window_set_property (GObject *object,
+                                 guint property_id,
+                                 const GValue *value,
+                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ORIGINAL_SOURCE:
+			mail_config_window_set_original_source (
+				E_MAIL_CONFIG_WINDOW (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_SESSION:
+			mail_config_window_set_session (
+				E_MAIL_CONFIG_WINDOW (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_window_get_property (GObject *object,
+                                 guint property_id,
+                                 GValue *value,
+                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ORIGINAL_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_window_get_original_source (
+				E_MAIL_CONFIG_WINDOW (object)));
+			return;
+
+		case PROP_SESSION:
+			g_value_set_object (
+				value,
+				e_mail_config_window_get_session (
+				E_MAIL_CONFIG_WINDOW (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_window_dispose (GObject *object)
+{
+	EMailConfigWindowPrivate *priv;
+
+	priv = E_MAIL_CONFIG_WINDOW_GET_PRIVATE (object);
+
+	if (priv->session != NULL) {
+		g_object_unref (priv->session);
+		priv->session = NULL;
+	}
+
+	if (priv->original_source != NULL) {
+		g_object_unref (priv->original_source);
+		priv->original_source = NULL;
+	}
+
+	if (priv->account_source != NULL) {
+		g_object_unref (priv->account_source);
+		priv->account_source = NULL;
+	}
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->transport_source != NULL) {
+		g_object_unref (priv->transport_source);
+		priv->transport_source = NULL;
+	}
+
+	if (priv->collection_source != NULL) {
+		g_object_unref (priv->collection_source);
+		priv->collection_source = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_window_parent_class)->dispose (object);
+}
+
+static void
+mail_config_window_constructed (GObject *object)
+{
+	EMailConfigWindow *window;
+	GtkWidget *container;
+	GtkWidget *widget;
+
+	window = E_MAIL_CONFIG_WINDOW (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_window_parent_class)->
+		constructed (object);
+
+	mail_config_window_setup_scratch_sources (window);
+
+	gtk_container_set_border_width (GTK_CONTAINER (window), 5);
+	gtk_window_set_title (GTK_WINDOW (window), _("Account Editor"));
+	gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
+
+	gtk_dialog_add_buttons (
+		GTK_DIALOG (window),
+		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+		GTK_STOCK_OK, GTK_RESPONSE_OK,
+		NULL);
+
+	container = gtk_dialog_get_content_area (GTK_DIALOG (window));
+
+	widget = gtk_grid_new ();
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 5);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = e_alert_bar_new ();
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+	window->priv->alert_bar = widget;  /* not referenced */
+	/* EAlertBar controls its own visibility. */
+
+	/* Add an extra-wide margin to the left and bottom.
+	 *
+	 * XXX The bottom margin is tricky.  We want a 24px margin between
+	 *     the notebook and the dialog action buttons, but we have to
+	 *     take style property defaults into consideration:
+	 *
+	 *     24 - action-area-border (5) - content-area-border (2) = 17
+	 */
+	widget = e_mail_config_notebook_new (
+		window->priv->session,
+		window->priv->account_source,
+		window->priv->identity_source,
+		window->priv->transport_source,
+		window->priv->collection_source);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_vexpand (widget, TRUE);
+	gtk_widget_set_margin_left (widget, 24);
+	gtk_widget_set_margin_bottom (widget, 17);
+	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 0, 1, 1);
+	window->priv->notebook = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	widget = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
+	gtk_widget_set_vexpand (widget, TRUE);
+	gtk_widget_set_valign (widget, GTK_ALIGN_FILL);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1);
+	gtk_widget_show (widget);
+
+	widget = e_mail_config_sidebar_new (
+		E_MAIL_CONFIG_NOTEBOOK (window->priv->notebook));
+	gtk_widget_set_vexpand (widget, TRUE);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	gtk_widget_show (widget);
+
+	/* Make the Apply button insensitive when required
+	 * fields in the notebook pages are incomplete. */
+
+	widget = gtk_dialog_get_widget_for_response (
+		GTK_DIALOG (window), GTK_RESPONSE_OK);
+
+	g_object_bind_property (
+		window->priv->notebook, "complete",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE);
+}
+
+static void
+mail_config_window_response (GtkDialog *dialog,
+                             gint response_id)
+{
+	/* Do not chain up.  GtkDialog does not implement this method. */
+
+	switch (response_id) {
+		case GTK_RESPONSE_OK:
+			mail_config_window_commit (
+				E_MAIL_CONFIG_WINDOW (dialog));
+			break;
+		case GTK_RESPONSE_CANCEL:
+			gtk_widget_destroy (GTK_WIDGET (dialog));
+			break;
+		default:
+			break;
+	}
+}
+
+static void
+mail_config_window_submit_alert (EAlertSink *alert_sink,
+                                 EAlert *alert)
+{
+	EMailConfigWindowPrivate *priv;
+	EAlertBar *alert_bar;
+	GtkWidget *dialog;
+	GtkWindow *parent;
+
+	priv = E_MAIL_CONFIG_WINDOW_GET_PRIVATE (alert_sink);
+
+	switch (e_alert_get_message_type (alert)) {
+		case GTK_MESSAGE_INFO:
+		case GTK_MESSAGE_WARNING:
+		case GTK_MESSAGE_ERROR:
+			alert_bar = E_ALERT_BAR (priv->alert_bar);
+			e_alert_bar_add_alert (alert_bar, alert);
+			break;
+
+		default:
+			parent = GTK_WINDOW (alert_sink);
+			dialog = e_alert_dialog_new (parent, alert);
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+			break;
+	}
+}
+
+static void
+e_mail_config_window_class_init (EMailConfigWindowClass *class)
+{
+	GObjectClass *object_class;
+	GtkDialogClass *dialog_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigWindowPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_window_set_property;
+	object_class->get_property = mail_config_window_get_property;
+	object_class->dispose = mail_config_window_dispose;
+	object_class->constructed = mail_config_window_constructed;
+
+	dialog_class = GTK_DIALOG_CLASS (class);
+	dialog_class->response = mail_config_window_response;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ORIGINAL_SOURCE,
+		g_param_spec_object (
+			"original-source",
+			"Original Source",
+			"Original mail account source",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SESSION,
+		g_param_spec_object (
+			"session",
+			"Session",
+			"Mail session",
+			E_TYPE_MAIL_SESSION,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_window_alert_sink_init (EAlertSinkInterface *interface)
+{
+	interface->submit_alert = mail_config_window_submit_alert;
+}
+
+static void
+e_mail_config_window_init (EMailConfigWindow *window)
+{
+	window->priv = E_MAIL_CONFIG_WINDOW_GET_PRIVATE (window);
+}
+
+GtkWidget *
+e_mail_config_window_new (EMailSession *session,
+                          ESource *original_source)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (original_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_WINDOW,
+		"original-source", original_source,
+		"session", session, NULL);
+}
+
+EMailSession *
+e_mail_config_window_get_session (EMailConfigWindow *window)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_WINDOW (window), NULL);
+
+	return window->priv->session;
+}
+
+ESource *
+e_mail_config_window_get_original_source (EMailConfigWindow *window)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_WINDOW (window), NULL);
+
+	return window->priv->original_source;
+}
+
diff --git a/mail/e-mail-config-window.h b/mail/e-mail-config-window.h
new file mode 100644
index 0000000..78a7c07
--- /dev/null
+++ b/mail/e-mail-config-window.h
@@ -0,0 +1,71 @@
+/*
+ * e-mail-config-window.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_WINDOW_H
+#define E_MAIL_CONFIG_WINDOW_H
+
+#include <gtk/gtk.h>
+
+#include <libemail-engine/e-mail-session.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_WINDOW \
+	(e_mail_config_window_get_type ())
+#define E_MAIL_CONFIG_WINDOW(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindow))
+#define E_MAIL_CONFIG_WINDOW_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindowClass))
+#define E_IS_MAIL_CONFIG_WINDOW(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_WINDOW))
+#define E_IS_MAIL_CONFIG_WINDOW_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_WINDOW))
+#define E_MAIL_CONFIG_WINDOW_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_WINDOW, EMailConfigWindowClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigWindow EMailConfigWindow;
+typedef struct _EMailConfigWindowClass EMailConfigWindowClass;
+typedef struct _EMailConfigWindowPrivate EMailConfigWindowPrivate;
+
+struct _EMailConfigWindow {
+	GtkDialog parent;
+	EMailConfigWindowPrivate *priv;
+};
+
+struct _EMailConfigWindowClass {
+	GtkDialogClass parent_class;
+};
+
+GType		e_mail_config_window_get_type	(void) G_GNUC_CONST;
+GtkWidget *	e_mail_config_window_new	(EMailSession *session,
+						 ESource *original_source);
+EMailSession *	e_mail_config_window_get_session
+						(EMailConfigWindow *window);
+ESource *	e_mail_config_window_get_original_source
+						(EMailConfigWindow *window);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_WINDOW_H */
+
diff --git a/mail/e-mail-folder-pane.c b/mail/e-mail-folder-pane.c
index 7e0457e..03168ce 100644
--- a/mail/e-mail-folder-pane.c
+++ b/mail/e-mail-folder-pane.c
@@ -74,7 +74,10 @@ folder_pane_set_preview_visible (EMailView *view,
 static guint
 mail_paned_view_open_selected_mail (EMailPanedView *view)
 {
+	EShell *shell;
 	EMailReader *reader;
+	EMailBackend *backend;
+	ESourceRegistry *registry;
 	GPtrArray *uids;
 	gint i;
 	GtkWindow *window;
@@ -88,6 +91,10 @@ mail_paned_view_open_selected_mail (EMailPanedView *view)
 	uids = e_mail_reader_get_selected_uids (reader);
 	g_return_val_if_fail (uids != NULL, 0);
 
+	backend = e_mail_reader_get_backend (reader);
+	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+	registry = e_shell_get_registry (shell);
+
 	/* XXX Either e_mail_reader_get_selected_uids()
 	 *     or MessageList should do this itself. */
 	g_ptr_array_set_free_func (uids, (GDestroyNotify) g_free);
@@ -97,9 +104,9 @@ mail_paned_view_open_selected_mail (EMailPanedView *view)
 		return 0;
 	}
 
-	if (em_utils_folder_is_drafts (folder) ||
-		em_utils_folder_is_outbox (folder) ||
-		em_utils_folder_is_templates (folder)) {
+	if (em_utils_folder_is_drafts (registry, folder) ||
+		em_utils_folder_is_outbox (registry, folder) ||
+		em_utils_folder_is_templates (registry, folder)) {
 		em_utils_edit_messages (reader, folder, uids, TRUE);
 		g_ptr_array_unref (uids);
 		return 0;
@@ -127,8 +134,8 @@ mail_paned_view_open_selected_mail (EMailPanedView *view)
 			CAMEL_VEE_FOLDER (folder),
 			(CamelVeeMessageInfo *) info, &real_uid);
 
-		if (em_utils_folder_is_drafts (real_folder) ||
-			em_utils_folder_is_outbox (real_folder)) {
+		if (em_utils_folder_is_drafts (registry, real_folder) ||
+			em_utils_folder_is_outbox (registry, real_folder)) {
 			GPtrArray *edits;
 
 			edits = g_ptr_array_new_with_free_func (
diff --git a/mail/e-mail-migrate.c b/mail/e-mail-migrate.c
index ffc5f1a..a485a1e 100644
--- a/mail/e-mail-migrate.c
+++ b/mail/e-mail-migrate.c
@@ -50,6 +50,9 @@
 
 #include <libedataserver/e-xml-utils.h>
 #include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-registry.h>
+#include <libedataserver/e-source-mail-account.h>
 
 #include <shell/e-shell.h>
 #include <shell/e-shell-migrate.h>
@@ -61,9 +64,6 @@
 #include <e-util/e-util-private.h>
 #include <e-util/e-plugin.h>
 
-#include <libemail-utils/e-account-utils.h>
-#include <libemail-utils/e-signature-utils.h>
-
 #include <libemail-engine/e-mail-folder-utils.h>
 
 #include "e-mail-backend.h"
@@ -221,50 +221,6 @@ cp (const gchar *src,
 	return FALSE;
 }
 
-#ifndef G_OS_WIN32
-
-#define SUBFOLDER_DIR_NAME     "subfolders"
-#define SUBFOLDER_DIR_NAME_LEN 10
-
-static void
-em_update_accounts_2_11 (void)
-{
-	EAccountList *accounts;
-	EIterator *iter;
-	gboolean changed = FALSE;
-
-	if (!(accounts = e_get_account_list ()))
-		return;
-
-	iter = e_list_get_iterator ((EList *) accounts);
-	while (e_iterator_is_valid (iter)) {
-		EAccount *account = (EAccount *) e_iterator_get (iter);
-
-		if (g_str_has_prefix (account->source->url, "spool://")) {
-			if (g_file_test (account->source->url + 8, G_FILE_TEST_IS_DIR)) {
-				gchar *str;
-
-				str = g_strdup_printf (
-					"spooldir://%s",
-					account->source->url + 8);
-
-				g_free (account->source->url);
-				account->source->url = str;
-				changed = TRUE;
-			}
-		}
-
-		e_iterator_next (iter);
-	}
-
-	g_object_unref (iter);
-
-	if (changed)
-		e_account_list_save (accounts);
-}
-
-#endif	/* !G_OS_WIN32 */
-
 static gboolean
 emm_setup_initial (const gchar *data_dir)
 {
@@ -600,27 +556,67 @@ static gboolean
 migrate_mbox_to_maildir (EShellBackend *shell_backend,
                          EMMigrateSession *session)
 {
-	CamelService *mbox_service, *maildir_service;
-	CamelStore *mbox_store, *maildir_store;
+	EShell *shell;
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceExtension *extension;
+	const gchar *extension_name;
+	CamelService *mbox_service;
+	CamelService *maildir_service;
+	CamelStore *mbox_store;
+	CamelStore *maildir_store;
 	CamelSettings *settings;
 	const gchar *data_dir;
+	const gchar *uid;
 	gchar *path;
 	struct MigrateStore ms;
+	GError *error = NULL;
 
 	data_dir = e_shell_backend_get_data_dir (shell_backend);
+	shell = e_shell_backend_get_shell (shell_backend);
+	registry = e_shell_get_registry (shell);
+
+	source = e_source_new (NULL, NULL, NULL);
+	e_source_set_display_name (source, "local_mbox");
 
-	mbox_service = camel_session_add_service (
-		CAMEL_SESSION (session), "local_mbox", "mbox",
-		CAMEL_PROVIDER_STORE, NULL);
+	uid = e_source_get_uid (source);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	extension = e_source_get_extension (source, extension_name);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (extension), "mbox");
+
+	extension_name = e_source_camel_get_extension_name ("mbox");
+	extension = e_source_get_extension (source, extension_name);
+	settings = e_source_camel_get_settings (E_SOURCE_CAMEL (extension));
 
-	settings = camel_service_get_settings (mbox_service);
 	path = g_build_filename (data_dir, "local_mbox", NULL);
 	g_object_set (settings, "path", path, NULL);
 	g_free (path);
 
-	maildir_service = camel_session_add_service (
-		CAMEL_SESSION (session), "local", "maildir",
-		CAMEL_PROVIDER_STORE, NULL);
+	e_source_registry_commit_source_sync (
+		registry, source, NULL, &error);
+
+	if (error == NULL)
+		mbox_service = camel_session_add_service (
+			CAMEL_SESSION (session), uid, "mbox",
+			CAMEL_PROVIDER_STORE, &error);
+
+	if (error == NULL)
+		maildir_service = camel_session_add_service (
+			CAMEL_SESSION (session), "local", "maildir",
+			CAMEL_PROVIDER_STORE, &error);
+
+	g_object_unref (source);
+
+	if (error != NULL) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	camel_service_set_settings (mbox_service, settings);
 
 	settings = camel_service_get_settings (maildir_service);
 	path = g_build_filename (data_dir, "local", NULL);
@@ -667,412 +663,6 @@ exit:
 }
 
 static gboolean
-create_mbox_account (EShellBackend *shell_backend,
-                     EMMigrateSession *session)
-{
-	EMailBackend *mail_backend;
-	EMailSession *mail_session;
-	CamelService *service;
-	CamelURL *url;
-	EAccountList *accounts;
-	EAccount *account;
-	const gchar *data_dir;
-	gchar *name, *id, *temp, *uri, *folder_uri;
-
-	mail_backend = E_MAIL_BACKEND (shell_backend);
-	mail_session = e_mail_backend_get_session (mail_backend);
-	data_dir = e_shell_backend_get_data_dir (shell_backend);
-
-	account = e_account_new ();
-	account->enabled = TRUE;
-
-	g_free (account->uid);
-	account->uid = g_strdup ("local_mbox");
-
-	url = camel_url_new ("mbox:", NULL);
-	temp = g_build_filename (data_dir, "local_mbox", NULL);
-	camel_url_set_path (url, temp);
-	g_free (temp);
-
-	uri = camel_url_to_string (url, 0);
-	e_account_set_string (account, E_ACCOUNT_SOURCE_URL, uri);
-
-#ifndef G_OS_WIN32
-	name = g_locale_to_utf8 (g_get_user_name (), -1, NULL, NULL, NULL);
-#else
-	name = g_strdup (g_get_user_name ());
-#endif
-
-	id = g_strconcat (name, "@", "localhost", NULL);
-	e_account_set_string (account, E_ACCOUNT_ID_NAME, name);
-	e_account_set_string (account, E_ACCOUNT_ID_ADDRESS, id);
-	e_account_set_string (account, E_ACCOUNT_NAME, id);
-
-	accounts = e_get_account_list ();
-	if (e_account_list_find (accounts, E_ACCOUNT_ID_ADDRESS, id)) {
-		g_object_unref (account);
-		goto exit;
-	}
-
-	/* This will also add it to the EMailSession. */
-	e_account_list_add (accounts, account);
-
-	service = camel_session_get_service (
-		CAMEL_SESSION (mail_session), account->uid);
-
-	folder_uri = e_mail_folder_uri_build (
-		CAMEL_STORE (service), "Sent");
-	e_account_set_string (
-		account, E_ACCOUNT_SENT_FOLDER_URI, folder_uri);
-	g_free (folder_uri);
-
-	folder_uri = e_mail_folder_uri_build (
-		CAMEL_STORE (service), "Drafts");
-	e_account_set_string (
-		account, E_ACCOUNT_DRAFTS_FOLDER_URI, folder_uri);
-	g_free (folder_uri);
-
-	e_account_list_save (accounts);
-
-exit:
-	camel_url_free (url);
-	g_free (uri);
-	g_free (name);
-	g_free (id);
-
-	return TRUE;
-}
-
-static void
-change_sent_and_drafts_local_folders (EShellBackend *shell_backend)
-{
-	EMailBackend *backend;
-	EMailSession *session;
-	EAccountList *accounts;
-	EIterator *iter;
-	const gchar *data_dir;
-	gboolean changed = FALSE;
-	CamelURL *url;
-	gchar *tmp_uri, *drafts_uri, *sent_uri, *old_drafts_uri, *old_sent_uri;
-
-	accounts = e_get_account_list ();
-	if (!accounts)
-		return;
-
-	backend = E_MAIL_BACKEND (shell_backend);
-	session = e_mail_backend_get_session (backend);
-
-	data_dir = e_shell_backend_get_data_dir (shell_backend);
-
-	tmp_uri = g_strconcat ("mbox:", data_dir, "/", "local", NULL);
-	url = camel_url_new (tmp_uri, NULL);
-	g_free (tmp_uri);
-
-	g_return_if_fail (url != NULL);
-
-	camel_url_set_fragment (url, "Drafts");
-	drafts_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-
-	camel_url_set_fragment (url, "Sent");
-	sent_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-
-	camel_url_free (url);
-
-	tmp_uri = g_strconcat (
-		"mbox:", g_get_home_dir (),
-		"/.evolution/mail/local", NULL);
-	url = camel_url_new (tmp_uri, NULL);
-	g_free (tmp_uri);
-
-	g_return_if_fail (url != NULL);
-
-	camel_url_set_fragment (url, "Drafts");
-	old_drafts_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-
-	camel_url_set_fragment (url, "Sent");
-	old_sent_uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-
-	camel_url_free (url);
-
-	for (iter = e_list_get_iterator ((EList *) accounts);
-	     e_iterator_is_valid (iter); e_iterator_next (iter)) {
-		EAccount *account = (EAccount *) e_iterator_get (iter);
-		const gchar *uri;
-
-		if (!account)
-			continue;
-
-		uri = e_account_get_string (account, E_ACCOUNT_DRAFTS_FOLDER_URI);
-		if (g_strcmp0 (uri, drafts_uri) == 0 ||
-		    g_strcmp0 (uri, old_drafts_uri) == 0) {
-			changed = TRUE;
-			e_account_set_string (
-				account, E_ACCOUNT_DRAFTS_FOLDER_URI,
-				e_mail_session_get_local_folder_uri (
-				session, E_MAIL_LOCAL_FOLDER_DRAFTS));
-		}
-
-		uri = e_account_get_string (account, E_ACCOUNT_SENT_FOLDER_URI);
-		if (g_strcmp0 (uri, sent_uri) == 0 || g_strcmp0 (uri, old_sent_uri) == 0) {
-			changed = TRUE;
-			e_account_set_string (
-				account, E_ACCOUNT_SENT_FOLDER_URI,
-				e_mail_session_get_local_folder_uri (
-				session, E_MAIL_LOCAL_FOLDER_SENT));
-		}
-	}
-
-	g_object_unref (iter);
-	g_free (old_drafts_uri);
-	g_free (drafts_uri);
-	g_free (old_sent_uri);
-	g_free (sent_uri);
-
-	if (changed)
-		e_account_list_save (accounts);
-}
-
-static void
-em_rename_camel_url_params (CamelURL *url)
-{
-	/* This list includes known URL parameters from built-in providers
-	 * in Camel, as well as from evolution-exchange, evolution-groupwise,
-	 * and evolution-mapi.  Add more as needed. */
-	static struct {
-		const gchar *url_parameter;
-		const gchar *property_name;
-	} camel_url_conversion[] = {
-		{ "account_uid",		"account-uid" },
-		{ "ad_auth",			"gc-auth-method" },
-		{ "ad_browse",			"gc-allow-browse" },
-		{ "ad_expand_groups",		"gc-expand-groups" },
-		{ "ad_limit",			"gc-results-limit" },
-		{ "ad_server",			"gc-server-name" },
-		{ "all_headers",		"fetch-headers" },
-		{ "basic_headers",		"fetch-headers" },
-		{ "cachedconn"			"concurrent-connections" },
-		{ "check_all",			"check-all" },
-		{ "check_lsub",			"check-subscribed" },
-		{ "command",			"shell-command" },
-		{ "delete_after",		"delete-after-days" },
-		{ "delete_expunged",		"delete-expunged" },
-		{ "disable_extensions",		"disable-extensions" },
-		{ "dotfolders",			"use-dot-folders" },
-		{ "filter",			"filter-inbox" },
-		{ "filter_junk",		"filter-junk" },
-		{ "filter_junk_inbox",		"filter-junk-inbox" },
-		{ "folder_hierarchy_relative",	"folder-hierarchy-relative" },
-		{ "imap_custom_headers",	"fetch-headers-extra" },
-		{ "keep_on_server",		"keep-on-server" },
-		{ "oab_offline",		"oab-offline" },
-		{ "oal_selected",		"oal-selected" },
-		{ "offline_sync",		"stay-synchronized" },
-		{ "override_namespace",		"use-namespace" },
-		{ "owa_path",			"owa-path" },
-		{ "owa_url",			"owa-url" },
-		{ "password_exp_warn_period",	"password-exp-warn-period" },
-		{ "real_junk_path",		"real-junk-path" },
-		{ "real_trash_path",		"real-trash-path" },
-		{ "show_short_notation",	"short-folder-names" },
-		{ "soap_port",			"soap-port" },
-		{ "ssl",			"security-method" },
-		{ "sync_offline",		"stay-synchronized" },
-		{ "use_command",		"use-shell-command" },
-		{ "use_idle",			"use-idle" },
-		{ "use_lsub",			"use-subscriptions" },
-		{ "use_qresync",		"use-qresync" },
-		{ "use_ssl",			"security-method" },
-		{ "xstatus",			"use-xstatus-headers" }
-	};
-
-	const gchar *param;
-	const gchar *use_param;
-	gint ii;
-
-	for (ii = 0; ii < G_N_ELEMENTS (camel_url_conversion); ii++) {
-		const gchar *key;
-		gpointer value;
-
-		key = camel_url_conversion[ii].url_parameter;
-		value = g_datalist_get_data (&url->params, key);
-
-		if (value == NULL)
-			continue;
-
-		g_datalist_remove_no_notify (&url->params, key);
-
-		key = camel_url_conversion[ii].property_name;
-
-		/* Deal with a few special enum cases where
-		 * the parameter value also needs renamed. */
-
-		if (strcmp (key, "all_headers") == 0) {
-			GEnumClass *enum_class;
-			GEnumValue *enum_value;
-
-			enum_class = g_type_class_ref (
-				CAMEL_TYPE_FETCH_HEADERS_TYPE);
-			enum_value = g_enum_get_value (
-				enum_class, CAMEL_FETCH_HEADERS_ALL);
-			if (enum_value != NULL) {
-				g_free (value);
-				value = g_strdup (enum_value->value_nick);
-			} else
-				g_warn_if_reached ();
-			g_type_class_unref (enum_class);
-		}
-
-		if (strcmp (key, "basic_headers") == 0) {
-			GEnumClass *enum_class;
-			GEnumValue *enum_value;
-
-			enum_class = g_type_class_ref (
-				CAMEL_TYPE_FETCH_HEADERS_TYPE);
-			enum_value = g_enum_get_value (
-				enum_class, CAMEL_FETCH_HEADERS_BASIC);
-			if (enum_value != NULL) {
-				g_free (value);
-				value = g_strdup (enum_value->value_nick);
-			} else
-				g_warn_if_reached ();
-			g_type_class_unref (enum_class);
-		}
-
-		if (strcmp (key, "imap_custom_headers") == 0)
-			g_strdelimit (value, " ", ',');
-
-		if (strcmp (key, "security-method") == 0) {
-			CamelNetworkSecurityMethod method;
-			GEnumClass *enum_class;
-			GEnumValue *enum_value;
-
-			if (strcmp (value, "always") == 0)
-				method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
-			else if (strcmp (value, "1") == 0)
-				method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
-			else if (strcmp (value, "when-possible") == 0)
-				method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT;
-			else
-				method = CAMEL_NETWORK_SECURITY_METHOD_NONE;
-
-			enum_class = g_type_class_ref (
-				CAMEL_TYPE_NETWORK_SECURITY_METHOD);
-			enum_value = g_enum_get_value (enum_class, method);
-			if (enum_value != NULL) {
-				g_free (value);
-				value = g_strdup (enum_value->value_nick);
-			} else
-				g_warn_if_reached ();
-			g_type_class_unref (enum_class);
-		}
-
-		g_datalist_set_data_full (&url->params, key, value, g_free);
-	}
-
-	/* A few more adjustments...
-	 *
-	 * These are all CAMEL_PROVIDER_CONF_CHECKSPIN settings.  The spin
-	 * button value is bound to "param" and the checkbox state is bound
-	 * to "use-param".  The "use-param" settings are new.  If "param"
-	 * exists but no "use-param", then set "use-param" to "true". */
-
-	param = g_datalist_get_data (&url->params, "gc-results-limit");
-	use_param = g_datalist_get_data (&url->params, "use-gc-results-limit");
-	if (param != NULL && *param != '\0' && use_param == NULL) {
-		g_datalist_set_data_full (
-			&url->params, "use-gc-results-limit",
-			g_strdup ("true"), (GDestroyNotify) g_free);
-	}
-
-	param = g_datalist_get_data (&url->params, "kerberos");
-	if (g_strcmp0 (param, "required") == 0) {
-		g_datalist_set_data_full (
-			&url->params, "kerberos",
-			g_strdup ("true"), (GDestroyNotify) g_free);
-	}
-
-	param = g_datalist_get_data (
-		&url->params, "password-exp-warn-period");
-	use_param = g_datalist_get_data (
-		&url->params, "use-password-exp-warn-period");
-	if (param != NULL && *param != '\0' && use_param == NULL) {
-		g_datalist_set_data_full (
-			&url->params, "use-password-exp-warn-period",
-			g_strdup ("true"), (GDestroyNotify) g_free);
-	}
-
-	param = g_datalist_get_data (&url->params, "real-junk-path");
-	use_param = g_datalist_get_data (&url->params, "use-real-junk-path");
-	if (param != NULL && *param != '\0' && use_param == NULL) {
-		g_datalist_set_data_full (
-			&url->params, "use-real-junk-path",
-			g_strdup ("true"), (GDestroyNotify) g_free);
-	}
-
-	param = g_datalist_get_data (&url->params, "real-trash-path");
-	use_param = g_datalist_get_data (&url->params, "use-real-trash-path");
-	if (param != NULL && *param != '\0' && use_param == NULL) {
-		g_datalist_set_data_full (
-			&url->params, "use-real-trash-path",
-			g_strdup ("true"), (GDestroyNotify) g_free);
-	}
-}
-
-static void
-em_rename_account_params (void)
-{
-	EAccountList *account_list;
-	EIterator *iterator;
-
-	/* XXX As of 3.2, CamelServices store settings in GObject properties,
-	 *     not CamelURL parameters.  CamelURL parameters are still used
-	 *     for storage in GConf until we can move account information to
-	 *     key files, but this is only within Evolution.  Some of the new
-	 *     GObject property names differ from the old CamelURL parameter
-	 *     names.  This routine renames the CamelURL parameter names to
-	 *     the GObject property names for all accounts, both the source
-	 *     and tranport URLs. */
-
-	account_list = e_get_account_list ();
-	iterator = e_list_get_iterator (E_LIST (account_list));
-
-	while (e_iterator_is_valid (iterator)) {
-		EAccount *account;
-		CamelURL *url = NULL;
-
-		/* XXX EIterator misuses const. */
-		account = (EAccount *) e_iterator_get (iterator);
-
-		if (account->source->url != NULL)
-			url = camel_url_new (account->source->url, NULL);
-
-		if (url != NULL) {
-			em_rename_camel_url_params (url);
-			g_free (account->source->url);
-			account->source->url = camel_url_to_string (url, 0);
-			camel_url_free (url);
-		}
-
-		url = NULL;
-
-		if (account->transport->url != NULL)
-			url = camel_url_new (account->transport->url, NULL);
-
-		if (url != NULL) {
-			em_rename_camel_url_params (url);
-			g_free (account->transport->url);
-			account->transport->url = camel_url_to_string (url, 0);
-			camel_url_free (url);
-		}
-
-		e_iterator_next (iterator);
-	}
-
-	g_object_unref (iterator);
-	e_account_list_save (account_list);
-}
-
-static gboolean
 migrate_local_store (EShellBackend *shell_backend)
 {
 	EMMigrateSession *session;
@@ -1101,8 +691,6 @@ migrate_local_store (EShellBackend *shell_backend)
 	camel_session_set_online (CAMEL_SESSION (session), FALSE);
 
 	migrate_mbox_to_maildir (shell_backend, session);
-	create_mbox_account (shell_backend, session);
-	change_sent_and_drafts_local_folders (shell_backend);
 
 	g_object_unref (session);
 
@@ -1279,10 +867,6 @@ e_mail_migrate (EShellBackend *shell_backend,
 		return emm_setup_initial (data_dir);
 
 #ifndef G_OS_WIN32
-	if (major < 2 || (major == 2 && minor < 12)) {
-		em_update_accounts_2_11 ();
-	}
-
 	if (major < 2 || (major == 2 && minor < 22))
 		em_update_message_notify_settings_2_21 ();
 
@@ -1299,10 +883,6 @@ e_mail_migrate (EShellBackend *shell_backend,
 		em_ensure_proxy_ignore_hosts_being_list ();
 	}
 
-	/* Rename account URL parameters to
-	 * match CamelSettings property names. */
-	em_rename_account_params ();
-
 	if (!migrate_local_store (shell_backend))
 		return FALSE;
 
diff --git a/mail/e-mail-paned-view.c b/mail/e-mail-paned-view.c
index bd76dd9..29910d8 100644
--- a/mail/e-mail-paned-view.c
+++ b/mail/e-mail-paned-view.c
@@ -809,6 +809,7 @@ mail_paned_view_update_view_instance (EMailView *view)
 	EShellWindow *shell_window;
 	EShellViewClass *shell_view_class;
 	EShellSettings *shell_settings;
+	ESourceRegistry *registry;
 	GalViewCollection *view_collection;
 	GalViewInstance *view_instance;
 	CamelFolder *folder;
@@ -826,6 +827,7 @@ mail_paned_view_update_view_instance (EMailView *view)
 
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	shell = e_shell_window_get_shell (shell_window);
+	registry = e_shell_get_registry (shell);
 	shell_settings = e_shell_get_shell_settings (shell);
 
 	reader = E_MAIL_READER (view);
@@ -844,9 +846,9 @@ mail_paned_view_update_view_instance (EMailView *view)
 	e_filename_make_safe (view_id);
 
 	outgoing_folder =
-		em_utils_folder_is_drafts (folder) ||
-		em_utils_folder_is_outbox (folder) ||
-		em_utils_folder_is_sent (folder);
+		em_utils_folder_is_drafts (registry, folder) ||
+		em_utils_folder_is_outbox (registry, folder) ||
+		em_utils_folder_is_sent (registry, folder);
 
 	if (e_shell_settings_get_boolean (shell_settings, "mail-global-view-setting"))
 		view_instance = e_shell_view_new_view_instance (
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 0a8e358..c46176e 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -30,6 +30,7 @@
 #include <glib/gi18n.h>
 #include <libxml/tree.h>
 #include <gtkhtml/gtkhtml.h>
+#include <gconf/gconf-client.h>
 #include <camel/camel.h>
 
 #include "libevolution-utils/e-alert-dialog.h"
@@ -358,7 +359,9 @@ copy_tree_state (EMailReader *src_reader,
 guint
 e_mail_reader_open_selected (EMailReader *reader)
 {
+	EShell *shell;
 	EMailBackend *backend;
+	ESourceRegistry *registry;
 	CamelFolder *folder;
 	GtkWindow *window;
 	GPtrArray *views;
@@ -368,6 +371,9 @@ e_mail_reader_open_selected (EMailReader *reader)
 	g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
 
 	backend = e_mail_reader_get_backend (reader);
+	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+	registry = e_shell_get_registry (shell);
+
 	folder = e_mail_reader_get_folder (reader);
 	uids = e_mail_reader_get_selected_uids (reader);
 	window = e_mail_reader_get_window (reader);
@@ -377,9 +383,9 @@ e_mail_reader_open_selected (EMailReader *reader)
 		return 0;
 	}
 
-	if (em_utils_folder_is_drafts (folder) ||
-		em_utils_folder_is_outbox (folder) ||
-		em_utils_folder_is_templates (folder)) {
+	if (em_utils_folder_is_drafts (registry, folder) ||
+		em_utils_folder_is_outbox (registry, folder) ||
+		em_utils_folder_is_templates (registry, folder)) {
 		em_utils_edit_messages (reader, folder, uids, TRUE);
 		return uids->len;
 	}
@@ -406,8 +412,8 @@ e_mail_reader_open_selected (EMailReader *reader)
 			CAMEL_VEE_FOLDER (folder),
 			(CamelVeeMessageInfo *) info, &real_uid);
 
-		if (em_utils_folder_is_drafts (real_folder) ||
-			em_utils_folder_is_outbox (real_folder)) {
+		if (em_utils_folder_is_drafts (registry, real_folder) ||
+			em_utils_folder_is_outbox (registry, real_folder)) {
 			GPtrArray *edits;
 
 			edits = g_ptr_array_new ();
@@ -1166,9 +1172,12 @@ void
 e_mail_reader_create_filter_from_selected (EMailReader *reader,
                                            gint filter_type)
 {
+	EShell *shell;
 	EActivity *activity;
+	EMailBackend *backend;
 	AsyncContext *context;
 	GCancellable *cancellable;
+	ESourceRegistry *registry;
 	CamelFolder *folder;
 	GPtrArray *uids;
 	const gchar *filter_source;
@@ -1176,12 +1185,16 @@ e_mail_reader_create_filter_from_selected (EMailReader *reader,
 
 	g_return_if_fail (E_IS_MAIL_READER (reader));
 
+	backend = e_mail_reader_get_backend (reader);
+	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+	registry = e_shell_get_registry (shell);
+
 	folder = e_mail_reader_get_folder (reader);
 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
-	if (em_utils_folder_is_sent (folder))
+	if (em_utils_folder_is_sent (registry, folder))
 		filter_source = E_FILTER_SOURCE_OUTGOING;
-	else if (em_utils_folder_is_outbox (folder))
+	else if (em_utils_folder_is_outbox (registry, folder))
 		filter_source = E_FILTER_SOURCE_OUTGOING;
 	else
 		filter_source = E_FILTER_SOURCE_INCOMING;
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 2cc78f8..e2cf279 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -28,6 +28,8 @@
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
 
+#include <libedataserver/e-source-mail-account.h>
+
 #ifdef HAVE_XFREE
 #include <X11/XF86keysym.h>
 #endif
@@ -39,7 +41,6 @@
 #include "widgets/misc/e-popup-action.h"
 #include "widgets/misc/e-menu-tool-action.h"
 
-#include "libemail-utils/e-account-utils.h"
 #include "libemail-utils/mail-mt.h"
 
 #include "libemail-engine/mail-ops.h"
@@ -892,6 +893,9 @@ static void
 action_mail_message_edit_cb (GtkAction *action,
                              EMailReader *reader)
 {
+	EShell *shell;
+	EMailBackend *backend;
+	ESourceRegistry *registry;
 	CamelFolder *folder;
 	GPtrArray *uids;
 	gboolean replace;
@@ -900,11 +904,15 @@ action_mail_message_edit_cb (GtkAction *action,
 	uids = e_mail_reader_get_selected_uids (reader);
 	g_return_if_fail (uids != NULL);
 
+	backend = e_mail_reader_get_backend (reader);
+	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+	registry = e_shell_get_registry (shell);
+
 	/* XXX Either e_mail_reader_get_selected_uids()
 	 *     or MessageList should do this itself. */
 	g_ptr_array_set_free_func (uids, (GDestroyNotify) g_free);
 
-	replace = em_utils_folder_is_drafts (folder);
+	replace = em_utils_folder_is_drafts (registry, folder);
 	em_utils_edit_messages (reader, folder, uids, replace);
 
 	g_ptr_array_unref (uids);
@@ -3027,6 +3035,7 @@ mail_reader_set_folder (EMailReader *reader,
 	EMailReaderPrivate *priv;
 	EMailDisplay *display;
 	CamelFolder *previous_folder;
+	ESourceRegistry *registry;
 	GtkWidget *message_list;
 	EMailBackend *backend;
 	EShell *shell;
@@ -3040,7 +3049,9 @@ mail_reader_set_folder (EMailReader *reader,
 
 	previous_folder = e_mail_reader_get_folder (reader);
 
+	backend = e_mail_reader_get_backend (reader);
 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+	registry = e_shell_get_registry (shell);
 
 	/* Only synchronize the folder if we're online. */
 	if (previous_folder != NULL && e_shell_get_online (shell))
@@ -3051,9 +3062,9 @@ mail_reader_set_folder (EMailReader *reader,
 		return;
 
 	outgoing = folder != NULL && (
-		em_utils_folder_is_drafts (folder) ||
-		em_utils_folder_is_outbox (folder) ||
-		em_utils_folder_is_sent (folder));
+		em_utils_folder_is_drafts (registry, folder) ||
+		em_utils_folder_is_outbox (registry, folder) ||
+		em_utils_folder_is_sent (registry, folder));
 
 	e_web_view_clear (E_WEB_VIEW (display));
 
@@ -4166,9 +4177,14 @@ e_mail_reader_changed (EMailReader *reader)
 guint32
 e_mail_reader_check_state (EMailReader *reader)
 {
+	EShell *shell;
 	GPtrArray *uids;
 	CamelFolder *folder;
 	CamelStore *store = NULL;
+	EMailBackend *backend;
+	ESourceRegistry *registry;
+	GList *list, *iter;
+	const gchar *extension_name;
 	const gchar *tag;
 	gboolean can_clear_flags = FALSE;
 	gboolean can_flag_completed = FALSE;
@@ -4182,6 +4198,7 @@ e_mail_reader_check_state (EMailReader *reader)
 	gboolean has_undeleted = FALSE;
 	gboolean has_unimportant = FALSE;
 	gboolean has_unread = FALSE;
+	gboolean have_enabled_account = FALSE;
 	gboolean drafts_or_outbox = FALSE;
 	gboolean store_supports_vjunk = FALSE;
 	gboolean is_mailing_list;
@@ -4191,6 +4208,10 @@ e_mail_reader_check_state (EMailReader *reader)
 
 	g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
 
+	backend = e_mail_reader_get_backend (reader);
+	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
+	registry = e_shell_get_registry (shell);
+
 	folder = e_mail_reader_get_folder (reader);
 	uids = e_mail_reader_get_selected_uids (reader);
 
@@ -4200,8 +4221,8 @@ e_mail_reader_check_state (EMailReader *reader)
 		is_junk_folder =
 			(folder->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0;
 		drafts_or_outbox =
-			em_utils_folder_is_drafts (folder) ||
-			em_utils_folder_is_outbox (folder);
+			em_utils_folder_is_drafts (registry, folder) ||
+			em_utils_folder_is_outbox (registry, folder);
 	}
 
 	/* Initialize this flag based on whether there are any
@@ -4286,7 +4307,21 @@ e_mail_reader_check_state (EMailReader *reader)
 		camel_folder_free_message_info (folder, info);
 	}
 
-	if (e_get_any_enabled_account () != NULL)
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+		ESource *source = E_SOURCE (iter->data);
+
+		if (e_source_get_enabled (source)) {
+			have_enabled_account = TRUE;
+			break;
+		}
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	if (have_enabled_account)
 		state |= E_MAIL_READER_HAVE_ENABLED_ACCOUNT;
 	if (uids->len == 1)
 		state |= E_MAIL_READER_SELECTION_SINGLE;
diff --git a/mail/e-mail-ui-session.c b/mail/e-mail-ui-session.c
index fd9a4a9..f5f5bdd 100644
--- a/mail/e-mail-ui-session.c
+++ b/mail/e-mail-ui-session.c
@@ -44,13 +44,13 @@
 
 #include <libedataserver/e-flag.h>
 #include <libedataserver/e-proxy.h>
+#include <libedataserver/e-source-mail-account.h>
 #include <libebackend/e-extensible.h>
 #include <libedataserverui/e-passwords.h>
 
 #include "e-mail-account-store.h"
 
 #include "e-util/e-util.h"
-#include "libemail-utils/e-account-utils.h"
 #include "libevolution-utils/e-alert-dialog.h"
 #include "e-util/e-util-private.h"
 
@@ -82,11 +82,11 @@ typedef struct _SourceContext SourceContext;
 
 struct _EMailUISessionPrivate {
 	FILE *filter_logfile;
+	ESourceRegistry *registry;
 	EMailAccountStore *account_store;
 	EMailLabelListStore *label_store;
 
-	EAccountList *account_list;
-	gulong account_changed_handler_id;
+	gulong source_changed_handler_id;
 };
 
 enum {
@@ -475,62 +475,28 @@ source_context_free (SourceContext *context)
 }
 
 static void
-mail_ui_session_dispose (GObject *object)
-{
-	EMailUISessionPrivate *priv;
-
-	priv = E_MAIL_UI_SESSION_GET_PRIVATE (object);
-
-	if (priv->account_store != NULL) {
-		e_mail_account_store_clear (priv->account_store);
-		g_object_unref (priv->account_store);
-		priv->account_store = NULL;
-	}
-
-	if (priv->label_store != NULL) {
-		g_object_unref (priv->label_store);
-		priv->label_store = NULL;
-	}
-
-	if (priv->account_list != NULL) {
-		g_signal_handler_disconnect (
-			priv->account_list,
-			priv->account_changed_handler_id);
-		g_object_unref (priv->account_list);
-		priv->account_list = NULL;
-	}
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (e_mail_ui_session_parent_class)->dispose (object);
-}
-
-static void
-mail_ui_session_account_changed_cb (EAccountList *account_list,
-                                 EAccount *account,
-                                 EMailSession *session)
+mail_ui_session_source_changed_cb (ESourceRegistry *registry,
+                                   ESource *source,
+                                   EMailSession *session)
 {
 	EMFolderTreeModel *folder_tree_model;
 	CamelService *service;
+	const gchar *extension_name;
+	const gchar *uid;
 
-	service = camel_session_get_service (
-		CAMEL_SESSION (session), account->uid);
+	uid = e_source_get_uid (source);
 
-	if (!CAMEL_IS_STORE (service))
+	/* We're only interested in mail account data sources. */
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	if (!e_source_has_extension (source, extension_name))
 		return;
 
-	/* Update the display name of the corresponding CamelStore.
-	 * EMailAccountStore listens for "notify" signals from each
-	 * service so it will detect this and update the model.
-	 *
-	 * XXX If EAccount defined GObject properties we could just
-	 *     bind EAccount:name to CamelService:display-name and
-	 *     be done with it.  Oh well.
-	 */
-
-	camel_service_set_display_name (service, account->name);
+	/* There should be a CamelStore with the same UID. */
+	service = camel_session_get_service (CAMEL_SESSION (session), uid);
+	g_return_if_fail (CAMEL_IS_STORE (service));
 
 	/* Remove the store from the folder tree model and, if the
-	 * account is still enabled, re-add it.  Easier than trying
+	 * source is still enabled, re-add it.  Easier than trying
 	 * to update the model with the store in place.
 	 *
 	 * em_folder_tree_model_add_store() already knows which types
@@ -542,34 +508,76 @@ mail_ui_session_account_changed_cb (EAccountList *account_list,
 	em_folder_tree_model_remove_store (
 		folder_tree_model, CAMEL_STORE (service));
 
-	if (account->enabled)
+	if (e_source_get_enabled (source))
 		em_folder_tree_model_add_store (
 			folder_tree_model, CAMEL_STORE (service));
 }
 
 static gboolean
-mail_ui_session_initialize_stores_idle (gpointer user_data)
+mail_ui_session_add_service_cb (SourceContext *context)
 {
-	EMailUISession *session = user_data;
-	EMailAccountStore *account_store;
-	EAccount *account;
+	EMailAccountStore *store;
+
+	/* The CamelService should be fully initialized by now. */
+	store = e_mail_ui_session_get_account_store (context->session);
+	e_mail_account_store_add_service (store, context->service);
+
+	return FALSE;
+}
+
+static void
+mail_ui_session_get_property (GObject *object,
+                              guint property_id,
+                              GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_STORE:
+			g_value_set_object (
+				value,
+				e_mail_ui_session_get_account_store (
+				E_MAIL_UI_SESSION (object)));
+			return;
+
+		case PROP_LABEL_STORE:
+			g_value_set_object (
+				value,
+				e_mail_ui_session_get_label_store (
+				E_MAIL_UI_SESSION (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_ui_session_dispose (GObject *object)
+{
+	EMailUISessionPrivate *priv;
 
-	g_return_val_if_fail (session != NULL, FALSE);
+	priv = E_MAIL_UI_SESSION_GET_PRIVATE (object);
 
-	account_store = e_mail_ui_session_get_account_store (session);
+	if (priv->registry != NULL) {
+		g_signal_handler_disconnect (
+			priv->registry,
+			priv->source_changed_handler_id);
+		g_object_unref (priv->registry);
+		priv->registry = NULL;
+	}
 
-	/* Initialize which account is default. */
-	account = e_get_default_account ();
-	if (account != NULL) {
-		CamelService *service;
+	if (priv->account_store != NULL) {
+		e_mail_account_store_clear (priv->account_store);
+		g_object_unref (priv->account_store);
+		priv->account_store = NULL;
+	}
 
-		service = camel_session_get_service (
-			CAMEL_SESSION (session), account->uid);
-		e_mail_account_store_set_default_service (
-			account_store, service);
+	if (priv->label_store != NULL) {
+		g_object_unref (priv->label_store);
+		priv->label_store = NULL;
 	}
 
-	return FALSE;
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_ui_session_parent_class)->dispose (object);
 }
 
 static void
@@ -577,19 +585,19 @@ mail_ui_session_constructed (GObject *object)
 {
 	EMailUISessionPrivate *priv;
 	EMFolderTreeModel *folder_tree_model;
+	ESourceRegistry *registry;
 	EMailSession *session;
-	EMailUISession *uisession;
-	EAccountList *account_list;
 	gulong handler_id;
 
 	session = E_MAIL_SESSION (object);
-	uisession = E_MAIL_UI_SESSION (object);
-	uisession->priv = priv = E_MAIL_UI_SESSION_GET_PRIVATE (object);
 
+	priv = E_MAIL_UI_SESSION_GET_PRIVATE (object);
 	priv->account_store = e_mail_account_store_new (session);
 
-	account_list = e_get_account_list ();
-	uisession->priv->account_list = g_object_ref (account_list);
+	/* Keep our own reference to the ESourceRegistry so we
+	 * can easily disconnect signal handlers in dispose(). */
+	registry = e_mail_session_get_registry (session);
+	priv->registry = g_object_ref (registry);
 
 	/* XXX Make sure the folder tree model is created before we
 	 *     add built-in CamelStores so it gets signals from the
@@ -601,19 +609,62 @@ mail_ui_session_constructed (GObject *object)
 	 * FIXME EMailSession should just own the default instance.
 	 */
 	folder_tree_model = em_folder_tree_model_get_default ();
+	em_folder_tree_model_set_session (folder_tree_model, session);
 
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (e_mail_ui_session_parent_class)->constructed (object);
 
-	em_folder_tree_model_set_session (folder_tree_model, session);
-
-	g_idle_add (mail_ui_session_initialize_stores_idle, object);
+	/* Listen for registry changes. */
 
 	handler_id = g_signal_connect (
-		account_list, "account-changed",
-		G_CALLBACK (mail_ui_session_account_changed_cb), session);
-	priv->account_changed_handler_id = handler_id;
+		registry, "source-changed",
+		G_CALLBACK (mail_ui_session_source_changed_cb), session);
+	priv->source_changed_handler_id = handler_id;
+}
+
+static CamelService *
+mail_ui_session_add_service (CamelSession *session,
+                             const gchar *uid,
+                             const gchar *protocol,
+                             CamelProviderType type,
+                             GError **error)
+{
+	CamelService *service;
+
+	/* Chain up to parent's constructed() method. */
+	service = CAMEL_SESSION_CLASS (e_mail_ui_session_parent_class)->
+		add_service (session, uid, protocol, type, error);
+
+	/* Inform the EMailAccountStore of the new CamelService
+	 * from an idle callback so the service has a chance to
+	 * fully initialize first. */
+	if (CAMEL_IS_STORE (service)) {
+		SourceContext *context;
 
+		context = g_slice_new0 (SourceContext);
+		context->session = g_object_ref (session);
+		context->service = g_object_ref (service);
+
+		g_idle_add_full (
+			G_PRIORITY_DEFAULT_IDLE,
+			(GSourceFunc) mail_ui_session_add_service_cb,
+			context, (GDestroyNotify) source_context_free);
+	}
+
+	return service;
+}
+
+static void
+mail_ui_session_remove_service (CamelSession *session,
+                                CamelService *service)
+{
+	EMailAccountStore *store;
+	EMailUISession *ui_session;
+
+	/* Passing a NULL parent window skips confirmation prompts. */
+	ui_session = E_MAIL_UI_SESSION (session);
+	store = e_mail_ui_session_get_account_store (ui_session);
+	e_mail_account_store_remove_service (store, NULL, service);
 }
 
 static gint
@@ -659,8 +710,8 @@ mail_ui_session_alert_user (CamelSession *session,
 
 static CamelFilterDriver *
 mail_ui_session_get_filter_driver (CamelSession *session,
-                                const gchar *type,
-                                GError **error)
+                                   const gchar *type,
+                                   GError **error)
 {
 	return (CamelFilterDriver *) mail_call_main (
 		MAIL_CALL_p_ppp, (MailMainFunc) main_get_filter_driver,
@@ -668,80 +719,14 @@ mail_ui_session_get_filter_driver (CamelSession *session,
 }
 
 static void
-mail_ui_session_set_property (GObject *object,
-                           guint property_id,
-                           const GValue *value,
-                           GParamSpec *pspec)
+mail_ui_session_refresh_service (EMailSession *session,
+                                 CamelService *service)
 {
-	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
+	g_debug ("*** Refreshing %s ***",
+		camel_service_get_display_name (service));
 
-static void
-mail_ui_session_get_property (GObject *object,
-                           guint property_id,
-                           GValue *value,
-                           GParamSpec *pspec)
-{
-	switch (property_id) {
-		case PROP_ACCOUNT_STORE:
-			g_value_set_object (
-				value,
-				e_mail_ui_session_get_account_store (
-				E_MAIL_UI_SESSION (object)));
-			return;
-
-		case PROP_LABEL_STORE:
-			g_value_set_object (
-				value,
-				e_mail_ui_session_get_label_store (
-				E_MAIL_UI_SESSION (object)));
-			return;
-	}
-
-	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static gboolean
-mail_ui_session_add_service_cb (SourceContext *context)
-{
-	EMailAccountStore *store;
-
-	store = e_mail_ui_session_get_account_store (context->session);
-	e_mail_account_store_add_service (store, context->service);
-
-	return FALSE;
-}
-
-static CamelService *
-mail_ui_session_add_service (CamelSession *session,
-                             const gchar *uid,
-                             const gchar *protocol,
-                             CamelProviderType type,
-                             GError **error)
-{
-	CamelService *service;
-
-	/* Chain up to parent's constructed() method. */
-	service = CAMEL_SESSION_CLASS (e_mail_ui_session_parent_class)->
-		add_service (session, uid, protocol, type, error);
-
-	/* Inform the EMailAccountStore of the new CamelService
-	 * from an idle callback so the service has a chance to
-	 * fully initialize first. */
-	if (CAMEL_IS_STORE (service)) {
-		SourceContext *context;
-
-		context = g_slice_new0 (SourceContext);
-		context->session = g_object_ref (session);
-		context->service = g_object_ref (service);
-
-		g_idle_add_full (
-			G_PRIORITY_DEFAULT_IDLE,
-			(GSourceFunc) mail_ui_session_add_service_cb,
-			context, (GDestroyNotify) source_context_free);
-	}
-
-	return service;
+	if (camel_session_get_online (CAMEL_SESSION (session)))
+		mail_receive_service (service);
 }
 
 static EMVFolderContext *
@@ -755,23 +740,24 @@ e_mail_ui_session_class_init (EMailUISessionClass *class)
 {
 	GObjectClass *object_class;
 	CamelSessionClass *session_class;
-	EMailSessionClass *emailsession_class;
+	EMailSessionClass *mail_session_class;
 
 	g_type_class_add_private (class, sizeof (EMailUISessionPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
-	object_class->set_property = mail_ui_session_set_property;
 	object_class->get_property = mail_ui_session_get_property;
 	object_class->dispose = mail_ui_session_dispose;
 	object_class->constructed = mail_ui_session_constructed;
 
 	session_class = CAMEL_SESSION_CLASS (class);
+	session_class->add_service = mail_ui_session_add_service;
+	session_class->remove_service = mail_ui_session_remove_service;
 	session_class->alert_user = mail_ui_session_alert_user;
 	session_class->get_filter_driver = mail_ui_session_get_filter_driver;
-	session_class->add_service = mail_ui_session_add_service;
 
-	emailsession_class = E_MAIL_SESSION_CLASS (class);
-	emailsession_class->create_vfolder_context = mail_ui_session_create_vfolder_context;
+	mail_session_class = E_MAIL_SESSION_CLASS (class);
+	mail_session_class->create_vfolder_context = mail_ui_session_create_vfolder_context;
+	mail_session_class->refresh_service = mail_ui_session_refresh_service;
 
 	g_object_class_install_property (
 		object_class,
@@ -803,16 +789,19 @@ e_mail_ui_session_init (EMailUISession *session)
 }
 
 EMailSession *
-e_mail_ui_session_new (void)
+e_mail_ui_session_new (ESourceRegistry *registry)
 {
 	const gchar *user_data_dir;
 	const gchar *user_cache_dir;
 
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
 	user_data_dir = mail_session_get_data_dir ();
 	user_cache_dir = mail_session_get_cache_dir ();
 
 	return g_object_new (
 		E_TYPE_MAIL_UI_SESSION,
+		"registry", registry,
 		"user-data-dir", user_data_dir,
 		"user-cache-dir", user_cache_dir,
 		NULL);
@@ -826,6 +815,14 @@ e_mail_ui_session_get_account_store (EMailUISession *session)
 	return session->priv->account_store;
 }
 
+EMailLabelListStore *
+e_mail_ui_session_get_label_store (EMailUISession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), NULL);
+
+	return session->priv->label_store;
+}
+
 void
 e_mail_ui_session_add_activity (EMailUISession *session,
                                 EActivity *activity)
@@ -836,11 +833,3 @@ e_mail_ui_session_add_activity (EMailUISession *session,
 	g_signal_emit (session, signals[ACTIVITY_ADDED], 0, activity);
 }
 
-EMailLabelListStore *
-e_mail_ui_session_get_label_store (EMailUISession *session)
-{
-	g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), NULL);
-
-	return session->priv->label_store;
-}
-
diff --git a/mail/e-mail-ui-session.h b/mail/e-mail-ui-session.h
index f6ef4b4..ebab600 100644
--- a/mail/e-mail-ui-session.h
+++ b/mail/e-mail-ui-session.h
@@ -75,16 +75,16 @@ struct _EMailUISessionClass {
 
 };
 
-GType		e_mail_ui_session_get_type		(void);
-EMailSession *	e_mail_ui_session_new			(void);
+GType		e_mail_ui_session_get_type	(void);
+EMailSession *	e_mail_ui_session_new		(ESourceRegistry *registry);
 EMailAccountStore *
 		e_mail_ui_session_get_account_store
 						(EMailUISession *session);
-void		e_mail_ui_session_add_activity	(EMailUISession *session,
-						 EActivity *activity);
 EMailLabelListStore *
 		e_mail_ui_session_get_label_store
 						(EMailUISession *session);
+void		e_mail_ui_session_add_activity	(EMailUISession *session,
+						 EActivity *activity);
 
 G_END_DECLS
 
diff --git a/mail/e-mail.h b/mail/e-mail.h
index 3b0d02d..694b8e3 100644
--- a/mail/e-mail.h
+++ b/mail/e-mail.h
@@ -20,6 +20,7 @@
 #define E_MAIL_H
 
 #include <mail/e-mail-attachment-bar.h>
+#include <mail/e-mail-authenticator.h>
 #include <mail/e-mail-backend.h>
 #include <mail/e-mail-browser.h>
 #include <mail/e-mail-display.h>
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 7ea3163..a39a5f8 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -31,17 +31,22 @@
 #include <glib/gi18n.h>
 
 #include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-mdn.h>
 
 #include <libevolution-utils/e-alert-dialog.h>
 #include <libevolution-utils/e-alert-sink.h>
 #include <e-util/e-util.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-utils/mail-mt.h>
 
 #include <libemail-engine/e-mail-folder-utils.h>
 #include <libemail-engine/e-mail-session.h>
 #include <libemail-engine/e-mail-session-utils.h>
+#include <libemail-engine/e-mail-utils.h>
 #include <libemail-engine/mail-ops.h>
 #include <libemail-engine/mail-tools.h>
 
@@ -366,23 +371,31 @@ finished:
 }
 
 static gboolean
-composer_presend_check_account (EMsgComposer *composer,
-                                EMailSession *session)
+composer_presend_check_identity (EMsgComposer *composer,
+                                 EMailSession *session)
 {
 	EComposerHeaderTable *table;
-	EAccount *account;
-	gboolean check_passed;
+	ESourceRegistry *registry;
+	ESource *source;
+	const gchar *uid;
+	gboolean success = TRUE;
 
 	table = e_msg_composer_get_header_table (composer);
-	account = e_composer_header_table_get_account (table);
-	check_passed = (account != NULL && account->enabled);
+	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, FALSE);
 
-	if (!check_passed)
+	if (!e_source_get_enabled (source)) {
 		e_alert_submit (
 			E_ALERT_SINK (composer),
 			"mail:send-no-account-enabled", NULL);
+		success = FALSE;
+	}
 
-	return check_passed;
+	g_object_unref (source);
+
+	return success;
 }
 
 static gboolean
@@ -812,9 +825,11 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer,
 {
 	AsyncContext *context;
 	EComposerHeaderTable *table;
-	const gchar *drafts_folder_uri = NULL;
+	ESourceRegistry *registry;
+	ESource *source;
 	const gchar *local_drafts_folder_uri;
-	EAccount *account;
+	const gchar *identity_uid;
+	gchar *drafts_folder_uri = NULL;
 
 	context = g_slice_new0 (AsyncContext);
 	context->message = g_object_ref (message);
@@ -822,18 +837,30 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer,
 	context->composer = g_object_ref (composer);
 	context->activity = g_object_ref (activity);
 
-	local_drafts_folder_uri =
-		e_mail_session_get_local_folder_uri (
-		session, E_MAIL_LOCAL_FOLDER_DRAFTS);
-
 	table = e_msg_composer_get_header_table (composer);
-	account = e_composer_header_table_get_account (table);
 
-	if (account != NULL && account->enabled)
-		drafts_folder_uri = account->drafts_folder_uri;
+	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);
+
+	/* Get the selected identity's preferred Drafts folder. */
+	if (source != NULL) {
+		ESourceMailComposition *extension;
+		const gchar *extension_name;
+		gchar *uri;
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+		extension = e_source_get_extension (source, extension_name);
+		uri = e_source_mail_composition_dup_drafts_folder (extension);
+
+		drafts_folder_uri = uri;
 
-	if (g_strcmp0 (drafts_folder_uri, local_drafts_folder_uri) == 0)
-		drafts_folder_uri = NULL;
+		g_object_unref (source);
+	}
+
+	local_drafts_folder_uri =
+		e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_DRAFTS);
 
 	if (drafts_folder_uri == NULL) {
 		composer_save_to_drafts_append_mail (context, NULL);
@@ -849,6 +876,8 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer,
 			G_PRIORITY_DEFAULT, cancellable,
 			(GAsyncReadyCallback)
 			composer_save_to_drafts_got_folder, context);
+
+		g_free (drafts_folder_uri);
 	}
 }
 
@@ -976,22 +1005,23 @@ create_new_composer (EShell *shell,
                      CamelFolder *folder)
 {
 	EMsgComposer *composer;
+	ESourceRegistry *registry;
 	EComposerHeaderTable *table;
-	EAccount *account = NULL;
+	ESource *source = NULL;
+	gchar *identity = NULL;
 
 	composer = e_msg_composer_new (shell);
 
 	table = e_msg_composer_get_header_table (composer);
+	registry = e_composer_header_table_get_registry (table);
 
 	if (folder != NULL) {
 		CamelStore *store;
-		const gchar *uid;
 		gchar *folder_uri;
 		GList *list;
 
 		store = camel_folder_get_parent_store (folder);
-		uid = camel_service_get_uid (CAMEL_SERVICE (store));
-		account = e_get_account_by_uid (uid);
+		source = em_utils_ref_mail_identity_for_store (registry, store);
 
 		folder_uri = e_mail_folder_uri_from_folder (folder);
 
@@ -1002,8 +1032,15 @@ create_new_composer (EShell *shell,
 		g_free (folder_uri);
 	}
 
-	e_composer_header_table_set_account (table, account);
+	if (source != NULL) {
+		identity = e_source_dup_uid (source);
+		g_object_unref (source);
+	}
+
 	e_composer_header_table_set_subject (table, subject);
+	e_composer_header_table_set_identity_uid (table, identity);
+
+	g_free (identity);
 
 	return composer;
 }
@@ -1049,8 +1086,8 @@ em_utils_compose_new_message_with_mailto (EShell *shell,
                                           CamelFolder *folder)
 {
 	EMsgComposer *composer;
+	ESourceRegistry *registry;
 	EComposerHeaderTable *table;
-	CamelService *service = NULL;
 
 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
 
@@ -1063,25 +1100,29 @@ em_utils_compose_new_message_with_mailto (EShell *shell,
 		composer = e_msg_composer_new (shell);
 
 	table = e_msg_composer_get_header_table (composer);
+	registry = e_composer_header_table_get_registry (table);
+
+	composer_set_no_change (composer);
+
+	gtk_window_present (GTK_WINDOW (composer));
+
+	/* If a CamelFolder was given, we need to backtrack and find
+	 * the corresponding ESource with a Mail Identity extension. */
 
 	if (folder != NULL) {
+		ESource *source;
 		CamelStore *store;
 
 		store = camel_folder_get_parent_store (folder);
-		service = CAMEL_SERVICE (store);
-	}
-
-	if (service != NULL) {
-		const gchar *display_name;
+		source = em_utils_ref_mail_identity_for_store (registry, store);
 
-		display_name = camel_service_get_display_name (service);
-		e_composer_header_table_set_account_name (table, display_name);
+		if (source != NULL) {
+			const gchar *uid = e_source_get_uid (source);
+			e_composer_header_table_set_identity_uid (table, uid);
+			g_object_unref (source);
+		}
 	}
 
-	composer_set_no_change (composer);
-
-	gtk_window_present (GTK_WINDOW (composer));
-
 	return composer;
 }
 
@@ -1302,6 +1343,7 @@ em_utils_edit_message (EShell *shell,
                        const gchar *message_uid)
 {
 	EMsgComposer *composer;
+	ESourceRegistry *registry;
 	gboolean folder_is_drafts;
 	gboolean folder_is_outbox;
 	gboolean folder_is_templates;
@@ -1310,9 +1352,10 @@ em_utils_edit_message (EShell *shell,
 	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
 	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
 
-	folder_is_drafts = em_utils_folder_is_drafts (folder);
-	folder_is_outbox = em_utils_folder_is_outbox (folder);
-	folder_is_templates = em_utils_folder_is_templates (folder);
+	registry = e_shell_get_registry (shell);
+	folder_is_drafts = em_utils_folder_is_drafts (registry, folder);
+	folder_is_outbox = em_utils_folder_is_outbox (registry, folder);
+	folder_is_templates = em_utils_folder_is_templates (registry, folder);
 
 	/* Template specific code follows. */
 	if (folder_is_templates) {
@@ -1339,19 +1382,23 @@ em_utils_edit_message (EShell *shell,
 	}
 
 	composer = e_msg_composer_new_with_message (shell, message, NULL);
-	if (folder && !folder_is_templates) {
+	if (!folder_is_templates) {
 		EComposerHeaderTable *table;
-		EAccount *account;
+		ESource *source;
 		CamelStore *store;
-		const gchar *uid;
 		gchar *folder_uri;
 		GList *list;
 
 		table = e_msg_composer_get_header_table (composer);
 
 		store = camel_folder_get_parent_store (folder);
-		uid = camel_service_get_uid (CAMEL_SERVICE (store));
-		account = e_get_account_by_uid (uid);
+		source = em_utils_ref_mail_identity_for_store (registry, store);
+
+		if (source != NULL) {
+			const gchar *uid = e_source_get_uid (source);
+			e_composer_header_table_set_identity_uid (table, uid);
+			g_object_unref (source);
+		}
 
 		folder_uri = e_mail_folder_uri_from_folder (folder);
 
@@ -1360,8 +1407,6 @@ em_utils_edit_message (EShell *shell,
 		g_list_free (list);
 
 		g_free (folder_uri);
-
-		e_composer_header_table_set_account (table, account);
 	}
 
 	e_msg_composer_remove_header (
@@ -1902,8 +1947,11 @@ static EMsgComposer *
 redirect_get_composer (EShell *shell,
                        CamelMimeMessage *message)
 {
+	EMsgComposer *composer;
+	ESourceRegistry *registry;
 	CamelMedium *medium;
-	EAccount *account;
+	ESource *source;
+	gchar *identity_uid = NULL;
 
 	medium = CAMEL_MEDIUM (message);
 
@@ -1919,10 +1967,23 @@ redirect_get_composer (EShell *shell,
 	while (camel_medium_get_header (medium, "Resent-Bcc"))
 		camel_medium_remove_header (medium, "Resent-Bcc");
 
-	account = em_utils_guess_account_with_recipients (message, NULL);
+	registry = e_shell_get_registry (shell);
+
+	/* This returns a new ESource reference. */
+	source = em_utils_guess_mail_identity_with_recipients (
+		registry, message, NULL);
+
+	if (source != NULL) {
+		identity_uid = e_source_dup_uid (source);
+		g_object_unref (source);
+	}
 
-	return e_msg_composer_new_redirect (
-		shell, message, account ? account->name : NULL, NULL);
+	composer = e_msg_composer_new_redirect (
+		shell, message, identity_uid, NULL);
+
+	g_free (identity_uid);
+
+	return composer;
 }
 
 /**
@@ -1989,7 +2050,7 @@ em_utils_camel_address_to_destination (CamelInternetAddress *iaddr)
 static EMsgComposer *
 reply_get_composer (EShell *shell,
                     CamelMimeMessage *message,
-                    EAccount *account,
+                    const gchar *identity_uid,
                     CamelInternetAddress *to,
                     CamelInternetAddress *cc,
                     CamelFolder *folder,
@@ -2030,9 +2091,9 @@ reply_get_composer (EShell *shell,
 	}
 
 	table = e_msg_composer_get_header_table (composer);
-	e_composer_header_table_set_account (table, account);
 	e_composer_header_table_set_subject (table, subject);
 	e_composer_header_table_set_destinations_to (table, tov);
+	e_composer_header_table_set_identity_uid (table, identity_uid);
 
 	/* Add destinations instead of setting, so we don't remove
 	 * automatic CC addresses that have already been added. */
@@ -2311,64 +2372,6 @@ get_reply_recipient (CamelMimeMessage *message,
 
 }
 
-static GHashTable *
-generate_recipient_hash (void)
-{
-	GHashTable *rcpt_hash;
-	EAccount *account, *def;
-	EAccountList *account_list;
-	EIterator *iterator;
-
-	account_list = e_get_account_list ();
-	rcpt_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
-
-	def = e_get_default_account ();
-
-	iterator = e_list_get_iterator (E_LIST (account_list));
-
-	while (e_iterator_is_valid (iterator)) {
-		account = (EAccount *) e_iterator_get (iterator);
-
-		if (account->id->address) {
-			EAccount *acnt;
-
-			/* Accounts with identical email addresses that are
-			 * enabled take precedence over the accounts that
-			 * aren't. If all accounts with matching email
-			 * addresses are disabled, then the first one in
-			 * the list takes precedence. The default account
-			 * always takes precedence no matter what. */
-			acnt = g_hash_table_lookup (
-				rcpt_hash, account->id->address);
-			if (acnt && acnt != def && !acnt->enabled && account->enabled) {
-				g_hash_table_remove (
-					rcpt_hash, acnt->id->address);
-				acnt = NULL;
-			}
-
-			if (!acnt)
-				g_hash_table_insert (
-					rcpt_hash, (gchar *)
-					account->id->address,
-					(gpointer) account);
-		}
-
-		e_iterator_next (iterator);
-	}
-
-	g_object_unref (iterator);
-
-	/* The default account has to be there if none
-	 * of the enabled accounts are present. */
-	if (g_hash_table_size (rcpt_hash) == 0 && def && def->id->address)
-		g_hash_table_insert (
-			rcpt_hash, (gchar *)
-			def->id->address,
-			(gpointer) def);
-
-	return rcpt_hash;
-}
-
 static void
 concat_unique_addrs (CamelInternetAddress *dest,
                      CamelInternetAddress *src,
@@ -2385,8 +2388,91 @@ concat_unique_addrs (CamelInternetAddress *dest,
 	}
 }
 
+static GHashTable *
+generate_recipient_hash (ESourceRegistry *registry)
+{
+	GHashTable *rcpt_hash;
+	ESource *default_source;
+	GList *list, *link;
+	const gchar *extension_name;
+
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+	rcpt_hash = g_hash_table_new (
+		(GHashFunc) camel_strcase_hash,
+		(GEqualFunc) camel_strcase_equal);
+
+	default_source = e_source_registry_ref_default_mail_identity (registry);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESource *cached_source;
+		ESourceMailIdentity *extension;
+		const gchar *address;
+		gboolean insert_source;
+		gboolean cached_is_default;
+		gboolean cached_is_enabled;
+		gboolean source_is_default;
+		gboolean source_is_enabled;
+
+		/* No default mail identity implies there are no mail
+		 * identities at all and so we should never get here. */
+		g_warn_if_fail (default_source != NULL);
+
+		source_is_default = e_source_equal (source, default_source);
+		source_is_enabled = e_source_get_enabled (source);
+
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		extension = e_source_get_extension (source, extension_name);
+
+		address = e_source_mail_identity_get_address (extension);
+
+		if (address == NULL)
+			continue;
+
+		cached_source = g_hash_table_lookup (rcpt_hash, address);
+
+		if (cached_source != NULL) {
+			cached_is_default = e_source_equal (
+				cached_source, default_source);
+			cached_is_enabled =
+				e_source_get_enabled (cached_source);
+		} else {
+			cached_is_default = FALSE;
+			cached_is_enabled = FALSE;
+		}
+
+		/* Accounts with identical email addresses that are enabled
+		 * take precedence over disabled accounts.  If all accounts
+		 * with matching email addresses are disabled, the first
+		 * one in the list takes precedence.  The default account
+		 * always takes precedence no matter what. */
+		insert_source =
+			source_is_default ||
+			cached_source == NULL ||
+			(source_is_enabled &&
+			 !cached_is_enabled &&
+			 !cached_is_default);
+
+		if (insert_source)
+			g_hash_table_insert (
+				rcpt_hash, (gchar *) address, source);
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	if (default_source != NULL)
+		g_object_unref (default_source);
+
+	return rcpt_hash;
+}
+
 void
-em_utils_get_reply_all (CamelMimeMessage *message,
+em_utils_get_reply_all (ESourceRegistry *registry,
+                        CamelMimeMessage *message,
                         CamelInternetAddress *to,
                         CamelInternetAddress *cc,
                         CamelNNTPAddress *postto)
@@ -2399,6 +2485,7 @@ em_utils_get_reply_all (CamelMimeMessage *message,
 	const gchar *posthdr = NULL;
 	GHashTable *rcpt_hash;
 
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 	g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (to));
 	g_return_if_fail (CAMEL_IS_INTERNET_ADDRESS (cc));
@@ -2415,7 +2502,7 @@ em_utils_get_reply_all (CamelMimeMessage *message,
 	if (postto != NULL && posthdr != NULL)
 		camel_address_decode (CAMEL_ADDRESS (postto), posthdr);
 
-	rcpt_hash = generate_recipient_hash ();
+	rcpt_hash = generate_recipient_hash (registry);
 
 	reply_to = get_reply_to (message);
 	to_addrs = camel_mime_message_get_recipients (
@@ -2804,10 +2891,12 @@ em_utils_reply_to_message (EShell *shell,
                            EMFormat *source_formatter,
                            CamelInternetAddress *address)
 {
+	ESourceRegistry *registry;
 	CamelInternetAddress *to, *cc;
 	CamelNNTPAddress *postto = NULL;
 	EMsgComposer *composer;
-	EAccount *account;
+	ESource *source;
+	gchar *identity_uid = NULL;
 	guint32 flags;
 
 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
@@ -2816,11 +2905,20 @@ em_utils_reply_to_message (EShell *shell,
 	to = camel_internet_address_new ();
 	cc = camel_internet_address_new ();
 
-	account = em_utils_guess_account_with_recipients (message, folder);
+	registry = e_shell_get_registry (shell);
+
+	/* This returns a new ESource reference. */
+	source = em_utils_guess_mail_identity_with_recipients (
+		registry, message, folder);
+	if (source != NULL) {
+		identity_uid = e_source_dup_uid (source);
+		g_object_unref (source);
+	}
+
 	flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN;
 
 	if (!address && (type == E_MAIL_REPLY_TO_FROM || type == E_MAIL_REPLY_TO_SENDER) &&
-	    folder && em_utils_folder_is_sent (folder))
+	    folder && em_utils_folder_is_sent (registry, folder))
 		type = E_MAIL_REPLY_TO_ALL;
 
 	switch (type) {
@@ -2852,12 +2950,12 @@ em_utils_reply_to_message (EShell *shell,
 		if (folder)
 			postto = camel_nntp_address_new ();
 
-		em_utils_get_reply_all (message, to, cc, postto);
+		em_utils_get_reply_all (registry, message, to, cc, postto);
 		break;
 	}
 
 	composer = reply_get_composer (
-		shell, message, account, to, cc, folder, postto);
+		shell, message, identity_uid, to, cc, folder, postto);
 	e_msg_composer_add_message_attachments (composer, message, TRUE);
 
 	if (postto)
@@ -2882,6 +2980,8 @@ em_utils_reply_to_message (EShell *shell,
 
 	gtk_widget_show (GTK_WIDGET (composer));
 
+	g_free (identity_uid);
+
 	return composer;
 }
 
@@ -2969,7 +3069,7 @@ em_configure_new_composer (EMsgComposer *composer,
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_account), session);
+		G_CALLBACK (composer_presend_check_identity), session);
 
 	g_signal_connect (
 		composer, "presend",
diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h
index 865254c..a525cec 100644
--- a/mail/em-composer-utils.h
+++ b/mail/em-composer-utils.h
@@ -67,7 +67,8 @@ gboolean	em_utils_is_munged_list_message	(CamelMimeMessage *message);
 void		em_utils_get_reply_sender	(CamelMimeMessage *message,
 						 CamelInternetAddress *to,
 						 CamelNNTPAddress *postto);
-void		em_utils_get_reply_all		(CamelMimeMessage *message,
+void		em_utils_get_reply_all		(ESourceRegistry *registry,
+						 CamelMimeMessage *message,
 						 CamelInternetAddress *to,
 						 CamelInternetAddress *cc,
 						 CamelNNTPAddress *postto);
diff --git a/mail/em-filter-source-element.c b/mail/em-filter-source-element.c
index 5848f93..4362b11 100644
--- a/mail/em-filter-source-element.c
+++ b/mail/em-filter-source-element.c
@@ -32,23 +32,18 @@
 #include <gtk/gtk.h>
 #include <camel/camel.h>
 
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+
+#include <shell/e-shell.h>
 #include <filter/e-filter-part.h>
-#include <libemail-utils/e-account-utils.h>
 
 #define EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), EM_TYPE_FILTER_SOURCE_ELEMENT, EMFilterSourceElementPrivate))
 
-typedef struct _SourceInfo {
-	gchar *account_name;
-	gchar *name;
-	gchar *address;
-	gchar *uid;
-} SourceInfo;
-
 struct _EMFilterSourceElementPrivate {
 	EMailSession *session;
-	GList *sources;
 	gchar *active_id;
 };
 
@@ -63,16 +58,6 @@ enum {
 };
 
 static void
-source_info_free (SourceInfo *info)
-{
-	g_free (info->account_name);
-	g_free (info->name);
-	g_free (info->address);
-	g_free (info->uid);
-	g_free (info);
-}
-
-static void
 filter_source_element_source_changed (GtkComboBox *combo_box,
                                       EMFilterSourceElement *fs)
 {
@@ -85,52 +70,6 @@ filter_source_element_source_changed (GtkComboBox *combo_box,
 }
 
 static void
-filter_source_element_add_source (EMFilterSourceElement *fs,
-                                  const gchar *account_name,
-                                  const gchar *name,
-                                  const gchar *addr,
-                                  const gchar *uid)
-{
-	SourceInfo *info;
-
-	g_return_if_fail (EM_IS_FILTER_SOURCE_ELEMENT (fs));
-
-	info = g_new0 (SourceInfo, 1);
-	info->account_name = g_strdup (account_name);
-	info->name = g_strdup (name);
-	info->address = g_strdup (addr);
-	info->uid = g_strdup (uid);
-
-	fs->priv->sources = g_list_append (fs->priv->sources, info);
-}
-
-static void
-filter_source_element_get_sources (EMFilterSourceElement *fs)
-{
-	EAccountList *accounts;
-	const EAccount *account;
-	EIterator *it;
-
-	/* should this get the global object from mail? */
-	accounts = e_get_account_list ();
-
-	for (it = e_list_get_iterator ((EList *) accounts);
-	     e_iterator_is_valid (it);
-	     e_iterator_next (it)) {
-		account = (const EAccount *) e_iterator_get (it);
-
-		if (account->source == NULL)
-			continue;
-
-		filter_source_element_add_source (
-			fs, account->name, account->id->name,
-			account->id->address, account->uid);
-	}
-
-	g_object_unref (it);
-}
-
-static void
 filter_source_element_set_session (EMFilterSourceElement *element,
                                    EMailSession *session)
 {
@@ -198,8 +137,6 @@ filter_source_element_finalize (GObject *object)
 
 	priv = EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE (object);
 
-	g_list_foreach (priv->sources, (GFunc) source_info_free, NULL);
-	g_list_free (priv->sources);
 	g_free (priv->active_id);
 
 	/* Chain up to parent's finalize() method. */
@@ -305,7 +242,6 @@ filter_source_element_clone (EFilterElement *fe)
 	EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
 	EMFilterSourceElement *cpy;
 	EMailSession *session;
-	GList *i;
 
 	session = em_filter_source_element_get_session (fs);
 	cpy = (EMFilterSourceElement *) em_filter_source_element_new (session);
@@ -313,13 +249,6 @@ filter_source_element_clone (EFilterElement *fe)
 
 	cpy->priv->active_id = g_strdup (fs->priv->active_id);
 
-	for (i = fs->priv->sources; i != NULL; i = g_list_next (i)) {
-		SourceInfo *info = (SourceInfo *) i->data;
-		filter_source_element_add_source (
-			cpy, info->account_name, info->name,
-			info->address, info->uid);
-	}
-
 	return (EFilterElement *) cpy;
 }
 
@@ -327,29 +256,42 @@ static GtkWidget *
 filter_source_element_get_widget (EFilterElement *fe)
 {
 	EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
+	EMailSession *session;
+	ESourceRegistry *registry;
+	GList *list, *link;
 	GtkWidget *widget;
 	GtkComboBox *combo_box;
-	GList *i;
-
-	if (fs->priv->sources == NULL)
-		filter_source_element_get_sources (fs);
+	const gchar *extension_name;
 
 	widget = gtk_combo_box_text_new ();
 	combo_box = GTK_COMBO_BOX (widget);
 
-	for (i = fs->priv->sources; i != NULL; i = g_list_next (i)) {
-		SourceInfo *info = (SourceInfo *) i->data;
+	session = em_filter_source_element_get_session (fs);
+	registry = e_mail_session_get_registry (session);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceMailIdentity *extension;
 		const gchar *display_name;
 		const gchar *address;
 		const gchar *name;
 		const gchar *uid;
 		gchar *label;
 
-		uid = info->uid;
-		display_name = info->account_name;
+		uid = e_source_get_uid (source);
+		display_name = e_source_get_display_name (source);
 
-		name = info->name;
-		address = info->address;
+		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+		extension = e_source_get_extension (source, extension_name);
+
+		name = e_source_mail_identity_get_name (extension);
+		address = e_source_mail_identity_get_address (extension);
+
+		if (name == NULL || address == NULL)
+			continue;
 
 		if (g_strcmp0 (display_name, address) == 0)
 			label = g_strdup_printf (
@@ -365,6 +307,8 @@ filter_source_element_get_widget (EFilterElement *fe)
 		g_free (label);
 	}
 
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
 	if (fs->priv->active_id != NULL) {
 		gtk_combo_box_set_active_id (combo_box, fs->priv->active_id);
 	} else {
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index 20337c5..d533c47 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -36,10 +36,14 @@
 
 #include <glib/gi18n.h>
 
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+
 #include <e-util/e-util.h>
 #include <shell/e-shell.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-utils/mail-mt.h>
 
 #include <libemail-engine/e-mail-folder-utils.h>
@@ -605,6 +609,64 @@ em_folder_tree_model_set_session (EMFolderTreeModel *model,
 	g_object_notify (G_OBJECT (model), "session");
 }
 
+/* Helper for em_folder_tree_model_set_folder_info() */
+static void
+folder_tree_model_get_drafts_folder_uri (ESourceRegistry *registry,
+                                         CamelStore *store,
+                                         gchar **drafts_folder_uri)
+{
+	ESource *source;
+	const gchar *extension_name;
+
+	/* In case we fail... */
+	*drafts_folder_uri = NULL;
+
+	source = em_utils_ref_mail_identity_for_store (registry, store);
+	if (source == NULL)
+		return;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
+	if (e_source_has_extension (source, extension_name)) {
+		ESourceMailComposition *extension;
+
+		extension = e_source_get_extension (source, extension_name);
+
+		*drafts_folder_uri =
+			e_source_mail_composition_dup_drafts_folder (extension);
+	}
+
+	g_object_unref (source);
+}
+
+/* Helper for em_folder_tree_model_set_folder_info() */
+static void
+folder_tree_model_get_sent_folder_uri (ESourceRegistry *registry,
+                                       CamelStore *store,
+                                       gchar **sent_folder_uri)
+{
+	ESource *source;
+	const gchar *extension_name;
+
+	/* In case we fail... */
+	*sent_folder_uri = NULL;
+
+	source = em_utils_ref_mail_identity_for_store (registry, store);
+	if (source == NULL)
+		return;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	if (e_source_has_extension (source, extension_name)) {
+		ESourceMailSubmission *extension;
+
+		extension = e_source_get_extension (source, extension_name);
+
+		*sent_folder_uri =
+			e_source_mail_submission_dup_sent_folder (extension);
+	}
+
+	g_object_unref (source);
+}
+
 void
 em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
                                       GtkTreeIter *iter,
@@ -615,8 +677,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 	GtkTreeRowReference *path_row;
 	GtkTreeStore *tree_store;
 	MailFolderCache *folder_cache;
+	ESourceRegistry *registry;
 	EMailSession *session;
-	EAccount *account;
 	guint unread;
 	GtkTreePath *path;
 	GtkTreeIter sub;
@@ -642,10 +704,10 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 
 	session = em_folder_tree_model_get_session (model);
 	folder_cache = e_mail_session_get_folder_cache (session);
+	registry = e_mail_session_get_registry (session);
 
 	uid = camel_service_get_uid (CAMEL_SERVICE (si->store));
 	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
-	account = e_get_account_by_uid (uid);
 
 	if (!fully_loaded)
 		load = (fi->child == NULL) && !(fi->flags &
@@ -668,8 +730,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 	unread = fi->unread;
 	if (mail_folder_cache_get_folder_from_uri (
 		folder_cache, uri, &folder) && folder) {
-		folder_is_drafts = em_utils_folder_is_drafts (folder);
-		folder_is_outbox = em_utils_folder_is_outbox (folder);
+		folder_is_drafts = em_utils_folder_is_drafts (registry, folder);
+		folder_is_outbox = em_utils_folder_is_outbox (registry, folder);
 
 		if (folder_is_drafts || folder_is_outbox) {
 			gint total;
@@ -712,20 +774,32 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 		}
 	}
 
-	if (account != NULL && (flags & CAMEL_FOLDER_TYPE_MASK) == 0) {
-		if (!folder_is_drafts && account->drafts_folder_uri != NULL) {
+	if ((flags & CAMEL_FOLDER_TYPE_MASK) == 0) {
+		gchar *drafts_folder_uri;
+		gchar *sent_folder_uri;
+
+		folder_tree_model_get_drafts_folder_uri (
+			registry, si->store, &drafts_folder_uri);
+
+		folder_tree_model_get_sent_folder_uri (
+			registry, si->store, &sent_folder_uri);
+
+		if (!folder_is_drafts && drafts_folder_uri != NULL) {
 			folder_is_drafts = e_mail_folder_uri_equal (
-				CAMEL_SESSION (session), uri,
-				account->drafts_folder_uri);
+				CAMEL_SESSION (session),
+				uri, drafts_folder_uri);
 		}
 
-		if (account->sent_folder_uri != NULL) {
+		if (sent_folder_uri != NULL) {
 			if (e_mail_folder_uri_equal (
-				CAMEL_SESSION (session), uri,
-				account->sent_folder_uri)) {
+				CAMEL_SESSION (session),
+				uri, sent_folder_uri)) {
 				add_flags = CAMEL_FOLDER_TYPE_SENT;
 			}
 		}
+
+		g_free (drafts_folder_uri);
+		g_free (sent_folder_uri);
 	}
 
 	/* Choose an icon name for the folder. */
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index aea13e9..f60346d 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -1546,17 +1546,22 @@ efh_write_attachment (EMFormat *emf,
 static void
 efh_preparse (EMFormat *emf)
 {
-	CamelInternetAddress *addr;
-
 	EMFormatHTML *efh = EM_FORMAT_HTML (emf);
+	CamelInternetAddress *addr;
+	CamelSession *session;
+	ESourceRegistry *registry;
 
 	if (!emf->message) {
 		efh->priv->can_load_images = FALSE;
 		return;
 	}
 
+	session = em_format_get_session (emf);
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
 	addr = camel_mime_message_get_from (emf->message);
-	efh->priv->can_load_images = em_utils_in_addressbook (addr, FALSE);
+	efh->priv->can_load_images = em_utils_in_addressbook (
+		registry, addr, FALSE);
 }
 
 static void
@@ -2678,6 +2683,8 @@ efh_format_full_headers (EMFormatHTML *efh,
 	gboolean have_icon = FALSE;
 	const gchar *photo_name = NULL;
 	CamelInternetAddress *cia = NULL;
+	CamelSession *session;
+	ESourceRegistry *registry;
 	gboolean face_decoded  = FALSE, contact_has_photo = FALSE;
 	guchar *face_header_value = NULL;
 	gsize face_header_len = 0;
@@ -2689,6 +2696,9 @@ efh_format_full_headers (EMFormatHTML *efh,
 	if (cancellable && g_cancellable_is_cancelled (cancellable))
 		return;
 
+	session = em_format_get_session (emf);
+	registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
 	ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
 	charset = camel_content_type_param (ct, "charset");
 	charset = camel_iconv_charset_name (charset);
@@ -2869,8 +2879,10 @@ efh_format_full_headers (EMFormatHTML *efh,
 
 		cia = camel_internet_address_new ();
 		camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
-		only_local_photo = em_format_html_get_only_local_photos (efh);
-		photopart = em_utils_contact_photo (cia, only_local_photo);
+		only_local_photo =
+			em_format_html_get_only_local_photos (efh);
+		photopart = em_utils_contact_photo (
+			registry, cia, only_local_photo);
 
 		if (photopart) {
 			g_string_append (buffer, "<td align=\"right\" valign=\"top\">");
diff --git a/mail/em-subscription-editor.c b/mail/em-subscription-editor.c
index f695a88..8221115 100644
--- a/mail/em-subscription-editor.c
+++ b/mail/em-subscription-editor.c
@@ -25,7 +25,6 @@
 #include <string.h>
 #include <glib/gi18n-lib.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-utils/mail-mt.h>
 #include <libemail-engine/mail-tools.h>
 #include <libemail-engine/mail-ops.h>
@@ -1555,19 +1554,24 @@ subscription_editor_constructed (GObject *object)
 	/* Pick an initial store based on the default mail account, if
 	 * one wasn't already given in em_subscription_editor_new(). */
 	if (editor->priv->initial_store == NULL) {
-		EAccount *account;
+		ESource *source;
+		ESourceRegistry *registry;
 		CamelService *service;
 		EMailSession *session;
 
-		account = e_get_default_account ();
-
 		session = em_subscription_editor_get_session (editor);
+		registry = e_mail_session_get_registry (session);
+
+		source = e_source_registry_ref_default_mail_account (registry);
 
 		service = camel_session_get_service (
-			CAMEL_SESSION (session), account->uid);
+			CAMEL_SESSION (session),
+			e_source_get_uid (source));
 
 		if (CAMEL_IS_SUBSCRIBABLE (service))
 			editor->priv->initial_store = g_object_ref (service);
+
+		g_object_unref (source);
 	}
 
 	/* Chain up to parent's constructed() method. */
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 8a6383d..11dc121 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -52,6 +52,15 @@
 #include <libedataserver/e-data-server-util.h>
 #include <libedataserver/e-flag.h>
 #include <libedataserver/e-proxy.h>
+#include <libedataserver/e-source-address-book.h>
+#include <libedataserver/e-source-autocomplete.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-composition.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-flag.h>
+#include <libedataserver/e-proxy.h>
 
 #include <e-util/e-util.h>
 #include <e-util/e-util-private.h>
@@ -62,7 +71,6 @@
 #include <shell/e-shell.h>
 #include <widgets/misc/e-attachment.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-utils/mail-mt.h>
 
 #include <libemail-engine/e-mail-folder-utils.h>
@@ -1266,10 +1274,13 @@ void
 em_utils_empty_trash (GtkWidget *parent,
                       EMailSession *session)
 {
+	ESourceRegistry *registry;
 	GList *list, *link;
 
 	g_return_if_fail (E_IS_MAIL_SESSION (session));
 
+	registry = e_mail_session_get_registry (session);
+
 	if (!em_utils_prompt_user ((GtkWindow *) parent,
 		"prompt-on-empty-trash",
 		"mail:ask-empty-trash", NULL))
@@ -1278,10 +1289,11 @@ em_utils_empty_trash (GtkWidget *parent,
 	list = camel_session_list_services (CAMEL_SESSION (session));
 
 	for (link = list; link != NULL; link = g_list_next (link)) {
-		EAccount *account;
 		CamelProvider *provider;
 		CamelService *service;
+		ESource *source;
 		const gchar *uid;
+		gboolean enabled = TRUE;
 
 		service = CAMEL_SERVICE (link->data);
 		provider = camel_service_get_provider (service);
@@ -1293,16 +1305,15 @@ em_utils_empty_trash (GtkWidget *parent,
 		if ((provider->flags & CAMEL_PROVIDER_IS_STORAGE) == 0)
 			continue;
 
-		account = e_get_account_by_uid (uid);
+		source = e_source_registry_ref_source (registry, uid);
 
-		/* The local store has no corresponding
-		 * EAccount, so skip the enabled check. */
-		if (account != NULL) {
-			if (!account->enabled)
-				continue;
+		if (source != NULL) {
+			enabled = e_source_get_enabled (source);
+			g_object_unref (source);
 		}
 
-		mail_empty_trash (CAMEL_STORE (service));
+		if (enabled)
+			mail_empty_trash (CAMEL_STORE (service));
 	}
 
 	g_list_free (list);
@@ -1310,29 +1321,6 @@ em_utils_empty_trash (GtkWidget *parent,
 
 /* ********************************************************************** */
 
-void
-em_utils_clear_get_password_canceled_accounts_flag (void)
-{
-	EAccountList *account_list;
-	EIterator *iterator;
-
-	account_list = e_get_account_list ();
-
-	for (iterator = e_list_get_iterator (E_LIST (account_list));
-	     e_iterator_is_valid (iterator);
-	     e_iterator_next (iterator)) {
-		EAccount *account = (EAccount *) e_iterator_get (iterator);
-
-		if (account && account->source)
-			account->source->get_password_canceled = FALSE;
-
-		if (account && account->transport)
-			account->transport->get_password_canceled = FALSE;
-	}
-
-	g_object_unref (iterator);
-}
-
 gchar *
 em_utils_url_unescape_amp (const gchar *url)
 {
diff --git a/mail/em-utils.h b/mail/em-utils.h
index bce64ee..303f0ef 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -27,7 +27,6 @@
 #include <sys/types.h>
 #include <camel/camel.h>
 #include <libedataserver/e-proxy.h>
-#include <libedataserver/e-account.h>
 
 #include <libemail-engine/e-mail-session.h>
 #include <libemail-engine/e-mail-utils.h>
@@ -73,14 +72,9 @@ gchar *em_utils_message_to_html (CamelSession *session, CamelMimeMessage *msg, c
 void		em_utils_empty_trash		(GtkWidget *parent,
 						 EMailSession *session);
 
-/* clears flag 'get_password_canceled' at every known accounts, so if needed, get_password will show dialog */
-void em_utils_clear_get_password_canceled_accounts_flag (void);
-
 /* Unescapes &amp; back to a real & in URIs */
 gchar *em_utils_url_unescape_amp (const gchar *url);
 
-void emu_free_mail_account_sort_order_cache (void);
-
 void emu_restore_folder_tree_state (EMFolderTree *folder_tree);
 
 gboolean em_utils_is_re_in_subject (struct _EShell *shell,
diff --git a/mail/mail-config.ui b/mail/mail-config.ui
index 0d906ed..224f659 100644
--- a/mail/mail-config.ui
+++ b/mail/mail-config.ui
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires evolution 0.0 -->
   <requires lib="gtk+" version="2.16"/>
   <object class="GtkDialog" id="add-custom-junk-header">
     <property name="width_request">400</property>
@@ -143,244 +142,6 @@
       <action-widget response="-3">junk-header-ok</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkDialog" id="add_script_signature">
-    <property name="can_focus">False</property>
-    <property name="type_hint">normal</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">12</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="button_add_script_add">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_action_appearance">False</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment30">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xscale">0</property>
-                    <property name="yscale">0</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox221">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">2</property>
-                        <child>
-                          <object class="GtkImage" id="image5">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="stock">gtk-add</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label547">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">_Add Signature</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button_add_script_cancel">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkVBox" id="vbox160">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <child>
-              <object class="GtkVBox" id="vbox_add_script_signature">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">12</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkHBox" id="hboxImageAndHelp">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkImage" id="pixmap1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="yalign">0</property>
-                        <property name="stock">gtk-dialog-info</property>
-                        <property name="icon-size">6</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label456">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">The output of this script will be used as your
-signature. The name you specify will be used
-for display purposes only. </property>
-                        <property name="wrap">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkTable" id="tblNameScript">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="n_rows">2</property>
-                    <property name="n_columns">2</property>
-                    <property name="column_spacing">6</property>
-                    <property name="row_spacing">6</property>
-                    <child>
-                      <object class="GtkLabel" id="label459">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">_Name:</property>
-                        <property name="use_underline">True</property>
-                        <property name="justify">center</property>
-                        <property name="mnemonic_widget">entry_add_script_name</property>
-                      </object>
-                      <packing>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label460">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">_Script:</property>
-                        <property name="use_underline">True</property>
-                        <property name="justify">center</property>
-                        <property name="mnemonic_widget">filechooserbutton_add_script</property>
-                      </object>
-                      <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="entry_add_script_name">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkFileChooserButton" id="filechooserbutton_add_script">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="title" translatable="yes"></property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options"></property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="0">button_add_script_add</action-widget>
-      <action-widget response="0">button_add_script_cancel</action-widget>
-    </action-widgets>
-  </object>
   <object class="GtkAdjustment" id="adjustment1">
     <property name="upper">10</property>
     <property name="value">1.5</property>
@@ -845,56 +606,6 @@ for display purposes only. </property>
             <property name="position">0</property>
           </packing>
         </child>
-        <child>
-          <object class="GtkVBox" id="signature-preview-section">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="spacing">6</property>
-            <child>
-              <object class="GtkLabel" id="signature-preview-header">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">Preview</property>
-                <attributes>
-                  <attribute name="weight" value="bold"/>
-                </attributes>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkAlignment" id="signature-preview-alignment">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="left_padding">12</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="signature-preview-scrolled-window">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="shadow_type">in</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
       </object>
       <packing>
         <property name="position">1</property>
@@ -1706,18 +1417,6 @@ for display purposes only. </property>
                                     <property name="y_options"></property>
                                   </packing>
                                 </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
-                                <child>
-                                  <placeholder/>
-                                </child>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -3287,13 +2986,26 @@ for display purposes only. </property>
       </packing>
     </child>
   </object>
-  <object class="GtkListStore" id="use_ssl_model">
-    <columns>
-      <!-- column-name Label -->
-      <column type="gchararray"/>
-      <!-- column-name Value -->
-      <column type="gchararray"/>
-    </columns>
+  <object class="GtkSizeGroup" id="composer-combo-box-size-group">
+    <widgets>
+      <widget name="comboboxReplyStyle"/>
+      <widget name="comboboxForwardStyle"/>
+    </widgets>
+  </object>
+  <object class="GtkSizeGroup" id="composer-label-size-group">
+    <widgets>
+      <widget name="lblCharset"/>
+      <widget name="lblReplyStyle"/>
+      <widget name="lblForwardStyle"/>
+    </widgets>
+  </object>
+  <object class="GtkListStore" id="use_ssl_model">
+    <columns>
+      <!-- column-name Label -->
+      <column type="gchararray"/>
+      <!-- column-name Value -->
+      <column type="gchararray"/>
+    </columns>
     <data>
       <row>
         <col id="0" translatable="yes">No encryption</col>
@@ -3309,2864 +3021,4 @@ for display purposes only. </property>
       </row>
     </data>
   </object>
-  <object class="GtkVBox" id="vboxFoldersBorder">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <property name="spacing">12</property>
-    <child>
-      <object class="GtkVBox" id="special-folders-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="special-folders-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Special Folders</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="special-folders-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="xscale">0</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="special-folders-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">5</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="drafts_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Drafts _Folder:</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="sent_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Sent _Messages Folder:</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="trash_folder_check">
-                    <property name="label" translatable="yes">_Trash Folder:</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="junk_folder_check">
-                    <property name="label" translatable="yes">_Junk Folder:</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="revert-button-alignment">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="xscale">0</property>
-                    <child>
-                      <object class="GtkButton" id="default_folders_button">
-                        <property name="label">gtk-revert-to-saved</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="use_stock">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">4</property>
-                    <property name="bottom_attach">5</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="EMFolderSelectionButton" id="drafts_button">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_action_appearance">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="EMFolderSelectionButton" id="sent_button">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_action_appearance">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="EMFolderSelectionButton" id="trash_folder_butt">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_action_appearance">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="EMFolderSelectionButton" id="junk_folder_butt">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_action_appearance">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="composing-messages-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="composing-messages-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Composing Messages</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="composing-messages-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="composing-messages-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">4</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkAlignment" id="always-bcc-alignment">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="left_padding">18</property>
-                    <child>
-                      <object class="GtkEntry" id="bcc_addrs">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="invisible_char">â</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="always_bcc">
-                    <property name="label" translatable="yes">Always _blind carbon-copy (bcc) to:</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="always-cc-alignment">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="left_padding">18</property>
-                    <child>
-                      <object class="GtkEntry" id="cc_addrs">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="invisible_char">â</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="always_cc">
-                    <property name="label" translatable="yes">Alway_s carbon-copy (cc) to:</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="message-receipts-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="message-receipts-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Message Receipts</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="message-receipts-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkHBox" id="message-receipts-hbox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">12</property>
-                <child>
-                  <object class="GtkLabel" id="label583">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">S_end message receipts:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">receipt_policy_dropdown</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkComboBox" id="receipt_policy_dropdown">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-  </object>
-  <object class="GtkVBox" id="vboxIdentityBorder">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <property name="spacing">12</property>
-    <child>
-      <object class="GtkVBox" id="management-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="management-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Account Information</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="management-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="management-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="column_spacing">6</property>
-                <property name="row_spacing">2</property>
-                <child>
-                  <object class="GtkVBox" id="account_vbox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkLabel" id="management_description_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Type the name by which you would like to refer to this account.
-For example: "Work" or "Personal"</property>
-                        <property name="use_markup">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkHBox" id="hboxIdentityName">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">12</property>
-                        <child>
-                          <object class="GtkLabel" id="management_name_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">_Name:</property>
-                            <property name="use_underline">True</property>
-                            <property name="justify">right</property>
-                            <property name="mnemonic_widget">management_name</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="management_name">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">â</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="right_attach">1</property>
-                    <property name="top_attach">0</property>
-                    <property name="bottom_attach">1</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="identity-required-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="identity-required-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Required Information</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="identity-required-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="identity-required-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">2</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkEntry" id="identity_address">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                    <accessibility>
-                      <relation type="labelled-by" target="identity_address_label"/>
-                      <relation type="labelled-by" target="identity-required-header"/>
-                    </accessibility>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="identity_address_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Email _Address:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">identity_address</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="identity_full_name_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Full Nam_e:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">identity_full_name</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="identity_full_name">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                    <accessibility>
-                      <relation type="labelled-by" target="identity-required-header"/>
-                      <relation type="labelled-by" target="identity_full_name_label"/>
-                    </accessibility>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="identity-optional-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="identity-optional-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Optional Information</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="identity-optional-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="identity-optional-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">4</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="sigLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Signat_ure:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">signature_dropdown</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="hbox169">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkComboBox" id="signature_dropdown">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="sigAddNew">
-                        <property name="label" translatable="yes">Add Ne_w Signature...</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="use_underline">True</property>
-                        <signal name="clicked" handler="sigAddNewClicked" swapped="no"/>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="pack_type">end</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="identity_organization">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                    <accessibility>
-                      <relation type="labelled-by" target="identity_organization_label"/>
-                      <relation type="labelled-by" target="identity-optional-header"/>
-                    </accessibility>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="identity_organization_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Or_ganization:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">identity_organization</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="identity_reply_to">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                    <accessibility>
-                      <relation type="labelled-by" target="identity-optional-header"/>
-                      <relation type="labelled-by" target="reply_to_label"/>
-                    </accessibility>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="reply_to_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Re_ply-To:</property>
-                    <property name="use_underline">True</property>
-                    <property name="justify">center</property>
-                    <property name="mnemonic_widget">identity_reply_to</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="management_default">
-                    <property name="label" translatable="yes">_Make this my default account</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="right_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-  </object>
-  <object class="GtkVBox" id="vboxSecurityBorder">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <property name="spacing">12</property>
-    <child>
-      <object class="GtkVBox" id="security-general-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="security-general-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">General</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="security-general-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkCheckButton" id="pgp_no_imip_sign">
-                <property name="label" translatable="yes">_Do not sign meeting requests (for Outlook compatibility)</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_underline">True</property>
-                <property name="draw_indicator">True</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="pgp-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="pgp-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Pretty Good Privacy (PGP/GPG)</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="pgp-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="pgp-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="column_spacing">6</property>
-                <property name="row_spacing">2</property>
-                <child>
-                  <object class="GtkVBox" id="vboxPGP">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox63">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">12</property>
-                        <child>
-                          <object class="GtkLabel" id="pgp_key_id_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">PGP/GPG _Key ID:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">pgp_key</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="pgp_key">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">â</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkHBox" id="hbox4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">12</property>
-                        <child>
-                          <object class="GtkLabel" id="pgp_hash_algo_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Si_gning algorithm:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">pgp_hash_algo</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkComboBox" id="pgp_hash_algo">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="model">hash_algo_model</property>
-                            <child>
-                              <object class="GtkCellRendererText" id="pgp_hash_algo_renderer"/>
-                              <attributes>
-                                <attribute name="text">0</attribute>
-                              </attributes>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkCheckButton" id="pgp_always_sign">
-                        <property name="label" translatable="yes">Al_ways sign outgoing messages when using this account</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkCheckButton" id="pgp_encrypt_to_self">
-                        <property name="label" translatable="yes">Always encrypt to _myself when sending encrypted messages</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkCheckButton" id="pgp_always_trust">
-                        <property name="label" translatable="yes">Always _trust keys in my keyring when encrypting</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">4</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="smime-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="smime-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Secure MIME (S/MIME)</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="smime-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="smime_table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">7</property>
-                <property name="n_columns">3</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkEntry" id="smime_sign_key">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="smime_encrypt_key">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">6</property>
-                    <property name="bottom_attach">7</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="smime_encrypt_to_self">
-                    <property name="label" translatable="yes">Also encrypt to sel_f when sending encrypted messages</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">5</property>
-                    <property name="bottom_attach">6</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="smime_encrypt_default">
-                    <property name="label" translatable="yes">Encrypt out_going messages (by default)</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">4</property>
-                    <property name="bottom_attach">5</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="smime_sign_default">
-                    <property name="label" translatable="yes">Digitally sign o_utgoing messages (by default)</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="right_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                    <property name="y_padding">6</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Encry_ption certificate:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">smime_encrypt_key</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">6</property>
-                    <property name="bottom_attach">7</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label469">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Sig_ning certificate:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">smime_sign_key</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="hbox208">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkButton" id="smime_encrypt_key_select">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="use_action_appearance">False</property>
-                        <child>
-                          <object class="GtkAlignment" id="alignment28">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xscale">0</property>
-                            <property name="yscale">0</property>
-                            <child>
-                              <object class="GtkHBox" id="hbox1">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="spacing">2</property>
-                                <child>
-                                  <object class="GtkImage" id="image3">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="stock">gtk-open</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="button98">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label" translatable="yes">S_elect...</property>
-                                    <property name="use_underline">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="smime_encrypt_key_clear">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="use_action_appearance">False</property>
-                        <child>
-                          <object class="GtkAlignment" id="alignment35">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xscale">0</property>
-                            <property name="yscale">0</property>
-                            <child>
-                              <object class="GtkHBox" id="hbox230">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="spacing">2</property>
-                                <child>
-                                  <object class="GtkImage" id="image10">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="stock">gtk-clear</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label577">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label" translatable="yes">Clea_r</property>
-                                    <property name="use_underline">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">6</property>
-                    <property name="bottom_attach">7</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="smime_hash_algo_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Signing _algorithm:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">smime_hash_algo</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="smime_hash_algo_alignment">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="xscale">0</property>
-                    <child>
-                      <object class="GtkComboBox" id="smime_hash_algo">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="model">hash_algo_model</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="smime_hash_algo_renderer"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="yalign">0</property>
-                    <property name="yscale">0</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox209">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">6</property>
-                        <child>
-                          <object class="GtkButton" id="smime_sign_key_select">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="use_action_appearance">False</property>
-                            <child>
-                              <object class="GtkAlignment" id="alignment29">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xscale">0</property>
-                                <property name="yscale">0</property>
-                                <child>
-                                  <object class="GtkHBox" id="hbox2">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="spacing">2</property>
-                                    <child>
-                                      <object class="GtkImage" id="image4">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="stock">gtk-open</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel" id="label2">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="label" translatable="yes">_Select...</property>
-                                        <property name="use_underline">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="smime_sign_key_clear">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="use_action_appearance">False</property>
-                            <child>
-                              <object class="GtkAlignment" id="alignment34">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xscale">0</property>
-                                <property name="yscale">0</property>
-                                <child>
-                                  <object class="GtkHBox" id="hbox229">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="spacing">2</property>
-                                    <child>
-                                      <object class="GtkImage" id="image9">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="stock">gtk-clear</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel" id="label576">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="label" translatable="yes">Cle_ar</property>
-                                        <property name="use_underline">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-  </object>
-  <object class="GtkVBox" id="vboxSourceBorder">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <property name="spacing">12</property>
-    <child>
-      <object class="GtkTable" id="source-type-table">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="n_rows">2</property>
-        <property name="n_columns">3</property>
-        <property name="column_spacing">12</property>
-        <property name="row_spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="source_type_label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Server _Type:</property>
-            <property name="use_underline">True</property>
-            <property name="justify">right</property>
-            <property name="mnemonic_widget">source_type_dropdown</property>
-          </object>
-          <packing>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="label442">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <property name="label" translatable="yes">Description:</property>
-            <property name="justify">center</property>
-          </object>
-          <packing>
-            <property name="top_attach">1</property>
-            <property name="bottom_attach">2</property>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="source_description">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <property name="label" translatable="yes">description</property>
-            <property name="wrap">True</property>
-            <property name="width-chars">40</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="right_attach">3</property>
-            <property name="top_attach">1</property>
-            <property name="bottom_attach">2</property>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkComboBoxText" id="source_type_dropdown">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="right_attach">3</property>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkHSeparator" id="source-separator">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="source-config-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="source-config-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Configuration</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="source-config-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="source-config-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">3</property>
-                <property name="n_columns">4</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="source_host_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Server:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">source_host</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="source_port_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label">_Port:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">source_port</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="source_user_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">User_name:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">source_user</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="source_host">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="EPortEntry" id="source_port" type-func="e_port_entry_get_type">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="has_entry">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">3</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="source_user">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">4</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="source_path_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Path:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">source_path_entry</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkFileChooserButton" id="source_path_entry">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="title" translatable="yes">Mailbox location</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="source-security-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="source-security-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Security</property>
-            <property name="mnemonic_widget">source_auth_dropdown</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="source-security-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkVBox" id="source-security-vbox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkHBox" id="source_ssl_hbox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">12</property>
-                    <child>
-                      <object class="GtkLabel" id="lblSourceUseSSL">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">_Use secure connection:</property>
-                        <property name="use_underline">True</property>
-                        <property name="justify">center</property>
-                        <property name="mnemonic_widget">source_use_ssl</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="source_use_ssl">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="model">use_ssl_model</property>
-                        <property name="id_column">1</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="source_use_ssl_renderer"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="source_ssl_disabled">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkImage" id="image2">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="stock">gtk-dialog-warning</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label514">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">SSL is not supported in this build of Evolution</property>
-                        <property name="justify">center</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">3</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="source-auth-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="source-auth-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">_Authentication Type</property>
-            <property name="use_underline">True</property>
-            <property name="mnemonic_widget">source_auth_dropdown</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="source-auth-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkVBox" id="source-auth-vbox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkHBox" id="hbox199">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="EAuthComboBox" id="source_auth_dropdown" type-func="e_auth_combo_box_get_type">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="source_check_supported">
-                        <property name="label" translatable="yes">Ch_eck for Supported Types</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="use_underline">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="source_remember_password">
-                    <property name="label" translatable="yes">Re_member password</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">4</property>
-      </packing>
-    </child>
-  </object>
-  <object class="GtkVBox" id="vboxTransportBorder">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <property name="spacing">12</property>
-    <child>
-      <object class="GtkTable" id="transport-type-table">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="n_rows">2</property>
-        <property name="n_columns">3</property>
-        <property name="column_spacing">12</property>
-        <property name="row_spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="transport_type_label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <property name="label" translatable="yes">Server _Type:</property>
-            <property name="use_underline">True</property>
-            <property name="justify">right</property>
-            <property name="mnemonic_widget">transport_type_dropdown</property>
-          </object>
-          <packing>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="label50">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <property name="label" translatable="yes">Description:</property>
-            <property name="justify">right</property>
-          </object>
-          <packing>
-            <property name="top_attach">1</property>
-            <property name="bottom_attach">2</property>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkComboBoxText" id="transport_type_dropdown">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="right_attach">3</property>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="transport_description">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="yalign">0</property>
-            <property name="label" translatable="yes">description</property>
-            <property name="wrap">True</property>
-            <property name="width-chars">40</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="right_attach">3</property>
-            <property name="top_attach">1</property>
-            <property name="bottom_attach">2</property>
-            <property name="x_options">GTK_FILL</property>
-            <property name="y_options"></property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkHSeparator" id="transport-separator">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="transport-server-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="transport-server-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Server Configuration</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="transport-server-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="transport-server-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">2</property>
-                <property name="n_columns">4</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="transport_host_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Server:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">transport_host</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="transport_port_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">_Port:</property>
-                    <property name="use_underline">True</property>
-                    <property name="justify">right</property>
-                    <property name="mnemonic_widget">transport_port</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="transport_host">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="EPortEntry" id="transport_port" type-func="e_port_entry_get_type">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="has_entry">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">3</property>
-                    <property name="x_options"></property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="transport_needs_auth">
-                    <property name="label" translatable="yes">Ser_ver requires authentication</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="transport-security-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="transport-security-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Security</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="transport-security-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="transport-security-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">2</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkHBox" id="transport_ssl_disabled">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkImage" id="image1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="stock">gtk-dialog-warning</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="transport_ssl_disabled_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">SSL is not supported in this build of Evolution</property>
-                        <property name="justify">center</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="transport_ssl_hbox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">12</property>
-                    <child>
-                      <object class="GtkLabel" id="lblTransportUseSSL">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">_Use secure connection:</property>
-                        <property name="use_underline">True</property>
-                        <property name="justify">center</property>
-                        <property name="mnemonic_widget">transport_use_ssl</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="transport_use_ssl">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="model">use_ssl_model</property>
-                        <property name="id_column">1</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="transport_use_ssl_renderer"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">3</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkVBox" id="transport-auth-section">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="transport-auth-header">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Authentication</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="transport-auth-alignment">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkTable" id="transport-auth-table">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">3</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="transport_auth_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">T_ype:</property>
-                    <property name="use_underline">True</property>
-                    <property name="justify">center</property>
-                    <property name="mnemonic_widget">transport_auth_dropdown</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="transport_user_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">User _Name:</property>
-                    <property name="use_underline">True</property>
-                    <property name="justify">right</property>
-                    <property name="mnemonic_widget">transport_user</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="transport_user">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">â</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkCheckButton" id="transport_remember_password">
-                    <property name="label" translatable="yes">Remember _password</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="use_action_appearance">False</property>
-                    <property name="use_underline">True</property>
-                    <property name="draw_indicator">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="xscale">0</property>
-                    <child>
-                      <object class="GtkHBox" id="hbox195">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">6</property>
-                        <child>
-                          <object class="EAuthComboBox" id="transport_auth_dropdown" type-func="e_auth_combo_box_get_type">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkButton" id="transport_check_supported">
-                            <property name="label" translatable="yes">Ch_eck for Supported Types</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">4</property>
-      </packing>
-    </child>
-  </object>
-  <object class="GtkSizeGroup" id="composer-combo-box-size-group">
-    <widgets>
-      <widget name="comboboxReplyStyle"/>
-      <widget name="comboboxForwardStyle"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="composer-label-size-group">
-    <widgets>
-      <widget name="lblCharset"/>
-      <widget name="lblReplyStyle"/>
-      <widget name="lblForwardStyle"/>
-    </widgets>
-  </object>
-  <object class="GtkVBox" id="vboxReviewBorder">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <child>
-      <object class="GtkTable" id="personal-details-table">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="n_rows">3</property>
-        <property name="n_columns">2</property>
-        <property name="row_spacing">4</property>
-        <property name="column_spacing">8</property>
-        <child>
-          <object class="GtkLabel" id="personal-details-label">
-            <property name="visible">True</property>
-           <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Personal Details:</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-           </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="personal-name-label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Name:</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="personal-name-entry">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="personal-email-label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Email address:</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="personal-email-entry">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">2</property>
-          </packing>
-        </child>
-        <child>
-          <placeholder/>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">True</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkTable" id="server-details-table">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="n_rows">5</property>
-        <property name="n_columns">3</property>
-        <property name="row_spacing">4</property>
-        <property name="column_spacing">8</property>
-        <child>
-          <object class="GtkLabel" id="details-label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Details:</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="details-label-receiving">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Receiving</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="details-label-sending">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Sending</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="details-server-type">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Server type:</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="details-server-address">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Server address:</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="details-user-name">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Username:</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">3</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="details-encryption">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">Encryption:</property>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">4</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="receive_server_type">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">none</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="send_server_type">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">none</property>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="receive_server_address">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">none</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="send_server_address">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">none</property>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="receive_username">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">3</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="send_username">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">3</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="receive_encryption">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">4</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="send_encryption">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xalign">0</property>
-            <property name="label" translatable="yes">label</property>
-          </object>
-          <packing>
-            <property name="left_attach">2</property>
-            <property name="top_attach">4</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">True</property>
-        <property name="position">3</property>
-      </packing>
-    </child>
-  </object>
 </interface>
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index ee3cd16..d68b928 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -29,12 +29,12 @@
 
 #include <glib/gi18n.h>
 
-#include <libedataserver/e-account-list.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-submission.h>
 
 #include <shell/e-shell.h>
 #include <e-util/e-util.h>
 
-#include <libemail-utils/e-account-utils.h>
 #include <libemail-utils/mail-mt.h>
 
 /* This is our hack, not part of libcamel. */
@@ -490,7 +490,7 @@ static struct _send_data *
 build_dialog (GtkWindow *parent,
               EMailSession *session,
               CamelFolder *outbox,
-              EAccount *outgoing_account,
+              CamelService *transport,
               gboolean allow_send)
 {
 	GtkDialog *gd;
@@ -508,7 +508,6 @@ build_dialog (GtkWindow *parent,
 	GtkWidget *progress_bar;
 	GtkWidget *cancel_button;
 	EMailAccountStore *account_store;
-	CamelService *transport = NULL;
 	struct _send_info *info;
 	gchar *pretty_url;
 	EMEventTargetSendReceive *target;
@@ -516,17 +515,6 @@ build_dialog (GtkWindow *parent,
 
 	account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
 
-	/* Convert the outgoing account to a CamelTransport. */
-	if (outgoing_account != NULL) {
-		gchar *transport_uid;
-
-		transport_uid = g_strdup_printf (
-			"%s-transport", outgoing_account->uid);
-		transport = camel_session_get_service (
-			CAMEL_SESSION (session), transport_uid);
-		g_free (transport_uid);
-	}
-
 	send_recv_dialog = gtk_dialog_new ();
 
 	gd = GTK_DIALOG (send_recv_dialog);
@@ -1124,14 +1112,57 @@ receive_update_got_store (CamelStore *store,
 	}
 }
 
+static CamelService *
+get_default_transport (EMailSession *session)
+{
+	ESource *source;
+	ESourceRegistry *registry;
+	CamelService *service;
+	const gchar *extension_name;
+	const gchar *uid;
+
+	registry = e_mail_session_get_registry (session);
+	source = e_source_registry_ref_default_mail_identity (registry);
+
+	if (source == NULL)
+		return NULL;
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
+	if (e_source_has_extension (source, extension_name)) {
+		ESourceMailSubmission *extension;
+		gchar *uid;
+
+		extension = e_source_get_extension (source, extension_name);
+		uid = e_source_mail_submission_dup_transport_uid (extension);
+
+		g_object_unref (source);
+		source = e_source_registry_ref_source (registry, uid);
+
+		g_free (uid);
+	} else {
+		g_object_unref (source);
+		source = NULL;
+	}
+
+	if (source == NULL)
+		return NULL;
+
+	uid = e_source_get_uid (source);
+	service = camel_session_get_service (CAMEL_SESSION (session), uid);
+
+	g_object_unref (source);
+
+	return service;
+}
+
 static GtkWidget *
 send_receive (GtkWindow *parent,
               EMailSession *session,
               gboolean allow_send)
 {
 	CamelFolder *local_outbox;
+	CamelService *transport;
 	struct _send_data *data;
-	EAccount *account;
 	GList *scan;
 
 	if (send_recv_dialog != NULL) {
@@ -1144,16 +1175,14 @@ send_receive (GtkWindow *parent,
 	if (!camel_session_get_online (CAMEL_SESSION (session)))
 		return send_recv_dialog;
 
-	account = e_get_default_account ();
-	if (!account || !account->transport->url)
-		return send_recv_dialog;
+	transport = get_default_transport (session);
 
 	local_outbox =
 		e_mail_session_get_local_folder (
 		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 
 	data = build_dialog (
-		parent, session, local_outbox, account, allow_send);
+		parent, session, local_outbox, transport, allow_send);
 
 	for (scan = data->infos; scan != NULL; scan = scan->next) {
 		struct _send_info *info = scan->data;
@@ -1165,7 +1194,7 @@ send_receive (GtkWindow *parent,
 		case SEND_RECEIVE:
 			mail_fetch_mail (
 				CAMEL_STORE (info->service),
-				info->keep_on_server, 0, -1,
+				CAMEL_FETCH_OLD_MESSAGES, -1,
 				E_FILTER_SOURCE_INCOMING,
 				NULL, NULL, NULL,
 				info->cancellable,
@@ -1210,201 +1239,6 @@ mail_receive (GtkWindow *parent,
 	return send_receive (parent, session, FALSE);
 }
 
-struct _auto_data {
-	EAccount *account;
-	EMailSession *session;
-	gint period;		/* in seconds */
-	gint timeout_id;
-};
-
-static GHashTable *auto_active;
-
-static gboolean
-auto_timeout (gpointer data)
-{
-	CamelService *service;
-	CamelSession *session;
-	struct _auto_data *info = data;
-
-	session = CAMEL_SESSION (info->session);
-
-	service = camel_session_get_service (
-		session, info->account->uid);
-	g_return_val_if_fail (CAMEL_IS_SERVICE (service), TRUE);
-
-	if (camel_session_get_online (session))
-		mail_receive_service (service);
-
-	return TRUE;
-}
-
-static void
-auto_account_removed (EAccountList *eal,
-                      EAccount *ea,
-                      gpointer dummy)
-{
-	struct _auto_data *info = g_object_get_data((GObject *)ea, "mail-autoreceive");
-
-	g_return_if_fail (info != NULL);
-
-	if (info->timeout_id) {
-		g_source_remove (info->timeout_id);
-		info->timeout_id = 0;
-	}
-}
-
-static void
-auto_account_finalized (struct _auto_data *info)
-{
-	if (info->session != NULL)
-		g_object_unref (info->session);
-	if (info->timeout_id)
-		g_source_remove (info->timeout_id);
-	g_free (info);
-}
-
-static void
-auto_account_commit (struct _auto_data *info)
-{
-	gint period, check;
-
-	check = info->account->enabled
-		&& e_account_get_bool (info->account, E_ACCOUNT_SOURCE_AUTO_CHECK)
-		&& e_account_get_string (info->account, E_ACCOUNT_SOURCE_URL);
-	period = e_account_get_int (info->account, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME) * 60;
-	period = MAX (60, period);
-
-	if (info->timeout_id
-	    && (!check
-		|| period != info->period)) {
-		g_source_remove (info->timeout_id);
-		info->timeout_id = 0;
-	}
-	info->period = period;
-	if (check && info->timeout_id == 0)
-		info->timeout_id = g_timeout_add_seconds (info->period, auto_timeout, info);
-}
-
-static void
-auto_account_added (EAccountList *eal,
-                    EAccount *ea,
-                    EMailSession *session)
-{
-	struct _auto_data *info;
-
-	info = g_malloc0 (sizeof (*info));
-	info->account = ea;
-	info->session = g_object_ref (session);
-	g_object_set_data_full (
-		G_OBJECT (ea), "mail-autoreceive", info,
-		(GDestroyNotify) auto_account_finalized);
-	auto_account_commit (info);
-}
-
-static void
-auto_account_changed (EAccountList *eal,
-                      EAccount *ea,
-                      gpointer dummy)
-{
-	struct _auto_data *info;
-
-	info = g_object_get_data (G_OBJECT (ea), "mail-autoreceive");
-
-	if (info != NULL)
-		auto_account_commit (info);
-}
-
-static void
-auto_online (EShell *shell)
-{
-	EIterator *iter;
-	EAccountList *accounts;
-	EShellSettings *shell_settings;
-	struct _auto_data *info;
-	gboolean can_update_all;
-
-	if (!e_shell_get_online (shell))
-		return;
-
-	shell_settings = e_shell_get_shell_settings (shell);
-
-	can_update_all =
-		e_shell_settings_get_boolean (
-			shell_settings, "mail-check-on-start") &&
-		e_shell_settings_get_boolean (
-			shell_settings, "mail-check-all-on-start");
-
-	accounts = e_get_account_list ();
-	for (iter = e_list_get_iterator ((EList *) accounts);
-	     e_iterator_is_valid (iter);
-	     e_iterator_next (iter)) {
-		EAccount *account = (EAccount *) e_iterator_get (iter);
-
-		if (!account || !account->enabled)
-			continue;
-
-		info = g_object_get_data (
-			G_OBJECT (account), "mail-autoreceive");
-		if (info && (info->timeout_id || can_update_all))
-			auto_timeout (info);
-	}
-
-	if (iter)
-		g_object_unref (iter);
-}
-
-/* call to setup initial, and after changes are made to the config */
-/* FIXME: Need a cleanup funciton for when object is deactivated */
-void
-mail_autoreceive_init (EMailSession *session)
-{
-	EShell *shell;
-	EShellSettings *shell_settings;
-	EAccountList *accounts;
-	EIterator *iter;
-
-	g_return_if_fail (E_IS_MAIL_SESSION (session));
-
-	if (auto_active)
-		return;
-
-	accounts = e_get_account_list ();
-	auto_active = g_hash_table_new (g_str_hash, g_str_equal);
-
-	g_signal_connect (
-		accounts, "account-added",
-		G_CALLBACK (auto_account_added), session);
-	g_signal_connect (
-		accounts, "account-removed",
-		G_CALLBACK (auto_account_removed), NULL);
-	g_signal_connect (
-		accounts, "account-changed",
-		G_CALLBACK (auto_account_changed), NULL);
-
-	for (iter = e_list_get_iterator ((EList *) accounts);
-	     e_iterator_is_valid (iter);
-	     e_iterator_next (iter))
-		auto_account_added (
-			accounts, (EAccount *)
-			e_iterator_get (iter), session);
-
-	shell = e_shell_get_default ();
-	shell_settings = e_shell_get_shell_settings (shell);
-
-	if (e_shell_settings_get_boolean (
-		shell_settings, "mail-check-on-start")) {
-		auto_online (shell);
-
-		/* also flush outbox on start */
-		if (e_shell_get_online (shell))
-			mail_send (session);
-	}
-
-	g_signal_connect (
-		shell, "notify::online",
-		G_CALLBACK (auto_online), NULL);
-}
-
 /* We setup the download info's in a hashtable, if we later
  * need to build the gui, we insert them in to add them. */
 void
@@ -1458,7 +1292,7 @@ mail_receive_service (CamelService *service)
 	case SEND_RECEIVE:
 		mail_fetch_mail (
 			CAMEL_STORE (service),
-			info->keep_on_server, 0, -1,
+			CAMEL_FETCH_OLD_MESSAGES, -1,
 			E_FILTER_SOURCE_INCOMING,
 			NULL, NULL, NULL,
 			info->cancellable,
@@ -1495,16 +1329,14 @@ mail_send (EMailSession *session)
 {
 	CamelFolder *local_outbox;
 	CamelService *service;
-	EAccount *account;
 	struct _send_info *info;
 	struct _send_data *data;
 	send_info_t type = SEND_INVALID;
-	gchar *transport_uid;
 
 	g_return_if_fail (E_IS_MAIL_SESSION (session));
 
-	account = e_get_default_transport ();
-	if (account == NULL || account->transport->url == NULL)
+	service = get_default_transport (session);
+	if (service == NULL)
 		return;
 
 	data = setup_send_data (session);
@@ -1515,24 +1347,12 @@ mail_send (EMailSession *session)
 		return;
 	}
 
-	transport_uid = g_strconcat (account->uid, "-transport", NULL);
-
-	service = camel_session_get_service (
-		CAMEL_SESSION (session), transport_uid);
-
-	if (!CAMEL_IS_TRANSPORT (service)) {
-		g_free (transport_uid);
-		return;
-	}
-
 	d(printf("starting non-interactive send of '%s'\n", transport->url));
 
 	type = get_receive_type (service);
 
-	if (type == SEND_INVALID) {
-		g_free (transport_uid);
+	if (type == SEND_INVALID)
 		return;
-	}
 
 	info = g_malloc0 (sizeof (*info));
 	info->type = SEND_SEND;
@@ -1556,10 +1376,6 @@ mail_send (EMailSession *session)
 		e_mail_session_get_local_folder (
 		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 
-	g_free (transport_uid);
-
-	g_return_if_fail (CAMEL_IS_TRANSPORT (service));
-
 	mail_send_queue (
 		session, local_outbox,
 		CAMEL_TRANSPORT (service),
diff --git a/mail/mail.error.xml b/mail/mail.error.xml
index c996362..65cf052 100644
--- a/mail/mail.error.xml
+++ b/mail/mail.error.xml
@@ -300,24 +300,6 @@ all proxy information will be deleted permanently.</_secondary>
     <button _label="_Disable" response="GTK_RESPONSE_YES"/>
   </error>
 
-  <error id="no-save-signature" type="error">
-    <_primary>Could not save signature file.</_primary>
-    <secondary xml:space="preserve">{0}.</secondary>
-  </error>
-
-  <error id="signature-notscript" type="error">
-    <_primary>Cannot set signature script "{0}".</_primary>
-    <_secondary xml:space="preserve">The script file must exist and be executable.</_secondary>
-  </error>
-
-  <error id="ask-signature-changed" type="question" default="GTK_RESPONSE_YES">
-    <_primary>Do you wish to save your changes?</_primary>
-    <_secondary xml:space="preserve">This signature has been changed, but has not been saved.</_secondary>
-    <button _label="_Discard changes" response="GTK_RESPONSE_NO"/>
-    <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
-    <button stock="gtk-save" response="GTK_RESPONSE_YES"/>
-  </error>
-
   <error id="vfolder-notexist" type="error">
     <_primary>Cannot edit Search Folder "{0}" as it does not exist.</_primary>
     <_secondary xml:space="preserve">This folder may have been added implicitly,
@@ -444,16 +426,6 @@ An mbox account will be created to preserve the old mbox folders. You can delete
     <button _label="N_ever" response="GTK_RESPONSE_CANCEL"/>
   </error>
 
-  <error id="signature-already-exists" type="error" modal="true">
-    <_primary>Signature Already Exists</_primary>
-    <_secondary>A signature already exists with the name "{0}". Please specify a different name. </_secondary>
-  </error>
-  
-  <error id="blank-signature" type="error" modal="true">
-    <_primary>Blank Signature</_primary>
-    <_secondary>Please provide an unique name to identify this signature.</_secondary>
-  </error>
-  
   <error id="send-no-account-enabled" type="warning">
     <_primary>This message cannot be sent because the account you chose to send with is not enabled</_primary>
     <_secondary xml:space="preserve">Please enable the account or send using another account.</_secondary>
diff --git a/mail/test-mail-autoconfig.c b/mail/test-mail-autoconfig.c
new file mode 100644
index 0000000..10977a1
--- /dev/null
+++ b/mail/test-mail-autoconfig.c
@@ -0,0 +1,53 @@
+/*
+ * test-mail-autoconfig.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <stdlib.h>
+
+#include "e-mail-autoconfig.h"
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+	EMailAutoconfig *autoconfig;
+	GError *error = NULL;
+
+	g_type_init ();
+
+	if (argc < 2) {
+		g_printerr ("USAGE: %s EMAIL-ADDRESS\n", argv[0]);
+		exit (EXIT_FAILURE);
+	}
+
+	autoconfig = e_mail_autoconfig_new_sync (argv[1], NULL, &error);
+
+	if (error != NULL) {
+		g_warn_if_fail (autoconfig == NULL);
+		g_printerr ("%s\n", error->message);
+		g_error_free (error);
+		exit (EXIT_FAILURE);
+	}
+
+	g_assert (E_IS_MAIL_AUTOCONFIG (autoconfig));
+
+	g_print ("%s\n", e_mail_autoconfig_get_markup_content (autoconfig));
+
+	g_object_unref (autoconfig);
+
+	return EXIT_SUCCESS;
+}



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