[evolution] Reorder accounts by drag-and-drop.



commit 7c0c40f83317228e0a725bfb5ca8854339d25588
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri Dec 9 10:34:55 2011 -0500

    Reorder accounts by drag-and-drop.
    
    This implements https://bugzilla.gnome.org/show_bug.cgi?id=663527#c3.
    
    Account reordering is now done by drag-and-drop instead of up/down
    buttons.
    
    Turned out to be a wee bit more complicated than I initially thought.
    
    This scraps EAccountManager and EAccountTreeView and replaces them with
    new classes centered around EMailAccountStore, which EMailSession owns.
    
    EMailAccountStore is the model behind the account list in Preferences.
    The folder tree model now uses it to sort its own top-level rows using
    gtk_tree_path_compare().  It also broadcasts account operations through
    signals so we don't have to rely so heavily on EAccountList signals,
    since EAccountList is going away soon.
    
    Also as part of this work, the e-mail-local.h and e-mail-store.h APIs
    have been merged into EMailSession and MailFolderCache.

 capplet/settings/mail-capplet-shell.c             |    5 -
 e-util/e-marshal.list                             |    1 +
 mail/Makefile.am                                  |   10 +-
 mail/e-mail-account-manager.c                     |  565 ++++++++
 mail/e-mail-account-manager.h                     |   78 ++
 mail/e-mail-account-store.c                       | 1439 +++++++++++++++++++++
 mail/e-mail-account-store.h                       |  144 ++
 mail/e-mail-account-tree-view.c                   |  283 ++++
 mail/e-mail-account-tree-view.h                   |   75 ++
 mail/e-mail-backend.c                             |  187 ++--
 mail/e-mail-backend.h                             |    7 -
 mail/e-mail-local.c                               |  154 ---
 mail/e-mail-local.h                               |   39 -
 mail/e-mail-migrate.c                             |   33 +-
 mail/e-mail-reader-utils.c                        |   12 +-
 mail/e-mail-session-utils.c                       |    5 +-
 mail/e-mail-session.c                             |  563 ++++++++-
 mail/e-mail-session.h                             |   20 +
 mail/e-mail-sidebar.c                             |   11 +-
 mail/e-mail-store.c                               |  500 -------
 mail/e-mail-store.h                               |   47 -
 mail/e-mail.h                                     |    2 -
 mail/em-account-editor.c                          |  131 ++-
 mail/em-composer-utils.c                          |   99 +-
 mail/em-composer-utils.h                          |    3 +-
 mail/em-folder-properties.c                       |   23 +-
 mail/em-folder-selection-button.c                 |    5 +-
 mail/em-folder-tree-model.c                       |  444 ++-----
 mail/em-folder-tree-model.h                       |    8 +-
 mail/em-folder-tree.c                             |   54 +-
 mail/em-folder-utils.c                            |   23 +-
 mail/em-utils.c                                   |  206 +---
 mail/em-utils.h                                   |    4 -
 mail/em-vfolder-rule.c                            |    1 -
 mail/importers/evolution-mbox-importer.c          |   10 +-
 mail/importers/mail-importer.c                    |    4 +-
 mail/mail-config.c                                |    1 -
 mail/mail-folder-cache.c                          |  426 +++++--
 mail/mail-folder-cache.h                          |   23 +-
 mail/mail-ops.c                                   |   49 +-
 mail/mail-send-recv.c                             |   47 +-
 mail/mail-vfolder.c                               |   40 +-
 modules/mail/e-mail-shell-backend.c               |   57 +-
 modules/mail/e-mail-shell-view-actions.c          |   71 +-
 modules/mail/e-mail-shell-view-private.c          |   10 +-
 modules/mail/e-mail-shell-view-private.h          |    2 -
 modules/mail/e-mail-shell-view.c                  |    4 +-
 modules/mail/em-account-prefs.c                   |  284 +----
 modules/mail/em-account-prefs.h                   |    6 +-
 modules/mdn/evolution-mdn.c                       |    7 +-
 modules/startup-wizard/evolution-startup-wizard.c |    7 -
 plugins/dbx-import/dbx-importer.c                 |   18 +-
 plugins/pst-import/pst-importer.c                 |   10 +-
 plugins/templates/templates.c                     |   98 +-
 po/POTFILES.in                                    |    8 +-
 widgets/misc/Makefile.am                          |    4 -
 widgets/misc/e-account-manager.c                  |  536 --------
 widgets/misc/e-account-manager.h                  |   83 --
 widgets/misc/e-account-tree-view.c                | 1401 --------------------
 widgets/misc/e-account-tree-view.h                |  132 --
 60 files changed, 4264 insertions(+), 4255 deletions(-)
---
diff --git a/capplet/settings/mail-capplet-shell.c b/capplet/settings/mail-capplet-shell.c
index 2bf464c..707efe3 100644
--- a/capplet/settings/mail-capplet-shell.c
+++ b/capplet/settings/mail-capplet-shell.c
@@ -40,7 +40,6 @@
 #include <mail/em-composer-utils.h>
 #include <mail/mail-config.h>
 #include <mail/mail-mt.h>
-#include <mail/e-mail-store.h>
 
 #include <shell/e-shell.h>
 
@@ -208,7 +207,6 @@ mail_capplet_shell_construct (MailCappletShell *shell,
 	GtkStyle *style = gtk_widget_get_default_style ();
 	EShell *eshell;
 	EMailSession *session;
-	gchar *custom_dir;
 
 	gtk_window_set_icon_name ((GtkWindow *)shell, "evolution");
 	gtk_window_set_title ((GtkWindow *)shell, _("Evolution account assistant"));
@@ -277,9 +275,6 @@ mail_capplet_shell_construct (MailCappletShell *shell,
 
 	mail_config_init (session);
 	mail_msg_init ();
-	custom_dir = g_build_filename (e_get_user_data_dir (), "mail", NULL);
-	e_mail_store_init (session, custom_dir);
-	g_free (custom_dir);
 
 	if (just_druid) {
 		MailViewChild *mc;
diff --git a/e-util/e-marshal.list b/e-util/e-marshal.list
index 884886c..6d3c1fc 100644
--- a/e-util/e-marshal.list
+++ b/e-util/e-marshal.list
@@ -7,6 +7,7 @@ BOOLEAN:INT,POINTER,INT,BOXED
 BOOLEAN:INT,POINTER,INT,OBJECT,INT,INT,UINT
 BOOLEAN:NONE
 BOOLEAN:OBJECT
+BOOLEAN:OBJECT,OBJECT
 BOOLEAN:OBJECT,DOUBLE,DOUBLE,BOOLEAN
 BOOLEAN:POINTER
 BOOLEAN:POINTER,BOOLEAN,POINTER
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 0859c55..8310cff 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -46,6 +46,9 @@ libevolution_mail_la_CPPFLAGS =				\
 
 mailinclude_HEADERS =					\
 	e-mail.h					\
+	e-mail-account-manager.h			\
+	e-mail-account-store.h				\
+	e-mail-account-tree-view.h			\
 	e-mail-attachment-bar.h				\
 	e-mail-backend.h				\
 	e-mail-browser.h				\
@@ -61,7 +64,6 @@ mailinclude_HEADERS =					\
 	e-mail-label-list-store.h			\
 	e-mail-label-manager.h				\
 	e-mail-label-tree-view.h			\
-	e-mail-local.h					\
 	e-mail-message-pane.h				\
 	e-mail-migrate.h				\
 	e-mail-notebook-view.h				\
@@ -72,7 +74,6 @@ mailinclude_HEADERS =					\
 	e-mail-session.h				\
 	e-mail-sidebar.h				\
 	e-mail-store-utils.h				\
-	e-mail-store.h					\
 	e-mail-tag-editor.h				\
 	e-mail-view.h					\
 	em-account-editor.h				\
@@ -121,6 +122,9 @@ mailinclude_HEADERS +=					\
 endif
 
 libevolution_mail_la_SOURCES =				\
+	e-mail-account-manager.c			\
+	e-mail-account-store.c				\
+	e-mail-account-tree-view.c			\
 	e-mail-attachment-bar.c				\
 	e-mail-backend.c				\
 	e-mail-browser.c				\
@@ -135,7 +139,6 @@ libevolution_mail_la_SOURCES =				\
 	e-mail-label-list-store.c			\
 	e-mail-label-manager.c				\
 	e-mail-label-tree-view.c			\
-	e-mail-local.c					\
 	e-mail-message-pane.c				\
 	e-mail-migrate.c				\
 	e-mail-notebook-view.c				\
@@ -146,7 +149,6 @@ libevolution_mail_la_SOURCES =				\
 	e-mail-session.c				\
 	e-mail-sidebar.c				\
 	e-mail-store-utils.c				\
-	e-mail-store.c					\
 	e-mail-tag-editor.c				\
 	e-mail-view.c					\
 	em-account-editor.c				\
diff --git a/mail/e-mail-account-manager.c b/mail/e-mail-account-manager.c
new file mode 100644
index 0000000..97a4fe3
--- /dev/null
+++ b/mail/e-mail-account-manager.c
@@ -0,0 +1,565 @@
+/*
+ * e-mail-account-manager.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-account-manager.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <mail/e-mail-account-tree-view.h>
+
+#define E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerPrivate))
+
+#define DEFAULT_ORDER_RESPONSE GTK_RESPONSE_APPLY
+
+struct _EMailAccountManagerPrivate {
+	EMailAccountStore *store;
+	gulong row_changed_handler_id;
+
+	GtkWidget *tree_view;		/* not referenced */
+	GtkWidget *add_button;		/* not referenced */
+	GtkWidget *edit_button;		/* not referenced */
+	GtkWidget *delete_button;	/* not referenced */
+	GtkWidget *default_button;	/* not referenced */
+};
+
+enum {
+	PROP_0,
+	PROP_STORE
+};
+
+enum {
+	ADD_ACCOUNT,
+	EDIT_ACCOUNT,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+	EMailAccountManager,
+	e_mail_account_manager,
+	GTK_TYPE_TABLE)
+
+static void
+mail_account_manager_add_cb (EMailAccountManager *manager)
+{
+	e_mail_account_manager_add_account (manager);
+}
+
+static void
+mail_account_manager_edit_cb (EMailAccountManager *manager)
+{
+	EMailAccountTreeView *tree_view;
+	EAccount *account;
+	CamelService *service;
+	const gchar *uid;
+
+	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);
+
+	e_mail_account_manager_edit_account (manager, account);
+}
+
+static void
+mail_account_manager_remove_cb (EMailAccountManager *manager)
+{
+	EMailAccountTreeView *tree_view;
+	EMailAccountStore *store;
+	CamelService *service;
+	gpointer parent;
+
+	tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
+	service = e_mail_account_tree_view_get_selected_service (tree_view);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+	store = e_mail_account_manager_get_store (manager);
+	e_mail_account_store_remove_service (store, parent, service);
+}
+
+static void
+mail_account_manager_enable_cb (EMailAccountManager *manager)
+{
+	EMailAccountTreeView *tree_view;
+	EMailAccountStore *store;
+	CamelService *service;
+	gpointer parent;
+
+	tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
+	service = e_mail_account_tree_view_get_selected_service (tree_view);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+	store = e_mail_account_manager_get_store (manager);
+	e_mail_account_store_enable_service (store, parent, service);
+}
+
+static void
+mail_account_manager_disable_cb (EMailAccountManager *manager)
+{
+	EMailAccountTreeView *tree_view;
+	EMailAccountStore *store;
+	CamelService *service;
+	gpointer parent;
+
+	tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
+	service = e_mail_account_tree_view_get_selected_service (tree_view);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
+	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+	store = e_mail_account_manager_get_store (manager);
+	e_mail_account_store_disable_service (store, parent, service);
+}
+
+static void
+mail_account_manager_default_cb (EMailAccountManager *manager)
+{
+	EMailAccountTreeView *tree_view;
+	EMailAccountStore *store;
+	CamelService *service;
+
+	tree_view = E_MAIL_ACCOUNT_TREE_VIEW (manager->priv->tree_view);
+	service = e_mail_account_tree_view_get_selected_service (tree_view);
+
+	store = e_mail_account_manager_get_store (manager);
+	e_mail_account_store_set_default_service (store, service);
+}
+
+static void
+mail_account_manager_info_bar_response_cb (EMailAccountManager *manager,
+                                           gint response)
+{
+	EMailAccountStore *store;
+
+	store = e_mail_account_manager_get_store (manager);
+
+	if (response == DEFAULT_ORDER_RESPONSE)
+		e_mail_account_store_reorder_services (store, NULL);
+}
+
+static gboolean
+mail_account_manager_key_press_event_cb (EMailAccountManager *manager,
+                                         GdkEventKey *event)
+{
+	if (event->keyval == GDK_KEY_Delete) {
+		mail_account_manager_remove_cb (manager);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+mail_account_manager_row_changed_cb (GtkTreeModel *tree_model,
+                                     GtkTreePath *path,
+                                     GtkTreeIter *iter,
+                                     EMailAccountManager *manager)
+{
+	GtkTreeView *tree_view;
+	GtkTreeSelection *selection;
+
+	tree_view = GTK_TREE_VIEW (manager->priv->tree_view);
+	selection = gtk_tree_view_get_selection (tree_view);
+
+	/* Update buttons for the selected row (which is not
+	 * necessarily the row that changed, but do it anyway). */
+	g_signal_emit_by_name (selection, "changed");
+}
+
+static void
+mail_account_manager_selection_changed_cb (EMailAccountManager *manager,
+                                           GtkTreeSelection *selection)
+{
+	GtkTreeModel *tree_model;
+	GtkTreeIter iter;
+	EMailAccountStore *store;
+	CamelService *default_service;
+	CamelService *service;
+	GtkWidget *add_button;
+	GtkWidget *edit_button;
+	GtkWidget *delete_button;
+	GtkWidget *default_button;
+	gboolean builtin;
+	gboolean sensitive;
+	gboolean not_default;
+
+	add_button = manager->priv->add_button;
+	edit_button = manager->priv->edit_button;
+	delete_button = manager->priv->delete_button;
+	default_button = manager->priv->default_button;
+
+	if (gtk_tree_selection_get_selected (selection, &tree_model, &iter)) {
+		gtk_tree_model_get (
+			tree_model, &iter,
+			E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service,
+			E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, &builtin,
+			-1);
+	} else {
+		service = NULL;
+		builtin = FALSE;
+	}
+
+	store = e_mail_account_manager_get_store (manager);
+	default_service = e_mail_account_store_get_default_service (store);
+	not_default = (service != default_service);
+
+	if (service == NULL)
+		gtk_widget_grab_focus (add_button);
+
+	sensitive = (service != NULL && !builtin);
+	gtk_widget_set_sensitive (edit_button, sensitive);
+
+	sensitive = (service != NULL && !builtin);
+	gtk_widget_set_sensitive (delete_button, sensitive);
+
+	sensitive = (service != NULL && !builtin && not_default);
+	gtk_widget_set_sensitive (default_button, sensitive);
+}
+
+static void
+mail_account_manager_set_store (EMailAccountManager *manager,
+                                EMailAccountStore *store)
+{
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+	g_return_if_fail (manager->priv->store == NULL);
+
+	manager->priv->store = g_object_ref (store);
+}
+
+static void
+mail_account_manager_set_property (GObject *object,
+                                   guint property_id,
+                                   const GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_STORE:
+			mail_account_manager_set_store (
+				E_MAIL_ACCOUNT_MANAGER (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_manager_get_property (GObject *object,
+                                   guint property_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_STORE:
+			g_value_set_object (
+				value,
+				e_mail_account_manager_get_store (
+				E_MAIL_ACCOUNT_MANAGER (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_manager_dispose (GObject *object)
+{
+	EMailAccountManagerPrivate *priv;
+
+	priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (object);
+
+	if (priv->store != NULL) {
+		g_signal_handler_disconnect (
+			priv->store, priv->row_changed_handler_id);
+		g_object_unref (priv->store);
+		priv->store = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_account_manager_parent_class)->dispose (object);
+}
+
+static void
+mail_account_manager_constructed (GObject *object)
+{
+	EMailAccountManager *manager;
+	EMailAccountStore *store;
+	GtkTreeSelection *selection;
+	GtkWidget *container;
+	GtkWidget *widget;
+	gulong handler_id;
+
+	manager = E_MAIL_ACCOUNT_MANAGER (object);
+	store = e_mail_account_manager_get_store (manager);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_account_manager_parent_class)->
+		constructed (object);
+
+	g_object_bind_property (
+		store, "busy",
+		manager, "sensitive",
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_INVERT_BOOLEAN);
+
+	handler_id = g_signal_connect (
+		store, "row-changed",
+		G_CALLBACK (mail_account_manager_row_changed_cb),
+		manager);
+
+	/* We disconnect the handler in dispose(). */
+	manager->priv->row_changed_handler_id = handler_id;
+
+	gtk_table_resize (GTK_TABLE (manager), 2, 2);
+	gtk_table_set_col_spacings (GTK_TABLE (manager), 6);
+	gtk_table_set_row_spacings (GTK_TABLE (manager), 0);
+
+	container = GTK_WIDGET (manager);
+
+	widget = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (
+		GTK_SCROLLED_WINDOW (widget),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (
+		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+	gtk_table_attach (
+		GTK_TABLE (container), widget, 0, 1, 0, 1,
+		GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = e_mail_account_tree_view_new (store);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	manager->priv->tree_view = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "enable",
+		G_CALLBACK (mail_account_manager_enable_cb), manager);
+
+	g_signal_connect_swapped (
+		widget, "disable",
+		G_CALLBACK (mail_account_manager_disable_cb), manager);
+
+	g_signal_connect_swapped (
+		widget, "key-press-event",
+		G_CALLBACK (mail_account_manager_key_press_event_cb),
+		manager);
+
+	g_signal_connect_swapped (
+		widget, "row-activated",
+		G_CALLBACK (mail_account_manager_edit_cb), manager);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+	g_signal_connect_swapped (
+		selection, "changed",
+		G_CALLBACK (mail_account_manager_selection_changed_cb),
+		manager);
+
+	container = GTK_WIDGET (manager);
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (
+		GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_info_bar_new ();
+	gtk_info_bar_set_message_type (
+		GTK_INFO_BAR (widget), GTK_MESSAGE_INFO);
+	gtk_info_bar_add_button (
+		GTK_INFO_BAR (widget),
+		_("_Restore Default"),
+		DEFAULT_ORDER_RESPONSE);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "response",
+		G_CALLBACK (mail_account_manager_info_bar_response_cb),
+		manager);
+
+	container = gtk_info_bar_get_content_area (GTK_INFO_BAR (widget));
+
+	widget = gtk_label_new (
+		_("You can drag and drop account names to reorder them."));
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = GTK_WIDGET (manager);
+
+	widget = gtk_vbutton_box_new ();
+	gtk_button_box_set_layout (
+		GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
+	gtk_box_set_spacing (GTK_BOX (widget), 6);
+	gtk_table_attach (
+		GTK_TABLE (container), widget,
+		1, 2, 0, 2, 0, GTK_FILL, 0, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_ADD);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->add_button = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_account_manager_add_cb), manager);
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_EDIT);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->edit_button = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_account_manager_edit_cb), manager);
+
+	widget = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->delete_button = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_account_manager_remove_cb), manager);
+
+	widget = gtk_button_new_with_mnemonic (_("De_fault"));
+	gtk_button_set_image (
+		GTK_BUTTON (widget),
+		gtk_image_new_from_icon_name (
+		"emblem-default", GTK_ICON_SIZE_BUTTON));
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	manager->priv->default_button = widget;  /* not referenced */
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_account_manager_default_cb), manager);
+
+	/* Initialize button states. */
+	g_signal_emit_by_name (selection, "changed");
+}
+
+static void
+e_mail_account_manager_class_init (EMailAccountManagerClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailAccountManagerPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_account_manager_set_property;
+	object_class->get_property = mail_account_manager_get_property;
+	object_class->dispose = mail_account_manager_dispose;
+	object_class->constructed = mail_account_manager_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_STORE,
+		g_param_spec_object (
+			"store",
+			"Store",
+			NULL,
+			E_TYPE_MAIL_ACCOUNT_STORE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	signals[ADD_ACCOUNT] = g_signal_new (
+		"add-account",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountManagerClass, add_account),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[EDIT_ACCOUNT] = g_signal_new (
+		"edit-account",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountManagerClass, edit_account),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		E_TYPE_ACCOUNT);
+}
+
+static void
+e_mail_account_manager_init (EMailAccountManager *manager)
+{
+	manager->priv = E_MAIL_ACCOUNT_MANAGER_GET_PRIVATE (manager);
+}
+
+GtkWidget *
+e_mail_account_manager_new (EMailAccountStore *store)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_ACCOUNT_MANAGER,
+		"store", store, NULL);
+}
+
+EMailAccountStore *
+e_mail_account_manager_get_store (EMailAccountManager *manager)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager), NULL);
+
+	return manager->priv->store;
+}
+
+void
+e_mail_account_manager_add_account (EMailAccountManager *manager)
+{
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager));
+
+	g_signal_emit (manager, signals[ADD_ACCOUNT], 0);
+}
+
+void
+e_mail_account_manager_edit_account (EMailAccountManager *manager,
+                                     EAccount *account)
+{
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_MANAGER (manager));
+	g_return_if_fail (E_IS_ACCOUNT (account));
+
+	g_signal_emit (manager, signals[EDIT_ACCOUNT], 0, account);
+}
+
diff --git a/mail/e-mail-account-manager.h b/mail/e-mail-account-manager.h
new file mode 100644
index 0000000..23f7890
--- /dev/null
+++ b/mail/e-mail-account-manager.h
@@ -0,0 +1,78 @@
+/*
+ * e-mail-account-manager.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_ACCOUNT_MANAGER_H
+#define E_MAIL_ACCOUNT_MANAGER_H
+
+#include <gtk/gtk.h>
+#include <e-util/e-account-utils.h>
+#include <mail/e-mail-account-store.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_ACCOUNT_MANAGER \
+	(e_mail_account_manager_get_type ())
+#define E_MAIL_ACCOUNT_MANAGER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManager))
+#define E_MAIL_ACCOUNT_MANAGER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass))
+#define E_IS_MAIL_ACCOUNT_MANAGER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_ACCOUNT_MANAGER))
+#define E_IS_MAIL_ACCOUNT_MANAGER_CLASS(cls) \
+	(G_TYPE_CHECK_INSTANCE_CLASS \
+	((cls), E_TYPE_MAIL_ACCOUNT_MANAGER))
+#define E_MAIL_ACCOUNT_MANAGER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_ACCOUNT_MANAGER, EMailAccountManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAccountManager EMailAccountManager;
+typedef struct _EMailAccountManagerClass EMailAccountManagerClass;
+typedef struct _EMailAccountManagerPrivate EMailAccountManagerPrivate;
+
+struct _EMailAccountManager {
+	GtkTable parent;
+	EMailAccountManagerPrivate *priv;
+};
+
+struct _EMailAccountManagerClass {
+	GtkTableClass parent_class;
+
+	/* Signals */
+	void		(*add_account)		(EMailAccountManager *manager);
+	void		(*edit_account)		(EMailAccountManager *manager,
+						 EAccount *account);
+};
+
+GType		e_mail_account_manager_get_type	(void) G_GNUC_CONST;
+GtkWidget *	e_mail_account_manager_new	(EMailAccountStore *store);
+EMailAccountStore *
+		e_mail_account_manager_get_store
+						(EMailAccountManager *manager);
+void		e_mail_account_manager_add_account
+						(EMailAccountManager *manager);
+void		e_mail_account_manager_edit_account
+						(EMailAccountManager *manager,
+						 EAccount *account);
+
+G_END_DECLS
+
+#endif /* E_MAIL_ACCOUNT_MANAGER_H */
diff --git a/mail/e-mail-account-store.c b/mail/e-mail-account-store.c
new file mode 100644
index 0000000..ccfbe3b
--- /dev/null
+++ b/mail/e-mail-account-store.c
@@ -0,0 +1,1439 @@
+/*
+ * e-mail-account-store.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-account-store.h"
+
+#include <config.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/e-extensible.h>
+
+#include <e-util/e-marshal.h>
+#include <e-util/e-account-utils.h>
+#include <e-util/e-alert-dialog.h>
+#include <mail/mail-ops.h>
+#include <mail/mail-vfolder.h>
+
+#define E_MAIL_ACCOUNT_STORE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStorePrivate))
+
+typedef struct _IndexItem IndexItem;
+
+struct _EMailAccountStorePrivate {
+	CamelService *default_service;
+	GHashTable *service_index;
+	gchar *sort_order_filename;
+	gboolean express_mode;
+	gpointer session;  /* weak pointer */
+	guint busy_count;
+};
+
+struct _IndexItem {
+	CamelService *service;
+	GtkTreeRowReference *reference;
+	gulong notify_handler_id;
+};
+
+enum {
+	PROP_0,
+	PROP_BUSY,
+	PROP_DEFAULT_SERVICE,
+	PROP_EXPRESS_MODE,
+	PROP_SESSION
+};
+
+enum {
+	SERVICE_ADDED,
+	SERVICE_REMOVED,
+	SERVICE_ENABLED,
+	SERVICE_DISABLED,
+	SERVICES_REORDERED,
+	REMOVE_REQUESTED,
+	ENABLE_REQUESTED,
+	DISABLE_REQUESTED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* Forward Declarations */
+static void	e_mail_account_store_interface_init
+						(GtkTreeModelIface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EMailAccountStore,
+	e_mail_account_store,
+	GTK_TYPE_LIST_STORE,
+	G_IMPLEMENT_INTERFACE (
+		GTK_TYPE_TREE_MODEL,
+		e_mail_account_store_interface_init)
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_EXTENSIBLE, NULL))
+
+static void
+index_item_free (IndexItem *item)
+{
+	g_signal_handler_disconnect (
+		item->service, item->notify_handler_id);
+
+	g_object_unref (item->service);
+	gtk_tree_row_reference_free (item->reference);
+
+	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,
+                             GtkTreeIter *iter)
+{
+	IndexItem *item;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	gboolean iter_set;
+
+	g_return_val_if_fail (service != NULL, FALSE);
+
+	item = g_hash_table_lookup (store->priv->service_index, service);
+
+	if (item == NULL)
+		return FALSE;
+
+	if (!gtk_tree_row_reference_valid (item->reference))
+		return FALSE;
+
+	model = gtk_tree_row_reference_get_model (item->reference);
+	path = gtk_tree_row_reference_get_path (item->reference);
+	iter_set = gtk_tree_model_get_iter (model, iter, path);
+	gtk_tree_path_free (path);
+
+	return iter_set;
+}
+
+static gint
+mail_account_store_default_compare (CamelService *service_a,
+                                    CamelService *service_b,
+                                    EMailAccountStore *store)
+{
+	const gchar *display_name_a;
+	const gchar *display_name_b;
+	const gchar *uid_a;
+	const gchar *uid_b;
+
+	uid_a = camel_service_get_uid (service_a);
+	uid_b = camel_service_get_uid (service_b);
+
+	/* Check for special cases first. */
+
+	if (e_mail_account_store_get_express_mode (store)) {
+		if (g_str_equal (uid_a, E_MAIL_SESSION_LOCAL_UID) &&
+		    g_str_equal (uid_b, E_MAIL_SESSION_VFOLDER_UID))
+			return -1;
+		else if (g_str_equal (uid_b, E_MAIL_SESSION_LOCAL_UID) &&
+			 g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID))
+			return 1;
+		else if (g_str_equal (uid_a, E_MAIL_SESSION_LOCAL_UID))
+			return 1;
+		else if (g_str_equal (uid_b, E_MAIL_SESSION_LOCAL_UID))
+			return -1;
+		else if (g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID))
+			return 1;
+		else if (g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID))
+			return -1;
+	} else {
+		if (g_str_equal (uid_a, E_MAIL_SESSION_LOCAL_UID))
+			return -1;
+		else if (g_str_equal (uid_b, E_MAIL_SESSION_LOCAL_UID))
+			return 1;
+		else if (g_str_equal (uid_a, E_MAIL_SESSION_VFOLDER_UID))
+			return 1;
+		else if (g_str_equal (uid_b, E_MAIL_SESSION_VFOLDER_UID))
+			return -1;
+	}
+
+	/* Otherwise sort them alphabetically. */
+
+	display_name_a = camel_service_get_display_name (service_a);
+	display_name_b = camel_service_get_display_name (service_b);
+
+	if (display_name_a == NULL)
+		display_name_a = "";
+
+	if (display_name_b == NULL)
+		display_name_b = "";
+
+	return g_utf8_collate (display_name_a, display_name_b);
+}
+
+static void
+mail_account_store_update_row (EMailAccountStore *store,
+                               CamelService *service,
+                               GtkTreeIter *iter)
+{
+	CamelProvider *provider;
+	gboolean is_default;
+	const gchar *backend_name;
+	const gchar *display_name;
+
+	is_default = (service == store->priv->default_service);
+	display_name = camel_service_get_display_name (service);
+
+	provider = camel_service_get_provider (service);
+	backend_name = (provider != NULL) ? provider->protocol : NULL;
+
+	gtk_list_store_set (
+		GTK_LIST_STORE (store), iter,
+		E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT, is_default,
+		E_MAIL_ACCOUNT_STORE_COLUMN_BACKEND_NAME, backend_name,
+		E_MAIL_ACCOUNT_STORE_COLUMN_DISPLAY_NAME, display_name,
+		-1);
+}
+
+static void
+mail_account_store_service_notify_cb (CamelService *service,
+                                      GParamSpec *pspec,
+                                      EMailAccountStore *store)
+{
+	GtkTreeIter iter;
+
+	if (mail_account_store_get_iter (store, service, &iter))
+		mail_account_store_update_row (store, service, &iter);
+}
+
+static void
+mail_account_store_clean_index (EMailAccountStore *store)
+{
+	GQueue trash = G_QUEUE_INIT;
+	GHashTable *hash_table;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	hash_table = store->priv->service_index;
+	g_hash_table_iter_init (&iter, hash_table);
+
+	/* Remove index items with invalid GtkTreeRowReferences. */
+
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		IndexItem *item = value;
+
+		if (!gtk_tree_row_reference_valid (item->reference))
+			g_queue_push_tail (&trash, key);
+	}
+
+	while ((key = g_queue_pop_head (&trash)) != NULL)
+		g_hash_table_remove (hash_table, key);
+}
+
+static void
+mail_account_store_update_index (EMailAccountStore *store,
+                                 GtkTreePath *path,
+                                 GtkTreeIter *iter)
+{
+	CamelService *service = NULL;
+	GHashTable *hash_table;
+	GtkTreeModel *model;
+	IndexItem *item;
+
+	model = GTK_TREE_MODEL (store);
+	hash_table = store->priv->service_index;
+
+	gtk_tree_model_get (
+		model, iter,
+		E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service, -1);
+
+	if (service == NULL)
+		return;
+
+	item = g_hash_table_lookup (hash_table, service);
+
+	if (item == NULL) {
+		item = g_slice_new0 (IndexItem);
+		item->service = g_object_ref (service);
+
+		item->notify_handler_id = g_signal_connect (
+			service, "notify", G_CALLBACK (
+			mail_account_store_service_notify_cb), store);
+
+		g_hash_table_insert (hash_table, item->service, item);
+	}
+
+	/* Update the row reference so the IndexItem will survive
+	 * drag-and-drop (new row is inserted, old row is deleted). */
+	gtk_tree_row_reference_free (item->reference);
+	item->reference = gtk_tree_row_reference_new (model, path);
+
+	g_object_unref (service);
+}
+
+static void
+mail_account_store_set_session (EMailAccountStore *store,
+                                EMailSession *session)
+{
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
+	g_return_if_fail (store->priv->session == NULL);
+
+	store->priv->session = session;
+
+	g_object_add_weak_pointer (
+		G_OBJECT (store->priv->session),
+		&store->priv->session);
+}
+
+static void
+mail_account_store_set_property (GObject *object,
+                                 guint property_id,
+                                 const GValue *value,
+                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_DEFAULT_SERVICE:
+			e_mail_account_store_set_default_service (
+				E_MAIL_ACCOUNT_STORE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_EXPRESS_MODE:
+			e_mail_account_store_set_express_mode (
+				E_MAIL_ACCOUNT_STORE (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_SESSION:
+			mail_account_store_set_session (
+				E_MAIL_ACCOUNT_STORE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_store_get_property (GObject *object,
+                                 guint property_id,
+                                 GValue *value,
+                                 GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BUSY:
+			g_value_set_boolean (
+				value,
+				e_mail_account_store_get_busy (
+				E_MAIL_ACCOUNT_STORE (object)));
+			return;
+
+		case PROP_DEFAULT_SERVICE:
+			g_value_set_object (
+				value,
+				e_mail_account_store_get_default_service (
+				E_MAIL_ACCOUNT_STORE (object)));
+			return;
+
+		case PROP_EXPRESS_MODE:
+			g_value_set_boolean (
+				value,
+				e_mail_account_store_get_express_mode (
+				E_MAIL_ACCOUNT_STORE (object)));
+			return;
+
+		case PROP_SESSION:
+			g_value_set_object (
+				value,
+				e_mail_account_store_get_session (
+				E_MAIL_ACCOUNT_STORE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_account_store_dispose (GObject *object)
+{
+	EMailAccountStorePrivate *priv;
+
+	priv = E_MAIL_ACCOUNT_STORE_GET_PRIVATE (object);
+
+	if (priv->session != NULL) {
+		g_object_remove_weak_pointer (
+			G_OBJECT (priv->session), &priv->session);
+		priv->session = NULL;
+	}
+
+	if (priv->default_service != NULL) {
+		g_object_unref (priv->default_service);
+		priv->default_service = NULL;
+	}
+
+	g_hash_table_remove_all (priv->service_index);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_account_store_parent_class)->dispose (object);
+}
+
+static void
+mail_account_store_finalize (GObject *object)
+{
+	EMailAccountStorePrivate *priv;
+
+	priv = E_MAIL_ACCOUNT_STORE_GET_PRIVATE (object);
+
+	g_warn_if_fail (priv->busy_count == 0);
+	g_hash_table_destroy (priv->service_index);
+	g_free (priv->sort_order_filename);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_account_store_parent_class)->finalize (object);
+}
+
+static void
+mail_account_store_constructed (GObject *object)
+{
+	EMailAccountStore *store;
+	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);
+	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));
+}
+
+static void
+mail_account_store_service_added (EMailAccountStore *store,
+                                  CamelService *service)
+{
+	/* Placeholder so subclasses can safely chain up. */
+}
+
+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;
+	const gchar *uid;
+
+	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);
+
+	if (account->enabled) {
+		CamelProvider *provider;
+
+		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));
+	}
+
+	/* 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);
+
+	e_account_list_remove (account_list, account);
+
+	e_account_list_save (account_list);
+}
+
+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. */
+
+	GSettings *settings;
+	const gchar *uid;
+
+	uid = camel_service_get_uid (service);
+
+	/* Handle built-in services that don't have an EAccount. */
+
+	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);
+
+		account->enabled = TRUE;
+
+		e_account_list_change (account_list, account);
+		e_account_list_save (account_list);
+	}
+}
+
+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. */
+
+	GSettings *settings;
+	const gchar *uid;
+
+	uid = camel_service_get_uid (service);
+
+	/* Handle built-in services that don't have an EAccount. */
+
+	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;
+
+		account_list = e_get_account_list ();
+		account = e_get_account_by_uid (uid);
+		g_return_if_fail (account != NULL);
+
+		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);
+	}
+}
+
+static void
+mail_account_store_services_reordered (EMailAccountStore *store,
+                                       gboolean default_restored)
+{
+	/* XXX Should this be made asynchronous? */
+
+	GError *error = NULL;
+
+	if (default_restored) {
+		const gchar *filename;
+
+		filename = store->priv->sort_order_filename;
+
+		if (g_file_test (filename, G_FILE_TEST_EXISTS))
+			g_unlink (filename);
+
+		return;
+	}
+
+	if (!e_mail_account_store_save_sort_order (store, &error)) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+	}
+}
+
+static gboolean
+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 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);
+
+	return (response == GTK_RESPONSE_YES);
+}
+
+static gboolean
+mail_account_store_enable_requested (EMailAccountStore *store,
+                                     GtkWindow *parent_window,
+                                     CamelService *service)
+{
+	return TRUE;
+}
+
+static gboolean
+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 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);
+}
+
+static void
+mail_account_store_row_changed (GtkTreeModel *tree_model,
+                                GtkTreePath *path,
+                                GtkTreeIter *iter)
+{
+	EMailAccountStore *store;
+
+	/* Neither GtkTreeModel nor GtkListStore implements
+	 * this method, so there is nothing to chain up to. */
+
+	store = E_MAIL_ACCOUNT_STORE (tree_model);
+	mail_account_store_update_index (store, path, iter);
+}
+
+static void
+mail_account_store_row_inserted (GtkTreeModel *tree_model,
+                                 GtkTreePath *path,
+                                 GtkTreeIter *iter)
+{
+	EMailAccountStore *store;
+
+	/* Neither GtkTreeModel nor GtkListStore implements
+	 * this method, so there is nothing to chain up to. */
+
+	store = E_MAIL_ACCOUNT_STORE (tree_model);
+	mail_account_store_update_index (store, path, iter);
+}
+
+static gboolean
+mail_account_store_true_proceed (GSignalInvocationHint *ihint,
+                                 GValue *return_accumulator,
+                                 const GValue *handler_return,
+                                 gpointer not_used)
+{
+	gboolean proceed;
+
+	proceed = g_value_get_boolean (handler_return);
+	g_value_set_boolean (return_accumulator, proceed);
+
+	return proceed;
+}
+
+static void
+e_mail_account_store_class_init (EMailAccountStoreClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (class, sizeof (EMailAccountStorePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_account_store_set_property;
+	object_class->get_property = mail_account_store_get_property;
+	object_class->dispose = mail_account_store_dispose;
+	object_class->finalize = mail_account_store_finalize;
+	object_class->constructed = mail_account_store_constructed;
+
+	class->service_added = mail_account_store_service_added;
+	class->service_removed = mail_account_store_service_removed;
+	class->service_enabled = mail_account_store_service_enabled;
+	class->service_disabled = mail_account_store_service_disabled;
+	class->services_reordered = mail_account_store_services_reordered;
+	class->remove_requested = mail_account_store_remove_requested;
+	class->enable_requested = mail_account_store_enable_requested;
+	class->disable_requested = mail_account_store_disable_requested;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_BUSY,
+		g_param_spec_boolean (
+			"busy",
+			"Busy",
+			"Whether async operations are in progress",
+			FALSE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_DEFAULT_SERVICE,
+		g_param_spec_object (
+			"default-service",
+			"Default Service",
+			"Default mail store",
+			CAMEL_TYPE_SERVICE,
+			G_PARAM_READWRITE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_EXPRESS_MODE,
+		g_param_spec_boolean (
+			"express-mode",
+			"Express Mode",
+			"Whether express mode is enabled",
+			FALSE,
+			G_PARAM_READWRITE |
+			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));
+
+	signals[SERVICE_ADDED] = g_signal_new (
+		"service-added",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, service_added),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		CAMEL_TYPE_SERVICE);
+
+	signals[SERVICE_REMOVED] = g_signal_new (
+		"service-removed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, service_removed),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		CAMEL_TYPE_SERVICE);
+
+	signals[SERVICE_ENABLED] = g_signal_new (
+		"service-enabled",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, service_enabled),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		CAMEL_TYPE_SERVICE);
+
+	signals[SERVICE_DISABLED] = g_signal_new (
+		"service-disabled",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, service_disabled),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__OBJECT,
+		G_TYPE_NONE, 1,
+		CAMEL_TYPE_SERVICE);
+
+	signals[SERVICES_REORDERED] = g_signal_new (
+		"services-reordered",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, services_reordered),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__BOOLEAN,
+		G_TYPE_NONE, 1,
+		G_TYPE_BOOLEAN);
+
+	signals[REMOVE_REQUESTED] = g_signal_new (
+		"remove-requested",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, remove_requested),
+		mail_account_store_true_proceed, NULL,
+		e_marshal_BOOLEAN__OBJECT_OBJECT,
+		G_TYPE_BOOLEAN, 2,
+		GTK_TYPE_WINDOW,
+		CAMEL_TYPE_SERVICE);
+
+	signals[ENABLE_REQUESTED] = g_signal_new (
+		"enable-requested",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, enable_requested),
+		mail_account_store_true_proceed, NULL,
+		e_marshal_BOOLEAN__OBJECT_OBJECT,
+		G_TYPE_BOOLEAN, 2,
+		GTK_TYPE_WINDOW,
+		CAMEL_TYPE_SERVICE);
+
+	signals[DISABLE_REQUESTED] = g_signal_new (
+		"disable-requested",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountStoreClass, disable_requested),
+		mail_account_store_true_proceed, NULL,
+		e_marshal_BOOLEAN__OBJECT_OBJECT,
+		G_TYPE_BOOLEAN, 2,
+		GTK_TYPE_WINDOW,
+		CAMEL_TYPE_SERVICE);
+}
+
+static void
+e_mail_account_store_interface_init (GtkTreeModelIface *interface)
+{
+	interface->row_changed = mail_account_store_row_changed;
+	interface->row_inserted = mail_account_store_row_inserted;
+}
+
+static void
+e_mail_account_store_init (EMailAccountStore *store)
+{
+	GType types[E_MAIL_ACCOUNT_STORE_NUM_COLUMNS];
+	GHashTable *service_index;
+	gint ii = 0;
+
+	service_index = g_hash_table_new_full (
+		(GHashFunc) g_direct_hash,
+		(GEqualFunc) g_direct_equal,
+		(GDestroyNotify) NULL,
+		(GDestroyNotify) index_item_free);
+
+	store->priv = E_MAIL_ACCOUNT_STORE_GET_PRIVATE (store);
+	store->priv->service_index = service_index;
+
+	types[ii++] = CAMEL_TYPE_SERVICE;	/* COLUMN_SERVICE */
+	types[ii++] = G_TYPE_BOOLEAN;		/* COLUMN_BUILTIN */
+	types[ii++] = G_TYPE_BOOLEAN;		/* COLUMN_ENABLED */
+	types[ii++] = G_TYPE_BOOLEAN;		/* COLUMN_DEFAULT */
+	types[ii++] = G_TYPE_STRING;		/* COLUMN_BACKEND_NAME */
+	types[ii++] = G_TYPE_STRING;		/* COLUMN_DISPLAY_NAME */
+
+	g_assert (ii == E_MAIL_ACCOUNT_STORE_NUM_COLUMNS);
+
+	gtk_list_store_set_column_types (
+		GTK_LIST_STORE (store),
+		G_N_ELEMENTS (types), types);
+}
+
+EMailAccountStore *
+e_mail_account_store_new (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_ACCOUNT_STORE,
+		"session", session, NULL);
+}
+
+void
+e_mail_account_store_clear (EMailAccountStore *store)
+{
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+
+	gtk_list_store_clear (GTK_LIST_STORE (store));
+	g_hash_table_remove_all (store->priv->service_index);
+}
+
+gboolean
+e_mail_account_store_get_busy (EMailAccountStore *store)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE);
+
+	return (store->priv->busy_count > 0);
+}
+
+EMailSession *
+e_mail_account_store_get_session (EMailAccountStore *store)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL);
+
+	return E_MAIL_SESSION (store->priv->session);
+}
+
+CamelService *
+e_mail_account_store_get_default_service (EMailAccountStore *store)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL);
+
+	return store->priv->default_service;
+}
+
+void
+e_mail_account_store_set_default_service (EMailAccountStore *store,
+                                          CamelService *service)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean iter_set;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+
+	if (service == store->priv->default_service)
+		return;
+
+	if (service != NULL) {
+		g_return_if_fail (CAMEL_IS_SERVICE (service));
+		g_object_ref (service);
+	}
+
+	if (store->priv->default_service != NULL)
+		g_object_unref (store->priv->default_service);
+
+	store->priv->default_service = service;
+
+	model = GTK_TREE_MODEL (store);
+	iter_set = gtk_tree_model_get_iter_first (model, &iter);
+
+	while (iter_set) {
+		CamelService *candidate;
+
+		gtk_tree_model_get (
+			model, &iter,
+			E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE,
+			&candidate, -1);
+
+		gtk_list_store_set (
+			GTK_LIST_STORE (model), &iter,
+			E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT,
+			service == candidate, -1);
+
+		g_object_unref (candidate);
+
+		iter_set = gtk_tree_model_iter_next (model, &iter);
+	}
+
+	g_object_notify (G_OBJECT (store), "default-service");
+}
+
+gboolean
+e_mail_account_store_get_express_mode (EMailAccountStore *store)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE);
+
+	return store->priv->express_mode;
+}
+
+void
+e_mail_account_store_set_express_mode (EMailAccountStore *store,
+                                       gboolean express_mode)
+{
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+
+	store->priv->express_mode = express_mode;
+
+	g_object_notify (G_OBJECT (store), "express-mode");
+}
+
+void
+e_mail_account_store_add_service (EMailAccountStore *store,
+                                  CamelService *service)
+{
+	GSettings *settings;
+	GtkTreeIter iter;
+	const gchar *filename;
+	const gchar *uid;
+	gboolean builtin;
+	gboolean enabled;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	/* Avoid duplicate services in the account store. */
+	if (mail_account_store_get_iter (store, service, &iter))
+		g_return_if_reached ();
+
+	uid = camel_service_get_uid (service);
+
+	/* Handle built-in services that don't have an EAccount. */
+
+	if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) {
+		builtin = TRUE;
+
+		settings = g_settings_new ("org.gnome.evolution.mail");
+		enabled = g_settings_get_boolean (settings, "enable-local");
+		g_object_unref (settings);
+
+	} else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) {
+		builtin = TRUE;
+
+		settings = g_settings_new ("org.gnome.evolution.mail");
+		enabled = g_settings_get_boolean (settings, "enable-vfolders");
+		g_object_unref (settings);
+
+	} else {
+		EAccount *account;
+
+		account = e_get_account_by_uid (uid);
+		g_return_if_fail (account != NULL);
+
+		builtin = FALSE;
+		enabled = account->enabled;
+	}
+
+	/* Where do we insert new services now that accounts can be
+	 * reordered?  This is just a simple policy I came up with.
+	 * It's certainly subject to debate and tweaking.
+	 *
+	 * Always insert new services in row 0 initially.  Then test
+	 * for the presence of the sort order file.  If present, the
+	 * user has messed around with the ordering so leave the new
+	 * service at row 0.  If not present, services are sorted in
+	 * their default order.  So re-apply the default order using
+	 * e_mail_account_store_reorder_services(store, NULL) so the
+	 * new service moves to its proper default position. */
+
+	gtk_list_store_prepend (GTK_LIST_STORE (store), &iter);
+
+	gtk_list_store_set (
+		GTK_LIST_STORE (store), &iter,
+		E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, service,
+		E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, builtin,
+		E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, enabled,
+		-1);
+
+	/* This populates the rest of the columns. */
+	mail_account_store_update_row (store, service, &iter);
+
+	g_signal_emit (store, signals[SERVICE_ADDED], 0, service);
+
+	if (enabled)
+		g_signal_emit (store, signals[SERVICE_ENABLED], 0, service);
+	else
+		g_signal_emit (store, signals[SERVICE_DISABLED], 0, service);
+
+	filename = store->priv->sort_order_filename;
+
+	if (!g_file_test (filename, G_FILE_TEST_EXISTS))
+		e_mail_account_store_reorder_services (store, NULL);
+}
+
+void
+e_mail_account_store_remove_service (EMailAccountStore *store,
+                                     GtkWindow *parent_window,
+                                     CamelService *service)
+{
+	GtkTreeIter iter;
+	gboolean proceed;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	if (!mail_account_store_get_iter (store, service, &iter))
+		g_return_if_reached ();
+
+	/* Possibly request user confirmation. */
+	g_signal_emit (
+		store, signals[REMOVE_REQUESTED], 0,
+		parent_window, service, &proceed);
+
+	if (proceed) {
+		g_object_ref (service);
+
+		gtk_list_store_remove (GTK_LIST_STORE (store), &iter);
+
+		mail_account_store_clean_index (store);
+
+		g_signal_emit (store, signals[SERVICE_REMOVED], 0, service);
+
+		g_object_unref (service);
+	}
+}
+
+void
+e_mail_account_store_enable_service (EMailAccountStore *store,
+                                     GtkWindow *parent_window,
+                                     CamelService *service)
+{
+	GtkTreeIter iter;
+	gboolean proceed;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	if (!mail_account_store_get_iter (store, service, &iter))
+		g_return_if_reached ();
+
+	/* Possibly request user confirmation. */
+	g_signal_emit (
+		store, signals[ENABLE_REQUESTED], 0,
+		parent_window, service, &proceed);
+
+	if (proceed) {
+		gtk_list_store_set (
+			GTK_LIST_STORE (store), &iter,
+			E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, TRUE, -1);
+
+		g_signal_emit (store, signals[SERVICE_ENABLED], 0, service);
+	}
+}
+
+void
+e_mail_account_store_disable_service (EMailAccountStore *store,
+                                      GtkWindow *parent_window,
+                                      CamelService *service)
+{
+	GtkTreeIter iter;
+	gboolean proceed;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	if (!mail_account_store_get_iter (store, service, &iter))
+		g_return_if_reached ();
+
+	/* Possibly request user confirmation. */
+	g_signal_emit (
+		store, signals[DISABLE_REQUESTED], 0,
+		parent_window, service, &proceed);
+
+	if (proceed) {
+		gtk_list_store_set (
+			GTK_LIST_STORE (store), &iter,
+			E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, FALSE, -1);
+
+		g_signal_emit (store, signals[SERVICE_DISABLED], 0, service);
+	}
+}
+
+void
+e_mail_account_store_reorder_services (EMailAccountStore *store,
+                                       GQueue *ordered_services)
+{
+	GQueue *current_order = NULL;
+	GQueue *default_order = NULL;
+	GtkTreeModel *tree_model;
+	GtkTreeIter iter;
+	gboolean use_default_order;
+	gboolean iter_set;
+	GList *head, *link;
+	gint *new_order;
+	gint n_children;
+	gint new_pos = 0;
+	guint length;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (store));
+
+	tree_model = GTK_TREE_MODEL (store);
+	n_children = gtk_tree_model_iter_n_children (tree_model, NULL);
+
+	/* Treat NULL queues and empty queues the same. */
+	if (ordered_services != NULL && g_queue_is_empty (ordered_services))
+		ordered_services = NULL;
+
+	use_default_order = (ordered_services == NULL);
+
+	if (ordered_services != NULL) {
+		length = g_queue_get_length (ordered_services);
+		g_return_if_fail (length == n_children);
+	}
+
+	current_order = g_queue_new ();
+	iter_set = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+	/* Build a queue of CamelServices in the order they appear in
+	 * the list store.  We'll use this to construct the mapping to
+	 * pass to gtk_list_store_reorder(). */
+	while (iter_set) {
+		GValue value = G_VALUE_INIT;
+		const gint column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE;
+
+		gtk_tree_model_get_value (tree_model, &iter, column, &value);
+		g_queue_push_tail (current_order, g_value_get_object (&value));
+		g_value_unset (&value);
+
+		iter_set = gtk_tree_model_iter_next (tree_model, &iter);
+	}
+
+	/* If a custom ordering was not given, revert to default. */
+	if (use_default_order) {
+		default_order = g_queue_copy (current_order);
+
+		g_queue_sort (
+			default_order, (GCompareDataFunc)
+			mail_account_store_default_compare, store);
+
+		ordered_services = default_order;
+	}
+
+	new_order = g_new0 (gint, n_children);
+	head = g_queue_peek_head_link (ordered_services);
+
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		GList *matching_link;
+		gint old_pos;
+
+		matching_link = g_queue_find (current_order, link->data);
+
+		if (matching_link == NULL || matching_link->data == NULL)
+			break;
+
+		old_pos = g_queue_link_index (current_order, matching_link);
+
+		matching_link->data = NULL;
+		new_order[new_pos++] = old_pos;
+	}
+
+	if (new_pos == n_children) {
+		gtk_list_store_reorder (GTK_LIST_STORE (store), new_order);
+		g_signal_emit (
+			store, signals[SERVICES_REORDERED], 0,
+			use_default_order);
+	}
+
+	g_free (new_order);
+
+	if (current_order != NULL)
+		g_queue_free (current_order);
+
+	if (default_order != NULL)
+		g_queue_free (default_order);
+}
+
+gint
+e_mail_account_store_compare_services (EMailAccountStore *store,
+                                       CamelService *service_a,
+                                       CamelService *service_b)
+{
+	GtkTreeModel *model;
+	GtkTreePath *path_a;
+	GtkTreePath *path_b;
+	GtkTreeIter iter_a;
+	GtkTreeIter iter_b;
+	gboolean iter_a_set;
+	gboolean iter_b_set;
+	gint result;
+
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), -1);
+	g_return_val_if_fail (CAMEL_IS_SERVICE (service_a), -1);
+	g_return_val_if_fail (CAMEL_IS_SERVICE (service_b), -1);
+
+	/* XXX This is horribly inefficient but should be
+	 *     over a small enough set to not be noticable. */
+
+	iter_a_set = mail_account_store_get_iter (store, service_a, &iter_a);
+	iter_b_set = mail_account_store_get_iter (store, service_b, &iter_b);
+
+	if (!iter_a_set && !iter_b_set)
+		return 0;
+
+	if (!iter_a_set)
+		return -1;
+
+	if (!iter_b_set)
+		return 1;
+
+	model = GTK_TREE_MODEL (store);
+
+	path_a = gtk_tree_model_get_path (model, &iter_a);
+	path_b = gtk_tree_model_get_path (model, &iter_b);
+
+	result = gtk_tree_path_compare (path_a, path_b);
+
+	gtk_tree_path_free (path_a);
+	gtk_tree_path_free (path_b);
+
+	return result;
+}
+
+gboolean
+e_mail_account_store_load_sort_order (EMailAccountStore *store,
+                                      GError **error)
+{
+	GQueue service_queue = G_QUEUE_INIT;
+	EMailSession *session;
+	GKeyFile *key_file;
+	const gchar *filename;
+	gchar **service_uids;
+	gboolean success = TRUE;
+	gsize ii, length;
+
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE);
+
+	session = e_mail_account_store_get_session (store);
+
+	key_file = g_key_file_new ();
+	filename = store->priv->sort_order_filename;
+
+	if (g_file_test (filename, G_FILE_TEST_EXISTS))
+		success = g_key_file_load_from_file (
+			key_file, filename, G_KEY_FILE_NONE, error);
+
+	if (!success) {
+		g_key_file_free (key_file);
+		return FALSE;
+	}
+
+	/* If the key is not present, length is set to zero. */
+	service_uids = g_key_file_get_string_list (
+		key_file, "Accounts", "SortOrder", &length, NULL);
+
+	for (ii = 0; ii < length; ii++) {
+		CamelService *service;
+
+		service = camel_session_get_service (
+			CAMEL_SESSION (session), service_uids[ii]);
+		if (service != NULL)
+			g_queue_push_tail (&service_queue, service);
+	}
+
+	e_mail_account_store_reorder_services (store, &service_queue);
+
+	g_queue_clear (&service_queue);
+	g_strfreev (service_uids);
+
+	g_key_file_free (key_file);
+
+	return TRUE;
+}
+
+gboolean
+e_mail_account_store_save_sort_order (EMailAccountStore *store,
+                                      GError **error)
+{
+	GKeyFile *key_file;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	const gchar **service_uids;
+	const gchar *filename;
+	gchar *contents;
+	gboolean iter_set;
+	gboolean success;
+	gsize length;
+	gsize ii = 0;
+
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), FALSE);
+
+	model = GTK_TREE_MODEL (store);
+	length = gtk_tree_model_iter_n_children (model, NULL);
+
+	/* Empty store, nothing to save. */
+	if (length == 0)
+		return TRUE;
+
+	service_uids = g_new0 (const gchar *, length);
+
+	iter_set = gtk_tree_model_get_iter_first (model, &iter);
+
+	while (iter_set) {
+		GValue value = G_VALUE_INIT;
+		const gint column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE;
+		CamelService *service;
+
+		gtk_tree_model_get_value (model, &iter, column, &value);
+		service = g_value_get_object (&value);
+		service_uids[ii++] = camel_service_get_uid (service);
+		g_value_unset (&value);
+
+		iter_set = gtk_tree_model_iter_next (model, &iter);
+	}
+
+	key_file = g_key_file_new ();
+	filename = store->priv->sort_order_filename;
+
+	g_key_file_set_string_list (
+		key_file, "Accounts", "SortOrder", service_uids, length);
+
+	contents = g_key_file_to_data (key_file, &length, NULL);
+	success = g_file_set_contents (filename, contents, length, error);
+	g_free (contents);
+
+	g_key_file_free (key_file);
+
+	g_free (service_uids);
+
+	return success;
+}
+
diff --git a/mail/e-mail-account-store.h b/mail/e-mail-account-store.h
new file mode 100644
index 0000000..e4355da
--- /dev/null
+++ b/mail/e-mail-account-store.h
@@ -0,0 +1,144 @@
+/*
+ * e-mail-account-store.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_ACCOUNT_STORE_H
+#define E_MAIL_ACCOUNT_STORE_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_ACCOUNT_STORE \
+	(e_mail_account_store_get_type ())
+#define E_MAIL_ACCOUNT_STORE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStore))
+#define E_MAIL_ACCOUNT_STORE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStoreClass))
+#define E_IS_MAIL_ACCOUNT_STORE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_ACCOUNT_STORE))
+#define E_IS_MAIL_ACOCUNT_STORE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_ACCOUNT_STORE))
+#define E_MAIL_ACCOUNT_STORE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_ACCOUNT_STORE, EMailAccountStoreClass))
+
+G_BEGIN_DECLS
+
+/* Avoid a circular dependency. */
+typedef struct _EMailSession EMailSession;
+
+typedef enum {
+	E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE,
+	E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN,
+	E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED,
+	E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT,
+	E_MAIL_ACCOUNT_STORE_COLUMN_BACKEND_NAME,
+	E_MAIL_ACCOUNT_STORE_COLUMN_DISPLAY_NAME,
+	E_MAIL_ACCOUNT_STORE_NUM_COLUMNS
+} EMailAccountStoreColumn;
+
+typedef struct _EMailAccountStore EMailAccountStore;
+typedef struct _EMailAccountStoreClass EMailAccountStoreClass;
+typedef struct _EMailAccountStorePrivate EMailAccountStorePrivate;
+
+struct _EMailAccountStore {
+	GtkListStore parent;
+	EMailAccountStorePrivate *priv;
+};
+
+struct _EMailAccountStoreClass {
+	GtkListStoreClass parent_class;
+
+	/* Signals */
+	void		(*service_added)	(EMailAccountStore *store,
+						 CamelService *service);
+	void		(*service_removed)	(EMailAccountStore *store,
+						 CamelService *service);
+	void		(*service_enabled)	(EMailAccountStore *store,
+						 CamelService *service);
+	void		(*service_disabled)	(EMailAccountStore *store,
+						 CamelService *service);
+	void		(*services_reordered)	(EMailAccountStore *store,
+						 gboolean default_restored);
+
+	/* These signals are for confirmation dialogs.
+	 * Signal handler should return FALSE to abort. */
+	gboolean	(*remove_requested)	(EMailAccountStore *store,
+						 GtkWindow *parent_window,
+						 CamelService *service);
+	gboolean	(*enable_requested)	(EMailAccountStore *store,
+						 GtkWindow *parent_window,
+						 CamelService *service);
+	gboolean	(*disable_requested)	(EMailAccountStore *store,
+						 GtkWindow *parent_window,
+						 CamelService *service);
+};
+
+GType		e_mail_account_store_get_type	(void) G_GNUC_CONST;
+EMailAccountStore *
+		e_mail_account_store_new	(EMailSession *session);
+void		e_mail_account_store_clear	(EMailAccountStore *store);
+gboolean	e_mail_account_store_get_busy	(EMailAccountStore *store);
+EMailSession *	e_mail_account_store_get_session
+						(EMailAccountStore *store);
+CamelService *	e_mail_account_store_get_default_service
+						(EMailAccountStore *store);
+void		e_mail_account_store_set_default_service
+						(EMailAccountStore *store,
+						 CamelService *service);
+gboolean	e_mail_account_store_get_express_mode
+						(EMailAccountStore *store);
+void		e_mail_account_store_set_express_mode
+						(EMailAccountStore *store,
+						 gboolean express_mode);
+void		e_mail_account_store_add_service
+						(EMailAccountStore *store,
+						 CamelService *service);
+void		e_mail_account_store_remove_service
+						(EMailAccountStore *store,
+						 GtkWindow *parent_window,
+						 CamelService *service);
+void		e_mail_account_store_enable_service
+						(EMailAccountStore *store,
+						 GtkWindow *parent_window,
+						 CamelService *service);
+void		e_mail_account_store_disable_service
+						(EMailAccountStore *store,
+						 GtkWindow *parent_window,
+						 CamelService *service);
+void		e_mail_account_store_reorder_services
+						(EMailAccountStore *store,
+						 GQueue *ordered_services);
+gint		e_mail_account_store_compare_services
+						(EMailAccountStore *store,
+						 CamelService *service_a,
+						 CamelService *service_b);
+gboolean	e_mail_account_store_load_sort_order
+						(EMailAccountStore *store,
+						 GError **error);
+gboolean	e_mail_account_store_save_sort_order
+						(EMailAccountStore *store,
+						 GError **error);
+
+G_END_DECLS
+
+#endif /* E_MAIL_ACCOUNT_STORE_H */
diff --git a/mail/e-mail-account-tree-view.c b/mail/e-mail-account-tree-view.c
new file mode 100644
index 0000000..269a03d
--- /dev/null
+++ b/mail/e-mail-account-tree-view.c
@@ -0,0 +1,283 @@
+/*
+ * e-mail-account-tree-view.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-account-tree-view.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#define E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewPrivate))
+
+struct _EMailAccountTreeViewPrivate {
+	gint placeholder;
+};
+
+enum {
+	ENABLE,
+	DISABLE,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+	EMailAccountTreeView,
+	e_mail_account_tree_view,
+	GTK_TYPE_TREE_VIEW)
+
+static void
+mail_account_tree_view_enabled_toggled_cb (GtkCellRendererToggle *cell_renderer,
+                                           const gchar *path_string,
+                                           EMailAccountTreeView *tree_view)
+{
+	GtkTreeSelection *selection;
+	GtkTreePath *path;
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+	/* Change the selection first so we act on the correct service. */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_selection_select_path (selection, path);
+	gtk_tree_path_free (path);
+
+	if (gtk_cell_renderer_toggle_get_active (cell_renderer))
+		g_signal_emit (tree_view, signals[DISABLE], 0);
+	else
+		g_signal_emit (tree_view, signals[ENABLE], 0);
+}
+
+static void
+mail_account_tree_view_constructed (GObject *object)
+{
+	GtkTreeView *tree_view;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *cell_renderer;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_account_tree_view_parent_class)->
+		constructed (object);
+
+	tree_view = GTK_TREE_VIEW (object);
+
+	gtk_tree_view_set_reorderable (tree_view, TRUE);
+
+	/* Column: Enabled */
+
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_expand (column, FALSE);
+	gtk_tree_view_column_set_title (column, _("Enabled"));
+
+	cell_renderer = gtk_cell_renderer_toggle_new ();
+	gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+	g_signal_connect (
+		cell_renderer, "toggled",
+		G_CALLBACK (mail_account_tree_view_enabled_toggled_cb),
+		tree_view);
+
+	gtk_tree_view_column_add_attribute (
+		column, cell_renderer, "active",
+		E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED);
+
+	gtk_tree_view_append_column (tree_view, column);
+
+	/* Column: Account Name */
+
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_expand (column, TRUE);
+	gtk_tree_view_column_set_title (column, _("Account Name"));
+
+	cell_renderer = gtk_cell_renderer_text_new ();
+	g_object_set (cell_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+	gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+	gtk_tree_view_column_add_attribute (
+		column, cell_renderer, "text",
+		E_MAIL_ACCOUNT_STORE_COLUMN_DISPLAY_NAME);
+
+	cell_renderer = gtk_cell_renderer_text_new ();
+	g_object_set (cell_renderer, "text", _("Default"), NULL);
+	gtk_tree_view_column_pack_end (column, cell_renderer, FALSE);
+
+	gtk_tree_view_column_add_attribute (
+		column, cell_renderer, "visible",
+		E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT);
+
+	cell_renderer = gtk_cell_renderer_pixbuf_new ();
+	g_object_set (
+		cell_renderer, "icon-name", "emblem-default",
+		"stock-size", GTK_ICON_SIZE_MENU, NULL);
+	gtk_tree_view_column_pack_end (column, cell_renderer, FALSE);
+
+	gtk_tree_view_column_add_attribute (
+		column, cell_renderer, "visible",
+		E_MAIL_ACCOUNT_STORE_COLUMN_DEFAULT);
+
+	gtk_tree_view_append_column (tree_view, column);
+
+	/* Column: Type */
+
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_expand (column, FALSE);
+	gtk_tree_view_column_set_title (column, _("Type"));
+
+	cell_renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+
+	gtk_tree_view_column_add_attribute (
+		column, cell_renderer, "text",
+		E_MAIL_ACCOUNT_STORE_COLUMN_BACKEND_NAME);
+
+	gtk_tree_view_append_column (tree_view, column);
+}
+
+static void
+mail_account_tree_view_drag_end (GtkWidget *widget,
+                                 GdkDragContext *context)
+{
+	GtkTreeModel *tree_model;
+
+	/* Chain up to parent's drag_end() method. */
+	GTK_WIDGET_CLASS (e_mail_account_tree_view_parent_class)->
+		drag_end (widget, context);
+
+	tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_STORE (tree_model));
+
+	g_signal_emit_by_name (tree_model, "services-reordered", FALSE);
+}
+
+static void
+e_mail_account_tree_view_class_init (EMailAccountTreeViewClass *class)
+{
+	GObjectClass *object_class;
+	GtkWidgetClass *widget_class;
+
+	g_type_class_add_private (class, sizeof (EMailAccountTreeViewPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = mail_account_tree_view_constructed;
+
+	widget_class = GTK_WIDGET_CLASS (class);
+	widget_class->drag_end = mail_account_tree_view_drag_end;
+
+	signals[ENABLE] = g_signal_new (
+		"enable",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountTreeViewClass, enable),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[DISABLE] = g_signal_new (
+		"disable",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (EMailAccountTreeViewClass, disable),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+}
+
+static void
+e_mail_account_tree_view_init (EMailAccountTreeView *tree_view)
+{
+	tree_view->priv = E_MAIL_ACCOUNT_TREE_VIEW_GET_PRIVATE (tree_view);
+}
+
+GtkWidget *
+e_mail_account_tree_view_new (EMailAccountStore *store)
+{
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_STORE (store), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_ACCOUNT_TREE_VIEW,
+		"model", store, NULL);
+}
+
+CamelService *
+e_mail_account_tree_view_get_selected_service (EMailAccountTreeView *tree_view)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *tree_model;
+	GtkTreeIter iter;
+	CamelService *service;
+	GValue value = G_VALUE_INIT;
+	gint column;
+
+	g_return_val_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view), NULL);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+	if (!gtk_tree_selection_get_selected (selection, &tree_model, &iter))
+		return NULL;
+
+	/* By convention, "get" functions don't return a new object
+	 * reference, so use gtk_tree_model_get_value() to avoid it.
+	 * The caller can always reference the object if needed. */
+
+	column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE;
+	gtk_tree_model_get_value (tree_model, &iter, column, &value);
+	service = g_value_get_object (&value);
+	g_value_unset (&value);
+
+	g_warn_if_fail (CAMEL_IS_SERVICE (service));
+
+	return service;
+}
+
+void
+e_mail_account_tree_view_set_selected_service (EMailAccountTreeView *tree_view,
+                                               CamelService *service)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *tree_model;
+	GtkTreeIter iter;
+	gboolean iter_set;
+
+	g_return_if_fail (E_IS_MAIL_ACCOUNT_TREE_VIEW (tree_view));
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+
+	iter_set = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+	while (iter_set) {
+		GValue value = G_VALUE_INIT;
+		CamelService *candidate;
+		gint column;
+
+		column = E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE;
+		gtk_tree_model_get_value (tree_model, &iter, column, &value);
+		candidate = g_value_get_object (&value);
+		g_value_unset (&value);
+
+		g_warn_if_fail (CAMEL_IS_SERVICE (candidate));
+
+		if (service == candidate) {
+			gtk_tree_selection_select_iter (selection, &iter);
+			break;
+		}
+
+		iter_set = gtk_tree_model_iter_next (tree_model, &iter);
+	}
+}
diff --git a/mail/e-mail-account-tree-view.h b/mail/e-mail-account-tree-view.h
new file mode 100644
index 0000000..e1fff83
--- /dev/null
+++ b/mail/e-mail-account-tree-view.h
@@ -0,0 +1,75 @@
+/*
+ * e-mail-account-tree-view.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_ACCOUNT_TREE_VIEW_H
+#define E_MAIL_ACCOUNT_TREE_VIEW_H
+
+#include <gtk/gtk.h>
+#include <mail/e-mail-account-store.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_ACCOUNT_TREE_VIEW \
+	(e_mail_account_tree_view_get_type ())
+#define E_MAIL_ACCOUNT_TREE_VIEW(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeView))
+#define E_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass))
+#define E_IS_MAIL_ACCOUNT_TREE_VIEW(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW))
+#define E_IS_MAIL_ACCOUNT_TREE_VIEW_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_ACCOUNT_TREE_VIEW))
+#define E_MAIL_ACCOUNT_TREE_VIEW_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_ACCOUNT_TREE_VIEW, EMailAccountTreeViewClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAccountTreeView EMailAccountTreeView;
+typedef struct _EMailAccountTreeViewClass EMailAccountTreeViewClass;
+typedef struct _EMailAccountTreeViewPrivate EMailAccountTreeViewPrivate;
+
+struct _EMailAccountTreeView {
+	GtkTreeView parent;
+	EMailAccountTreeViewPrivate *priv;
+};
+
+struct _EMailAccountTreeViewClass {
+	GtkTreeViewClass parent_class;
+
+	/* Signals */
+	void		(*enable)	(EMailAccountTreeView *tree_view);
+	void		(*disable)	(EMailAccountTreeView *tree_view);
+};
+
+GType		e_mail_account_tree_view_get_type
+					(void) G_GNUC_CONST;
+GtkWidget *	e_mail_account_tree_view_new
+					(EMailAccountStore *store);
+CamelService *	e_mail_account_tree_view_get_selected_service
+					(EMailAccountTreeView *tree_view);
+void		e_mail_account_tree_view_set_selected_service
+					(EMailAccountTreeView *tree_view,
+					 CamelService *service);
+
+G_END_DECLS
+
+#endif /* E_MAIL_ACCOUNT_TREE_VIEW_H */
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index aedbdd2..0640c7f 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -41,10 +41,8 @@
 #include "shell/e-shell.h"
 
 #include "mail/e-mail-folder-utils.h"
-#include "mail/e-mail-local.h"
 #include "mail/e-mail-migrate.h"
 #include "mail/e-mail-session.h"
-#include "mail/e-mail-store.h"
 #include "mail/e-mail-store-utils.h"
 #include "mail/em-event.h"
 #include "mail/em-folder-tree-model.h"
@@ -71,16 +69,9 @@ enum {
 	PROP_SESSION
 };
 
-enum {
-	ACCOUNT_SORT_ORDER_CHANGED,
-	LAST_SIGNAL
-};
-
 /* FIXME Kill this thing.  It's a horrible hack. */
 extern gint camel_application_is_exiting;
 
-static guint signals[LAST_SIGNAL];
-
 G_DEFINE_ABSTRACT_TYPE (
 	EMailBackend,
 	e_mail_backend,
@@ -135,18 +126,6 @@ mail_backend_store_operation_done_cb (CamelStore *store,
 	g_object_unref (activity);
 }
 
-/* Helper for mail_backend_prepare_for_offline_cb() */
-static void
-mail_store_prepare_for_offline_cb (CamelService *service,
-                                   EActivity *activity)
-{
-	/* FIXME Not passing a GCancellable. */
-	e_mail_store_go_offline (
-		CAMEL_STORE (service), G_PRIORITY_DEFAULT, NULL,
-		(GAsyncReadyCallback) mail_backend_store_operation_done_cb,
-		g_object_ref (activity));
-}
-
 static void
 mail_backend_prepare_for_offline_cb (EShell *shell,
                                      EActivity *activity,
@@ -154,6 +133,7 @@ mail_backend_prepare_for_offline_cb (EShell *shell,
 {
 	GtkWindow *window;
 	EMailSession *session;
+	GList *list, *link;
 	gboolean synchronize = FALSE;
 
 	window = e_shell_get_active_window (shell);
@@ -170,20 +150,25 @@ mail_backend_prepare_for_offline_cb (EShell *shell,
 			CAMEL_SESSION (session), FALSE);
 	}
 
-	e_mail_store_foreach (
-		session, (GFunc) mail_store_prepare_for_offline_cb, activity);
-}
+	list = camel_session_list_services (CAMEL_SESSION (session));
 
-/* Helper for mail_backend_prepare_for_online_cb() */
-static void
-mail_store_prepare_for_online_cb (CamelService *service,
-                                  EActivity *activity)
-{
-	/* FIXME Not passing a GCancellable. */
-	e_mail_store_go_online (
-		CAMEL_STORE (service), G_PRIORITY_DEFAULT, NULL,
-		(GAsyncReadyCallback) mail_backend_store_operation_done_cb,
-		g_object_ref (activity));
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		CamelService *service;
+
+		service = CAMEL_SERVICE (link->data);
+
+		if (!CAMEL_IS_STORE (service))
+			continue;
+
+		/* FIXME Not passing a GCancellable. */
+		e_mail_store_go_offline (
+			CAMEL_STORE (service), G_PRIORITY_DEFAULT,
+			NULL, (GAsyncReadyCallback)
+			mail_backend_store_operation_done_cb,
+			g_object_ref (activity));
+	}
+
+	g_list_free (list);
 }
 
 static void
@@ -192,17 +177,35 @@ mail_backend_prepare_for_online_cb (EShell *shell,
                                     EMailBackend *backend)
 {
 	EMailSession *session;
+	GList *list, *link;
 
 	session = e_mail_backend_get_session (backend);
 	camel_session_set_online (CAMEL_SESSION (session), TRUE);
 
-	e_mail_store_foreach (
-		session, (GFunc) mail_store_prepare_for_online_cb, activity);
+	list = camel_session_list_services (CAMEL_SESSION (session));
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		CamelService *service;
+
+		service = CAMEL_SERVICE (link->data);
+
+		if (!CAMEL_IS_STORE (service))
+			continue;
+
+		/* FIXME Not passing a GCancellable. */
+		e_mail_store_go_online (
+			CAMEL_STORE (service), G_PRIORITY_DEFAULT,
+			NULL, (GAsyncReadyCallback)
+			mail_backend_store_operation_done_cb,
+			g_object_ref (activity));
+	}
+
+	g_list_free (link);
 }
 
 /* Helper for mail_backend_prepare_for_quit_cb() */
 static void
-mail_backend_delete_junk (CamelStore *store,
+mail_backend_delete_junk (CamelService *service,
                           EMailBackend *backend)
 {
 	CamelFolder *folder;
@@ -212,7 +215,8 @@ mail_backend_delete_junk (CamelStore *store,
 	guint ii;
 
 	/* FIXME camel_store_get_junk_folder_sync() may block. */
-	folder = camel_store_get_junk_folder_sync (store, NULL, NULL);
+	folder = camel_store_get_junk_folder_sync (
+		CAMEL_STORE (service), NULL, NULL);
 	if (folder == NULL)
 		return;
 
@@ -232,24 +236,6 @@ mail_backend_delete_junk (CamelStore *store,
 }
 
 /* Helper for mail_backend_prepare_for_quit_cb() */
-static void
-mail_backend_final_sync (CamelStore *store,
-                         gpointer user_data)
-{
-	struct {
-		EActivity *activity;
-		gboolean empty_trash;
-	} *sync_data = user_data;
-
-	/* FIXME Not passing a GCancellable. */
-	/* FIXME This operation should be queued. */
-	camel_store_synchronize (
-		store, sync_data->empty_trash, G_PRIORITY_DEFAULT, NULL,
-		(GAsyncReadyCallback) mail_backend_store_operation_done_cb,
-		g_object_ref (sync_data->activity));
-}
-
-/* Helper for mail_backend_prepare_for_quit_cb() */
 static gboolean
 mail_backend_poll_to_quit (EActivity *activity)
 {
@@ -273,14 +259,10 @@ mail_backend_prepare_for_quit_cb (EShell *shell,
 {
 	EAccountList *account_list;
 	EMailSession *session;
+	GList *list, *link;
 	gboolean delete_junk;
 	gboolean empty_trash;
 
-	struct {
-		EActivity *activity;
-		gboolean empty_trash;
-	} sync_data;
-
 	session = e_mail_backend_get_session (backend);
 
 	delete_junk = e_mail_backend_delete_junk_policy_decision (backend);
@@ -296,15 +278,40 @@ mail_backend_prepare_for_quit_cb (EShell *shell,
 	/* Cancel all pending activities. */
 	mail_cancel_all ();
 
-	if (delete_junk)
-		e_mail_store_foreach (
-			session, (GFunc) mail_backend_delete_junk, backend);
+	list = camel_session_list_services (CAMEL_SESSION (session));
+
+	if (delete_junk) {
+		for (link = list; link != NULL; link = g_list_next (link)) {
+			CamelService *service;
+
+			service = CAMEL_SERVICE (link->data);
+
+			if (!CAMEL_IS_STORE (service))
+				continue;
+
+			mail_backend_delete_junk (service, backend);
+		}
+	}
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		CamelService *service;
 
-	sync_data.activity = activity;
-	sync_data.empty_trash = empty_trash;
+		service = CAMEL_SERVICE (link->data);
 
-	e_mail_store_foreach (
-		session, (GFunc) mail_backend_final_sync, &sync_data);
+		if (!CAMEL_IS_STORE (service))
+			continue;
+
+		/* FIXME Not passing a GCancellable. */
+		/* FIXME This operation should be queued. */
+		camel_store_synchronize (
+			CAMEL_STORE (service),
+			empty_trash, G_PRIORITY_DEFAULT,
+			NULL, (GAsyncReadyCallback)
+			mail_backend_store_operation_done_cb,
+			g_object_ref (activity));
+	}
+
+	g_list_free (list);
 
 	/* Now we poll until all activities are actually cancelled or finished.
 	 * Reffing the activity delays quitting; the reference count
@@ -324,6 +331,8 @@ mail_backend_quit_requested_cb (EShell *shell,
                                 EShellQuitReason reason,
                                 EShellBackend *mail_shell_backend)
 {
+	EMailBackend *backend;
+	EMailSession *session;
 	CamelFolder *folder;
 	GtkWindow *window;
 	gint response;
@@ -348,7 +357,11 @@ mail_backend_quit_requested_cb (EShell *shell,
 
 	/* Check Outbox for any unsent messages. */
 
-	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+	backend = E_MAIL_BACKEND (mail_shell_backend);
+	session = e_mail_backend_get_session (backend);
+
+	folder = e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 	if (folder == NULL)
 		return;
 
@@ -373,6 +386,7 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache,
 	CamelStoreClass *class;
 	EAccountList *account_list;
 	EIterator *iterator;
+	EMailSession *session;
 	const gchar *local_drafts_folder_uri;
 	const gchar *local_sent_folder_uri;
 	gboolean write_config = FALSE;
@@ -385,10 +399,15 @@ mail_backend_folder_deleted_cb (MailFolderCache *folder_cache,
 	class = CAMEL_STORE_GET_CLASS (store);
 	g_return_if_fail (class->compare_folder_name != NULL);
 
+	session = e_mail_backend_get_session (backend);
+
 	local_drafts_folder_uri =
-		e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS);
+		e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_DRAFTS);
+
 	local_sent_folder_uri =
-		e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT);
+		e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_SENT);
 
 	uri = e_mail_folder_uri_build (store, folder_name);
 
@@ -744,7 +763,6 @@ mail_backend_constructed (GObject *object)
 	EMailBackendPrivate *priv;
 	EShell *shell;
 	EShellBackend *shell_backend;
-	EMFolderTreeModel *folder_tree_model;
 	MailFolderCache *folder_cache;
 
 	priv = E_MAIL_BACKEND_GET_PRIVATE (object);
@@ -779,14 +797,6 @@ mail_backend_constructed (GObject *object)
 	 *       Give EAccountComboBox a CamelSession property. */
 	e_account_combo_box_set_session (CAMEL_SESSION (priv->session));
 
-	/* FIXME EMailBackend should own the default EMFolderTreeModel. */
-	folder_tree_model = em_folder_tree_model_get_default ();
-
-	/* FIXME This is creating a circular reference.  Perhaps the
-	 *       should only hold a weak pointer to EMailBackend? */
-	em_folder_tree_model_set_backend (
-		folder_tree_model, E_MAIL_BACKEND (object));
-
 	g_signal_connect (
 		shell, "prepare-for-offline",
 		G_CALLBACK (mail_backend_prepare_for_offline_cb),
@@ -856,15 +866,6 @@ e_mail_backend_class_init (EMailBackendClass *class)
 			NULL,
 			E_TYPE_MAIL_SESSION,
 			G_PARAM_READABLE));
-
-	signals[ACCOUNT_SORT_ORDER_CHANGED] = g_signal_new (
-		"account-sort-order-changed",
-		G_TYPE_FROM_CLASS (class),
-		G_SIGNAL_RUN_LAST,
-		G_STRUCT_OFFSET (EMailBackendClass, account_sort_order_changed),
-		NULL, NULL,
-		g_cclosure_marshal_VOID__VOID,
-		G_TYPE_NONE, 0);
 }
 
 static void
@@ -965,11 +966,3 @@ e_mail_backend_submit_alert (EMailBackend *backend,
 	va_end (va);
 }
 
-void
-e_mail_backend_account_sort_order_changed (EMailBackend *backend)
-{
-	g_return_if_fail (backend != NULL);
-	g_return_if_fail (E_IS_MAIL_BACKEND (backend));
-
-	g_signal_emit (backend, signals[ACCOUNT_SORT_ORDER_CHANGED], 0);
-}
diff --git a/mail/e-mail-backend.h b/mail/e-mail-backend.h
index 4d3cc10..6d42519 100644
--- a/mail/e-mail-backend.h
+++ b/mail/e-mail-backend.h
@@ -67,10 +67,6 @@ struct _EMailBackendClass {
 						(EMailBackend *backend);
 	gboolean	(*empty_trash_policy_decision)
 						(EMailBackend *backend);
-
-	/* Signals */
-	void		(*account_sort_order_changed)
-						(EMailBackend *backend);
 };
 
 GType		e_mail_backend_get_type		(void);
@@ -83,9 +79,6 @@ void		e_mail_backend_submit_alert	(EMailBackend *backend,
 						 const gchar *tag,
 						 ...) G_GNUC_NULL_TERMINATED;
 
-void		e_mail_backend_account_sort_order_changed
-						(EMailBackend *backend);
-
 G_END_DECLS
 
 #endif /* E_MAIL_BACKEND_H */
diff --git a/mail/e-mail-migrate.c b/mail/e-mail-migrate.c
index f3ce503..fdf5684 100644
--- a/mail/e-mail-migrate.c
+++ b/mail/e-mail-migrate.c
@@ -64,8 +64,6 @@
 
 #include "e-mail-backend.h"
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
-#include "e-mail-store.h"
 #include "em-utils.h"
 
 #define d(x) x
@@ -277,7 +275,7 @@ emm_setup_initial (const gchar *data_dir)
 
 	d(printf("Setting up initial mail tree\n"));
 
-	base = g_build_filename(data_dir, "local", NULL);
+	base = g_build_filename (data_dir, "local", NULL);
 	if (g_mkdir_with_parents (base, 0700) == -1 && errno != EEXIST) {
 		g_free (base);
 		return FALSE;
@@ -671,7 +669,7 @@ create_mbox_account (EShellBackend *shell_backend,
 {
 	EMailBackend *mail_backend;
 	EMailSession *mail_session;
-	CamelStore *store;
+	CamelService *service;
 	CamelURL *url;
 	EAccountList *accounts;
 	EAccount *account;
@@ -682,9 +680,6 @@ create_mbox_account (EShellBackend *shell_backend,
 	mail_session = e_mail_backend_get_session (mail_backend);
 	data_dir = e_shell_backend_get_data_dir (shell_backend);
 
-	/* Initialize the mail stores early so we can add a new one. */
-	e_mail_store_init (mail_session, data_dir);
-
 	account = e_account_new ();
 	account->enabled = TRUE;
 
@@ -716,15 +711,20 @@ create_mbox_account (EShellBackend *shell_backend,
 		goto exit;
 	}
 
+	/* This will also add it to the EMailSession. */
 	e_account_list_add (accounts, account);
-	store = e_mail_store_add_by_account (mail_session, account);
 
-	folder_uri = e_mail_folder_uri_build (store, "Sent");
+	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 (store, "Drafts");
+	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);
@@ -743,6 +743,8 @@ exit:
 static void
 change_sent_and_drafts_local_folders (EShellBackend *shell_backend)
 {
+	EMailBackend *backend;
+	EMailSession *session;
 	EAccountList *accounts;
 	EIterator *iter;
 	const gchar *data_dir;
@@ -754,6 +756,9 @@ change_sent_and_drafts_local_folders (EShellBackend *shell_backend)
 	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);
@@ -797,8 +802,8 @@ change_sent_and_drafts_local_folders (EShellBackend *shell_backend)
 			changed = TRUE;
 			e_account_set_string (
 				account, E_ACCOUNT_DRAFTS_FOLDER_URI,
-				e_mail_local_get_folder_uri (
-				E_MAIL_LOCAL_FOLDER_DRAFTS));
+				e_mail_session_get_local_folder_uri (
+				session, E_MAIL_LOCAL_FOLDER_DRAFTS));
 		}
 
 		uri = e_account_get_string (account, E_ACCOUNT_SENT_FOLDER_URI);
@@ -806,8 +811,8 @@ change_sent_and_drafts_local_folders (EShellBackend *shell_backend)
 			changed = TRUE;
 			e_account_set_string (
 				account, E_ACCOUNT_SENT_FOLDER_URI,
-				e_mail_local_get_folder_uri (
-				E_MAIL_LOCAL_FOLDER_SENT));
+				e_mail_session_get_local_folder_uri (
+				session, E_MAIL_LOCAL_FOLDER_SENT));
 		}
 	}
 
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index a58eb1f..ffca3d8 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -40,7 +40,6 @@
 #include "mail/e-mail-backend.h"
 #include "mail/e-mail-browser.h"
 #include "mail/e-mail-folder-utils.h"
-#include "mail/e-mail-local.h"
 #include "mail/em-composer-utils.h"
 #include "mail/em-format-html-print.h"
 #include "mail/em-utils.h"
@@ -191,15 +190,16 @@ void
 e_mail_reader_delete_folder (EMailReader *reader,
                              CamelFolder *folder)
 {
-	CamelStore *local_store;
-	CamelStore *parent_store;
 	EMailBackend *backend;
 	EMailSession *session;
 	EAlertSink *alert_sink;
+	CamelStore *parent_store;
 	MailFolderCache *folder_cache;
 	GtkWindow *parent = e_shell_get_active_window (NULL);
 	GtkWidget *dialog;
+	gboolean store_is_local;
 	const gchar *full_name;
+	const gchar *uid;
 	CamelFolderInfoFlags flags = 0;
 	gboolean have_flags;
 
@@ -209,14 +209,16 @@ e_mail_reader_delete_folder (EMailReader *reader,
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
 
+	uid = camel_service_get_uid (CAMEL_SERVICE (parent_store));
+	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+
 	backend = e_mail_reader_get_backend (reader);
 	session = e_mail_backend_get_session (backend);
 
-	local_store = e_mail_local_get_store ();
 	alert_sink = e_mail_reader_get_alert_sink (reader);
 	folder_cache = e_mail_session_get_folder_cache (session);
 
-	if (parent_store == local_store &&
+	if (store_is_local &&
 		mail_reader_is_special_local_folder (full_name)) {
 		e_mail_backend_submit_alert (
 			backend, "mail:no-delete-special-folder",
diff --git a/mail/e-mail-session-utils.c b/mail/e-mail-session-utils.c
index eca58bc..f1c27a3 100644
--- a/mail/e-mail-session-utils.c
+++ b/mail/e-mail-session-utils.c
@@ -27,7 +27,6 @@
 #include <glib/gi18n-lib.h>
 
 #include <mail/mail-tools.h>
-#include <mail/e-mail-local.h>
 #include <mail/e-mail-folder-utils.h>
 #include <e-util/e-account-utils.h>
 #include <filter/e-filter-rule.h>
@@ -508,7 +507,9 @@ mail_session_send_to_thread (GSimpleAsyncResult *simple,
 
 	/* Append the sent message to a Sent folder. */
 
-	local_sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);
+	local_sent_folder =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_SENT);
 
 	/* Try to extract a CamelFolder from the Sent folder URI. */
 	if (context->sent_folder_uri != NULL) {
diff --git a/mail/e-mail-session.c b/mail/e-mail-session.c
index 03f4961..6d04c2c 100644
--- a/mail/e-mail-session.c
+++ b/mail/e-mail-session.c
@@ -52,9 +52,9 @@
 #include "e-util/e-alert-dialog.h"
 #include "e-util/e-util-private.h"
 
+#include "e-mail-account-store.h"
 #include "e-mail-folder-utils.h"
 #include "e-mail-junk-filter.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 #include "em-composer-utils.h"
 #include "em-filter-context.h"
@@ -71,13 +71,26 @@
 	((obj), E_TYPE_MAIL_SESSION, EMailSessionPrivate))
 
 typedef struct _AsyncContext AsyncContext;
+typedef struct _SourceContext SourceContext;
 
 struct _EMailSessionPrivate {
+	EMailAccountStore *account_store;
 	MailFolderCache *folder_cache;
 
+	EAccountList *account_list;
+	gulong account_added_handler_id;
+	gulong account_changed_handler_id;
+
+	CamelStore *local_store;
+	CamelStore *vfolder_store;
+
 	FILE *filter_logfile;
 	GHashTable *junk_filters;
 	EProxy *proxy;
+
+	/* Local folder cache. */
+	GPtrArray *local_folders;
+	GPtrArray *local_folder_uris;
 };
 
 struct _AsyncContext {
@@ -90,10 +103,27 @@ struct _AsyncContext {
 	CamelFolder *folder;
 };
 
+struct _SourceContext {
+	EMailSession *session;
+	CamelService *service;
+};
+
 enum {
 	PROP_0,
+	PROP_ACCOUNT_STORE,
 	PROP_FOLDER_CACHE,
-	PROP_JUNK_FILTER_NAME
+	PROP_JUNK_FILTER_NAME,
+	PROP_LOCAL_STORE,
+	PROP_VFOLDER_STORE
+};
+
+static const gchar *local_folder_names[E_MAIL_NUM_LOCAL_FOLDERS] = {
+	N_("Inbox"),		/* E_MAIL_LOCAL_FOLDER_INBOX */
+	N_("Drafts"),		/* E_MAIL_LOCAL_FOLDER_DRAFTS */
+	N_("Outbox"),		/* E_MAIL_LOCAL_FOLDER_OUTBOX */
+	N_("Sent"),		/* E_MAIL_LOCAL_FOLDER_SENT */
+	N_("Templates"),	/* E_MAIL_LOCAL_FOLDER_TEMPLATES */
+	"Inbox"			/* E_MAIL_LOCAL_FOLDER_LOCAL_INBOX */
 };
 
 static gchar *mail_data_dir;
@@ -463,6 +493,18 @@ async_context_free (AsyncContext *context)
 	g_slice_free (AsyncContext, context);
 }
 
+static void
+source_context_free (SourceContext *context)
+{
+	if (context->session != NULL)
+		g_object_unref (context->session);
+
+	if (context->service != NULL)
+		g_object_unref (context->service);
+
+	g_slice_free (SourceContext, context);
+}
+
 static gchar *
 mail_session_make_key (CamelService *service,
                        const gchar *item)
@@ -553,6 +595,270 @@ 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;
+	gboolean transport_only;
+	GError *error = NULL;
+
+	/* check whether it's transport-only accounts */
+	transport_only =
+		(account->source == NULL) ||
+		(account->source->url == NULL) ||
+		(*account->source->url == '\0');
+	if (transport_only)
+		goto handle_transport;
+
+	/* Load the service, but don't connect.  Check its provider,
+	 * and if this belongs in the folder tree model, add it. */
+
+	url = camel_url_new (account->source->url, NULL);
+	if (url != NULL) {
+		provider = camel_provider_get (url->protocol, NULL);
+		camel_url_free (url);
+	} else {
+		provider = NULL;
+	}
+
+	if (provider == NULL) {
+		/* In case we do not have a provider here, we handle
+		 * the special case of having multiple mail identities
+		 * eg. a dummy account having just SMTP server defined */
+		goto handle_transport;
+	}
+
+	service = camel_session_add_service (
+		CAMEL_SESSION (session),
+		account->uid, provider->protocol,
+		CAMEL_PROVIDER_STORE, &error);
+
+	if (error != NULL) {
+		g_warning (
+			"Failed to add service: %s: %s",
+			account->name, error->message);
+		g_error_free (error);
+		return;
+	}
+
+	camel_service_set_display_name (service, account->name);
+
+handle_transport:
+
+	/* 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". */
+
+	if (account->transport) {
+		GError *transport_error = NULL;
+
+		url = camel_url_new (
+			account->transport->url,
+			&transport_error);
+
+		if (url != NULL) {
+			provider = camel_provider_get (
+				url->protocol, &transport_error);
+			camel_url_free (url);
+		} else
+			provider = NULL;
+
+		if (provider != NULL) {
+			gchar *transport_uid;
+
+			transport_uid = g_strconcat (
+				account->uid, "-transport", NULL);
+
+			camel_session_add_service (
+				CAMEL_SESSION (session),
+				transport_uid, provider->protocol,
+				CAMEL_PROVIDER_TRANSPORT, &transport_error);
+
+			g_free (transport_uid);
+		}
+
+		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_account_added_cb (EAccountList *account_list,
+                               EAccount *account,
+                               EMailSession *session)
+{
+	mail_session_add_by_account (session, account);
+}
+
+static void
+mail_session_account_changed_cb (EAccountList *account_list,
+                                 EAccount *account,
+                                 EMailSession *session)
+{
+	EMFolderTreeModel *folder_tree_model;
+	CamelService *service;
+
+	service = camel_session_get_service (
+		CAMEL_SESSION (session), account->uid);
+
+	if (!CAMEL_IS_STORE (service))
+		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);
+
+	/* Remove the store from the folder tree model and, if the
+	 * account 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
+	 * of stores to disregard, so we don't have to deal with that
+	 * here. */
+
+	folder_tree_model = em_folder_tree_model_get_default ();
+
+	em_folder_tree_model_remove_store (
+		folder_tree_model, CAMEL_STORE (service));
+
+	if (account->enabled)
+		em_folder_tree_model_add_store (
+			folder_tree_model, CAMEL_STORE (service));
+}
+
+static gboolean
+mail_session_add_service_cb (SourceContext *context)
+{
+	EMailAccountStore *store;
+
+	store = e_mail_session_get_account_store (context->session);
+	e_mail_account_store_add_service (store, context->service);
+
+	return FALSE;
+}
+
+static void
+mail_session_add_local_store (EMailSession *session)
+{
+	CamelLocalSettings *local_settings;
+	CamelSession *camel_session;
+	CamelSettings *settings;
+	CamelService *service;
+	const gchar *data_dir;
+	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;
+	}
+
+	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);
+
+	path = g_build_filename (data_dir, E_MAIL_SESSION_LOCAL_UID, NULL);
+	camel_local_settings_set_path (local_settings, path);
+	g_free (path);
+
+	/* Shouldn't need to worry about other mail applications
+	 * altering files in our local mail store. */
+	g_object_set (service, "need-summary-check", FALSE, NULL);
+
+	/* Populate the local folder cache. */
+	for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) {
+		CamelFolder *folder;
+		gchar *folder_uri;
+		const gchar *display_name;
+		GError *error = NULL;
+
+		display_name = local_folder_names[ii];
+
+		/* XXX This blocks but should be fast. */
+		if (ii == E_MAIL_LOCAL_FOLDER_LOCAL_INBOX)
+			folder = camel_store_get_inbox_folder_sync (
+				CAMEL_STORE (service), NULL, &error);
+		else
+			folder = camel_store_get_folder_sync (
+				CAMEL_STORE (service), display_name,
+				CAMEL_STORE_FOLDER_CREATE, NULL, &error);
+
+		folder_uri = e_mail_folder_uri_build (
+			CAMEL_STORE (service), display_name);
+
+		/* The arrays take ownership of the items added. */
+		g_ptr_array_add (session->priv->local_folders, folder);
+		g_ptr_array_add (session->priv->local_folder_uris, folder_uri);
+
+		if (error != NULL) {
+			g_critical ("%s: %s", G_STRFUNC, error->message);
+			g_error_free (error);
+		}
+	}
+
+	session->priv->local_store = g_object_ref (service);
+}
+
+static void
+mail_session_add_vfolder_store (EMailSession *session)
+{
+	CamelSession *camel_session;
+	CamelService *service;
+	GError *error = NULL;
+
+	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;
+	}
+
+	g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+	camel_service_set_display_name (service, _("Search Folders"));
+	em_utils_connect_service_sync (service, NULL, NULL);
+
+	/* XXX There's more configuration to do in vfolder_load_storage()
+	 *     but it requires an EMailBackend, which we don't have access
+	 *     to from here, so it has to be called from elsewhere.  Kinda
+	 *     thinking about reworking that... */
+
+	session->priv->vfolder_store = g_object_ref (service);
+}
+
+static void
 mail_session_set_property (GObject *object,
                            guint property_id,
                            const GValue *value,
@@ -576,6 +882,13 @@ mail_session_get_property (GObject *object,
                            GParamSpec *pspec)
 {
 	switch (property_id) {
+		case PROP_ACCOUNT_STORE:
+			g_value_set_object (
+				value,
+				e_mail_session_get_account_store (
+				E_MAIL_SESSION (object)));
+			return;
+
 		case PROP_FOLDER_CACHE:
 			g_value_set_object (
 				value,
@@ -589,6 +902,20 @@ mail_session_get_property (GObject *object,
 				mail_session_get_junk_filter_name (
 				E_MAIL_SESSION (object)));
 			return;
+
+		case PROP_LOCAL_STORE:
+			g_value_set_object (
+				value,
+				e_mail_session_get_local_store (
+				E_MAIL_SESSION (object)));
+			return;
+
+		case PROP_VFOLDER_STORE:
+			g_value_set_object (
+				value,
+				e_mail_session_get_vfolder_store (
+				E_MAIL_SESSION (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -601,11 +928,41 @@ mail_session_dispose (GObject *object)
 
 	priv = E_MAIL_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->folder_cache != NULL) {
 		g_object_unref (priv->folder_cache);
 		priv->folder_cache = NULL;
 	}
 
+	if (priv->account_list != NULL) {
+		g_signal_handler_disconnect (
+			priv->account_list,
+			priv->account_added_handler_id);
+		g_signal_handler_disconnect (
+			priv->account_list,
+			priv->account_changed_handler_id);
+		g_object_unref (priv->account_list);
+		priv->account_list = NULL;
+	}
+
+	if (priv->local_store != NULL) {
+		g_object_unref (priv->local_store);
+		priv->local_store = NULL;
+	}
+
+	if (priv->vfolder_store != NULL) {
+		g_object_unref (priv->vfolder_store);
+		priv->vfolder_store = NULL;
+	}
+
+	g_ptr_array_set_size (priv->local_folders, 0);
+	g_ptr_array_set_size (priv->local_folder_uris, 0);
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (e_mail_session_parent_class)->dispose (object);
 }
@@ -620,6 +977,9 @@ mail_session_finalize (GObject *object)
 	g_hash_table_destroy (priv->junk_filters);
 	g_object_unref (priv->proxy);
 
+	g_ptr_array_free (priv->local_folders, TRUE);
+	g_ptr_array_free (priv->local_folder_uris, TRUE);
+
 	g_free (mail_data_dir);
 	g_free (mail_config_dir);
 
@@ -642,17 +1002,87 @@ mail_session_notify (GObject *object,
 static void
 mail_session_constructed (GObject *object)
 {
-	EMailSessionPrivate *priv;
+	EMFolderTreeModel *folder_tree_model;
+	EMailSession *session;
 	EExtensible *extensible;
 	GType extension_type;
-	GList *list, *iter;
+	GList *list, *link;
 	GSettings *settings;
+	EAccountList *account_list;
+	EIterator *iter;
+	EAccount *account;
+	gulong handler_id;
 
-	priv = E_MAIL_SESSION_GET_PRIVATE (object);
+	session = E_MAIL_SESSION (object);
 
 	/* 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);
+
+	session->priv->account_store = e_mail_account_store_new (session);
+
+	/* This must be created after the account store. */
+	session->priv->folder_cache = mail_folder_cache_new (session);
+
+	/* XXX Make sure the folder tree model is created before we
+	 *     add built-in CamelStores so it gets signals from the
+	 *     EMailAccountStore.
+	 *
+	 * XXX This is creating a circular reference.  Perhaps the
+	 *     model should only hold a weak pointer to EMailSession?
+	 *
+	 * 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);
+
+	/* Add built-in CamelStores. */
+
+	mail_session_add_local_store (session);
+	mail_session_add_vfolder_store (session);
+
+	/* Load user-defined mail accounts. */
+
+	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);
+
+		if (account->enabled)
+			mail_session_add_by_account (session, account);
+
+		e_iterator_next (iter);
+	}
+
+	g_object_unref (iter);
+
+	/* Initialize which account is default. */
+
+	account = e_get_default_account ();
+	if (account != NULL) {
+		CamelService *service;
+
+		service = camel_session_get_service (
+			CAMEL_SESSION (session), account->uid);
+		e_mail_account_store_set_default_service (
+			session->priv->account_store, service);
+	}
+
+	/* Listen for account list updates. */
+
+	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;
+
+	handler_id = g_signal_connect (
+		account_list, "account-changed",
+		G_CALLBACK (mail_session_account_changed_cb), session);
+	session->priv->account_changed_handler_id = handler_id;
+
 	extensible = E_EXTENSIBLE (object);
 	e_extensible_load_extensions (extensible);
 
@@ -661,11 +1091,11 @@ mail_session_constructed (GObject *object)
 	extension_type = E_TYPE_MAIL_JUNK_FILTER;
 	list = e_extensible_list_extensions (extensible, extension_type);
 
-	for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+	for (link = list; link != NULL; link = g_list_next (link)) {
 		EMailJunkFilter *junk_filter;
 		EMailJunkFilterClass *class;
 
-		junk_filter = E_MAIL_JUNK_FILTER (iter->data);
+		junk_filter = E_MAIL_JUNK_FILTER (link->data);
 		class = E_MAIL_JUNK_FILTER_GET_CLASS (junk_filter);
 
 		if (!CAMEL_IS_JUNK_FILTER (junk_filter)) {
@@ -693,17 +1123,21 @@ mail_session_constructed (GObject *object)
 		/* No need to reference the EMailJunkFilter since
 		 * EMailSession owns the reference to it already. */
 		g_hash_table_insert (
-			priv->junk_filters,
+			session->priv->junk_filters,
 			(gpointer) class->filter_name,
 			junk_filter);
 	}
 
 	g_list_free (list);
 
-	/* Bind the "junk-default-plugin" GSettings key to our "junk-filter-name" property. */
+	/* 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", G_SETTINGS_BIND_DEFAULT);
+	g_settings_bind (
+		settings, "junk-default-plugin",
+		object, "junk-filter-name",
+		G_SETTINGS_BIND_DEFAULT);
 	g_object_unref (settings);
 }
 
@@ -765,6 +1199,22 @@ mail_session_add_service (CamelSession *session,
 		}
 	}
 
+	/* 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_session_add_service_cb,
+			context, (GDestroyNotify) source_context_free);
+	}
+
 	return service;
 }
 
@@ -1073,7 +1523,8 @@ mail_session_forward_to (CamelSession *session,
 
 	/* and send it */
 	info = camel_message_info_new (NULL);
-	out_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+	out_folder = e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_OUTBOX);
 	camel_message_info_set_flags (
 		info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
 
@@ -1300,6 +1751,28 @@ e_mail_session_class_init (EMailSessionClass *class)
 			NULL,
 			G_PARAM_READWRITE |
 			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_LOCAL_STORE,
+		g_param_spec_object (
+			"local-store",
+			"Local Store",
+			"Built-in local store",
+			CAMEL_TYPE_STORE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_VFOLDER_STORE,
+		g_param_spec_object (
+			"vfolder-store",
+			"Search Folder Store",
+			"Built-in search folder store",
+			CAMEL_TYPE_STORE,
+			G_PARAM_READABLE |
+			G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -1308,11 +1781,17 @@ e_mail_session_init (EMailSession *session)
 	GSettings *settings;
 
 	session->priv = E_MAIL_SESSION_GET_PRIVATE (session);
-	session->priv->folder_cache = mail_folder_cache_new ();
 	session->priv->junk_filters = g_hash_table_new (
 		(GHashFunc) g_str_hash, (GEqualFunc) g_str_equal);
 	session->priv->proxy = e_proxy_new ();
 
+	session->priv->local_folders =
+		g_ptr_array_new_with_free_func (
+		(GDestroyNotify) g_object_unref);
+	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);
 
@@ -1348,6 +1827,14 @@ e_mail_session_new (void)
 		NULL);
 }
 
+EMailAccountStore *
+e_mail_session_get_account_store (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return session->priv->account_store;
+}
+
 MailFolderCache *
 e_mail_session_get_folder_cache (EMailSession *session)
 {
@@ -1356,6 +1843,58 @@ e_mail_session_get_folder_cache (EMailSession *session)
 	return session->priv->folder_cache;
 }
 
+CamelStore *
+e_mail_session_get_local_store (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return session->priv->local_store;
+}
+
+CamelStore *
+e_mail_session_get_vfolder_store (EMailSession *session)
+{
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return session->priv->vfolder_store;
+}
+
+CamelFolder *
+e_mail_session_get_local_folder (EMailSession *session,
+                                 EMailLocalFolder type)
+{
+	GPtrArray *local_folders;
+	CamelFolder *folder;
+
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	local_folders = session->priv->local_folders;
+	g_return_val_if_fail (type < local_folders->len, NULL);
+
+	folder = g_ptr_array_index (local_folders, type);
+	g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+
+	return folder;
+}
+
+const gchar *
+e_mail_session_get_local_folder_uri (EMailSession *session,
+                                     EMailLocalFolder type)
+{
+	GPtrArray *local_folder_uris;
+	const gchar *folder_uri;
+
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	local_folder_uris = session->priv->local_folder_uris;
+	g_return_val_if_fail (type < local_folder_uris->len, NULL);
+
+	folder_uri = g_ptr_array_index (local_folder_uris, type);
+	g_return_val_if_fail (folder_uri != NULL, NULL);
+
+	return folder_uri;
+}
+
 GList *
 e_mail_session_get_available_junk_filters (EMailSession *session)
 {
diff --git a/mail/e-mail-session.h b/mail/e-mail-session.h
index 165b335..e10e3c3 100644
--- a/mail/e-mail-session.h
+++ b/mail/e-mail-session.h
@@ -26,6 +26,8 @@
 #define E_MAIL_SESSION_H
 
 #include <camel/camel.h>
+#include <mail/e-mail-enums.h>
+#include <mail/e-mail-account-store.h>
 #include <mail/mail-folder-cache.h>
 
 /* Standard GObject macros */
@@ -47,8 +49,15 @@
 	(G_TYPE_INSTANCE_GET_CLASS \
 	((obj), E_TYPE_MAIL_SESSION, EMailSessionClass))
 
+/* Built-in CamelServices */
+#define E_MAIL_SESSION_LOCAL_UID   "local"	/* "On This Computer" */
+#define E_MAIL_SESSION_VFOLDER_UID "vfolder"	/* "Search Folders" */
+
 G_BEGIN_DECLS
 
+/* Avoids a circular dependency. */
+typedef struct _EMailAccountStore EMailAccountStore;
+
 typedef struct _EMailSession EMailSession;
 typedef struct _EMailSessionClass EMailSessionClass;
 typedef struct _EMailSessionPrivate EMailSessionPrivate;
@@ -64,8 +73,19 @@ struct _EMailSessionClass {
 
 GType		e_mail_session_get_type		(void);
 EMailSession *	e_mail_session_new		(void);
+EMailAccountStore *
+		e_mail_session_get_account_store
+						(EMailSession *session);
 MailFolderCache *
 		e_mail_session_get_folder_cache	(EMailSession *session);
+CamelStore *	e_mail_session_get_local_store	(EMailSession *session);
+CamelStore *	e_mail_session_get_vfolder_store
+						(EMailSession *session);
+CamelFolder *	e_mail_session_get_local_folder	(EMailSession *session,
+						 EMailLocalFolder type);
+const gchar *	e_mail_session_get_local_folder_uri
+						(EMailSession *session,
+						 EMailLocalFolder type);
 GList *		e_mail_session_get_available_junk_filters
 						(EMailSession *session);
 CamelFolder *	e_mail_session_get_inbox_sync	(EMailSession *session,
diff --git a/mail/e-mail-sidebar.c b/mail/e-mail-sidebar.c
index 35048f8..9a93581 100644
--- a/mail/e-mail-sidebar.c
+++ b/mail/e-mail-sidebar.c
@@ -28,7 +28,6 @@
 #include <string.h>
 #include <camel/camel.h>
 
-#include "mail/e-mail-local.h"
 #include "mail/em-utils.h"
 
 #define E_MAIL_SIDEBAR_GET_PRIVATE(obj) \
@@ -338,6 +337,8 @@ mail_sidebar_check_state (EMailSidebar *sidebar)
 	GtkTreeIter iter;
 	CamelStore *store;
 	gchar *full_name;
+	const gchar *uid;
+	gboolean store_is_local;
 	gboolean allows_children = TRUE;
 	gboolean can_delete = TRUE;
 	gboolean is_junk = FALSE;
@@ -360,12 +361,12 @@ mail_sidebar_check_state (EMailSidebar *sidebar)
 		COL_BOOL_IS_STORE, &is_store,
 		COL_UINT_FLAGS, &folder_flags, -1);
 
+	uid = camel_service_get_uid (CAMEL_SERVICE (store));
+	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+
 	if (!is_store && full_name != NULL) {
-		CamelStore *local_store;
 		guint32 folder_type;
 
-		local_store = e_mail_local_get_store ();
-
 		/* Is this a virtual junk or trash folder? */
 		is_junk = (strcmp (full_name, CAMEL_VJUNK_NAME) == 0);
 		is_trash = (strcmp (full_name, CAMEL_VTRASH_NAME) == 0);
@@ -378,7 +379,7 @@ mail_sidebar_check_state (EMailSidebar *sidebar)
 		allows_children = !(is_junk || is_trash);
 
 		/* Don't allow deletion of special local folders. */
-		if (store == local_store) {
+		if (store_is_local) {
 			can_delete =
 				(strcmp (full_name, "Drafts") != 0) &&
 				(strcmp (full_name, "Inbox") != 0) &&
diff --git a/mail/e-mail.h b/mail/e-mail.h
index 7c40b20..02c169c 100644
--- a/mail/e-mail.h
+++ b/mail/e-mail.h
@@ -32,7 +32,6 @@
 #include <mail/e-mail-label-list-store.h>
 #include <mail/e-mail-label-manager.h>
 #include <mail/e-mail-label-tree-view.h>
-#include <mail/e-mail-local.h>
 #include <mail/e-mail-message-pane.h>
 #include <mail/e-mail-migrate.h>
 #include <mail/e-mail-notebook-view.h>
@@ -42,7 +41,6 @@
 #include <mail/e-mail-session.h>
 #include <mail/e-mail-session-utils.h>
 #include <mail/e-mail-sidebar.h>
-#include <mail/e-mail-store.h>
 #include <mail/e-mail-store-utils.h>
 #include <mail/e-mail-tag-editor.h>
 #include <mail/e-mail-view.h>
diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c
index 6bd96ef..7b84112 100644
--- a/mail/em-account-editor.c
+++ b/mail/em-account-editor.c
@@ -60,8 +60,6 @@
 #include "e-mail-backend.h"
 #include "e-mail-folder-utils.h"
 #include "e-mail-junk-options.h"
-#include "e-mail-local.h"
-#include "e-mail-store.h"
 #include "em-config.h"
 #include "em-folder-selection-button.h"
 #include "em-account-editor.h"
@@ -301,26 +299,10 @@ emae_set_original_account (EMAccountEditor *emae,
 		modified_account = e_account_new ();
 		modified_account->enabled = TRUE;
 		emae->priv->new_account = TRUE;
-
-		e_account_set_string (
-			modified_account, E_ACCOUNT_DRAFTS_FOLDER_URI,
-			e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS));
-
-		e_account_set_string (
-			modified_account, E_ACCOUNT_SENT_FOLDER_URI,
-			e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT));
-
-		/* encrypt to self by default */
-		e_account_set_bool (modified_account, E_ACCOUNT_PGP_ENCRYPT_TO_SELF, TRUE);
-		e_account_set_bool (modified_account, E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, TRUE);
 	}
 
 	emae->priv->original_account = original_account;
 	emae->priv->modified_account = modified_account;
-
-	g_signal_connect_swapped (
-		emae->priv->modified_account, "changed",
-		G_CALLBACK (emae_config_target_changed_cb), emae);
 }
 
 static void
@@ -909,6 +891,52 @@ emae_finalize (GObject *object)
 }
 
 static void
+emae_constructed (GObject *object)
+{
+	EMAccountEditor *emae;
+
+	emae = EM_ACCOUNT_EDITOR (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (em_account_editor_parent_class)->constructed (object);
+
+	/* Set some defaults on the new account before we get started. */
+	if (emae->priv->new_account) {
+		EMailBackend *backend;
+		EMailSession *session;
+
+		backend = em_account_editor_get_backend (emae);
+		session = e_mail_backend_get_session (backend);
+
+		/* Pick local Drafts folder. */
+		e_account_set_string (
+			emae->priv->modified_account,
+			E_ACCOUNT_DRAFTS_FOLDER_URI,
+			e_mail_session_get_local_folder_uri (
+			session, E_MAIL_LOCAL_FOLDER_DRAFTS));
+
+		/* Pick local Sent folder. */
+		e_account_set_string (
+			emae->priv->modified_account,
+			E_ACCOUNT_SENT_FOLDER_URI,
+			e_mail_session_get_local_folder_uri (
+			session, E_MAIL_LOCAL_FOLDER_SENT));
+
+		/* Encrypt to self by default. */
+		e_account_set_bool (
+			emae->priv->modified_account,
+			E_ACCOUNT_PGP_ENCRYPT_TO_SELF, TRUE);
+		e_account_set_bool (
+			emae->priv->modified_account,
+			E_ACCOUNT_SMIME_ENCRYPT_TO_SELF, TRUE);
+	}
+
+	g_signal_connect_swapped (
+		emae->priv->modified_account, "changed",
+		G_CALLBACK (emae_config_target_changed_cb), emae);
+}
+
+static void
 em_account_editor_class_init (EMAccountEditorClass *class)
 {
 	GObjectClass *object_class;
@@ -920,6 +948,7 @@ em_account_editor_class_init (EMAccountEditorClass *class)
 	object_class->get_property = emae_get_property;
 	object_class->dispose = emae_dispose;
 	object_class->finalize = emae_finalize;
+	object_class->constructed = emae_constructed;
 
 	g_object_class_install_property (
 		object_class,
@@ -1295,15 +1324,29 @@ default_folders_clicked (GtkButton *button,
                          gpointer user_data)
 {
 	EMAccountEditor *emae = user_data;
-	const gchar *uri;
+	EMFolderSelectionButton *folder_button;
+	EMailBackend *backend;
+	EMailSession *session;
+	const gchar *folder_uri;
 
-	uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS);
-	em_folder_selection_button_set_folder_uri ((EMFolderSelectionButton *) emae->priv->drafts_folder_button, uri);
-	emae_account_folder_changed ((EMFolderSelectionButton *) emae->priv->drafts_folder_button, emae);
+	backend = em_account_editor_get_backend (emae);
+	session = e_mail_backend_get_session (backend);
 
-	uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_SENT);
-	em_folder_selection_button_set_folder_uri ((EMFolderSelectionButton *) emae->priv->sent_folder_button, uri);
-	emae_account_folder_changed ((EMFolderSelectionButton *) emae->priv->sent_folder_button, emae);
+	folder_button =
+		EM_FOLDER_SELECTION_BUTTON (
+		emae->priv->drafts_folder_button);
+	folder_uri = e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_DRAFTS);
+	em_folder_selection_button_set_folder_uri (folder_button, folder_uri);
+	emae_account_folder_changed (folder_button, emae);
+
+	folder_button =
+		EM_FOLDER_SELECTION_BUTTON (
+		emae->priv->sent_folder_button);
+	folder_uri = e_mail_session_get_local_folder_uri (
+		session, E_MAIL_LOCAL_FOLDER_SENT);
+	em_folder_selection_button_set_folder_uri (folder_button, folder_uri);
+	emae_account_folder_changed (folder_button, emae);
 
 	gtk_toggle_button_set_active (emae->priv->trash_folder_check, FALSE);
 	gtk_toggle_button_set_active (emae->priv->junk_folder_check, FALSE);
@@ -1805,10 +1848,12 @@ emae_account_folder (EMAccountEditor *emae,
 	EAccount *account;
 	EMFolderSelectionButton *folder;
 	EMailBackend *backend;
+	EMailSession *session;
 	const gchar *uri;
 
 	account = em_account_editor_get_modified_account (emae);
 	backend = em_account_editor_get_backend (emae);
+	session = e_mail_backend_get_session (backend);
 
 	folder = (EMFolderSelectionButton *) e_builder_get_widget (builder, name);
 	em_folder_selection_button_set_backend (folder, backend);
@@ -1817,7 +1862,7 @@ emae_account_folder (EMAccountEditor *emae,
 	if (uri != NULL) {
 		em_folder_selection_button_set_folder_uri (folder, uri);
 	} else {
-		uri = e_mail_local_get_folder_uri (deffolder);
+		uri = e_mail_session_get_local_folder_uri (session, deffolder);
 		em_folder_selection_button_set_folder_uri (folder, uri);
 	}
 
@@ -5136,7 +5181,6 @@ emae_commit (EConfig *ec,
 	camel_url_free (url);
 
 	if (original_account != NULL) {
-		d (printf ("Committing account '%s'\n", e_account_get_string (modified_account, E_ACCOUNT_NAME)));
 		forget_password_if_needed (original_account, modified_account, E_ACCOUNT_SOURCE_SAVE_PASSWD, E_ACCOUNT_SOURCE_URL);
 		forget_password_if_needed (original_account, modified_account, E_ACCOUNT_TRANSPORT_SAVE_PASSWD, E_ACCOUNT_TRANSPORT_URL);
 
@@ -5144,30 +5188,25 @@ emae_commit (EConfig *ec,
 		account = original_account;
 		e_account_list_change (accounts, account);
 	} else {
-		CamelProvider *provider;
-
-		d (printf ("Adding new account '%s'\n", e_account_get_string (modified_account, E_ACCOUNT_NAME)));
 		e_account_list_add (accounts, modified_account);
 		account = modified_account;
+	}
 
-		provider = emae_get_store_provider (emae);
+	if (gtk_toggle_button_get_active (emae->priv->default_account)) {
+		EMailBackend *backend;
+		EMailSession *session;
+		EMailAccountStore *store;
+		CamelService *service;
 
-		/* HACK: this will add the account to the folder tree.
-		 * We should just be listening to the account list directly for changed events */
-		if (account->enabled
-		    && provider != NULL
-		    && (provider->flags & CAMEL_PROVIDER_IS_STORAGE)) {
-			EMailBackend *backend;
-			EMailSession *session;
-
-			backend = em_account_editor_get_backend (emae);
-			session = e_mail_backend_get_session (backend);
-			e_mail_store_add_by_account (session, account);
-		}
-	}
+		backend = em_account_editor_get_backend (emae);
+		session = e_mail_backend_get_session (backend);
 
-	if (gtk_toggle_button_get_active (emae->priv->default_account))
-		e_account_list_set_default (accounts, account);
+		service = camel_session_get_service (
+			CAMEL_SESSION (session), account->uid);
+
+		store = e_mail_session_get_account_store (session);
+		e_mail_account_store_set_default_service (store, service);
+	}
 
 	e_account_list_save (accounts);
 }
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 0eceeea..f6a938b 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -45,7 +45,6 @@
 #include "shell/e-shell.h"
 
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 #include "e-mail-session-utils.h"
 #include "em-utils.h"
@@ -74,6 +73,7 @@ typedef struct _ForwardData ForwardData;
 
 struct _AsyncContext {
 	CamelMimeMessage *message;
+	EMailSession *session;
 	EMsgComposer *composer;
 	EActivity *activity;
 	EMailReader *reader;
@@ -98,6 +98,9 @@ async_context_free (AsyncContext *context)
 	if (context->message != NULL)
 		g_object_unref (context->message);
 
+	if (context->session != NULL)
+		g_object_unref (context->session);
+
 	if (context->composer != NULL)
 		g_object_unref (context->composer);
 
@@ -206,7 +209,8 @@ is_group_definition (const gchar *str)
 }
 
 static gboolean
-composer_presend_check_recipients (EMsgComposer *composer)
+composer_presend_check_recipients (EMsgComposer *composer,
+                                   EMailSession *session)
 {
 	EDestination **recipients;
 	EDestination **recipients_bcc;
@@ -358,7 +362,8 @@ finished:
 }
 
 static gboolean
-composer_presend_check_account (EMsgComposer *composer)
+composer_presend_check_account (EMsgComposer *composer,
+                                EMailSession *session)
 {
 	EComposerHeaderTable *table;
 	EAccount *account;
@@ -377,7 +382,8 @@ composer_presend_check_account (EMsgComposer *composer)
 }
 
 static gboolean
-composer_presend_check_downloads (EMsgComposer *composer)
+composer_presend_check_downloads (EMsgComposer *composer,
+                                  EMailSession *session)
 {
 	EAttachmentView *view;
 	EAttachmentStore *store;
@@ -396,7 +402,8 @@ composer_presend_check_downloads (EMsgComposer *composer)
 }
 
 static gboolean
-composer_presend_check_plugins (EMsgComposer *composer)
+composer_presend_check_plugins (EMsgComposer *composer,
+                                EMailSession *session)
 {
 	EMEvent *eme;
 	EMEventTargetComposer *target;
@@ -428,7 +435,8 @@ composer_presend_check_plugins (EMsgComposer *composer)
 }
 
 static gboolean
-composer_presend_check_subject (EMsgComposer *composer)
+composer_presend_check_subject (EMsgComposer *composer,
+                                EMailSession *session)
 {
 	EComposerHeaderTable *table;
 	const gchar *subject;
@@ -446,7 +454,8 @@ composer_presend_check_subject (EMsgComposer *composer)
 }
 
 static gboolean
-composer_presend_check_unwanted_html (EMsgComposer *composer)
+composer_presend_check_unwanted_html (EMsgComposer *composer,
+                                      EMailSession *session)
 {
 	EDestination **recipients;
 	EComposerHeaderTable *table;
@@ -556,10 +565,10 @@ exit:
 static void
 em_utils_composer_send_cb (EMsgComposer *composer,
                            CamelMimeMessage *message,
-                           EActivity *activity)
+                           EActivity *activity,
+                           EMailSession *session)
 {
 	AsyncContext *context;
-	CamelSession *session;
 	GCancellable *cancellable;
 
 	context = g_slice_new0 (AsyncContext);
@@ -568,10 +577,9 @@ em_utils_composer_send_cb (EMsgComposer *composer,
 	context->activity = g_object_ref (activity);
 
 	cancellable = e_activity_get_cancellable (activity);
-	session = e_msg_composer_get_session (context->composer);
 
 	e_mail_session_send_to (
-		E_MAIL_SESSION (session), message,
+		session, message,
 		G_PRIORITY_DEFAULT, cancellable, NULL, NULL,
 		(GAsyncReadyCallback) composer_send_completed,
 		context);
@@ -593,6 +601,7 @@ composer_set_no_change (EMsgComposer *composer)
 /* delete original messages from Outbox folder */
 static void
 manage_x_evolution_replace_outbox (EMsgComposer *composer,
+                                   EMailSession *session,
                                    CamelMimeMessage *message,
                                    GCancellable *cancellable)
 {
@@ -610,7 +619,8 @@ manage_x_evolution_replace_outbox (EMsgComposer *composer,
 	if (!message_uid)
 		return;
 
-	outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+	outbox = e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 	g_return_if_fail (outbox != NULL);
 
 	camel_folder_set_message_flags (
@@ -708,7 +718,8 @@ composer_save_to_drafts_append_mail (AsyncContext *context,
 	CamelMessageInfo *info;
 
 	local_drafts_folder =
-		e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_DRAFTS);
+		e_mail_session_get_local_folder (
+		context->session, E_MAIL_LOCAL_FOLDER_DRAFTS);
 
 	if (drafts_folder == NULL)
 		drafts_folder = g_object_ref (local_drafts_folder);
@@ -778,24 +789,24 @@ composer_save_to_drafts_got_folder (EMailSession *session,
 static void
 em_utils_composer_save_to_drafts_cb (EMsgComposer *composer,
                                      CamelMimeMessage *message,
-                                     EActivity *activity)
+                                     EActivity *activity,
+                                     EMailSession *session)
 {
 	AsyncContext *context;
 	EComposerHeaderTable *table;
 	const gchar *drafts_folder_uri = NULL;
 	const gchar *local_drafts_folder_uri;
-	CamelSession *session;
 	EAccount *account;
 
 	context = g_slice_new0 (AsyncContext);
 	context->message = g_object_ref (message);
+	context->session = g_object_ref (session);
 	context->composer = g_object_ref (composer);
 	context->activity = g_object_ref (activity);
 
-	session = e_msg_composer_get_session (composer);
-
 	local_drafts_folder_uri =
-		e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_DRAFTS);
+		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);
@@ -816,9 +827,9 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer,
 		context->folder_uri = g_strdup (drafts_folder_uri);
 
 		e_mail_session_uri_to_folder (
-			E_MAIL_SESSION (session),
-			drafts_folder_uri, 0, G_PRIORITY_DEFAULT,
-			cancellable, (GAsyncReadyCallback)
+			session, drafts_folder_uri, 0,
+			G_PRIORITY_DEFAULT, cancellable,
+			(GAsyncReadyCallback)
 			composer_save_to_drafts_got_folder, context);
 	}
 }
@@ -851,7 +862,7 @@ composer_save_to_outbox_completed (CamelFolder *outbox_folder,
 
 	/* special processing for Outbox folder */
 	manage_x_evolution_replace_outbox (
-		context->composer, context->message,
+		context->composer, context->session, context->message,
 		e_activity_get_cancellable (context->activity));
 
 	e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
@@ -869,7 +880,8 @@ exit:
 static void
 em_utils_composer_save_to_outbox_cb (EMsgComposer *composer,
                                      CamelMimeMessage *message,
-                                     EActivity *activity)
+                                     EActivity *activity,
+                                     EMailSession *session)
 {
 	AsyncContext *context;
 	CamelFolder *outbox_folder;
@@ -878,11 +890,15 @@ em_utils_composer_save_to_outbox_cb (EMsgComposer *composer,
 
 	context = g_slice_new0 (AsyncContext);
 	context->message = g_object_ref (message);
+	context->session = g_object_ref (session);
 	context->composer = g_object_ref (composer);
 	context->activity = g_object_ref (activity);
 
 	cancellable = e_activity_get_cancellable (activity);
-	outbox_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+
+	outbox_folder =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 
 	info = camel_message_info_new (NULL);
 	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);
@@ -900,7 +916,8 @@ static void
 em_utils_composer_print_cb (EMsgComposer *composer,
                             GtkPrintOperationAction action,
                             CamelMimeMessage *message,
-                            EActivity *activity)
+                            EActivity *activity,
+                            EMailSession *session)
 {
 	EMFormatHTMLPrint *efhp;
 
@@ -2719,7 +2736,7 @@ em_utils_reply_to_message (EShell *shell,
 
 static void
 post_header_clicked_cb (EComposerPostHeader *header,
-                        EMsgComposer *composer)
+                        EMailSession *session)
 {
 	EShell *shell;
 	EShellBackend *shell_backend;
@@ -2731,14 +2748,14 @@ post_header_clicked_cb (EComposerPostHeader *header,
 	GList *list;
 
 	/* FIXME Figure out a way to pass the mail backend in. */
-	shell = e_msg_composer_get_shell (composer);
+	shell = e_shell_get_default ();
 	shell_backend = e_shell_get_backend_by_name (shell, "mail");
 
 	/* FIXME Limit the folder tree to the NNTP account? */
 	model = em_folder_tree_model_get_default ();
 
 	dialog = em_folder_selector_new (
-		GTK_WINDOW (composer),
+		/* FIXME GTK_WINDOW (composer) */ NULL,
 		E_MAIL_BACKEND (shell_backend),
 		model, EM_FOLDER_SELECTOR_CAN_CREATE,
 		_("Posting destination"),
@@ -2788,13 +2805,15 @@ exit:
  * things the #EMsgComposer instance can't do itself.
  **/
 void
-em_configure_new_composer (EMsgComposer *composer)
+em_configure_new_composer (EMsgComposer *composer,
+                           EMailSession *session)
 {
 	EComposerHeaderTable *table;
 	EComposerHeaderType header_type;
 	EComposerHeader *header;
 
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
 
 	header_type = E_COMPOSER_HEADER_POST_TO;
 	table = e_msg_composer_get_header_table (composer);
@@ -2802,43 +2821,43 @@ em_configure_new_composer (EMsgComposer *composer)
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_recipients), NULL);
+		G_CALLBACK (composer_presend_check_recipients), session);
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_account), NULL);
+		G_CALLBACK (composer_presend_check_account), session);
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_downloads), NULL);
+		G_CALLBACK (composer_presend_check_downloads), session);
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_plugins), NULL);
+		G_CALLBACK (composer_presend_check_plugins), session);
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_subject), NULL);
+		G_CALLBACK (composer_presend_check_subject), session);
 
 	g_signal_connect (
 		composer, "presend",
-		G_CALLBACK (composer_presend_check_unwanted_html), NULL);
+		G_CALLBACK (composer_presend_check_unwanted_html), session);
 
 	g_signal_connect (
 		composer, "send",
-		G_CALLBACK (em_utils_composer_send_cb), NULL);
+		G_CALLBACK (em_utils_composer_send_cb), session);
 
 	g_signal_connect (
 		composer, "save-to-drafts",
-		G_CALLBACK (em_utils_composer_save_to_drafts_cb), NULL);
+		G_CALLBACK (em_utils_composer_save_to_drafts_cb), session);
 
 	g_signal_connect (
 		composer, "save-to-outbox",
-		G_CALLBACK (em_utils_composer_save_to_outbox_cb), NULL);
+		G_CALLBACK (em_utils_composer_save_to_outbox_cb), session);
 
 	g_signal_connect (
 		composer, "print",
-		G_CALLBACK (em_utils_composer_print_cb), NULL);
+		G_CALLBACK (em_utils_composer_print_cb), session);
 
 	/* Handle "Post To:" button clicks, which displays a folder tree
 	 * widget.  The composer doesn't know about folder tree widgets,
@@ -2849,5 +2868,5 @@ em_configure_new_composer (EMsgComposer *composer)
 	 *       the folder selector dialog.  See the handler function. */
 	g_signal_connect (
 		header, "clicked",
-		G_CALLBACK (post_header_clicked_cb), composer);
+		G_CALLBACK (post_header_clicked_cb), session);
 }
diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h
index 215e6bb..093001d 100644
--- a/mail/em-composer-utils.h
+++ b/mail/em-composer-utils.h
@@ -79,7 +79,8 @@ EMsgComposer *	em_utils_reply_to_message	(EShell *shell,
 						 CamelInternetAddress *address);
 EDestination **	em_utils_camel_address_to_destination
 						(CamelInternetAddress *iaddr);
-void		em_configure_new_composer	(EMsgComposer *composer);
+void		em_configure_new_composer	(EMsgComposer *composer,
+						 EMailSession *session);
 
 G_END_DECLS
 
diff --git a/mail/em-folder-properties.c b/mail/em-folder-properties.c
index 310aa76..9dbffba 100644
--- a/mail/em-folder-properties.c
+++ b/mail/em-folder-properties.c
@@ -34,7 +34,6 @@
 
 #include "e-mail-backend.h"
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "mail-ops.h"
 #include "mail-mt.h"
 #include "mail-vfolder.h"
@@ -249,25 +248,26 @@ emfp_dialog_run (AsyncContext *context)
 	EMConfigTargetFolder *target;
 	EShellWindow *shell_window;
 	EShellView *shell_view;
-	CamelStore *local_store;
 	CamelStore *parent_store;
+	CamelFolderSummary *summary;
+	gboolean store_is_local;
 	gboolean hide_deleted;
 	GSettings *settings;
 	const gchar *name;
+	const gchar *uid;
 
 	shell_view = context->shell_view;
 	shell_window = e_shell_view_get_shell_window (shell_view);
 
-	local_store = e_mail_local_get_store ();
 	parent_store = camel_folder_get_parent_store (context->folder);
 
 	/* Get number of VISIBLE and DELETED messages, instead of TOTAL
 	 * messages.  VISIBLE+DELETED gives the correct count that matches
 	 * the label below the Send & Receive button. */
-	name = camel_folder_get_display_name (context->folder);
-	context->total = camel_folder_summary_get_visible_count (context->folder->summary);
-	context->unread = camel_folder_summary_get_unread_count (context->folder->summary);
-	deleted = camel_folder_summary_get_deleted_count (context->folder->summary);
+	summary = context->folder->summary;
+	context->total = camel_folder_summary_get_visible_count (summary);
+	context->unread = camel_folder_summary_get_unread_count (summary);
+	deleted = camel_folder_summary_get_deleted_count (summary);
 
 	settings = g_settings_new ("org.gnome.evolution.mail");
 	hide_deleted = !g_settings_get_boolean (settings, "show-deleted");
@@ -290,7 +290,12 @@ emfp_dialog_run (AsyncContext *context)
 		context->total = camel_folder_summary_count (
 			context->folder->summary);
 
-	if (parent_store == local_store
+	name = camel_folder_get_display_name (context->folder);
+
+	uid = camel_service_get_uid (CAMEL_SERVICE (parent_store));
+	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+
+	if (store_is_local
 	    && (!strcmp (name, "Drafts")
 		|| !strcmp (name, "Templates")
 		|| !strcmp (name, "Inbox")
@@ -474,7 +479,7 @@ em_folder_properties_show (EShellView *shell_view,
 
 	/* Show the Edit Rule dialog for Search Folders, but not "Unmatched".
 	 * "Unmatched" is a special Search Folder which can't be modified. */
-	if (g_strcmp0 (uid, "vfolder") == 0) {
+	if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0) {
 		if (g_strcmp0 (folder_name, CAMEL_UNMATCHED_NAME) != 0) {
 			gchar *folder_uri;
 
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index 1b8ef6c..1532e42 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -258,6 +258,7 @@ folder_selection_button_clicked (GtkButton *button)
 	EMFolderSelector *selector;
 	EMFolderTree *folder_tree;
 	EMFolderTreeModel *model = NULL;
+	EMailSession *session;
 	GtkWidget *dialog;
 	GtkTreeSelection *selection;
 	gpointer parent;
@@ -267,9 +268,11 @@ folder_selection_button_clicked (GtkButton *button)
 	parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
 	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
 
+	session = e_mail_backend_get_session (priv->backend);
+
 	if (priv->store != NULL) {
 		model = em_folder_tree_model_new ();
-		em_folder_tree_model_set_backend (model, priv->backend);
+		em_folder_tree_model_set_session (model, session);
 		em_folder_tree_model_add_store (model, priv->store);
 	}
 
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index 27fa44a..dea9daa 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -51,8 +51,6 @@
 #include "em-event.h"
 
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
-#include "e-mail-store.h"
 #include "shell/e-shell.h"
 
 #define EM_FOLDER_TREE_MODEL_GET_PRIVATE(obj) \
@@ -67,24 +65,20 @@ struct _EMFolderTreeModelPrivate {
 	 * mimic the sidebar. */
 	GtkTreeSelection *selection;  /* weak reference */
 
-	EAccountList *accounts;
-	EMailBackend *backend;
+	EMailSession *session;
+	EMailAccountStore *account_store;
 
 	/* CamelStore -> EMFolderTreeStoreInfo */
 	GHashTable *store_index;
 
 	/* URI -> GtkTreeRowReference */
 	GHashTable *uri_index;
-
-	gulong account_changed_id;
-	gulong account_removed_id;
-	gulong account_added_id;
 };
 
 enum {
 	PROP_0,
 	PROP_SELECTION,
-	PROP_BACKEND
+	PROP_SESSION
 };
 
 enum {
@@ -123,111 +117,66 @@ folder_tree_model_sort (GtkTreeModel *model,
                         gpointer unused)
 {
 	EMFolderTreeModel *folder_tree_model;
-	EMailBackend *backend;
 	gchar *aname, *bname;
-	CamelStore *store;
-	gboolean is_store;
+	CamelService *service_a;
+	CamelService *service_b;
+	gboolean a_is_store;
+	gboolean b_is_store;
 	const gchar *store_uid = NULL;
-	guint32 aflags, bflags;
-	guint asortorder, bsortorder;
+	guint32 flags_a, flags_b;
 	gint rv = -2;
 
 	folder_tree_model = EM_FOLDER_TREE_MODEL (model);
-	backend = em_folder_tree_model_get_backend (folder_tree_model);
-	g_return_val_if_fail (backend != NULL, -1);
 
 	gtk_tree_model_get (
 		model, a,
-		COL_BOOL_IS_STORE, &is_store,
-		COL_POINTER_CAMEL_STORE, &store,
+		COL_BOOL_IS_STORE, &a_is_store,
+		COL_POINTER_CAMEL_STORE, &service_a,
 		COL_STRING_DISPLAY_NAME, &aname,
-		COL_UINT_FLAGS, &aflags,
-		COL_UINT_SORTORDER, &asortorder,
+		COL_UINT_FLAGS, &flags_a,
 		-1);
 
 	gtk_tree_model_get (
 		model, b,
+		COL_BOOL_IS_STORE, &b_is_store,
+		COL_POINTER_CAMEL_STORE, &service_b,
 		COL_STRING_DISPLAY_NAME, &bname,
-		COL_UINT_FLAGS, &bflags,
-		COL_UINT_SORTORDER, &bsortorder,
+		COL_UINT_FLAGS, &flags_b,
 		-1);
 
-	if (CAMEL_IS_SERVICE (store))
-		store_uid = camel_service_get_uid (CAMEL_SERVICE (store));
+	if (CAMEL_IS_SERVICE (service_a))
+		store_uid = camel_service_get_uid (service_a);
 
-	if (is_store) {
-		EShell *shell;
-		EShellBackend *shell_backend;
-		EShellSettings *shell_settings;
-
-		shell_backend = E_SHELL_BACKEND (backend);
-		shell = e_shell_backend_get_shell (shell_backend);
-		shell_settings = e_shell_get_shell_settings (shell);
-
-		if (e_shell_settings_get_boolean (
-			shell_settings, "mail-sort-accounts-alpha")) {
-			const gchar *on_this_computer = _("On This Computer");
-			const gchar *search_folders = _("Search Folders");
-
-			/* On This Computer is always first, and Search Folders
-			 * is always last. */
-			if (e_shell_get_express_mode (shell)) {
-				if (g_str_equal (aname, on_this_computer) &&
-				    g_str_equal (bname, search_folders))
-					rv = -1;
-				else if (g_str_equal (bname, on_this_computer) &&
-					 g_str_equal (aname, search_folders))
-					rv = 1;
-				else if (g_str_equal (aname, on_this_computer))
-					rv = 1;
-				else if (g_str_equal (bname, on_this_computer))
-					rv = -1;
-				else if (g_str_equal (aname, search_folders))
-					rv = 1;
-				else if (g_str_equal (bname, search_folders))
-					rv = -1;
-			} else {
-				if (g_str_equal (aname, on_this_computer))
-					rv = -1;
-				else if (g_str_equal (bname, on_this_computer))
-					rv = 1;
-				else if (g_str_equal (aname, search_folders))
-					rv = 1;
-				else if (g_str_equal (bname, search_folders))
-					rv = -1;
-			}
-		} else if (asortorder || bsortorder) {
-			if (asortorder < bsortorder)
-				rv = -1;
-			else if (asortorder > bsortorder)
-				rv = 1;
-			else
-				rv = 0;
-		}
-	} else if (g_strcmp0 (store_uid, "vfolder") == 0) {
+	if (a_is_store && b_is_store) {
+		rv = e_mail_account_store_compare_services (
+			folder_tree_model->priv->account_store,
+			service_a, service_b);
+
+	} else if (g_strcmp0 (store_uid, E_MAIL_SESSION_VFOLDER_UID) == 0) {
 		/* UNMATCHED is always last. */
 		if (aname && !strcmp (aname, _("UNMATCHED")))
 			rv = 1;
 		else if (bname && !strcmp (bname, _("UNMATCHED")))
 			rv = -1;
+
 	} else {
 		/* Inbox is always first. */
-		if ((aflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX)
+		if ((flags_a & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX)
 			rv = -1;
-		else if ((bflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX)
+		else if ((flags_b & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX)
 			rv = 1;
 	}
 
-	if (aname == NULL) {
-		if (bname == NULL)
+	if (rv == -2) {
+		if (aname != NULL && bname != NULL)
+			rv = g_utf8_collate (aname, bname);
+		else if (aname == bname)
 			rv = 0;
-		else
+		else if (aname == NULL)
 			rv = -1;
-	} else if (bname == NULL)
-		rv = 1;
-
-	if (rv == -2)
-		rv = g_utf8_collate (aname, bname);
+		else
+			rv = 1;
+	}
 
 	g_free (aname);
 	g_free (bname);
@@ -236,175 +185,44 @@ folder_tree_model_sort (GtkTreeModel *model,
 }
 
 static void
-account_changed_cb (EAccountList *accounts,
-                    EAccount *account,
-                    EMFolderTreeModel *model)
+folder_tree_model_service_removed (EMailAccountStore *account_store,
+                                   CamelService *service,
+                                   EMFolderTreeModel *folder_tree_model)
 {
-	EMailBackend *backend;
-	EMailSession *session;
-	CamelService *service;
-
-	backend = em_folder_tree_model_get_backend (model);
-	session = e_mail_backend_get_session (backend);
-
-	service = camel_session_get_service (
-		CAMEL_SESSION (session), account->uid);
-
-	if (!CAMEL_IS_STORE (service))
-		return;
-
-	em_folder_tree_model_remove_store (model, CAMEL_STORE (service));
-
-	/* check if store needs to be added at all*/
-	if (!account->enabled)
-		return;
-
-	em_folder_tree_model_add_store (model, CAMEL_STORE (service));
+	em_folder_tree_model_remove_store (
+		folder_tree_model, CAMEL_STORE (service));
 }
 
 static void
-account_removed_cb (EAccountList *accounts,
-                    EAccount *account,
-                    EMFolderTreeModel *model)
+folder_tree_model_service_enabled (EMailAccountStore *account_store,
+                                   CamelService *service,
+                                   EMFolderTreeModel *folder_tree_model)
 {
-	EMailBackend *backend;
-	EMailSession *session;
-	CamelService *service;
-
-	backend = em_folder_tree_model_get_backend (model);
-	session = e_mail_backend_get_session (backend);
-
-	service = camel_session_get_service (
-		CAMEL_SESSION (session), account->uid);
-
-	if (!CAMEL_IS_STORE (service))
-		return;
-
-	em_folder_tree_model_remove_store (model, CAMEL_STORE (service));
+	em_folder_tree_model_add_store (
+		folder_tree_model, CAMEL_STORE (service));
 }
 
-/* HACK: FIXME: the component should listen to the account object directly */
 static void
-account_added_cb (EAccountList *accounts,
-                  EAccount *account,
-                  EMFolderTreeModel *model)
+folder_tree_model_service_disabled (EMailAccountStore *account_store,
+                                    CamelService *service,
+                                    EMFolderTreeModel *folder_tree_model)
 {
-	EMailBackend *backend;
-	EMailSession *session;
-
-	backend = em_folder_tree_model_get_backend (model);
-	session = e_mail_backend_get_session (backend);
-
-	e_mail_store_add_by_account (session, account);
+	em_folder_tree_model_remove_store (
+		folder_tree_model, CAMEL_STORE (service));
 }
 
 static void
-folder_tree_model_sort_changed (EMFolderTreeModel *tree_model)
+folder_tree_model_services_reordered (EMailAccountStore *account_store,
+                                      gboolean default_restored,
+                                      EMFolderTreeModel *folder_tree_model)
 {
-	GtkTreeModel *model;
-
-	g_return_if_fail (tree_model != NULL);
-	g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (tree_model));
-
-	model = GTK_TREE_MODEL (tree_model);
-	if (!model)
-		return;
-
-	/* this invokes also sort on a GtkTreeStore */
+	/* This forces the tree store to re-sort. */
 	gtk_tree_sortable_set_default_sort_func (
-		GTK_TREE_SORTABLE (model),
+		GTK_TREE_SORTABLE (folder_tree_model),
 		folder_tree_model_sort, NULL, NULL);
 }
 
 static void
-account_sort_order_changed_cb (EMFolderTreeModel *folder_tree_model)
-{
-	EMailBackend *mail_backend;
-	GtkTreeModel *model;
-	GtkTreeStore *tree_store;
-	GtkTreeIter iter;
-
-	g_return_if_fail (folder_tree_model != NULL);
-
-	model = GTK_TREE_MODEL (folder_tree_model);
-	g_return_if_fail (model != NULL);
-
-	tree_store = GTK_TREE_STORE (folder_tree_model);
-	g_return_if_fail (tree_store != NULL);
-
-	if (!gtk_tree_model_get_iter_first (model, &iter))
-		return;
-
-	mail_backend = em_folder_tree_model_get_backend (folder_tree_model);
-
-	do {
-		CamelStore *store = NULL;
-
-		gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, -1);
-
-		if (store) {
-			const gchar *account_uid;
-			guint sortorder;
-
-			account_uid = camel_service_get_uid (CAMEL_SERVICE (store));
-			sortorder = em_utils_get_account_sort_order (mail_backend, account_uid);
-
-			gtk_tree_store_set (tree_store, &iter, COL_UINT_SORTORDER, sortorder, -1);
-		}
-	} while (gtk_tree_model_iter_next (model, &iter));
-
-	folder_tree_model_sort_changed (folder_tree_model);
-}
-
-static void
-add_remove_special_folder (EMFolderTreeModel *model,
-                           const gchar *account_uid,
-                           gboolean add)
-{
-	EMailBackend *backend;
-	EMailSession *session;
-	CamelService *service;
-
-	backend = em_folder_tree_model_get_backend (model);
-	session = e_mail_backend_get_session (backend);
-
-	service = camel_session_get_service (
-		CAMEL_SESSION (session), account_uid);
-
-	if (!CAMEL_IS_STORE (service))
-		return;
-
-	if (add)
-		em_folder_tree_model_add_store (model, CAMEL_STORE (service));
-	else
-		em_folder_tree_model_remove_store (model, CAMEL_STORE (service));
-}
-
-static void
-enable_local_folders_changed_cb (EMFolderTreeModel *model,
-                                 GParamSpec *spec,
-                                 EShellSettings *shell_settings)
-{
-	g_return_if_fail (model != NULL);
-	g_return_if_fail (shell_settings != NULL);
-
-	add_remove_special_folder (model, "local",
-		e_shell_settings_get_boolean (shell_settings, "mail-enable-local-folders"));
-}
-
-static void
-enable_search_folders_changed_cb (EMFolderTreeModel *model,
-                                  GParamSpec *spec,
-                                  EShellSettings *shell_settings)
-{
-	g_return_if_fail (model != NULL);
-	g_return_if_fail (shell_settings != NULL);
-
-	add_remove_special_folder (model, "vfolder",
-		e_shell_settings_get_boolean (shell_settings, "mail-enable-search-folders"));
-}
-
-static void
 folder_tree_model_selection_finalized_cb (EMFolderTreeModel *model)
 {
 	model->priv->selection = NULL;
@@ -425,8 +243,8 @@ folder_tree_model_set_property (GObject *object,
 				g_value_get_object (value));
 			return;
 
-		case PROP_BACKEND:
-			em_folder_tree_model_set_backend (
+		case PROP_SESSION:
+			em_folder_tree_model_set_session (
 				EM_FOLDER_TREE_MODEL (object),
 				g_value_get_object (value));
 			return;
@@ -449,10 +267,10 @@ folder_tree_model_get_property (GObject *object,
 				EM_FOLDER_TREE_MODEL (object)));
 			return;
 
-		case PROP_BACKEND:
+		case PROP_SESSION:
 			g_value_set_object (
 				value,
-				em_folder_tree_model_get_backend (
+				em_folder_tree_model_get_session (
 				EM_FOLDER_TREE_MODEL (object)));
 			return;
 	}
@@ -474,26 +292,17 @@ folder_tree_model_dispose (GObject *object)
 		priv->selection = NULL;
 	}
 
-	if (priv->backend != NULL) {
-		EShell *shell;
-		EShellBackend *shell_backend;
-		EShellSettings *shell_settings;
-
-		shell_backend = E_SHELL_BACKEND (priv->backend);
-		shell = e_shell_backend_get_shell (shell_backend);
-		shell_settings = e_shell_get_shell_settings (shell);
-
-		g_signal_handlers_disconnect_by_func (
-			priv->backend, account_sort_order_changed_cb, object);
-		g_signal_handlers_disconnect_by_func (
-			shell_settings, account_sort_order_changed_cb, object);
-		g_signal_handlers_disconnect_by_func (
-			shell_settings, enable_local_folders_changed_cb, object);
-		g_signal_handlers_disconnect_by_func (
-			shell_settings, enable_search_folders_changed_cb, object);
-
-		g_object_unref (priv->backend);
-		priv->backend = NULL;
+	if (priv->session != NULL) {
+		g_object_unref (priv->session);
+		priv->session = NULL;
+	}
+
+	if (priv->account_store != NULL) {
+		g_signal_handlers_disconnect_matched (
+			priv->account_store, G_SIGNAL_MATCH_DATA,
+			0, 0, NULL, NULL, object);
+		g_object_unref (priv->account_store);
+		priv->account_store = NULL;
 	}
 
 	/* Chain up to parent's dispose() method. */
@@ -510,13 +319,6 @@ folder_tree_model_finalize (GObject *object)
 	g_hash_table_destroy (priv->store_index);
 	g_hash_table_destroy (priv->uri_index);
 
-	g_signal_handler_disconnect (
-		priv->accounts, priv->account_changed_id);
-	g_signal_handler_disconnect (
-		priv->accounts, priv->account_removed_id);
-	g_signal_handler_disconnect (
-		priv->accounts, priv->account_added_id);
-
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -524,8 +326,6 @@ folder_tree_model_finalize (GObject *object)
 static void
 folder_tree_model_constructed (GObject *object)
 {
-	EMFolderTreeModelPrivate *priv;
-
 	GType col_types[] = {
 		G_TYPE_STRING,   /* display name */
 		G_TYPE_POINTER,  /* store object */
@@ -542,8 +342,6 @@ folder_tree_model_constructed (GObject *object)
 		G_TYPE_UINT	 /* user's sortorder */
 	};
 
-	priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (object);
-
 	gtk_tree_store_set_column_types (
 		GTK_TREE_STORE (object), NUM_COLUMNS, col_types);
 	gtk_tree_sortable_set_default_sort_func (
@@ -554,17 +352,6 @@ folder_tree_model_constructed (GObject *object)
 		GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
 		GTK_SORT_ASCENDING);
 
-	priv->accounts = e_get_account_list ();
-	priv->account_changed_id = g_signal_connect (
-		priv->accounts, "account-changed",
-		G_CALLBACK (account_changed_cb), object);
-	priv->account_removed_id = g_signal_connect (
-		priv->accounts, "account-removed",
-		G_CALLBACK (account_removed_cb), object);
-	priv->account_added_id = g_signal_connect (
-		priv->accounts, "account-added",
-		G_CALLBACK (account_added_cb), object);
-
 	/* Chain up to parent's constructed() method. */
 	G_OBJECT_CLASS (parent_class)->constructed (object);
 }
@@ -586,12 +373,12 @@ em_folder_tree_model_class_init (EMFolderTreeModelClass *class)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_BACKEND,
+		PROP_SESSION,
 		g_param_spec_object (
-			"backend",
+			"session",
 			NULL,
 			NULL,
-			E_TYPE_MAIL_BACKEND,
+			E_TYPE_MAIL_SESSION,
 			G_PARAM_READWRITE));
 
 	g_object_class_install_property (
@@ -754,60 +541,63 @@ em_folder_tree_model_set_selection (EMFolderTreeModel *model,
 	g_object_notify (G_OBJECT (model), "selection");
 }
 
-EMailBackend *
-em_folder_tree_model_get_backend (EMFolderTreeModel *model)
+EMailSession *
+em_folder_tree_model_get_session (EMFolderTreeModel *model)
 {
 	g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL);
 
-	return model->priv->backend;
+	return model->priv->session;
 }
 
 void
-em_folder_tree_model_set_backend (EMFolderTreeModel *model,
-                                  EMailBackend *backend)
+em_folder_tree_model_set_session (EMFolderTreeModel *model,
+                                  EMailSession *session)
 {
 	g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
 
-	if (backend != NULL) {
-		g_return_if_fail (E_IS_MAIL_BACKEND (backend));
-		g_object_ref (backend);
+	if (session != NULL) {
+		g_return_if_fail (E_IS_MAIL_SESSION (session));
+		g_object_ref (session);
 	}
 
-	if (model->priv->backend != NULL)
-		g_object_unref (model->priv->backend);
+	if (model->priv->session != NULL)
+		g_object_unref (model->priv->session);
 
-	model->priv->backend = backend;
+	model->priv->session = session;
 
 	/* FIXME Technically we should be disconnecting this signal
-	 *       when replacing an old backend with a new backend,
+	 *       when replacing an old session with a new session,
 	 *       but at present this function is only called once. */
-	if (backend != NULL) {
+	if (session != NULL) {
+		EMailAccountStore *account_store;
 		MailFolderCache *folder_cache;
-		EMailSession *session;
-		EShell *shell;
-		EShellBackend *shell_backend;
-		EShellSettings *shell_settings;
-
-		shell_backend = E_SHELL_BACKEND (backend);
-		shell = e_shell_backend_get_shell (shell_backend);
-		shell_settings = e_shell_get_shell_settings (shell);
 
-		session = e_mail_backend_get_session (backend);
 		folder_cache = e_mail_session_get_folder_cache (session);
+		account_store = e_mail_session_get_account_store (session);
 
-		g_signal_connect_swapped (
-			backend, "account-sort-order-changed",
-			G_CALLBACK (account_sort_order_changed_cb), model);
+		/* Keep our own reference since we connect to its signals. */
+		g_warn_if_fail (model->priv->account_store == NULL);
+		model->priv->account_store = g_object_ref (account_store);
 
-		g_signal_connect_swapped (
-			shell_settings, "notify::mail-sort-accounts-alpha",
-			G_CALLBACK (account_sort_order_changed_cb), model);
-		g_signal_connect_swapped (
-			shell_settings, "notify::mail-enable-local-folders",
-			G_CALLBACK (enable_local_folders_changed_cb), model);
-		g_signal_connect_swapped (
-			shell_settings, "notify::mail-enable-search-folders",
-			G_CALLBACK (enable_search_folders_changed_cb), model);
+		g_signal_connect (
+			account_store, "service-removed",
+			G_CALLBACK (folder_tree_model_service_removed),
+			model);
+
+		g_signal_connect (
+			account_store, "service-enabled",
+			G_CALLBACK (folder_tree_model_service_enabled),
+			model);
+
+		g_signal_connect (
+			account_store, "service-disabled",
+			G_CALLBACK (folder_tree_model_service_disabled),
+			model);
+
+		g_signal_connect (
+			account_store, "services-reordered",
+			G_CALLBACK (folder_tree_model_services_reordered),
+			model);
 
 		g_signal_connect_swapped (
 			folder_cache, "folder-unread-updated",
@@ -815,7 +605,7 @@ em_folder_tree_model_set_backend (EMFolderTreeModel *model,
 			model);
 	}
 
-	g_object_notify (G_OBJECT (model), "backend");
+	g_object_notify (G_OBJECT (model), "session");
 }
 
 void
@@ -828,7 +618,6 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 	GtkTreeRowReference *uri_row, *path_row;
 	GtkTreeStore *tree_store;
 	MailFolderCache *folder_cache;
-	EMailBackend *backend;
 	EMailSession *session;
 	EAccount *account;
 	guint unread;
@@ -845,6 +634,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 	gboolean folder_is_drafts = FALSE;
 	gboolean folder_is_outbox = FALSE;
 	gboolean folder_is_templates = FALSE;
+	gboolean store_is_local;
 	gchar *uri;
 
 	/* Make sure we don't already know about it. */
@@ -853,11 +643,11 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 
 	tree_store = GTK_TREE_STORE (model);
 
-	backend = em_folder_tree_model_get_backend (model);
-	session = e_mail_backend_get_session (backend);
+	session = em_folder_tree_model_get_session (model);
 	folder_cache = e_mail_session_get_folder_cache (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)
@@ -907,7 +697,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 	flags = fi->flags;
 	display_name = fi->display_name;
 
-	if (si->store == e_mail_local_get_store ()) {
+	if (store_is_local) {
 		if (strcmp (fi->full_name, "Drafts") == 0) {
 			folder_is_drafts = TRUE;
 			display_name = _("Drafts");
@@ -1202,7 +992,6 @@ void
 em_folder_tree_model_add_store (EMFolderTreeModel *model,
                                 CamelStore *store)
 {
-	EMailBackend *mail_backend;
 	EMFolderTreeModelStoreInfo *si;
 	GtkTreeRowReference *reference;
 	GtkTreeStore *tree_store;
@@ -1212,7 +1001,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
 	CamelProvider *provider;
 	CamelURL *service_url;
 	const gchar *display_name;
-	const gchar *account_uid;
 	gchar *uri;
 
 	g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
@@ -1223,7 +1011,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
 	service = CAMEL_SERVICE (store);
 	provider = camel_service_get_provider (service);
 	display_name = camel_service_get_display_name (service);
-	account_uid = camel_service_get_uid (service);
 
 	/* Ignore stores that should not be added to the tree model. */
 
@@ -1245,8 +1032,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
 	if (si != NULL)
 		em_folder_tree_model_remove_store (model, store);
 
-	mail_backend = em_folder_tree_model_get_backend (model);
-
 	/* Add the store to the tree. */
 	gtk_tree_store_append (tree_store, &iter, NULL);
 	gtk_tree_store_set (
@@ -1257,7 +1042,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
 		COL_BOOL_LOAD_SUBDIRS, TRUE,
 		COL_BOOL_IS_STORE, TRUE,
 		COL_STRING_URI, uri,
-		COL_UINT_SORTORDER, em_utils_get_account_sort_order (mail_backend, account_uid),
 		-1);
 
 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
index 0ed007a..1bf5483 100644
--- a/mail/em-folder-tree-model.h
+++ b/mail/em-folder-tree-model.h
@@ -26,7 +26,6 @@
 #include <gtk/gtk.h>
 #include <camel/camel.h>
 
-#include <mail/e-mail-backend.h>
 #include <mail/e-mail-session.h>
 
 /* Standard GObject macros */
@@ -73,7 +72,6 @@ enum {
 					 * been added to the tree */
 	COL_UINT_UNREAD_LAST_SEL,	/* last known unread count */
 	COL_BOOL_IS_DRAFT,		/* %TRUE for a draft folder */
-	COL_UINT_SORTORDER,		/* user sort-order for the node */
 	NUM_COLUMNS
 };
 
@@ -120,11 +118,11 @@ GtkTreeSelection *
 void		em_folder_tree_model_set_selection
 					(EMFolderTreeModel *model,
 					 GtkTreeSelection *selection);
-EMailBackend *	em_folder_tree_model_get_backend
+EMailSession *	em_folder_tree_model_get_session
 					(EMFolderTreeModel *model);
-void		em_folder_tree_model_set_backend
+void		em_folder_tree_model_set_session
 					(EMFolderTreeModel *model,
-					 EMailBackend *backend);
+					 EMailSession *session);
 void		em_folder_tree_model_set_folder_info
 					(EMFolderTreeModel *model,
 					 GtkTreeIter *iter,
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 48cf6af..5ef1845 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -62,9 +62,7 @@
 #include "em-event.h"
 
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
-#include "e-mail-store.h"
 
 #define d(x)
 
@@ -720,15 +718,17 @@ folder_tree_render_display_name (GtkTreeViewColumn *column,
                                  GtkTreeModel *model,
                                  GtkTreeIter *iter)
 {
+	CamelService *service;
 	PangoWeight weight;
 	gboolean is_store, bold, subdirs_unread = FALSE;
 	gboolean editable;
 	guint unread;
-	gchar *display;
 	gchar *name;
 
 	gtk_tree_model_get (
-		model, iter, COL_STRING_DISPLAY_NAME, &name,
+		model, iter,
+		COL_STRING_DISPLAY_NAME, &name,
+		COL_POINTER_CAMEL_STORE, &service,
 		COL_BOOL_IS_STORE, &is_store,
 		COL_UINT_UNREAD, &unread, -1);
 
@@ -747,8 +747,17 @@ folder_tree_render_display_name (GtkTreeViewColumn *column,
 
 	bold = !editable && (bold || subdirs_unread);
 	weight = bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
+	g_object_set (renderer, "weight", weight, NULL);
+
+	if (is_store) {
+		const gchar *display_name;
+
+		display_name = camel_service_get_display_name (service);
+		g_object_set (renderer, "text", display_name, NULL);
+
+	} else if (!editable && unread > 0) {
+		gchar *name_and_unread;
 
-	if (!is_store && !editable && unread) {
 		/* Translators: This is the string used for displaying the
 		 * folder names in folder trees. The first "%s" will be
 		 * replaced by the folder's name and "%u" will be replaced
@@ -767,16 +776,17 @@ folder_tree_render_display_name (GtkTreeViewColumn *column,
 		 * Do not translate the "folder-display|" part. Remove it
 		 * from your translation.
 		 */
-		display = g_strdup_printf (
+		name_and_unread = g_strdup_printf (
 			C_("folder-display", "%s (%u%s)"),
 			name, unread, subdirs_unread ? "+" : "");
-		g_free (name);
-	} else
-		display = name;
+		g_object_set (renderer, "text", name_and_unread, NULL);
+		g_free (name_and_unread);
 
-	g_object_set (renderer, "text", display, "weight", weight, NULL);
+	} else {
+		g_object_set (renderer, "text", name, NULL);
+	}
 
-	g_free (display);
+	g_free (name);
 }
 
 static void
@@ -1783,18 +1793,10 @@ em_folder_tree_new_with_model (EMailBackend *backend,
                                EAlertSink *alert_sink,
                                EMFolderTreeModel *model)
 {
-	EMailSession *session;
-	const gchar *data_dir;
-
 	g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
 	g_return_val_if_fail (E_IS_ALERT_SINK (alert_sink), NULL);
 	g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL);
 
-	session = e_mail_backend_get_session (backend);
-	data_dir = e_shell_backend_get_data_dir (E_SHELL_BACKEND (backend));
-
-	e_mail_store_init (session, data_dir);
-
 	return g_object_new (
 		EM_TYPE_FOLDER_TREE,
 		"alert-sink", alert_sink,
@@ -2283,7 +2285,6 @@ folder_tree_drop_target (EMFolderTree *folder_tree,
 	EMFolderTreePrivate *p = folder_tree->priv;
 	gchar *dst_full_name = NULL;
 	gchar *src_full_name = NULL;
-	CamelStore *local;
 	CamelStore *dst_store;
 	CamelStore *src_store = NULL;
 	GdkAtom atom = GDK_NONE;
@@ -2292,6 +2293,7 @@ folder_tree_drop_target (EMFolderTree *folder_tree,
 	GtkTreeIter iter;
 	GList *targets;
 	const gchar *uid;
+	gboolean src_is_local;
 	gboolean src_is_vfolder;
 	gboolean dst_is_vfolder;
 	guint32 flags = 0;
@@ -2314,10 +2316,8 @@ folder_tree_drop_target (EMFolderTree *folder_tree,
 		COL_STRING_FULL_NAME, &dst_full_name,
 		COL_UINT_FLAGS, &flags, -1);
 
-	local = e_mail_local_get_store ();
-
 	uid = camel_service_get_uid (CAMEL_SERVICE (dst_store));
-	dst_is_vfolder = (g_strcmp0 (uid, "vfolder") == 0);
+	dst_is_vfolder = (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0);
 
 	targets = gdk_drag_context_list_targets (context);
 
@@ -2392,13 +2392,17 @@ folder_tree_drop_target (EMFolderTree *folder_tree,
 	if (src_store != NULL && src_full_name != NULL) {
 
 		uid = camel_service_get_uid (CAMEL_SERVICE (src_store));
-		src_is_vfolder = (g_strcmp0 (uid, "vfolder") == 0);
+
+		src_is_local =
+			(g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+		src_is_vfolder =
+			(g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0);
 
 		/* FIXME: this is a total hack, but i think all we can do at present */
 		/* Check for dragging from special folders which can't be moved/copied */
 
 		/* Don't allow moving any of the the special local folders. */
-		if (src_store == local && is_special_local_folder (src_full_name)) {
+		if (src_is_local && is_special_local_folder (src_full_name)) {
 			GdkAtom xfolder;
 
 			/* force copy for special local folders */
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index e72b801..2ac87d7 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -59,9 +59,7 @@
 #include "em-folder-properties.h"
 
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
-#include "e-mail-store.h"
 #include "e-mail-store-utils.h"
 
 #define d(x)
@@ -339,15 +337,15 @@ emfu_copy_folder_selected (EMailBackend *backend,
 	EMailSession *session;
 	struct _copy_folder_data *cfd = data;
 	CamelStore *tostore = NULL;
-	CamelStore *local_store;
 	CamelService *service;
+	gboolean store_is_local;
+	const gchar *uid;
 	gchar *tobase = NULL;
 	GError *local_error = NULL;
 
 	if (uri == NULL)
 		goto fail;
 
-	local_store = e_mail_local_get_store ();
 	session = e_mail_backend_get_session (backend);
 
 	service = CAMEL_SERVICE (cfd->source_store);
@@ -365,7 +363,10 @@ emfu_copy_folder_selected (EMailBackend *backend,
 
 	g_return_if_fail (CAMEL_IS_STORE (service));
 
-	if (cfd->delete && cfd->source_store == local_store &&
+	uid = camel_service_get_uid (CAMEL_SERVICE (cfd->source_store));
+	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+
+	if (cfd->delete && store_is_local &&
 		emfu_is_special_local_folder (cfd->source_folder_name)) {
 		e_mail_backend_submit_alert (
 			backend, "mail:no-rename-special-folder",
@@ -426,7 +427,7 @@ emfu_copy_folder_exclude (EMFolderTree *tree,
 	/* handles moving to/from vfolders */
 
 	uid = camel_service_get_uid (CAMEL_SERVICE (cfd->source_store));
-	fromvfolder = (g_strcmp0 (uid, "vfolder") == 0);
+	fromvfolder = (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0);
 
 	gtk_tree_model_get (
 		model, iter,
@@ -434,7 +435,7 @@ emfu_copy_folder_exclude (EMFolderTree *tree,
 		COL_POINTER_CAMEL_STORE, &store, -1);
 
 	uid = camel_service_get_uid (CAMEL_SERVICE (store));
-	tovfolder = (g_strcmp0 (uid, "vfolder") == 0);
+	tovfolder = (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0);
 
 	/* moving from vfolder to normal- not allowed */
 	if (fromvfolder && !tovfolder && cfd->delete)
@@ -566,9 +567,9 @@ em_folder_utils_create_folder (GtkWindow *parent,
 	shell_settings = e_shell_get_shell_settings (shell);
 
 	model = em_folder_tree_model_new ();
-	em_folder_tree_model_set_backend (model, backend);
-
 	session = e_mail_backend_get_session (backend);
+	em_folder_tree_model_set_session (model, session);
+
 	list = camel_session_list_services (CAMEL_SESSION (session));
 
 	for (link = list; link != NULL; link = g_list_next (link)) {
@@ -587,9 +588,9 @@ em_folder_utils_create_folder (GtkWindow *parent,
 			continue;
 
 		uid = camel_service_get_uid (service);
-		if (g_strcmp0 (uid, "local") == 0)
+		if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0)
 			prop = "mail-enable-local-folders";
-		else if (g_strcmp0 (uid, "vfolder") == 0)
+		else if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0)
 			prop = "mail-enable-search-folders";
 
 		if (prop && !e_shell_settings_get_boolean (shell_settings, prop))
diff --git a/mail/em-utils.c b/mail/em-utils.c
index c15f8b6..bfda405 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -71,7 +71,6 @@
 #include "em-composer-utils.h"
 #include "em-format-quote.h"
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 
 /* XXX This is a dirty hack on a dirty hack.  We really need
@@ -84,8 +83,6 @@ extern const gchar *shell_builtin_backend;
 
 #define d(x)
 
-static void free_account_sort_order_cache (void);
-
 gboolean
 em_utils_ask_open_many (GtkWindow *parent,
                         gint how_many)
@@ -998,17 +995,18 @@ em_utils_folder_is_templates (CamelFolder *folder)
 
 	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 =
-		e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
+		e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_TEMPLATES);
 
 	if (folder == local_templates_folder)
 		return TRUE;
 
 	folder_uri = e_mail_folder_uri_from_folder (folder);
 
-	store = camel_folder_get_parent_store (folder);
-	session = camel_service_get_session (CAMEL_SERVICE (store));
-
 	account_list = e_get_account_list ();
 	iterator = e_list_get_iterator (E_LIST (account_list));
 
@@ -1053,17 +1051,18 @@ em_utils_folder_is_drafts (CamelFolder *folder)
 
 	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_drafts_folder =
-		e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_DRAFTS);
+		e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS);
 
 	if (folder == local_drafts_folder)
 		return TRUE;
 
 	folder_uri = e_mail_folder_uri_from_folder (folder);
 
-	store = camel_folder_get_parent_store (folder);
-	session = camel_service_get_session (CAMEL_SERVICE (store));
-
 	account_list = e_get_account_list ();
 	iterator = e_list_get_iterator (E_LIST (account_list));
 
@@ -1108,17 +1107,18 @@ em_utils_folder_is_sent (CamelFolder *folder)
 
 	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_sent_folder =
-		e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);
+		e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_SENT);
 
 	if (folder == local_sent_folder)
 		return TRUE;
 
 	folder_uri = e_mail_folder_uri_from_folder (folder);
 
-	store = camel_folder_get_parent_store (folder);
-	session = camel_service_get_session (CAMEL_SERVICE (store));
-
 	account_list = e_get_account_list ();
 	iterator = e_list_get_iterator (E_LIST (account_list));
 
@@ -1153,12 +1153,18 @@ em_utils_folder_is_sent (CamelFolder *folder)
 gboolean
 em_utils_folder_is_outbox (CamelFolder *folder)
 {
+	CamelStore *store;
+	CamelSession *session;
 	CamelFolder *local_outbox_folder;
 
 	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_outbox_folder =
-		e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+		e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_OUTBOX);
 
 	return (folder == local_outbox_folder);
 }
@@ -1911,8 +1917,6 @@ emu_free_mail_cache (void)
 	photos_cache = NULL;
 
 	G_UNLOCK (photos_cache);
-
-	free_account_sort_order_cache ();
 }
 
 void
@@ -2269,169 +2273,3 @@ em_utils_disconnect_service_sync (CamelService *service,
 	return res;
 }
 
-G_LOCK_DEFINE_STATIC (accounts_sort_order_cache);
-static GHashTable *accounts_sort_order_cache = NULL; /* account_uid string to sort order uint */
-
-static void
-free_account_sort_order_cache (void)
-{
-	G_LOCK (accounts_sort_order_cache);
-
-	if (accounts_sort_order_cache) {
-		g_hash_table_destroy (accounts_sort_order_cache);
-		accounts_sort_order_cache = NULL;
-	}
-
-	G_UNLOCK (accounts_sort_order_cache);
-}
-
-static void
-fill_accounts_sort_order_cache (EMailBackend *backend,
-                                gboolean force_reload)
-{
-	GSList *account_uids;
-
-	G_LOCK (accounts_sort_order_cache);
-
-	if (!force_reload && accounts_sort_order_cache) {
-		G_UNLOCK (accounts_sort_order_cache);
-		return;
-	}
-
-	if (!accounts_sort_order_cache)
-		accounts_sort_order_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-	else
-		g_hash_table_remove_all (accounts_sort_order_cache);
-
-	account_uids = em_utils_load_accounts_sort_order (backend);
-	if (account_uids) {
-		GSList *iter;
-		guint index;
-
-		for (index = 1, iter = account_uids; iter; index++, iter = iter->next) {
-			if (iter->data)
-				g_hash_table_insert (accounts_sort_order_cache, iter->data, GUINT_TO_POINTER (index));
-		}
-
-		/* items are stolen into the cache */
-		/* g_slist_foreach (account_uids, (GFunc) g_free, NULL); */
-		g_slist_free (account_uids);
-	}
-
-	G_UNLOCK (accounts_sort_order_cache);
-}
-
-static gchar *
-emu_get_sort_order_filename (EMailBackend *backend)
-{
-	g_return_val_if_fail (backend != NULL, NULL);
-
-	return g_build_filename (
-		e_shell_backend_get_config_dir (E_SHELL_BACKEND (backend)),
-		"sortorder.ini", NULL);
-}
-
-static GKeyFile *
-emu_get_sort_order_key_file (EMailBackend *backend)
-{
-	gchar *filename;
-	GKeyFile *key_file;
-
-	g_return_val_if_fail (backend != NULL, NULL);
-
-	filename = emu_get_sort_order_filename (backend);
-	g_return_val_if_fail (filename != NULL, NULL);
-
-	key_file = g_key_file_new ();
-	g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, NULL);
-
-	g_free (filename);
-
-	return key_file;
-}
-
-void
-em_utils_save_accounts_sort_order (EMailBackend *backend,
-                                   const GSList *account_uids)
-{
-	gchar *filename;
-	GKeyFile *key_file;
-	gint ii;
-	gchar key[32];
-	gchar *content;
-	gsize length = 0;
-
-	key_file = emu_get_sort_order_key_file (backend);
-	g_return_if_fail (key_file != NULL);
-
-	filename = emu_get_sort_order_filename (backend);
-	g_return_if_fail (filename != NULL);
-
-	g_key_file_remove_group (key_file, "accounts", NULL);
-
-	for (ii = 0; account_uids; ii++, account_uids = account_uids->next) {
-		sprintf (key, "%d", ii);
-
-		g_key_file_set_string (key_file, "accounts", key, account_uids->data);
-	}
-
-	content = g_key_file_to_data (key_file, &length, NULL);
-	if (content)
-		g_file_set_contents (filename, content, length, NULL);
-
-	g_free (content);
-	g_free (filename);
-	g_key_file_free (key_file);
-
-	fill_accounts_sort_order_cache (backend, TRUE);
-	e_mail_backend_account_sort_order_changed (backend);
-}
-
-GSList *
-em_utils_load_accounts_sort_order (EMailBackend *backend)
-{
-	GKeyFile *key_file;
-	GSList *account_uids = NULL;
-	gchar key[32];
-	gchar *value;
-	gint ii;
-
-	key_file = emu_get_sort_order_key_file (backend);
-	g_return_val_if_fail (key_file != NULL, NULL);
-
-	ii = 0;
-	do {
-		sprintf (key, "%d", ii);
-		ii++;
-
-		value = g_key_file_get_string (key_file, "accounts", key, NULL);
-		if (!value)
-			break;
-
-		account_uids = g_slist_prepend (account_uids, value);
-	} while (*key);
-
-	g_key_file_free (key_file);
-
-	return g_slist_reverse (account_uids);
-}
-
-guint
-em_utils_get_account_sort_order (EMailBackend *backend,
-                                 const gchar *account_uid)
-{
-	guint res;
-
-	g_return_val_if_fail (backend != NULL, 0);
-	g_return_val_if_fail (account_uid != NULL, 0);
-
-	fill_accounts_sort_order_cache (backend, FALSE);
-
-	G_LOCK (accounts_sort_order_cache);
-
-	res = GPOINTER_TO_UINT (g_hash_table_lookup (accounts_sort_order_cache, account_uid));
-
-	G_UNLOCK (accounts_sort_order_cache);
-
-	return res;
-}
diff --git a/mail/em-utils.h b/mail/em-utils.h
index b7e3ec6..0a27266 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -98,10 +98,6 @@ gboolean em_utils_is_local_delivery_mbox_file (CamelURL *url);
 gboolean em_utils_connect_service_sync (CamelService *service, GCancellable *cancellable, GError **error);
 gboolean em_utils_disconnect_service_sync (CamelService *service, gboolean clean, GCancellable *cancellable, GError **error);
 
-void	em_utils_save_accounts_sort_order (EMailBackend *backend, const GSList *account_uids);
-GSList *em_utils_load_accounts_sort_order (EMailBackend *backend);
-guint	em_utils_get_account_sort_order   (EMailBackend *backend, const gchar *account_uid);
-
 G_END_DECLS
 
 #endif /* __EM_UTILS_H__ */
diff --git a/mail/em-vfolder-rule.c b/mail/em-vfolder-rule.c
index 8310599..3f0c220 100644
--- a/mail/em-vfolder-rule.c
+++ b/mail/em-vfolder-rule.c
@@ -33,7 +33,6 @@
 #include "em-vfolder-context.h"
 #include "em-vfolder-rule.h"
 #include "mail/e-mail-folder-utils.h"
-#include "mail/e-mail-store.h"
 #include "mail/em-utils.h"
 #include "mail/em-folder-tree.h"
 #include "mail/em-folder-selector.h"
diff --git a/mail/importers/evolution-mbox-importer.c b/mail/importers/evolution-mbox-importer.c
index 3c97bd9..b158d60 100644
--- a/mail/importers/evolution-mbox-importer.c
+++ b/mail/importers/evolution-mbox-importer.c
@@ -45,8 +45,6 @@
 #include "shell/e-shell-sidebar.h"
 
 #include "mail/e-mail-backend.h"
-#include "mail/e-mail-local.h"
-#include "mail/e-mail-store.h"
 #include "mail/em-folder-selection-button.h"
 #include "mail/em-folder-tree-model.h"
 #include "mail/em-folder-tree.h"
@@ -85,6 +83,8 @@ mbox_getwidget (EImport *ei,
 {
 	EShell *shell;
 	EShellBackend *shell_backend;
+	EMailBackend *backend;
+	EMailSession *session;
 	GtkWindow *window;
 	GtkWidget *hbox, *w;
 	GtkLabel *label;
@@ -96,6 +96,9 @@ mbox_getwidget (EImport *ei,
 	shell = e_shell_get_default ();
 	shell_backend = e_shell_get_backend_by_name (shell, "mail");
 
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
+
 	/* preselect the folder selected in a mail view */
 	window = e_shell_get_active_window (shell);
 	if (E_IS_SHELL_WINDOW (window)) {
@@ -129,7 +132,8 @@ mbox_getwidget (EImport *ei,
 
 	if (!select_uri) {
 		const gchar *uri;
-		uri = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_INBOX);
+		uri = e_mail_session_get_local_folder_uri (
+			session, E_MAIL_LOCAL_FOLDER_INBOX);
 		select_uri = g_strdup (uri);
 	}
 
diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c
index e28de37..558359c 100644
--- a/mail/importers/mail-importer.c
+++ b/mail/importers/mail-importer.c
@@ -41,7 +41,6 @@
 
 #include "mail-mt.h"
 #include "mail-tools.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 
 #include "mail-importer.h"
@@ -124,7 +123,8 @@ import_mbox_exec (struct _import_mbox_msg *m,
 	}
 
 	if (m->uri == NULL || m->uri[0] == 0)
-		folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX);
+		folder = e_mail_session_get_local_folder (
+			m->session, E_MAIL_LOCAL_FOLDER_INBOX);
 	else
 		folder = e_mail_session_uri_to_folder_sync (
 			m->session, m->uri, CAMEL_STORE_FOLDER_CREATE,
diff --git a/mail/mail-config.c b/mail/mail-config.c
index bbad256..883612b 100644
--- a/mail/mail-config.c
+++ b/mail/mail-config.c
@@ -34,7 +34,6 @@
 #include "e-util/e-account-utils.h"
 #include "e-util/e-signature-utils.h"
 
-#include "e-mail-local.h"
 #include "e-mail-folder-utils.h"
 #include "mail-config.h"
 #include "mail-tools.h"
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index cab15c5..d9e3bef 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -49,7 +49,6 @@
 
 #include "em-utils.h"
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 #include "e-mail-store-utils.h"
 
@@ -62,7 +61,12 @@
 
 /* This code is a mess, there is no reason it should be so complicated. */
 
+typedef struct _StoreInfo StoreInfo;
+
 struct _MailFolderCachePrivate {
+	gpointer session;  /* weak pointer */
+	EMailAccountStore *account_store;
+
 	/* source id for the ping timeout callback */
 	guint ping_id;
 	/* Store to storeinfo table, active stores */
@@ -82,6 +86,11 @@ struct _MailFolderCachePrivate {
 };
 
 enum {
+	PROP_0,
+	PROP_SESSION
+};
+
+enum {
 	FOLDER_AVAILABLE,
 	FOLDER_UNAVAILABLE,
 	FOLDER_DELETED,
@@ -94,7 +103,7 @@ enum {
 static guint signals[LAST_SIGNAL];
 
 struct _folder_info {
-	struct _store_info *store_info;	/* 'parent' link */
+	StoreInfo *store_info;	/* 'parent' link */
 
 	gchar *full_name;	/* full name of folder/folderinfo */
 
@@ -124,14 +133,26 @@ struct _folder_update {
 	gchar *msg_subject; /* ... and its subject. */
 };
 
-struct _store_info {
+struct _StoreInfo {
 	GHashTable *folders;	/* by full_name */
 	CamelStore *store;	/* the store for these folders */
+	gboolean first_update;	/* TRUE initially, then FALSE forever */
+
+	/* Hold a reference to keep them alive. */
+	CamelFolder *vjunk;
+	CamelFolder *vtrash;
 
 	/* Outstanding folderinfo requests */
 	GQueue folderinfo_updates;
 };
 
+struct _update_data {
+	NoteDoneFunc done;
+	gpointer data;
+	MailFolderCache *cache;
+	GCancellable *cancellable;
+};
+
 G_DEFINE_TYPE (MailFolderCache, mail_folder_cache, G_TYPE_OBJECT)
 
 static void
@@ -147,6 +168,66 @@ free_update (struct _folder_update *up)
 	g_free (up);
 }
 
+static void
+free_folder_info (struct _folder_info *mfi)
+{
+	g_free (mfi->full_name);
+	g_free (mfi);
+}
+
+static StoreInfo *
+store_info_new (CamelStore *store)
+{
+	StoreInfo *info;
+	GHashTable *folders;
+
+	folders = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) NULL,
+		(GDestroyNotify) free_folder_info);
+
+	info = g_slice_new0 (StoreInfo);
+	info->folders = folders;
+	info->store = g_object_ref (store);
+	info->first_update = TRUE;
+
+	/* If these are vfolders then they need to be opened
+	 * now, otherwise they won't keep track of all folders. */
+	if (store->flags & CAMEL_STORE_VJUNK)
+		info->vjunk = camel_store_get_junk_folder_sync (
+			store, NULL, NULL);
+	if (store->flags & CAMEL_STORE_VTRASH)
+		info->vtrash = camel_store_get_trash_folder_sync (
+			store, NULL, NULL);
+
+	g_queue_init (&info->folderinfo_updates);
+
+	return info;
+}
+
+static void
+store_info_free (StoreInfo *info)
+{
+	struct _update_data *ud;
+
+	while (!g_queue_is_empty (&info->folderinfo_updates)) {
+		ud = g_queue_pop_head (&info->folderinfo_updates);
+		g_cancellable_cancel (ud->cancellable);
+	}
+
+	g_hash_table_destroy (info->folders);
+	g_object_unref (info->store);
+
+	if (info->vjunk != NULL)
+		g_object_unref (info->vjunk);
+
+	if (info->vtrash != NULL)
+		g_object_unref (info->vtrash);
+
+	g_slice_free (StoreInfo, info);
+}
+
 static gboolean
 flush_updates_idle_cb (MailFolderCache *cache)
 {
@@ -334,9 +415,10 @@ folder_changed_cb (CamelFolder *folder,
 	CamelFolder *local_drafts;
 	CamelFolder *local_outbox;
 	CamelFolder *local_sent;
+	CamelSession *session;
 	CamelStore *parent_store;
 	CamelMessageInfo *info;
-	struct _store_info *si;
+	StoreInfo *si;
 	struct _folder_info *mfi;
 	const gchar *full_name;
 	gint new = 0;
@@ -346,6 +428,7 @@ folder_changed_cb (CamelFolder *folder,
 
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
+	session = camel_service_get_session (CAMEL_SERVICE (parent_store));
 
 	if (!last_newmail_per_folder)
 		last_newmail_per_folder = g_hash_table_new (g_direct_hash, g_direct_equal);
@@ -355,9 +438,12 @@ folder_changed_cb (CamelFolder *folder,
 		g_hash_table_lookup (last_newmail_per_folder, folder));
 	new_latest_received = latest_received;
 
-	local_drafts = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_DRAFTS);
-	local_outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
-	local_sent = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);
+	local_drafts = e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS);
+	local_outbox = e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_OUTBOX);
+	local_sent = e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_SENT);
 
 	if (!CAMEL_IS_VEE_FOLDER (folder)
 	    && folder != local_drafts
@@ -451,16 +537,9 @@ unset_folder_info (MailFolderCache *cache,
 }
 
 static void
-free_folder_info (struct _folder_info *mfi)
-{
-	g_free (mfi->full_name);
-	g_free (mfi);
-}
-
-static void
 setup_folder (MailFolderCache *cache,
               CamelFolderInfo *fi,
-              struct _store_info *si)
+              StoreInfo *si)
 {
 	struct _folder_info *mfi;
 	struct _folder_update *up;
@@ -493,7 +572,7 @@ setup_folder (MailFolderCache *cache,
 static void
 create_folders (MailFolderCache *cache,
                 CamelFolderInfo *fi,
-                struct _store_info *si)
+                StoreInfo *si)
 {
 	while (fi) {
 		setup_folder (cache, fi, si);
@@ -510,7 +589,7 @@ store_folder_subscribed_cb (CamelStore *store,
                             CamelFolderInfo *info,
                             MailFolderCache *cache)
 {
-	struct _store_info *si;
+	StoreInfo *si;
 
 	g_mutex_lock (cache->priv->stores_mutex);
 	si = g_hash_table_lookup (cache->priv->stores, store);
@@ -543,7 +622,7 @@ store_folder_unsubscribed_cb (CamelStore *store,
                               CamelFolderInfo *info,
                               MailFolderCache *cache)
 {
-	struct _store_info *si;
+	StoreInfo *si;
 	struct _folder_info *mfi;
 
 	g_mutex_lock (cache->priv->stores_mutex);
@@ -572,7 +651,7 @@ store_folder_deleted_cb (CamelStore *store,
 
 static void
 rename_folders (MailFolderCache *cache,
-                struct _store_info *si,
+                StoreInfo *si,
                 const gchar *oldbase,
                 const gchar *newbase,
                 CamelFolderInfo *fi)
@@ -678,7 +757,7 @@ store_folder_renamed_cb (CamelStore *store,
                          CamelFolderInfo *info,
                          MailFolderCache *cache)
 {
-	struct _store_info *si;
+	StoreInfo *si;
 
 	g_mutex_lock (cache->priv->stores_mutex);
 	si = g_hash_table_lookup (cache->priv->stores, store);
@@ -703,13 +782,6 @@ store_folder_renamed_cb (CamelStore *store,
 	g_mutex_unlock (cache->priv->stores_mutex);
 }
 
-struct _update_data {
-	NoteDoneFunc done;
-	gpointer data;
-	MailFolderCache *cache;
-	GCancellable *cancellable;
-};
-
 static void
 unset_folder_info_hash (gchar *path,
                         struct _folder_info *mfi,
@@ -720,11 +792,31 @@ unset_folder_info_hash (gchar *path,
 }
 
 static void
-free_folder_info_hash (gchar *path,
-                       struct _folder_info *mfi,
-                       gpointer data)
+mail_folder_cache_first_update (MailFolderCache *cache,
+                                StoreInfo *info)
 {
-	free_folder_info (mfi);
+	EMailSession *session;
+	const gchar *uid;
+
+	session = mail_folder_cache_get_session (cache);
+	uid = camel_service_get_uid (CAMEL_SERVICE (info->store));
+
+	if (info->vjunk != NULL)
+		mail_folder_cache_note_folder (cache, info->vjunk);
+
+	if (info->vtrash != NULL)
+		mail_folder_cache_note_folder (cache, info->vtrash);
+
+	/* Some extra work for the "On This Computer" store. */
+	if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0) {
+		CamelFolder *folder;
+		gint ii;
+
+		for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) {
+			folder = e_mail_session_get_local_folder (session, ii);
+			mail_folder_cache_note_folder (cache, folder);
+		}
+	}
 }
 
 static void
@@ -733,7 +825,7 @@ update_folders (CamelStore *store,
                 struct _update_data *ud)
 {
 	CamelFolderInfo *fi;
-	struct _store_info *si;
+	StoreInfo *si;
 	GError *error = NULL;
 
 	fi = camel_store_get_folder_info_finish (store, result, &error);
@@ -756,6 +848,12 @@ update_folders (CamelStore *store,
 	}
 	g_mutex_unlock (ud->cache->priv->stores_mutex);
 
+	/* Do some extra work for the first update. */
+	if (si != NULL && si->first_update) {
+		mail_folder_cache_first_update (ud->cache, si);
+		si->first_update = FALSE;
+	}
+
 	if (fi != NULL) {
 		gboolean free_fi = TRUE;
 
@@ -913,7 +1011,7 @@ struct _find_info {
 
 static void
 storeinfo_find_folder_info (CamelStore *store,
-                            struct _store_info *si,
+                            StoreInfo *si,
                             struct _find_info *fi)
 {
 	gchar *folder_name;
@@ -933,34 +1031,175 @@ storeinfo_find_folder_info (CamelStore *store,
 }
 
 static void
+mail_folder_cache_service_added (EMailAccountStore *account_store,
+                                 CamelService *service,
+                                 MailFolderCache *cache)
+{
+	mail_folder_cache_note_store (
+		cache, CAMEL_STORE (service), NULL, NULL, NULL);
+}
+
+static void
+mail_folder_cache_service_removed (EMailAccountStore *account_store,
+                                   CamelService *service,
+                                   MailFolderCache *cache)
+{
+	StoreInfo *si;
+
+	if (cache->priv->stores == NULL)
+		return;
+
+	g_mutex_lock (cache->priv->stores_mutex);
+
+	si = g_hash_table_lookup (cache->priv->stores, service);
+	if (si != NULL) {
+		g_hash_table_remove (cache->priv->stores, service);
+
+		g_signal_handlers_disconnect_matched (
+			service, G_SIGNAL_MATCH_DATA,
+			0, 0, NULL, NULL, cache);
+
+		g_hash_table_foreach (
+			si->folders, (GHFunc)
+			unset_folder_info_hash, cache);
+
+		store_info_free (si);
+	}
+
+	g_mutex_unlock (cache->priv->stores_mutex);
+}
+
+static void
+mail_folder_cache_set_session (MailFolderCache *cache,
+                               EMailSession *session)
+{
+	g_return_if_fail (E_IS_MAIL_SESSION (session));
+	g_return_if_fail (cache->priv->session == NULL);
+
+	cache->priv->session = session;
+
+	g_object_add_weak_pointer (
+		G_OBJECT (cache->priv->session),
+		&cache->priv->session);
+}
+
+static void
+mail_folder_cache_set_property (GObject *object,
+                                guint property_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SESSION:
+			mail_folder_cache_set_session (
+				MAIL_FOLDER_CACHE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_folder_cache_get_property (GObject *object,
+                                guint property_id,
+                                GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SESSION:
+			g_value_set_object (
+				value,
+				mail_folder_cache_get_session (
+				MAIL_FOLDER_CACHE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_folder_cache_dispose (GObject *object)
+{
+	MailFolderCachePrivate *priv;
+
+	priv = MAIL_FOLDER_CACHE_GET_PRIVATE (object);
+
+	if (priv->session != NULL) {
+		g_object_remove_weak_pointer (
+			G_OBJECT (priv->session), &priv->session);
+		priv->session = NULL;
+	}
+
+	if (priv->account_store != NULL) {
+		g_signal_handlers_disconnect_matched (
+			priv->account_store, G_SIGNAL_MATCH_DATA,
+			0, 0, NULL, NULL, object);
+		g_object_unref (priv->account_store);
+		priv->account_store = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (mail_folder_cache_parent_class)->dispose (object);
+}
+
+static void
 mail_folder_cache_finalize (GObject *object)
 {
-	MailFolderCache *cache = (MailFolderCache *) object;
+	MailFolderCachePrivate *priv;
 
-	g_hash_table_destroy (cache->priv->stores);
-	g_mutex_free (cache->priv->stores_mutex);
+	priv = MAIL_FOLDER_CACHE_GET_PRIVATE (object);
 
-	if (cache->priv->ping_id > 0) {
-		g_source_remove (cache->priv->ping_id);
-		cache->priv->ping_id = 0;
+	g_hash_table_destroy (priv->stores);
+	g_mutex_free (priv->stores_mutex);
+
+	if (priv->ping_id > 0) {
+		g_source_remove (priv->ping_id);
+		priv->ping_id = 0;
 	}
 
-	if (cache->priv->update_id > 0) {
-		g_source_remove (cache->priv->update_id);
-		cache->priv->update_id = 0;
+	if (priv->update_id > 0) {
+		g_source_remove (priv->update_id);
+		priv->update_id = 0;
 	}
 
-	while (!g_queue_is_empty (&cache->priv->local_folder_uris))
-		g_free (g_queue_pop_head (&cache->priv->local_folder_uris));
+	while (!g_queue_is_empty (&priv->local_folder_uris))
+		g_free (g_queue_pop_head (&priv->local_folder_uris));
 
-	while (!g_queue_is_empty (&cache->priv->remote_folder_uris))
-		g_free (g_queue_pop_head (&cache->priv->remote_folder_uris));
+	while (!g_queue_is_empty (&priv->remote_folder_uris))
+		g_free (g_queue_pop_head (&priv->remote_folder_uris));
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (mail_folder_cache_parent_class)->finalize (object);
 }
 
 static void
+mail_folder_cache_constructed (GObject *object)
+{
+	MailFolderCache *cache;
+	EMailSession *session;
+	EMailAccountStore *account_store;
+
+	cache = MAIL_FOLDER_CACHE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (mail_folder_cache_parent_class)->constructed (object);
+
+	session = mail_folder_cache_get_session (cache);
+	account_store = e_mail_session_get_account_store (session);
+
+	cache->priv->account_store = g_object_ref (account_store);
+
+	g_signal_connect (
+		account_store, "service-added",
+		G_CALLBACK (mail_folder_cache_service_added), cache);
+
+	g_signal_connect (
+		account_store, "service-removed",
+		G_CALLBACK (mail_folder_cache_service_removed), cache);
+}
+
+static void
 mail_folder_cache_folder_available (MailFolderCache *cache,
                                     CamelStore *store,
                                     const gchar *folder_name)
@@ -1118,12 +1357,28 @@ mail_folder_cache_class_init (MailFolderCacheClass *class)
 	g_type_class_add_private (class, sizeof (MailFolderCachePrivate));
 
 	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_folder_cache_set_property;
+	object_class->get_property = mail_folder_cache_get_property;
+	object_class->dispose = mail_folder_cache_dispose;
 	object_class->finalize = mail_folder_cache_finalize;
+	object_class->constructed = mail_folder_cache_constructed;
 
 	class->folder_available = mail_folder_cache_folder_available;
 	class->folder_unavailable = mail_folder_cache_folder_unavailable;
 	class->folder_deleted = mail_folder_cache_folder_deleted;
 
+	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));
+
 	/**
 	 * MailFolderCache::folder-available
 	 * @store: the #CamelStore containing the folder
@@ -1274,9 +1529,21 @@ mail_folder_cache_init (MailFolderCache *cache)
 }
 
 MailFolderCache *
-mail_folder_cache_new (void)
+mail_folder_cache_new (EMailSession *session)
 {
-	return g_object_new (MAIL_TYPE_FOLDER_CACHE, NULL);
+	g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
+
+	return g_object_new (
+		MAIL_TYPE_FOLDER_CACHE,
+		"session", session, NULL);
+}
+
+EMailSession *
+mail_folder_cache_get_session (MailFolderCache *cache)
+{
+	g_return_val_if_fail (MAIL_IS_FOLDER_CACHE (cache), NULL);
+
+	return E_MAIL_SESSION (cache->priv->session);
 }
 
 /**
@@ -1294,12 +1561,12 @@ mail_folder_cache_note_store (MailFolderCache *cache,
                               gpointer data)
 {
 	CamelSession *session;
-	struct _store_info *si;
+	StoreInfo *si;
 	struct _update_data *ud;
 	gint hook = 0;
 
+	g_return_if_fail (MAIL_IS_FOLDER_CACHE (cache));
 	g_return_if_fail (CAMEL_IS_STORE (store));
-	g_return_if_fail (mail_in_main_thread ());
 
 	session = camel_service_get_session (CAMEL_SERVICE (store));
 
@@ -1307,11 +1574,8 @@ mail_folder_cache_note_store (MailFolderCache *cache,
 
 	si = g_hash_table_lookup (cache->priv->stores, store);
 	if (si == NULL) {
-		si = g_malloc0 (sizeof (*si));
-		si->folders = g_hash_table_new (g_str_hash, g_str_equal);
-		si->store = g_object_ref (store);
+		si = store_info_new (store);
 		g_hash_table_insert (cache->priv->stores, store, si);
-		g_queue_init (&si->folderinfo_updates);
 		hook = TRUE;
 	}
 
@@ -1389,55 +1653,6 @@ mail_folder_cache_note_store (MailFolderCache *cache,
 }
 
 /**
- * mail_folder_cache_note_store_remove:
- *
- * Notify the cache that the specified @store can be removed from the cache
- */
-void
-mail_folder_cache_note_store_remove (MailFolderCache *cache,
-                                     CamelStore *store)
-{
-	struct _store_info *si;
-
-	g_return_if_fail (CAMEL_IS_STORE (store));
-
-	if (cache->priv->stores == NULL)
-		return;
-
-	d(printf("store removed!!\n"));
-	g_mutex_lock (cache->priv->stores_mutex);
-	si = g_hash_table_lookup (cache->priv->stores, store);
-	if (si) {
-		GList *link;
-
-		g_hash_table_remove (cache->priv->stores, store);
-
-		g_signal_handlers_disconnect_matched (
-			store, G_SIGNAL_MATCH_DATA,
-			0, 0, NULL, NULL, cache);
-
-		g_hash_table_foreach (
-			si->folders, (GHFunc)
-			unset_folder_info_hash, cache);
-
-		link = g_queue_peek_head_link (&si->folderinfo_updates);
-
-		while (link != NULL) {
-			struct _update_data *ud = link->data;
-			g_cancellable_cancel (ud->cancellable);
-			link = g_list_next (link);
-		}
-
-		g_object_unref (si->store);
-		g_hash_table_foreach (si->folders, (GHFunc) free_folder_info_hash, NULL);
-		g_hash_table_destroy (si->folders);
-		g_free (si);
-	}
-
-	g_mutex_unlock (cache->priv->stores_mutex);
-}
-
-/**
  * mail_folder_cache_note_folder:
  *
  * When a folder has been opened, notify it for watching.  The folder must have
@@ -1449,10 +1664,13 @@ mail_folder_cache_note_folder (MailFolderCache *cache,
                                CamelFolder *folder)
 {
 	CamelStore *parent_store;
-	struct _store_info *si;
+	StoreInfo *si;
 	struct _folder_info *mfi;
 	const gchar *full_name;
 
+	g_return_if_fail (MAIL_IS_FOLDER_CACHE (cache));
+	g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
 
diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h
index 146ead5..78d5fd9 100644
--- a/mail/mail-folder-cache.h
+++ b/mail/mail-folder-cache.h
@@ -49,6 +49,9 @@
 
 G_BEGIN_DECLS
 
+/* Avoid a circular dependency. */
+typedef struct _EMailSession EMailSession;
+
 typedef struct _MailFolderCache MailFolderCache;
 typedef struct _MailFolderCacheClass MailFolderCacheClass;
 typedef struct _MailFolderCachePrivate MailFolderCachePrivate;
@@ -107,34 +110,32 @@ struct _MailFolderCacheClass {
 
 GType		mail_folder_cache_get_type	(void) G_GNUC_CONST;
 MailFolderCache *
-		mail_folder_cache_new		(void);
-void		mail_folder_cache_note_store	(MailFolderCache *self,
+		mail_folder_cache_new		(EMailSession *session);
+EMailSession *	mail_folder_cache_get_session	(MailFolderCache *cache);
+void		mail_folder_cache_note_store	(MailFolderCache *cache,
 						 CamelStore *store,
 						 GCancellable *cancellable,
 						 NoteDoneFunc done,
 						 gpointer data);
-void		mail_folder_cache_note_store_remove
-						(MailFolderCache *self,
-						 CamelStore *store);
-void		mail_folder_cache_note_folder	(MailFolderCache *self,
+void		mail_folder_cache_note_folder	(MailFolderCache *cache,
 						 CamelFolder *folder);
 gboolean	mail_folder_cache_get_folder_from_uri
-						(MailFolderCache *self,
+						(MailFolderCache *cache,
 						 const gchar *uri,
 						 CamelFolder **folderp);
 gboolean	mail_folder_cache_get_folder_info_flags
-						(MailFolderCache *self,
+						(MailFolderCache *cache,
 						 CamelFolder *folder,
 						 CamelFolderInfoFlags *flags);
 gboolean	mail_folder_cache_get_folder_has_children
-						(MailFolderCache *self,
+						(MailFolderCache *cache,
 						 CamelFolder *folder,
 						 gboolean *found);
 void		mail_folder_cache_get_local_folder_uris
-						(MailFolderCache *self,
+						(MailFolderCache *cache,
 						 GQueue *out_queue);
 void		mail_folder_cache_get_remote_folder_uris
-						(MailFolderCache *self,
+						(MailFolderCache *cache,
 						 GQueue *out_queue);
 
 G_END_DECLS
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 24a494d..4ff12b3 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -43,7 +43,6 @@
 #include "mail-ops.h"
 #include "mail-tools.h"
 
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 #include "e-mail-session-utils.h"
 
@@ -213,18 +212,23 @@ fetch_mail_exec (struct _fetch_mail_msg *m,
 {
 	struct _filter_mail_msg *fm = (struct _filter_mail_msg *) m;
 	CamelFolder *folder = NULL;
+	CamelService *service;
+	CamelSession *session;
 	CamelURL *url;
 	gboolean is_local_delivery;
 	const gchar *uid;
 	gint i;
 
-	fm->destination = e_mail_local_get_folder (
-		E_MAIL_LOCAL_FOLDER_LOCAL_INBOX);
+	service = CAMEL_SERVICE (m->store);
+	session = camel_service_get_session (service);
+
+	fm->destination = e_mail_session_get_local_folder (
+		E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_LOCAL_INBOX);
 	if (fm->destination == NULL)
 		goto fail;
 	g_object_ref (fm->destination);
 
-	url = camel_service_new_camel_url (CAMEL_SERVICE (m->store));
+	url = camel_service_new_camel_url (service);
 	is_local_delivery = em_utils_is_local_delivery_mbox_file (url);
 
 	if (is_local_delivery) {
@@ -250,7 +254,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m,
 		g_free (path);
 		g_free (url_string);
 	} else {
-		uid = camel_service_get_uid (CAMEL_SERVICE (m->store));
+		uid = camel_service_get_uid (service);
 
 		folder = fm->source_folder =
 			e_mail_session_get_inbox_sync (
@@ -344,7 +348,7 @@ fail:
 	 * there is no need to keep the connection alive forever */
 	if (!is_local_delivery)
 		em_utils_disconnect_service_sync (
-			CAMEL_SERVICE (m->store), TRUE, cancellable, NULL);
+			service, TRUE, cancellable, NULL);
 }
 
 static void
@@ -670,7 +674,8 @@ mail_send_message (struct _send_queue_msg *m,
 		}
 
 		if (!folder) {
-			folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);
+			folder = e_mail_session_get_local_folder (
+				session, E_MAIL_LOCAL_FOLDER_SENT);
 			g_object_ref (folder);
 		}
 
@@ -683,7 +688,8 @@ mail_send_message (struct _send_queue_msg *m,
 			if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 				goto exit;
 
-			sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);
+			sent_folder = e_mail_session_get_local_folder (
+				session, E_MAIL_LOCAL_FOLDER_SENT);
 
 			if (folder != sent_folder) {
 				const gchar *description;
@@ -801,6 +807,7 @@ send_queue_exec (struct _send_queue_msg *m,
                  GCancellable *cancellable,
                  GError **error)
 {
+	EMailSession *session;
 	CamelFolder *sent_folder;
 	GPtrArray *uids, *send_uids = NULL;
 	gint i, j;
@@ -808,7 +815,11 @@ send_queue_exec (struct _send_queue_msg *m,
 
 	d(printf("sending queue\n"));
 
-	sent_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_SENT);
+	session = e_mail_backend_get_session (m->backend);
+
+	sent_folder =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_SENT);
 
 	if (!(uids = camel_folder_get_uids (m->queue)))
 		return;
@@ -1489,19 +1500,25 @@ expunge_folder_exec (struct _sync_folder_msg *m,
                      GCancellable *cancellable,
                      GError **error)
 {
+	EMailSession *session;
 	CamelFolder *local_inbox;
-	CamelStore *local_store;
 	CamelStore *parent_store;
 	gboolean is_local_inbox_or_trash;
+	gboolean store_is_local;
 	gboolean success = TRUE;
+	const gchar *uid;
 
-	local_inbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_INBOX);
-	is_local_inbox_or_trash = (m->folder == local_inbox);
-
-	local_store = e_mail_local_get_store ();
+	session = e_mail_backend_get_session (m->backend);
 	parent_store = camel_folder_get_parent_store (m->folder);
+	uid = camel_service_get_uid (CAMEL_SERVICE (parent_store));
+	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+
+	local_inbox =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_INBOX);
+	is_local_inbox_or_trash = (m->folder == local_inbox);
 
-	if (!is_local_inbox_or_trash && local_store == parent_store) {
+	if (store_is_local && !is_local_inbox_or_trash) {
 		CamelFolder *trash;
 
 		trash = camel_store_get_trash_folder_sync (
@@ -1591,7 +1608,7 @@ empty_trash_exec (struct _empty_trash_msg *m,
 		return;
 
 	/* do this before expunge, to know which messages will be expunged */
-	if (g_strcmp0 (uid, "local") == 0)
+	if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0)
 		success = expunge_pop3_stores (
 			trash, m->backend, cancellable, error);
 
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index 44c5158..36c7176 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -36,7 +36,6 @@
 #include "e-util/e-util.h"
 
 #include "e-mail-folder-utils.h"
-#include "e-mail-local.h"
 #include "e-mail-session.h"
 #include "em-event.h"
 #include "em-filter-rule.h"
@@ -164,10 +163,13 @@ free_send_info (struct _send_info *info)
 }
 
 static struct _send_data *
-setup_send_data (void)
+setup_send_data (EMailBackend *backend)
 {
+	EMailSession *session;
 	struct _send_data *data;
 
+	session = e_mail_backend_get_session (backend);
+
 	if (send_data == NULL) {
 		send_data = data = g_malloc0 (sizeof (*data));
 		data->lock = g_mutex_new ();
@@ -175,8 +177,9 @@ setup_send_data (void)
 			g_str_hash, g_str_equal,
 			(GDestroyNotify) NULL,
 			(GDestroyNotify) free_folder_info);
-		data->inbox = e_mail_local_get_folder (
-			E_MAIL_LOCAL_FOLDER_LOCAL_INBOX);
+		data->inbox =
+			e_mail_session_get_local_folder (
+			session, E_MAIL_LOCAL_FOLDER_LOCAL_INBOX);
 		g_object_ref (data->inbox);
 		data->active = g_hash_table_new_full (
 			g_str_hash, g_str_equal,
@@ -520,7 +523,7 @@ build_dialog (GtkWindow *parent,
 	gtk_widget_show (scrolled_window);
 
 	/* must bet setup after send_recv_dialog as it may re-trigger send-recv button */
-	data = setup_send_data ();
+	data = setup_send_data (backend);
 
 	row = 0;
 	iter = e_list_get_iterator ((EList *) accounts);
@@ -810,8 +813,9 @@ receive_done (gpointer data)
 
 		session = e_mail_backend_get_session (info->backend);
 
-		local_outbox = e_mail_local_get_folder (
-			E_MAIL_LOCAL_FOLDER_OUTBOX);
+		local_outbox =
+			e_mail_session_get_local_folder (
+			session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 
 		service = camel_session_get_service (
 			CAMEL_SESSION (session),
@@ -1126,7 +1130,10 @@ send_receive (GtkWindow *parent,
 
 	accounts = e_get_account_list ();
 
-	local_outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+	local_outbox =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
+
 	data = build_dialog (
 		parent, backend, accounts,
 		local_outbox, account, allow_send);
@@ -1280,11 +1287,12 @@ auto_account_changed (EAccountList *eal,
                       EAccount *ea,
                       gpointer dummy)
 {
-	struct _auto_data *info = g_object_get_data((GObject *)ea, "mail-autoreceive");
+	struct _auto_data *info;
 
-	g_return_if_fail (info != NULL);
+	info = g_object_get_data (G_OBJECT (ea), "mail-autoreceive");
 
-	auto_account_commit (info);
+	if (info != NULL)
+		auto_account_commit (info);
 }
 
 static void
@@ -1394,7 +1402,7 @@ mail_receive_account (EMailBackend *backend,
 	CamelURL *url;
 	send_info_t type = SEND_INVALID;
 
-	data = setup_send_data ();
+	data = setup_send_data (backend);
 	info = g_hash_table_lookup (data->active, account->uid);
 
 	if (info != NULL)
@@ -1450,8 +1458,9 @@ mail_receive_account (EMailBackend *backend,
 		break;
 	case SEND_SEND:
 		/* todo, store the folder in info? */
-		local_outbox = e_mail_local_get_folder (
-			E_MAIL_LOCAL_FOLDER_OUTBOX);
+		local_outbox =
+			e_mail_session_get_local_folder (
+			session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 		mail_send_queue (
 			info->backend,
 			local_outbox,
@@ -1487,7 +1496,7 @@ mail_send (EMailBackend *backend)
 	if (account == NULL || account->transport->url == NULL)
 		return;
 
-	data = setup_send_data ();
+	data = setup_send_data (backend);
 	info = g_hash_table_lookup (data->active, SEND_URI_KEY);
 	if (info != NULL) {
 		info->again++;
@@ -1525,11 +1534,13 @@ mail_send (EMailBackend *backend)
 
 	g_hash_table_insert (data->active, (gpointer) SEND_URI_KEY, info);
 
-	/* todo, store the folder in info? */
-	local_outbox = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
-
 	session = e_mail_backend_get_session (backend);
 
+	/* todo, store the folder in info? */
+	local_outbox =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
+
 	service = camel_session_get_service (
 		CAMEL_SESSION (session), transport_uid);
 
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index b37d042..99caa6c 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -49,11 +49,6 @@
 #include "mail-tools.h"
 #include "mail-vfolder.h"
 
-#include "e-mail-local.h"
-#include "e-mail-store.h"
-
-#define VFOLDER_SERVICE_UID "vfolder"
-
 #define d(x)  /* (printf("%s:%s: ",  G_STRLOC, G_STRFUNC), (x))*/
 
 static EMVFolderContext *context;	/* context remains open all time */
@@ -720,7 +715,7 @@ rule_changed (EFilterRule *rule,
 	session = e_mail_backend_get_session (backend);
 
 	service = camel_session_get_service (
-		CAMEL_SESSION (session), VFOLDER_SERVICE_UID);
+		CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID);
 	g_return_if_fail (CAMEL_IS_SERVICE (service));
 
 	/* if the folder has changed name, then add it, then remove the old manually */
@@ -820,7 +815,7 @@ context_rule_added (ERuleContext *ctx,
 	session = e_mail_backend_get_session (backend);
 
 	service = camel_session_get_service (
-		CAMEL_SESSION (session), VFOLDER_SERVICE_UID);
+		CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID);
 	g_return_if_fail (CAMEL_IS_SERVICE (service));
 
 	/* this always runs quickly */
@@ -853,7 +848,7 @@ context_rule_removed (ERuleContext *ctx,
 	session = e_mail_backend_get_session (backend);
 
 	service = camel_session_get_service (
-		CAMEL_SESSION (session), VFOLDER_SERVICE_UID);
+		CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID);
 	g_return_if_fail (CAMEL_IS_SERVICE (service));
 
 	/* TODO: remove from folder info cache? */
@@ -1008,8 +1003,7 @@ vfolder_load_storage (EMailBackend *backend)
 	/* lock for loading storage, it is safe to call it more than once */
 	G_LOCK_DEFINE_STATIC (vfolder_hash);
 
-	CamelService *service;
-	const gchar *key;
+	CamelStore *vfolder_store;
 	const gchar *config_dir;
 	gchar *user;
 	EFilterRule *rule;
@@ -1034,27 +1028,14 @@ vfolder_load_storage (EMailBackend *backend)
 
 	config_dir = mail_session_get_config_dir ();
 	session = e_mail_backend_get_session (backend);
-
-	/* first, create the vfolder store, and set it up */
-	service = camel_session_add_service (
-		CAMEL_SESSION (session), "vfolder",
-		"vfolder", CAMEL_PROVIDER_STORE, NULL);
-	if (service != NULL) {
-		camel_service_set_display_name (service, _("Search Folders"));
-		em_utils_connect_service_sync (service, NULL, NULL);
-	} else {
-		g_warning("Cannot open vfolder store - no vfolders available");
-		return;
-	}
-
-	g_return_if_fail (CAMEL_IS_STORE (service));
+	vfolder_store = e_mail_session_get_vfolder_store (session);
 
 	g_signal_connect (
-		service, "folder-deleted",
+		vfolder_store, "folder-deleted",
 		G_CALLBACK (store_folder_deleted_cb), backend);
 
 	g_signal_connect (
-		service, "folder-renamed",
+		vfolder_store, "folder-renamed",
 		G_CALLBACK (store_folder_renamed_cb), NULL);
 
 	/* load our rules */
@@ -1076,9 +1057,6 @@ vfolder_load_storage (EMailBackend *backend)
 		context, "rule_removed",
 		G_CALLBACK (context_rule_removed), context);
 
-	/* load store to mail component */
-	e_mail_store_add (session, CAMEL_STORE (service));
-
 	/* and setup the rules we have */
 	rule = NULL;
 	while ((rule = e_rule_context_next_rule ((ERuleContext *) context, rule, NULL))) {
@@ -1092,9 +1070,7 @@ vfolder_load_storage (EMailBackend *backend)
 
 	/* reenable the feature if required */
 	settings = g_settings_new ("org.gnome.evolution.mail");
-	key = "enable-vfolders";
-	if (!g_settings_get_boolean (settings, key))
-		g_settings_set_boolean (settings, key, TRUE);
+	g_settings_set_boolean (settings, "enable-vfolders", TRUE);
 	g_object_unref (settings);
 
 	folder_cache = e_mail_session_get_folder_cache (session);
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index aba140b..64817fa 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -43,7 +43,6 @@
 #include "e-mail-folder-utils.h"
 #include "e-mail-reader.h"
 #include "e-mail-session.h"
-#include "e-mail-store.h"
 #include "em-account-editor.h"
 #include "em-account-prefs.h"
 #include "em-composer-prefs.h"
@@ -220,18 +219,6 @@ mail_shell_backend_sync_store_done_cb (CamelStore *store,
 	mail_shell_backend->priv->mail_sync_in_progress--;
 }
 
-static void
-mail_shell_backend_sync_store_cb (CamelStore *store,
-                                  EMailShellBackend *mail_shell_backend)
-{
-	mail_shell_backend->priv->mail_sync_in_progress++;
-
-	mail_sync_store (
-		store, FALSE,
-		mail_shell_backend_sync_store_done_cb,
-		mail_shell_backend);
-}
-
 static gboolean
 mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend)
 {
@@ -239,6 +226,7 @@ mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend)
 	EShellBackend *shell_backend;
 	EMailBackend *backend;
 	EMailSession *session;
+	GList *list, *link;
 
 	shell_backend = E_SHELL_BACKEND (mail_shell_backend);
 	shell = e_shell_backend_get_shell (shell_backend);
@@ -254,10 +242,25 @@ mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend)
 	backend = E_MAIL_BACKEND (mail_shell_backend);
 	session = e_mail_backend_get_session (backend);
 
-	e_mail_store_foreach (
-		session, (GFunc)
-		mail_shell_backend_sync_store_cb,
-		mail_shell_backend);
+	list = camel_session_list_services (CAMEL_SESSION (session));
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		CamelService *service;
+
+		service = CAMEL_SERVICE (link->data);
+
+		if (!CAMEL_IS_STORE (service))
+			continue;
+
+		mail_shell_backend->priv->mail_sync_in_progress++;
+
+		mail_sync_store (
+			CAMEL_STORE (service), FALSE,
+			mail_shell_backend_sync_store_done_cb,
+			mail_shell_backend);
+	}
+
+	g_list_free (list);
 
 exit:
 	return TRUE;
@@ -309,8 +312,13 @@ mail_shell_backend_window_added_cb (GtkApplication *application,
                                     EShellBackend *shell_backend)
 {
 	EShell *shell = E_SHELL (application);
+	EMailBackend *backend;
+	EMailSession *session;
 	const gchar *backend_name;
 
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
+
 	/* This applies to both the composer and signature editor. */
 	if (GTKHTML_IS_EDITOR (window)) {
 		EShellSettings *shell_settings;
@@ -339,7 +347,8 @@ mail_shell_backend_window_added_cb (GtkApplication *application,
 		e_shell_backend_start (shell_backend);
 
 		/* Integrate the new composer into the mail module. */
-		em_configure_new_composer (E_MSG_COMPOSER (window));
+		em_configure_new_composer (
+			E_MSG_COMPOSER (window), session);
 		return;
 	}
 
@@ -449,8 +458,9 @@ mail_shell_backend_start (EShellBackend *shell_backend)
 	EShellSettings *shell_settings;
 	EMailBackend *backend;
 	EMailSession *session;
+	EMailAccountStore *account_store;
 	gboolean enable_search_folders;
-	const gchar *data_dir;
+	GError *error = NULL;
 
 	priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend);
 
@@ -459,15 +469,18 @@ mail_shell_backend_start (EShellBackend *shell_backend)
 
 	backend = E_MAIL_BACKEND (shell_backend);
 	session = e_mail_backend_get_session (backend);
-	data_dir = e_shell_backend_get_data_dir (shell_backend);
-
-	e_mail_store_init (session, data_dir);
+	account_store = e_mail_session_get_account_store (session);
 
 	enable_search_folders = e_shell_settings_get_boolean (
 		shell_settings, "mail-enable-search-folders");
 	if (enable_search_folders)
 		vfolder_load_storage (backend);
 
+	if (!e_mail_account_store_load_sort_order (account_store, &error)) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+	}
+
 	mail_autoreceive_init (backend);
 
 	if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL)
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index abe3d2b..5de727e 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -84,45 +84,31 @@ action_mail_account_disable_cb (GtkAction *action,
 	EMailShellSidebar *mail_shell_sidebar;
 	EShellBackend *shell_backend;
 	EShellView *shell_view;
+	EShellWindow *shell_window;
 	EMailBackend *backend;
 	EMailSession *session;
+	EMailAccountStore *account_store;
 	EMFolderTree *folder_tree;
-	CamelService *service;
 	CamelStore *store;
-	EAccountList *account_list;
-	EAccount *account;
-	const gchar *uid;
 
 	mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
 
 	shell_view = E_SHELL_VIEW (mail_shell_view);
 	shell_backend = e_shell_view_get_shell_backend (shell_view);
+	shell_window = e_shell_view_get_shell_window (shell_view);
 
 	backend = E_MAIL_BACKEND (shell_backend);
 	session = e_mail_backend_get_session (backend);
+	account_store = e_mail_session_get_account_store (session);
 
 	folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
 	store = em_folder_tree_get_selected_store (folder_tree);
 	g_return_if_fail (store != NULL);
 
-	service = CAMEL_SERVICE (store);
-	uid = camel_service_get_uid (service);
-	account = e_get_account_by_uid (uid);
-	g_return_if_fail (account != NULL);
-
-	account_list = e_get_account_list ();
-
-	if (e_account_list_account_has_proxies (account_list, account))
-		e_account_list_remove_account_proxies (account_list, account);
-
-	account->enabled = !account->enabled;
-	e_account_list_change (account_list, account);
-	e_mail_store_remove_by_account (session, account);
-
-	if (account->parent_uid != NULL)
-		e_account_list_remove (account_list, account);
-
-	e_account_list_save (account_list);
+	e_mail_account_store_disable_service (
+		account_store,
+		GTK_WINDOW (shell_window),
+		CAMEL_SERVICE (store));
 
 	e_shell_view_update_actions (shell_view);
 }
@@ -206,22 +192,6 @@ action_mail_download_finished_cb (CamelStore *store,
 }
 
 static void
-action_mail_download_foreach_cb (CamelStore *store,
-                                 EMailReader *reader)
-{
-	EActivity *activity;
-	GCancellable *cancellable;
-
-	activity = e_mail_reader_new_activity (reader);
-	cancellable = e_activity_get_cancellable (activity);
-
-	e_mail_store_prepare_for_offline (
-		store, G_PRIORITY_DEFAULT,
-		cancellable, (GAsyncReadyCallback)
-		action_mail_download_finished_cb, activity);
-}
-
-static void
 action_mail_download_cb (GtkAction *action,
                          EMailShellView *mail_shell_view)
 {
@@ -230,6 +200,7 @@ action_mail_download_cb (GtkAction *action,
 	EMailReader *reader;
 	EMailBackend *backend;
 	EMailSession *session;
+	GList *list, *link;
 
 	mail_shell_content = mail_shell_view->priv->mail_shell_content;
 	mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
@@ -238,8 +209,28 @@ action_mail_download_cb (GtkAction *action,
 	backend = e_mail_reader_get_backend (reader);
 	session = e_mail_backend_get_session (backend);
 
-	e_mail_store_foreach (
-		session, (GFunc) action_mail_download_foreach_cb, reader);
+	list = camel_session_list_services (CAMEL_SESSION (session));
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		EActivity *activity;
+		CamelService *service;
+		GCancellable *cancellable;
+
+		service = CAMEL_SERVICE (link->data);
+
+		if (!CAMEL_IS_STORE (service))
+			continue;
+
+		activity = e_mail_reader_new_activity (reader);
+		cancellable = e_activity_get_cancellable (activity);
+
+		e_mail_store_prepare_for_offline (
+			CAMEL_STORE (service), G_PRIORITY_DEFAULT,
+			cancellable, (GAsyncReadyCallback)
+			action_mail_download_finished_cb, activity);
+	}
+
+	g_list_free (list);
 }
 
 static void
diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c
index ab669d3..534a258 100644
--- a/modules/mail/e-mail-shell-view-private.c
+++ b/modules/mail/e-mail-shell-view-private.c
@@ -937,13 +937,14 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view)
 	EShellView *shell_view;
 	EMailReader *reader;
 	EMailView *mail_view;
-	CamelStore *local_store;
 	CamelStore *parent_store;
 	CamelFolder *folder;
 	GPtrArray *uids;
 	GString *buffer;
+	gboolean store_is_local;
 	const gchar *display_name;
 	const gchar *folder_name;
+	const gchar *uid;
 	gchar *title;
 	guint32 num_deleted;
 	guint32 num_junked;
@@ -962,8 +963,6 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view)
 	reader = E_MAIL_READER (mail_view);
 	folder = e_mail_reader_get_folder (reader);
 
-	local_store = e_mail_local_get_store ();
-
 	/* If no folder is selected, reset the sidebar banners
 	 * to their default values and stop. */
 	if (folder == NULL) {
@@ -1058,9 +1057,12 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view)
 
 	em_utils_uids_free (uids);
 
+	uid = camel_service_get_uid (CAMEL_SERVICE (parent_store));
+	store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
+
 	/* Choose a suitable folder name for displaying. */
 	display_name = folder_name;
-	if (parent_store == local_store) {
+	if (store_is_local) {
 		if (strcmp (folder_name, "Drafts") == 0)
 			display_name = _("Drafts");
 		else if (strcmp (folder_name, "Inbox") == 0)
diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h
index 5bc477d..24b5e53 100644
--- a/modules/mail/e-mail-shell-view-private.h
+++ b/modules/mail/e-mail-shell-view-private.h
@@ -40,13 +40,11 @@
 #include "e-mail-label-action.h"
 #include "e-mail-label-dialog.h"
 #include "e-mail-label-list-store.h"
-#include "e-mail-local.h"
 #include "e-mail-reader.h"
 #include "e-mail-reader-utils.h"
 #include "e-mail-session.h"
 #include "e-mail-session-utils.h"
 #include "e-mail-sidebar.h"
-#include "e-mail-store.h"
 #include "e-mail-store-utils.h"
 #include "em-composer-utils.h"
 #include "em-folder-properties.h"
diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c
index 02a31c2..45246e6 100644
--- a/modules/mail/e-mail-shell-view.c
+++ b/modules/mail/e-mail-shell-view.c
@@ -558,7 +558,7 @@ all_accounts:
 
 	/* FIXME Complete lack of error checking here. */
 	service = camel_session_get_service (
-		CAMEL_SESSION (session), "vfolder");
+		CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID);
 	em_utils_connect_service_sync (service, NULL, NULL);
 
 	search_folder = (CamelVeeFolder *) camel_vee_folder_new (
@@ -719,7 +719,7 @@ current_account:
 
 	/* FIXME Complete lack of error checking here. */
 	service = camel_session_get_service (
-		CAMEL_SESSION (session), "vfolder");
+		CAMEL_SESSION (session), E_MAIL_SESSION_VFOLDER_UID);
 	em_utils_connect_service_sync (service, NULL, NULL);
 
 	search_folder = (CamelVeeFolder *) camel_vee_folder_new (
diff --git a/modules/mail/em-account-prefs.c b/modules/mail/em-account-prefs.c
index ddf51d8..9506e75 100644
--- a/modules/mail/em-account-prefs.c
+++ b/modules/mail/em-account-prefs.c
@@ -36,8 +36,6 @@
 #include "e-util/e-account-utils.h"
 
 #include "e-mail-backend.h"
-#include "e-mail-local.h"
-#include "e-mail-store.h"
 #include "em-config.h"
 #include "em-account-editor.h"
 #include "em-utils.h"
@@ -45,6 +43,10 @@
 #include "shell/e-shell.h"
 #include "capplet/settings/mail-capplet-shell.h"
 
+#define EM_ACCOUNT_PREFS_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsPrivate))
+
 struct _EMAccountPrefsPrivate {
 	EMailBackend *backend;
 	gpointer assistant; /* weak pointer */
@@ -59,101 +61,23 @@ enum {
 G_DEFINE_TYPE (
 	EMAccountPrefs,
 	em_account_prefs,
-	E_TYPE_ACCOUNT_MANAGER)
-
-static gboolean
-account_prefs_toggle_enable_special (EMAccountPrefs *prefs,
-                                     EAccountTreeViewSelectedType type,
-                                     gboolean enabled)
-{
-	const gchar *prop = NULL;
-	EShell *shell;
-	EShellSettings *shell_settings;
-
-	g_return_val_if_fail (prefs != NULL, FALSE);
-	g_return_val_if_fail (prefs->priv != NULL, FALSE);
-
-	if (type == E_ACCOUNT_TREE_VIEW_SELECTED_LOCAL)
-		prop = "mail-enable-local-folders";
-	else if (type == E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER)
-		prop = "mail-enable-search-folders";
-
-	if (!prop)
-		return FALSE;
-
-	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (prefs->priv->backend));
-	shell_settings = e_shell_get_shell_settings (shell);
-
-	e_shell_settings_set_boolean (shell_settings, prop, enabled);
-
-	/* make sure "Search Folders" are loaded when enabled */
-	if (enabled && type == E_ACCOUNT_TREE_VIEW_SELECTED_VFOLDER)
-		vfolder_load_storage (prefs->priv->backend);
-
-	return TRUE;
-}
+	E_TYPE_MAIL_ACCOUNT_MANAGER)
 
 static void
-account_prefs_enable_account_cb (EAccountTreeView *tree_view,
-                                 EMAccountPrefs *prefs)
-{
-	EAccount *account;
-	EMailSession *session;
-
-	account = e_account_tree_view_get_selected (tree_view);
-	if (!account) {
-		if (account_prefs_toggle_enable_special (prefs, e_account_tree_view_get_selected_type (tree_view), TRUE))
-			return;
-	}
-
-	g_return_if_fail (account != NULL);
-
-	session = e_mail_backend_get_session (prefs->priv->backend);
-	e_mail_store_add_by_account (session, account);
-}
-
-static void
-account_prefs_disable_account_cb (EAccountTreeView *tree_view,
+account_prefs_service_enabled_cb (EMailAccountStore *store,
+                                  CamelService *service,
                                   EMAccountPrefs *prefs)
 {
-	EAccountList *account_list;
-	EAccount *account;
-	EMailSession *session;
-	gpointer parent;
-	gint response;
-
-	account = e_account_tree_view_get_selected (tree_view);
-	if (!account) {
-		if (account_prefs_toggle_enable_special (prefs, e_account_tree_view_get_selected_type (tree_view), FALSE))
-			return;
-	}
-
-	g_return_if_fail (account != NULL);
-
-	session = e_mail_backend_get_session (prefs->priv->backend);
-
-	account_list = e_account_tree_view_get_account_list (tree_view);
-	g_return_if_fail (account_list != NULL);
-
-	if (!e_account_list_account_has_proxies (account_list, account)) {
-		e_mail_store_remove_by_account (session, account);
-		return;
-	}
-
-	parent = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
-	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
-
-	response = e_alert_run_dialog_for_args (
-		parent, "mail:ask-delete-proxy-accounts", NULL);
-
-	if (response != GTK_RESPONSE_YES) {
-		g_signal_stop_emission_by_name (tree_view, "disable-account");
-		return;
-	}
+	EMailBackend *backend;
+	const gchar *uid;
 
-	e_account_list_remove_account_proxies (account_list, account);
+	uid = camel_service_get_uid (service);
+	backend = em_account_prefs_get_backend (prefs);
 
-	e_mail_store_remove_by_account (session, account);
+	/* FIXME Kind of a gross hack.  EMailSession doesn't have
+	 *       access to EMailBackend so it can't do this itself. */
+	if (g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0)
+		vfolder_load_storage (backend);
 }
 
 static void
@@ -206,7 +130,7 @@ account_prefs_dispose (GObject *object)
 {
 	EMAccountPrefsPrivate *priv;
 
-	priv = EM_ACCOUNT_PREFS (object)->priv;
+	priv = EM_ACCOUNT_PREFS_GET_PRIVATE (object);
 
 	if (priv->backend != NULL) {
 		g_object_unref (priv->backend);
@@ -230,13 +154,30 @@ account_prefs_dispose (GObject *object)
 }
 
 static void
-account_prefs_add_account (EAccountManager *manager)
+account_prefs_constructed (GObject *object)
+{
+	EMailAccountManager *manager;
+	EMailAccountStore *store;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (em_account_prefs_parent_class)->constructed (object);
+
+	manager = E_MAIL_ACCOUNT_MANAGER (object);
+	store = e_mail_account_manager_get_store (manager);
+
+	g_signal_connect (
+		store, "service-enabled",
+		G_CALLBACK (account_prefs_service_enabled_cb), manager);
+}
+
+static void
+account_prefs_add_account (EMailAccountManager *manager)
 {
 	EMAccountPrefsPrivate *priv;
 	EMAccountEditor *emae;
 	gpointer parent;
 
-	priv = EM_ACCOUNT_PREFS (manager)->priv;
+	priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager);
 
 	if (priv->assistant != NULL) {
 		gtk_window_present (GTK_WINDOW (priv->assistant));
@@ -275,25 +216,20 @@ account_prefs_add_account (EAccountManager *manager)
 }
 
 static void
-account_prefs_edit_account (EAccountManager *manager)
+account_prefs_edit_account (EMailAccountManager *manager,
+                            EAccount *account)
 {
 	EMAccountPrefsPrivate *priv;
 	EMAccountEditor *emae;
-	EAccountTreeView *tree_view;
-	EAccount *account;
 	gpointer parent;
 
-	priv = EM_ACCOUNT_PREFS (manager)->priv;
+	priv = EM_ACCOUNT_PREFS_GET_PRIVATE (manager);
 
 	if (priv->editor != NULL) {
 		gtk_window_present (GTK_WINDOW (priv->editor));
 		return;
 	}
 
-	tree_view = e_account_manager_get_tree_view (manager);
-	account = e_account_tree_view_get_selected (tree_view);
-	g_return_if_fail (account != NULL);
-
 	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
 	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
 
@@ -320,64 +256,10 @@ account_prefs_edit_account (EAccountManager *manager)
 }
 
 static void
-account_prefs_delete_account (EAccountManager *manager)
-{
-	EMAccountPrefsPrivate *priv;
-	EAccountTreeView *tree_view;
-	EAccountList *account_list;
-	EAccount *account;
-	EMailSession *session;
-	gboolean has_proxies;
-	gpointer parent;
-	gint response;
-
-	priv = EM_ACCOUNT_PREFS (manager)->priv;
-	session = e_mail_backend_get_session (priv->backend);
-
-	account_list = e_account_manager_get_account_list (manager);
-	tree_view = e_account_manager_get_tree_view (manager);
-	account = e_account_tree_view_get_selected (tree_view);
-	g_return_if_fail (account != NULL);
-
-	/* Make sure we aren't editing anything... */
-	if (priv->editor != NULL)
-		return;
-
-	parent = gtk_widget_get_toplevel (GTK_WIDGET (manager));
-	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
-
-	has_proxies =
-		e_account_list_account_has_proxies (account_list, account);
-
-	response = e_alert_run_dialog_for_args (
-		parent, has_proxies ?
-		"mail:ask-delete-account-with-proxies" :
-		"mail:ask-delete-account", NULL);
-
-	if (response != GTK_RESPONSE_YES) {
-		g_signal_stop_emission_by_name (manager, "delete-account");
-		return;
-	}
-
-	/* Remove the account from the folder tree. */
-	if (account->enabled)
-		e_mail_store_remove_by_account (session, account);
-
-	/* Remove all the proxies the account has created. */
-	if (has_proxies)
-		e_account_list_remove_account_proxies (account_list, account);
-
-	/* Remove it from the config file. */
-	e_account_list_remove (account_list, account);
-
-	e_account_list_save (account_list);
-}
-
-static void
 em_account_prefs_class_init (EMAccountPrefsClass *class)
 {
 	GObjectClass *object_class;
-	EAccountManagerClass *account_manager_class;
+	EMailAccountManagerClass *account_manager_class;
 
 	g_type_class_add_private (class, sizeof (EMAccountPrefsPrivate));
 
@@ -385,11 +267,11 @@ em_account_prefs_class_init (EMAccountPrefsClass *class)
 	object_class->set_property = account_prefs_set_property;
 	object_class->get_property = account_prefs_get_property;
 	object_class->dispose = account_prefs_dispose;
+	object_class->constructed = account_prefs_constructed;
 
-	account_manager_class = E_ACCOUNT_MANAGER_CLASS (class);
+	account_manager_class = E_MAIL_ACCOUNT_MANAGER_CLASS (class);
 	account_manager_class->add_account = account_prefs_add_account;
 	account_manager_class->edit_account = account_prefs_edit_account;
-	account_manager_class->delete_account = account_prefs_delete_account;
 
 	g_object_class_install_property (
 		object_class,
@@ -406,41 +288,7 @@ em_account_prefs_class_init (EMAccountPrefsClass *class)
 static void
 em_account_prefs_init (EMAccountPrefs *prefs)
 {
-	EAccountManager *manager;
-	EAccountTreeView *tree_view;
-
-	prefs->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-		prefs, EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsPrivate);
-
-	manager = E_ACCOUNT_MANAGER (prefs);
-	tree_view = e_account_manager_get_tree_view (manager);
-
-	g_signal_connect (
-		tree_view, "enable-account",
-		G_CALLBACK (account_prefs_enable_account_cb), prefs);
-
-	g_signal_connect (
-		tree_view, "disable-account",
-		G_CALLBACK (account_prefs_disable_account_cb), prefs);
-}
-
-static void
-account_tree_view_sort_order_changed_cb (EAccountTreeView *tree_view,
-                                         EMailBackend *backend)
-{
-	GSList *account_uids;
-
-	g_return_if_fail (tree_view != NULL);
-	g_return_if_fail (backend != NULL);
-
-	account_uids = e_account_tree_view_get_sort_order (tree_view);
-	if (!account_uids)
-		return;
-
-	em_utils_save_accounts_sort_order (backend, account_uids);
-
-	g_slist_foreach (account_uids, (GFunc) g_free, NULL);
-	g_slist_free (account_uids);
+	prefs->priv = EM_ACCOUNT_PREFS_GET_PRIVATE (prefs);
 }
 
 GtkWidget *
@@ -448,60 +296,20 @@ em_account_prefs_new (EPreferencesWindow *window)
 {
 	EShell *shell;
 	EShellBackend *shell_backend;
-	EAccountList *account_list;
-	EAccountTreeView *tree_view;
+	EMailAccountStore *account_store;
 	EMailSession *session;
-	const gchar *data_dir;
-	GtkWidget *res;
-	GSList *account_uids;
-
-	account_list = e_get_account_list ();
-	g_return_val_if_fail (E_IS_ACCOUNT_LIST (account_list), NULL);
 
 	/* XXX Figure out a better way to get the mail backend. */
 	shell = e_preferences_window_get_shell (window);
 	shell_backend = e_shell_get_backend_by_name (shell, "mail");
 
 	session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
-	data_dir = e_shell_backend_get_data_dir (shell_backend);
+	account_store = e_mail_session_get_account_store (session);
 
-	/* Make sure the e-mail-local is initialized. */
-	e_mail_local_init (session, data_dir);
-
-	res = g_object_new (
+	return g_object_new (
 		EM_TYPE_ACCOUNT_PREFS,
-		"account-list", account_list,
+		"store", account_store,
 		"backend", shell_backend, NULL);
-
-	tree_view = e_account_manager_get_tree_view (E_ACCOUNT_MANAGER (res));
-	e_account_tree_view_set_express_mode (tree_view, e_shell_get_express_mode (shell));
-
-	g_object_bind_property (
-		e_shell_get_shell_settings (shell), "mail-sort-accounts-alpha",
-		tree_view, "sort-alpha",
-		G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
-
-	g_object_bind_property (
-		e_shell_get_shell_settings (shell), "mail-enable-local-folders",
-		tree_view, "enable-local-folders",
-		G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
-
-	g_object_bind_property (
-		e_shell_get_shell_settings (shell), "mail-enable-search-folders",
-		tree_view, "enable-search-folders",
-		G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
-
-	account_uids = em_utils_load_accounts_sort_order (E_MAIL_BACKEND (shell_backend));
-	if (account_uids) {
-		e_account_tree_view_set_sort_order (tree_view, account_uids);
-		g_slist_foreach (account_uids, (GFunc) g_free, NULL);
-		g_slist_free (account_uids);
-	}
-
-	g_signal_connect (tree_view, "sort-order-changed",
-		G_CALLBACK (account_tree_view_sort_order_changed_cb), shell_backend);
-
-	return res;
 }
 
 EMailBackend *
diff --git a/modules/mail/em-account-prefs.h b/modules/mail/em-account-prefs.h
index 667b83f..b7ba5b0 100644
--- a/modules/mail/em-account-prefs.h
+++ b/modules/mail/em-account-prefs.h
@@ -26,7 +26,7 @@
 #include <table/e-table.h>
 #include <libedataserver/e-account-list.h>
 #include <mail/e-mail-backend.h>
-#include <misc/e-account-manager.h>
+#include <mail/e-mail-account-manager.h>
 #include <widgets/misc/e-preferences-window.h>
 
 /* Standard GObject macros */
@@ -55,12 +55,12 @@ typedef struct _EMAccountPrefsClass EMAccountPrefsClass;
 typedef struct _EMAccountPrefsPrivate EMAccountPrefsPrivate;
 
 struct _EMAccountPrefs {
-	EAccountManager parent;
+	EMailAccountManager parent;
 	EMAccountPrefsPrivate *priv;
 };
 
 struct _EMAccountPrefsClass {
-	EAccountManagerClass parent_class;
+	EMailAccountManagerClass parent_class;
 };
 
 GType		em_account_prefs_get_type	(void);
diff --git a/modules/mdn/evolution-mdn.c b/modules/mdn/evolution-mdn.c
index 4311ab7..6ce5dec 100644
--- a/modules/mdn/evolution-mdn.c
+++ b/modules/mdn/evolution-mdn.c
@@ -26,7 +26,6 @@
 #include <e-util/e-account-utils.h>
 
 #include <mail/em-utils.h>
-#include <mail/e-mail-local.h>
 #include <mail/e-mail-reader.h>
 #include <mail/mail-send-recv.h>
 #include <mail/em-composer-utils.h>
@@ -188,6 +187,7 @@ mdn_notify_sender (EAccount *account,
 	CamelFolder *out_folder;
 	CamelMessageInfo *receipt_info;
 	EMailBackend *backend;
+	EMailSession *session;
 	const gchar *message_id;
 	const gchar *message_date;
 	const gchar *message_subject;
@@ -202,6 +202,7 @@ mdn_notify_sender (EAccount *account,
 	gchar *ua;
 
 	backend = e_mail_reader_get_backend (reader);
+	session = e_mail_backend_get_session (backend);
 
 	/* Tag the message immediately even though we haven't actually sent
 	 * the read receipt yet.  Not a big deal if we fail to send it, and
@@ -361,7 +362,9 @@ mdn_notify_sender (EAccount *account,
 
 	/* Send the receipt. */
 	receipt_info = camel_message_info_new (NULL);
-	out_folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_OUTBOX);
+	out_folder =
+		e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_OUTBOX);
 	camel_message_info_set_flags (
 		receipt_info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
 
diff --git a/modules/startup-wizard/evolution-startup-wizard.c b/modules/startup-wizard/evolution-startup-wizard.c
index 54727df..de15b72 100644
--- a/modules/startup-wizard/evolution-startup-wizard.c
+++ b/modules/startup-wizard/evolution-startup-wizard.c
@@ -29,7 +29,6 @@
 #include <e-util/e-import.h>
 
 #include <mail/e-mail-backend.h>
-#include <mail/e-mail-local.h>
 #include <mail/em-account-editor.h>
 #include <capplet/settings/mail-capplet-shell.h>
 #include <calendar/gui/calendar-config.h>
@@ -433,22 +432,16 @@ startup_wizard_new_assistant (EStartupWizard *extension)
 	EShell *shell;
 	EShellBackend *shell_backend;
 	EMailBackend *backend;
-	EMailSession *session;
 	EMAccountEditor *emae;
 	EConfig *config;
 	EConfigItem *config_item;
 	GtkWidget *widget;
 	GSList *items = NULL;
-	const gchar *data_dir;
 
 	shell = startup_wizard_get_shell (extension);
 	shell_backend = e_shell_get_backend_by_name (shell, "mail");
 
 	backend = E_MAIL_BACKEND (shell_backend);
-	session = e_mail_backend_get_session (backend);
-	data_dir = e_shell_backend_get_data_dir (shell_backend);
-
-	e_mail_local_init (session, data_dir);
 
 	emae = em_account_editor_new (
 		NULL, EMAE_ASSISTANT, backend,
diff --git a/plugins/dbx-import/dbx-importer.c b/plugins/dbx-import/dbx-importer.c
index b838bdf..f7bedc8 100644
--- a/plugins/dbx-import/dbx-importer.c
+++ b/plugins/dbx-import/dbx-importer.c
@@ -65,7 +65,6 @@
 #include <libedataserverui/e-source-selector-dialog.h>
 
 #include <mail/e-mail-backend.h>
-#include <mail/e-mail-local.h>
 #include <mail/em-folder-selection-button.h>
 #include <mail/mail-mt.h>
 #include <mail/mail-tools.h>
@@ -203,6 +202,8 @@ org_gnome_evolution_readdbx_getwidget (EImport *ei,
 {
 	EShell *shell;
 	EShellBackend *shell_backend;
+	EMailBackend *backend;
+	EMailSession *session;
 	GtkWidget *hbox, *w;
 	GtkLabel *label;
 	gchar *select_uri = NULL;
@@ -238,10 +239,18 @@ org_gnome_evolution_readdbx_getwidget (EImport *ei,
 		}
 	}
 #endif
+
+	shell = e_shell_get_default ();
+	shell_backend = e_shell_get_backend_by_name (shell, "mail");
+
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
+
 	if (!select_uri) {
 		const gchar *local_inbox_uri;
-		local_inbox_uri = e_mail_local_get_folder_uri (
-			E_MAIL_LOCAL_FOLDER_INBOX);
+		local_inbox_uri =
+			e_mail_session_get_local_folder_uri (
+			session, E_MAIL_LOCAL_FOLDER_INBOX);
 		select_uri = g_strdup (local_inbox_uri);
 	}
 
@@ -252,9 +261,6 @@ org_gnome_evolution_readdbx_getwidget (EImport *ei,
 
 	label = GTK_LABEL (w);
 
-	shell = e_shell_get_default ();
-	shell_backend = e_shell_get_backend_by_name (shell, "mail");
-
 	w = em_folder_selection_button_new (
 		E_MAIL_BACKEND (shell_backend),
 		_("Select folder"),
diff --git a/plugins/pst-import/pst-importer.c b/plugins/pst-import/pst-importer.c
index 8ef6012..c7d1801 100644
--- a/plugins/pst-import/pst-importer.c
+++ b/plugins/pst-import/pst-importer.c
@@ -54,7 +54,6 @@
 #include <libedataserverui/e-client-utils.h>
 
 #include <mail/e-mail-backend.h>
-#include <mail/e-mail-local.h>
 #include <mail/em-folder-selection-button.h>
 #include <mail/mail-mt.h>
 #include <mail/mail-tools.h>
@@ -228,6 +227,7 @@ get_suggested_foldername (EImportTargetURI *target)
 {
 	EShell *shell;
 	EShellBackend *shell_backend;
+	EMailBackend *backend;
 	EMailSession *session;
 	GtkWindow *window;
 	const gchar *inbox;
@@ -241,7 +241,9 @@ get_suggested_foldername (EImportTargetURI *target)
 	 *     data, I don't see how else to get to it. */
 	shell = e_shell_get_default ();
 	shell_backend = e_shell_get_backend_by_name (shell, "mail");
-	session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
+
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
 
 	foldername = NULL;
 
@@ -284,7 +286,9 @@ get_suggested_foldername (EImportTargetURI *target)
 	if (!foldername) {
 		/* Suggest a folder that is in the same mail storage as the users' inbox,
 		 * with a name derived from the .PST file */
-		inbox = e_mail_local_get_folder_uri (E_MAIL_LOCAL_FOLDER_INBOX);
+		inbox =
+			e_mail_session_get_local_folder_uri (
+			session, E_MAIL_LOCAL_FOLDER_INBOX);
 
 		delim = g_strrstr (inbox, "#");
 		if (delim != NULL) {
diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c
index d8921bc..714a6f0 100644
--- a/plugins/templates/templates.c
+++ b/plugins/templates/templates.c
@@ -33,7 +33,6 @@
 #include <e-util/e-config.h>
 
 #include <mail/e-mail-folder-utils.h>
-#include <mail/e-mail-local.h>
 #include <mail/e-mail-reader.h>
 #include <mail/e-mail-session.h>
 #include <mail/em-composer-utils.h>
@@ -764,6 +763,7 @@ create_new_message (CamelFolder *folder,
 	CamelDataWrapper *dw;
 	struct _camel_header_raw *header;
 	EMailBackend *backend;
+	EMailSession *session;
 	EShell *shell;
 	const gchar *message_uid;
 	gint i;
@@ -798,9 +798,11 @@ create_new_message (CamelFolder *folder,
 	message_uid = context->message_uid;
 
 	backend = e_mail_reader_get_backend (context->reader);
+	session = e_mail_backend_get_session (backend);
 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
-	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
+	folder = e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_TEMPLATES);
 
 	new = camel_mime_message_new ();
 	new_multipart = camel_multipart_new ();
@@ -995,7 +997,8 @@ action_reply_with_template_cb (GtkAction *action,
 }
 
 static void
-build_template_menus_recurse (GtkUIManager *ui_manager,
+build_template_menus_recurse (CamelStore *local_store,
+                              GtkUIManager *ui_manager,
                               GtkActionGroup *action_group,
                               const gchar *menu_path,
                               guint *action_count,
@@ -1003,10 +1006,9 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
                               CamelFolderInfo *folder_info,
                               EShellView *shell_view)
 {
-	CamelStore *store;
-	EShellWindow *shell_window = e_shell_view_get_shell_window (shell_view);
+	EShellWindow *shell_window;
 
-	store = e_mail_local_get_store ();
+	shell_window = e_shell_view_get_shell_window (shell_view);
 
 	while (folder_info != NULL) {
 		CamelFolder *folder;
@@ -1019,9 +1021,10 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 		guint ii;
 
 		display_name = folder_info->display_name;
+
 		/* FIXME Not passing a GCancellable or GError here. */
 		folder = camel_store_get_folder_sync (
-			store, folder_info->full_name, 0, NULL, NULL);
+			local_store, folder_info->full_name, 0, NULL, NULL);
 
 		action_name = g_strdup_printf (
 			"templates-menu-%d", *action_count);
@@ -1044,9 +1047,12 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 
 		/* Disconnect previous connection to avoid possible multiple calls because
 		 * folder is a persistent structure */
-		g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
-		g_signal_connect (folder, "changed",
-			G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
+		g_signal_handlers_disconnect_by_func (
+			folder, G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
+		g_signal_connect (
+			folder, "changed",
+			G_CALLBACK (templates_folder_msg_changed_cb),
+			shell_window);
 
 		path = g_strdup_printf ("%s/%s", menu_path, action_name);
 
@@ -1056,6 +1062,7 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 		/* Add submenus, if any. */
 		if (folder_info->child != NULL)
 			build_template_menus_recurse (
+				local_store,
 				ui_manager, action_group,
 				path, action_count, merge_id,
 				folder_info->child, shell_view);
@@ -1130,6 +1137,10 @@ static void
 got_message_draft_cb (EMsgComposer *composer,
                       GAsyncResult *result)
 {
+	EShell *shell;
+	EShellBackend *shell_backend;
+	EMailBackend *backend;
+	EMailSession *session;
 	CamelMimeMessage *message;
 	CamelMessageInfo *info;
 	CamelFolder *folder;
@@ -1157,8 +1168,15 @@ got_message_draft_cb (EMsgComposer *composer,
 
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
+	shell = e_shell_get_default ();
+	shell_backend = e_shell_get_backend_by_name (shell, "mail");
+
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
+
 	/* Get the templates folder and all UIDs of the messages there. */
-	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
+	folder = e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_TEMPLATES);
 
 	info = camel_message_info_new (NULL);
 
@@ -1201,8 +1219,11 @@ build_menu (EShellWindow *shell_window,
             GtkActionGroup *action_group)
 {
 	EShellView *shell_view;
+	EShellBackend *shell_backend;
+	EMailBackend *backend;
+	EMailSession *session;
 	CamelFolder *folder;
-	CamelStore *store;
+	CamelStore *local_store;
 	CamelFolderInfo *folder_info;
 	GtkUIManager *ui_manager;
 	guint merge_id;
@@ -1211,28 +1232,32 @@ build_menu (EShellWindow *shell_window,
 
 	ui_manager = e_shell_window_get_ui_manager (shell_window);
 	shell_view = e_shell_window_get_shell_view (shell_window, "mail");
+	shell_backend = e_shell_view_get_shell_backend (shell_view);
+
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
+	local_store = e_mail_session_get_local_store (session);
 
 	merge_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (action_group), "merge-id"));
 
 	/* Now recursively build template submenus in the pop-up menu. */
-	store = e_mail_local_get_store ();
-	folder = e_mail_local_get_folder (
-		E_MAIL_LOCAL_FOLDER_TEMPLATES);
+	folder = e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_TEMPLATES);
 	full_name = camel_folder_get_full_name (folder);
 
 	/* FIXME Not passing a GCancellable or GError here. */
 	folder_info = camel_store_get_folder_info_sync (
-		store, full_name,
+		local_store, full_name,
 		CAMEL_STORE_FOLDER_INFO_RECURSIVE |
 		CAMEL_STORE_FOLDER_INFO_FAST, NULL, NULL);
 
 	build_template_menus_recurse (
-		ui_manager, action_group,
+		local_store, ui_manager, action_group,
 		"/mail-message-popup/mail-message-templates",
 		&action_count, merge_id, folder_info,
 		shell_view);
 
-	camel_store_free_folder_info (store, folder_info);
+	camel_store_free_folder_info (local_store, folder_info);
 }
 
 static void
@@ -1325,32 +1350,49 @@ static void
 mail_shell_view_created_cb (EShellWindow *shell_window,
                             EShellView *shell_view)
 {
+	EMailBackend *backend;
+	EMailSession *session;
+	EShellBackend *shell_backend;
 	GtkUIManager *ui_manager;
 	GtkActionGroup *action_group;
 	CamelFolder *folder;
-	CamelStore *store;
+	CamelStore *local_store;
 	guint merge_id;
 
 	ui_manager = e_shell_window_get_ui_manager (shell_window);
 	e_shell_window_add_action_group (shell_window, "templates");
 	action_group = e_lookup_action_group (ui_manager, "templates");
+
 	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
-	g_object_set_data (G_OBJECT (action_group), "merge-id",
-			   GUINT_TO_POINTER (merge_id));
 
-	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
-	store = e_mail_local_get_store ();
+	g_object_set_data (
+		G_OBJECT (action_group), "merge-id",
+		GUINT_TO_POINTER (merge_id));
+
+	shell_backend = e_shell_view_get_shell_backend (shell_view);
+
+	backend = E_MAIL_BACKEND (shell_backend);
+	session = e_mail_backend_get_session (backend);
+	local_store = e_mail_session_get_local_store (session);
 
-	g_signal_connect (folder, "changed",
+	folder = e_mail_session_get_local_folder (
+		session, E_MAIL_LOCAL_FOLDER_TEMPLATES);
+
+	g_signal_connect (
+		folder, "changed",
 		G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
-	g_signal_connect (store, "folder-created",
+	g_signal_connect (
+		local_store, "folder-created",
 		G_CALLBACK (templates_folder_changed_cb), shell_window);
-	g_signal_connect (store, "folder-deleted",
+	g_signal_connect (
+		local_store, "folder-deleted",
 		G_CALLBACK (templates_folder_changed_cb), shell_window);
-	g_signal_connect (store, "folder-renamed",
+	g_signal_connect (
+		local_store, "folder-renamed",
 		G_CALLBACK (templates_folder_renamed_cb), shell_window);
 
-	g_signal_connect (shell_view, "update-actions",
+	g_signal_connect (
+		shell_view, "update-actions",
 		G_CALLBACK (update_actions_cb), action_group);
 }
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 69b8498..b257780 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -178,7 +178,8 @@ filter/e-rule-context.c
 filter/e-rule-editor.c
 filter/filter.error.xml
 [type: gettext/glade]filter/filter.ui
-mail/em-account-editor.c
+mail/e-mail-account-manager.c
+mail/e-mail-account-tree-view.c
 mail/e-mail-attachment-bar.c
 mail/e-mail-browser.c
 mail/e-mail-display.c
@@ -188,16 +189,15 @@ mail/e-mail-label-dialog.c
 mail/e-mail-label-list-store.c
 mail/e-mail-label-manager.c
 mail/e-mail-label-tree-view.c
-mail/e-mail-local.c
 mail/e-mail-migrate.c
 mail/e-mail-notebook-view.c
 mail/e-mail-reader.c
 mail/e-mail-reader-utils.c
 mail/e-mail-session.c
 mail/e-mail-session-utils.c
-mail/e-mail-store.c
 mail/e-mail-store-utils.c
 mail/e-mail-tag-editor.c
+mail/em-account-editor.c
 mail/em-composer-utils.c
 mail/em-filter-editor.c
 mail/em-filter-folder-element.c
@@ -424,8 +424,6 @@ widgets/menus/gal-view-instance-save-as-dialog.c
 widgets/menus/gal-view-new-dialog.c
 [type: gettext/glade]widgets/menus/gal-view-new-dialog.ui
 widgets/misc/ea-calendar-item.c
-widgets/misc/e-account-manager.c
-widgets/misc/e-account-tree-view.c
 widgets/misc/e-action-combo-box.c
 widgets/misc/e-activity-proxy.c
 widgets/misc/e-alert-bar.c
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 5235c1c..71194d1 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -6,8 +6,6 @@ ui_DATA = e-send-options.ui
 
 widgetsinclude_HEADERS =			\
 	e-account-combo-box.h			\
-	e-account-manager.h			\
-	e-account-tree-view.h			\
 	e-action-combo-box.h			\
 	e-activity-bar.h			\
 	e-activity-proxy.h			\
@@ -91,8 +89,6 @@ libemiscwidgets_la_CPPFLAGS =						\
 libemiscwidgets_la_SOURCES =			\
 	$(widgetsinclude_HEADERS)		\
 	e-account-combo-box.c			\
-	e-account-manager.c			\
-	e-account-tree-view.c			\
 	e-action-combo-box.c			\
 	e-activity-bar.c			\
 	e-activity-proxy.c			\



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