[evolution-ews/account-mgmt] Adapt to the new ESource API.



commit 162336f6b11c04bfe438f613df1300ee0310b6e1
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri May 4 18:22:13 2012 -0400

    Adapt to the new ESource API.

 configure.ac                                       |   16 +-
 src/Makefile.am                                    |    4 +-
 .../exchange-ews-account-listener.c                |    2 +
 .../exchange-ews-account-listener.h                |    2 -
 .../exchange-ews-account-setup.c                   |  348 --------
 src/addressbook/e-book-backend-ews-factory.c       |    5 +
 src/addressbook/e-book-backend-ews.c               |  402 ++++++----
 src/addressbook/ews-oab-decoder.h                  |    2 -
 src/calendar/e-cal-backend-ews-factory.c           |    5 +
 src/calendar/e-cal-backend-ews-utils.c             |    1 -
 src/calendar/e-cal-backend-ews.c                   |  613 ++++++++------
 src/camel/camel-ews-folder.c                       |    2 +-
 src/camel/camel-ews-store.c                        |    6 +-
 src/camel/camel-ews-transport.c                    |    3 +-
 src/camel/camel-ews-utils.c                        |  119 +---
 src/modules/Makefile.am                            |   76 ++
 src/modules/e-mail-config-ews-autodiscover.c       |  345 +++++++
 src/modules/e-mail-config-ews-autodiscover.h       |   71 ++
 src/modules/e-mail-config-ews-backend.c            |  352 ++++++++
 src/modules/e-mail-config-ews-backend.h            |   66 ++
 src/modules/e-mail-config-ews-gal.c                |  389 ++++++++
 src/modules/e-mail-config-ews-gal.h                |   65 ++
 src/modules/e-mail-config-ews-oal-combo-box.c      |  365 ++++++++
 src/modules/e-mail-config-ews-oal-combo-box.h      |   82 ++
 src/modules/e-mail-config-ews-ooo-page.c           |  937 ++++++++++++++++++++
 src/modules/e-mail-config-ews-ooo-page.h           |   80 ++
 src/modules/module-ews-backend.c                   |  822 +++++++++++++++++
 src/modules/module-ews-mail-config.c               |   43 +
 src/modules/module-ews-mail-config.error.xml       |   14 +
 src/server/Makefile.am                             |    4 +
 src/{utils => server}/camel-ews-settings.c         |   80 ++-
 src/{utils => server}/camel-ews-settings.h         |    4 +
 src/server/e-ews-connection.c                      |  894 ++++++++++++--------
 src/server/e-ews-connection.h                      |   59 +-
 src/server/e-source-ews-folder.c                   |  254 ++++++
 src/server/e-source-ews-folder.h                   |   78 ++
 src/utils/Makefile.am                              |    4 -
 src/utils/ews-esource-utils.c                      |  306 -------
 src/utils/ews-esource-utils.h                      |   65 --
 39 files changed, 5355 insertions(+), 1630 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 80f4fc3..5832644 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,7 +74,6 @@ AS_COMPILER_FLAGS(WARNING_FLAGS,
 	-Wno-unused-parameter
 	-Wno-deprecated-declarations
 	-Wdeclaration-after-statement
-	-Wno-unused-but-set-variable
 	-Werror-implicit-function-declaration
 	-Wformat-nonliteral -Wformat-security -Winit-self
 	-Wmissing-declarations -Wmissing-include-dirs
@@ -157,6 +156,11 @@ dnl ****************************
 PKG_CHECK_MODULES(EVOLUTION_SHELL, evolution-shell-3.0 >= evo_minimum_version)
 
 dnl ****************************
+dnl Check for evolution mail
+dnl ****************************
+PKG_CHECK_MODULES(EVOLUTION_MAIL, evolution-mail-3.0 >= evo_minimum_version)
+
+dnl ****************************
 dnl Check for sqlite3 
 dnl ****************************
 PKG_CHECK_MODULES(SQLITE3, sqlite3)
@@ -192,6 +196,9 @@ AC_SUBST_FILE(EVO_PLUGIN_RULE)
 dnl *******************
 dnl Special directories
 dnl *******************
+errordir=`$PKG_CONFIG --variable=errordir evolution-plugin-3.0`
+AC_SUBST(errordir)
+
 plugindir=`$PKG_CONFIG --variable=plugindir evolution-plugin-3.0`
 AC_SUBST(plugindir)
 
@@ -213,6 +220,11 @@ AC_SUBST(ecal_backenddir)
 ebook_backenddir=`$PKG_CONFIG --variable=backenddir libedata-book-1.2`
 AC_SUBST(ebook_backenddir)
 
+eds_moduledir=`$PKG_CONFIG --variable=moduledir libebackend-1.2`
+AC_SUBST(eds_moduledir)
+
+evo_moduledir=`$PKG_CONFIG --variable=moduledir evolution-shell-3.0`
+AC_SUBST(evo_moduledir)
 
 dnl *************
 dnl Gtk Doc stuff
@@ -229,11 +241,11 @@ src/server/Makefile
 src/server/tests/Makefile
 src/server/libeews.pc
 src/utils/Makefile
-src/account-setup-eplugin/Makefile
 src/addressbook/Makefile
 src/addressbook/lzx/Makefile
 src/calendar/Makefile
 src/camel/Makefile
+src/modules/Makefile
 po/Makefile.in
 ])
 AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index 5e406f0..d761b74 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = server server/tests utils camel account-setup-eplugin calendar addressbook
-DIST_SUBDIRS = server utils camel account-setup-eplugin calendar addressbook
+SUBDIRS = server server/tests utils camel calendar addressbook modules
+DIST_SUBDIRS = server utils camel calendar addressbook modules
 
 -include $(top_srcdir)/git.mk
diff --git a/src/account-setup-eplugin/exchange-ews-account-listener.c b/src/account-setup-eplugin/exchange-ews-account-listener.c
index 10e1516..0022ae9 100644
--- a/src/account-setup-eplugin/exchange-ews-account-listener.c
+++ b/src/account-setup-eplugin/exchange-ews-account-listener.c
@@ -28,8 +28,10 @@
 #include <mail/e-mail-backend.h>
 
 #include <camel/camel.h>
+#if 0  /* ACCOUNT_MGMT */
 #include <libedataserver/e-account.h>
 #include <libedataserver/e-account-list.h>
+#endif /* ACCOUNT_MGMT */
 #include <libebook/e-book.h>
 
 #include "camel/camel-ews-store-summary.h"
diff --git a/src/account-setup-eplugin/exchange-ews-account-listener.h b/src/account-setup-eplugin/exchange-ews-account-listener.h
index 399b5af..f7ccfee 100644
--- a/src/account-setup-eplugin/exchange-ews-account-listener.h
+++ b/src/account-setup-eplugin/exchange-ews-account-listener.h
@@ -44,8 +44,6 @@ struct _ExchangeEWSAccountListenerClass {
 	GObjectClass parent_class;
 };
 
-void				exchange_ews_add_esource (CamelURL *url, const gchar *folder_name, const gchar *fid, gint folder_type);
-void				exchange_ews_remove_esource (CamelURL *url, const gchar *folder_name, const gchar *fid, gint folder_type);
 GType				exchange_ews_account_listener_get_type (void);
 ExchangeEWSAccountListener *	exchange_ews_account_listener_new (void);
 
diff --git a/src/account-setup-eplugin/exchange-ews-account-setup.c b/src/account-setup-eplugin/exchange-ews-account-setup.c
index eadc36f..ba5e6ac 100644
--- a/src/account-setup-eplugin/exchange-ews-account-setup.c
+++ b/src/account-setup-eplugin/exchange-ews-account-setup.c
@@ -30,7 +30,6 @@
 
 #include <libedataserver/e-xml-hash-utils.h>
 #include <libedataserverui/e-passwords.h>
-#include <libedataserver/e-account.h>
 #include <libedataserver/eds-version.h>
 
 #include <e-util/e-dialog-utils.h>
@@ -103,36 +102,6 @@ exchange_ews_accounts_peek_config_listener ()
 	return config_listener;
 }
 
-struct _AutoDiscCallBackData {
-	EConfig *config;
-	GtkWidget *host_entry;
-	GtkWidget *oab_entry;
-};
-
-static void autodiscover_callback (EwsUrls *urls, gpointer user_data, GError *error)
-{
-	struct _AutoDiscCallBackData *cbdata = (struct _AutoDiscCallBackData *) user_data;
-
-	if (error) {
-		g_warning ("Autodiscover failed: %s", error->message);
-		e_notice (NULL, GTK_MESSAGE_ERROR, _("Autodiscover failed: %s"), error->message);
-		g_clear_error (&error);
-	}
-	if (urls) {
-		gchar *oab_url;
-
-		gtk_entry_set_text (GTK_ENTRY (cbdata->host_entry), urls->as_url);
-
-		oab_url = g_strconcat (urls->oab_url, "oab.xml", NULL);
-		gtk_entry_set_text (GTK_ENTRY (cbdata->oab_entry), oab_url);
-		g_free (oab_url);
-
-		g_free (urls->as_url);
-		g_free (urls->oab_url);
-		g_free (urls);
-	}
-}
-
 static gchar *
 get_password (EMConfigTargetSettings *target_account)
 {
@@ -175,171 +144,6 @@ get_password (EMConfigTargetSettings *target_account)
 	return password;
 }
 
-static void
-validate_credentials (GtkWidget *widget,
-                      struct _AutoDiscCallBackData *cbdata)
-{
-	EConfig *config = cbdata->config;
-	EMConfigTargetSettings *target_account = (EMConfigTargetSettings *)(config->target);
-	gchar *password = NULL;
-	CamelEwsSettings *ews_settings;
-
-	ews_settings = CAMEL_EWS_SETTINGS (target_account->storage_settings);
-
-	password = get_password (target_account);
-	/*Can there be a account without password ?*/
-	if (password && *password) {
-		e_ews_autodiscover_ws_url (
-			autodiscover_callback, cbdata,
-			target_account->email_address,
-			password,
-			camel_ews_settings_get_hosturl (ews_settings),
-			camel_network_settings_get_user (CAMEL_NETWORK_SETTINGS (ews_settings)));
-	}
-	g_free (password);
-}
-
-static void
-oab_url_changed (GtkWidget *entry,
-                 EConfig *config)
-{
-	EMConfigTargetSettings *target = (EMConfigTargetSettings *)(config->target);
-	CamelEwsSettings *ews_settings;
-	const gchar *oaburl;
-
-	ews_settings = CAMEL_EWS_SETTINGS (target->storage_settings);
-	oaburl = gtk_entry_get_text (GTK_ENTRY (entry));
-	camel_ews_settings_set_oaburl (ews_settings, oaburl);
-}
-
-static void
-host_url_changed (GtkWidget *entry,
-                  EConfig *config)
-{
-	EMConfigTargetSettings *target = (EMConfigTargetSettings *)(config->target);
-	CamelEwsSettings *ews_settings;
-	const gchar *hosturl;
-
-	ews_settings = CAMEL_EWS_SETTINGS (target->storage_settings);
-	hosturl = gtk_entry_get_text (GTK_ENTRY (entry));
-	camel_ews_settings_set_hosturl (ews_settings, hosturl);
-}
-
-GtkWidget *
-org_gnome_exchange_ews_account_setup (EPlugin *epl,
-                                      EConfigHookItemFactoryData *data)
-{
-	EMConfigTargetSettings *target_account;
-	EShell *shell;
-	CamelSettings *settings;
-	CamelEwsSettings *ews_settings;
-	CamelNetworkSettings *network_settings;
-	GtkWidget *hbox = NULL;
-	gint row;
-	GtkWidget *label, *oab_label;
-	GtkWidget *host_url, *oab_url;
-	GtkWidget *auto_discover;
-	const gchar *host;
-	const gchar *host_url_val;
-	const gchar *oab_url_val;
-	const gchar *temp, *email_id;
-	struct _AutoDiscCallBackData *cbdata;
-
-	target_account = (EMConfigTargetSettings *) data->config->target;
-	settings = target_account->storage_settings;
-
-	if (!CAMEL_IS_EWS_SETTINGS (settings))
-		return NULL;
-
-	/* Verify the storage and transport settings are shared. */
-	g_warn_if_fail (
-		target_account->storage_settings ==
-		target_account->transport_settings);
-
-	ews_settings = CAMEL_EWS_SETTINGS (settings);
-	network_settings = CAMEL_NETWORK_SETTINGS (settings);
-
-	host = camel_network_settings_get_host (network_settings);
-
-	host_url_val = camel_ews_settings_get_hosturl (ews_settings);
-	oab_url_val = camel_ews_settings_get_oaburl (ews_settings);
-	cbdata = g_new0 (struct _AutoDiscCallBackData, 1);
-	/* FIXME free cbdata */
-
-	g_object_get (data->parent, "n-rows", &row, NULL);
-
-	/* Set email_id */
-	email_id = target_account->email_address;
-	camel_ews_settings_set_email (ews_settings, email_id);
-	temp = g_strstr_len (email_id, -1, "@");
-
-	/* Don't overwrite the host if it's already been set */
-	if (temp != NULL && (host == NULL || *host == '\0')) {
-		camel_network_settings_set_host (network_settings, temp + 1);
-		host = camel_network_settings_get_host (network_settings);
-	}
-
-	if (temp != NULL && (host_url_val == NULL || *host_url_val == '\0')) {
-		gchar *temp_host_url;
-
-		temp_host_url = g_strdup_printf (
-			"https://exchange.%s/EWS/Exchange.asmx";, temp + 1);
-		camel_ews_settings_set_hosturl (ews_settings, temp_host_url);
-		host_url_val = camel_ews_settings_get_hosturl (ews_settings);
-		g_free (temp_host_url);
-	}
-
-	/* OAB url entry */
-	oab_label = gtk_label_new_with_mnemonic (_("OAB U_RL:"));
-	gtk_widget_show (oab_label);
-
-	oab_url = gtk_entry_new ();
-	gtk_label_set_mnemonic_widget (GTK_LABEL (oab_label), oab_url);
-	if (oab_url_val && *oab_url_val)
-		gtk_entry_set_text (GTK_ENTRY (oab_url), oab_url_val);
-	g_signal_connect (oab_url, "changed", G_CALLBACK (oab_url_changed), data->config);
-	gtk_widget_show (oab_url);
-
-	/* Host url and Autodiscover button */
-	hbox = gtk_hbox_new (FALSE, 6);
-	label = gtk_label_new_with_mnemonic (_("_Host URL:"));
-	gtk_widget_show (label);
-
-	host_url = gtk_entry_new ();
-	gtk_label_set_mnemonic_widget (GTK_LABEL (label), host_url);
-	if (host_url_val && *host_url_val)
-		gtk_entry_set_text (GTK_ENTRY (host_url), host_url_val);
-	else
-		gtk_entry_set_text (GTK_ENTRY (host_url), "https://exchange.server.com/EWS/Exchange.asmx";);
-	g_signal_connect (host_url, "changed", G_CALLBACK (host_url_changed), data->config);
-	gtk_box_pack_start (GTK_BOX (hbox), host_url, TRUE, TRUE, 0);
-
-	cbdata->config = data->config;
-	cbdata->host_entry = host_url;
-	cbdata->oab_entry = oab_url;
-	auto_discover = gtk_button_new_with_mnemonic (_("Fetch _URL"));
-	gtk_box_pack_start (GTK_BOX (hbox), auto_discover, FALSE, FALSE, 0);
-	g_signal_connect (G_OBJECT(auto_discover), "clicked",  G_CALLBACK(validate_credentials), cbdata);
-
-	/* Add Host entry */
-	gtk_table_attach (GTK_TABLE (data->parent), label, 0, 1, row, row + 1, 0, 0, 0, 0);
-	gtk_widget_show_all (GTK_WIDGET (hbox));
-	gtk_table_attach (GTK_TABLE (data->parent), GTK_WIDGET (hbox), 1, 2, row, row + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
-	row++;
-
-	/* Add OAB entry */
-	gtk_table_attach (GTK_TABLE (data->parent), oab_label, 0, 1, row, row + 1, 0, 0, 0, 0);
-	gtk_table_attach (GTK_TABLE (data->parent), oab_url, 1, 2, row, row + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
-	row++;
-
-	/* If evolution is offline, dsensitize fetch button and oab entry */
-	shell = e_shell_get_default ();
-	if (!e_shell_get_online (shell))
-		gtk_widget_set_sensitive (auto_discover, FALSE);
-
-	return hbox;
-}
-
 gboolean
 org_gnome_exchange_ews_check_options (EPlugin *epl,
                                       EConfigHookPageCheckData *data)
@@ -397,69 +201,6 @@ struct _oab_setting_data {
 };
 
 static void
-clear_combo (GtkComboBoxText *combo_box)
-{
-	GtkListStore *store;
-
-	g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo_box));
-
-	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)));
-	gtk_list_store_clear (store);
-}
-
-static void
-update_camel_url (struct _oab_setting_data *cbdata)
-{
-	EMConfigTargetSettings *target = (EMConfigTargetSettings *) cbdata->config->target;
-	CamelEwsSettings *ews_settings;
-
-	ews_settings = CAMEL_EWS_SETTINGS (target->storage_settings);
-
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cbdata->check))) {
-		gint num;
-
-		gtk_widget_set_sensitive (cbdata->hbox, TRUE);
-		camel_ews_settings_set_oab_offline (ews_settings, TRUE);
-		num = gtk_combo_box_get_active (GTK_COMBO_BOX (cbdata->combo_text));
-
-		/* Set the active oal */
-		if (cbdata->oals && num != -1) {
-			gchar *mangled_oal;
-			EwsOAL *oal = g_slist_nth_data (cbdata->oals, num);
-
-			mangled_oal = g_strconcat (oal->id, ":", oal->name, NULL);
-			camel_ews_settings_set_oal_selected (ews_settings, mangled_oal);
-			g_free (mangled_oal);
-		}
-	} else {
-		gtk_widget_set_sensitive (cbdata->hbox, FALSE);
-		camel_ews_settings_set_oab_offline (ews_settings, FALSE);
-		camel_ews_settings_set_oal_selected (ews_settings, NULL);
-
-		if (cbdata->oals == NULL)
-			clear_combo (GTK_COMBO_BOX_TEXT (cbdata->combo_text));
-	}
-}
-
-static void
-cache_setting_toggled (GtkToggleButton *check,
-                       gpointer user_data)
-{
-	struct _oab_setting_data *cbdata = (struct _oab_setting_data *) user_data;
-
-	update_camel_url (cbdata);
-}
-
-static void
-combo_selection_changed (GtkComboBox *combo,
-                         gpointer user_data)
-{
-	struct _oab_setting_data *cbdata = (struct _oab_setting_data *) user_data;
-
-	update_camel_url (cbdata);
-}
-
-static void
 ews_oal_list_ready (GObject *obj,
                     GAsyncResult *res,
                     gpointer user_data)
@@ -490,9 +231,7 @@ ews_oal_list_ready (GObject *obj,
 	}
 	cbdata->oals = oals;
 
-	g_signal_handlers_block_by_func (cbdata->combo_text, combo_selection_changed, cbdata);
 	clear_combo (GTK_COMBO_BOX_TEXT (cbdata->combo_text));
-	g_signal_handlers_unblock_by_func (cbdata->combo_text, combo_selection_changed, cbdata);
 
 	for (l = oals; l != NULL; l = g_slist_next (l)) {
 		EwsOAL *oal = l->data;
@@ -525,15 +264,12 @@ fetch_button_clicked_cb (GtkButton *button,
 	network_settings = CAMEL_NETWORK_SETTINGS (target->storage_settings);
 
 	/* De-sensitize fetch_button and get the list from the server */
-	g_signal_handlers_block_by_func (cbdata->combo_text, combo_selection_changed, cbdata);
 
 	clear_combo (GTK_COMBO_BOX_TEXT (cbdata->combo_text));
 	gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cbdata->combo_text), _("Fetching..."));
 	gtk_combo_box_set_active (GTK_COMBO_BOX (cbdata->combo_text), 0);
 	gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
 
-	g_signal_handlers_unblock_by_func (cbdata->combo_text, combo_selection_changed, cbdata);
-
 	/* Fetch the oab lists from server */
 	oab_url = camel_ews_settings_get_oaburl (ews_settings);
 	user = camel_network_settings_get_user (network_settings);
@@ -548,18 +284,6 @@ fetch_button_clicked_cb (GtkButton *button,
 	g_free (password);
 }
 
-static void
-ews_oal_free (gpointer data,
-              gpointer user_data)
-{
-	EwsOAL *oal = (EwsOAL *) data;
-
-	g_free (oal->id);
-	g_free (oal->dn);
-	g_free (oal->name);
-	g_free (oal);
-}
-
 static gboolean
 table_deleted_cb (GtkWidget *widget,
                   gpointer user_data)
@@ -578,76 +302,6 @@ table_deleted_cb (GtkWidget *widget,
 	return FALSE;
 }
 
-static void
-init_widgets (struct _oab_setting_data *cbdata)
-{
-	EMConfigTargetSettings *target_account;
-	CamelEwsSettings *ews_settings;
-	const gchar *selected_list;
-	const gchar *oab_url;
-
-	target_account = (EMConfigTargetSettings *) cbdata->config->target;
-
-	ews_settings = CAMEL_EWS_SETTINGS (target_account->storage_settings);
-	selected_list = camel_ews_settings_get_oal_selected (ews_settings);
-	oab_url = camel_ews_settings_get_oaburl (ews_settings);
-
-	if (camel_ews_settings_get_oab_offline (ews_settings)) {
-		g_signal_handlers_block_by_func (cbdata->check, cache_setting_toggled, cbdata);
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbdata->check), TRUE);
-		g_signal_handlers_unblock_by_func (cbdata->check, cache_setting_toggled, cbdata);
-
-		/* selected list will be of form "id:name" */
-		if (selected_list && gtk_combo_box_get_active (GTK_COMBO_BOX (cbdata->combo_text)) == -1) {
-			const gchar *tmp;
-
-			tmp = strrchr (selected_list, ':');
-			gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (cbdata->combo_text), tmp + 1);
-
-			g_signal_handlers_block_by_func (cbdata->combo_text, combo_selection_changed, cbdata);
-			gtk_combo_box_set_active (GTK_COMBO_BOX (cbdata->combo_text), 0);
-			g_signal_handlers_unblock_by_func (cbdata->combo_text, combo_selection_changed, cbdata);
-		}
-	} else
-		gtk_widget_set_sensitive (cbdata->hbox, FALSE);
-
-	/* If oab url is not set, dsensitize*/
-	if (!oab_url) {
-		gtk_widget_set_sensitive (cbdata->check, FALSE);
-		gtk_widget_set_sensitive (cbdata->hbox, FALSE);
-	} else
-		gtk_widget_set_sensitive (cbdata->check, TRUE);
-}
-
-static void
-ews_prepare_receive_options_page (GtkWidget *page,
-                                  gpointer user_data)
-{
-	struct _oab_setting_data *cbdata = (struct _oab_setting_data *) user_data;
-	GtkWidget *receive_options;
-
-	receive_options = e_config_page_get (cbdata->config, "20.receive_options");
-	if (receive_options == page)
-		init_widgets (cbdata);
-}
-
-static void
-ews_assistant_page_changed_cb (GtkAssistant *assistant,
-                               GtkWidget *page,
-                               gpointer user_data)
-{
-	ews_prepare_receive_options_page (page, user_data);
-}
-
-static void
-ews_page_switched_cb (GtkNotebook *notebook,
-                      GtkWidget *page,
-                      guint page_num,
-                      gpointer user_data)
-{
-	ews_prepare_receive_options_page (page, user_data);
-}
-
 GtkWidget *
 org_gnome_ews_oab_settings (EPlugin *epl,
                             EConfigHookItemFactoryData *data)
@@ -706,9 +360,7 @@ org_gnome_ews_oab_settings (EPlugin *epl,
 	cbdata->config = data->config;
 
 	/* Connect the signals */
-	g_signal_connect (check, "toggled", G_CALLBACK (cache_setting_toggled), cbdata);
 	g_signal_connect (G_OBJECT (fetch_button), "clicked",  G_CALLBACK (fetch_button_clicked_cb), cbdata);
-	g_signal_connect (GTK_COMBO_BOX (oal_combo), "changed", G_CALLBACK (combo_selection_changed), cbdata);
 
 	/* Init widgets when the page is changed to receiving options page */
 	if (GTK_IS_ASSISTANT (data->config->widget))
diff --git a/src/addressbook/e-book-backend-ews-factory.c b/src/addressbook/e-book-backend-ews-factory.c
index 8f736fb..c928d4c 100644
--- a/src/addressbook/e-book-backend-ews-factory.c
+++ b/src/addressbook/e-book-backend-ews-factory.c
@@ -26,6 +26,9 @@
 #endif
 
 #include <libedata-book/e-book-backend-factory.h>
+
+#include "server/e-source-ews-folder.h"
+
 #include "e-book-backend-ews.h"
 
 typedef EBookBackendFactory EBookBackendEwsFactory;
@@ -63,6 +66,8 @@ e_book_backend_ews_factory_init (EBookBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+	e_source_ews_folder_type_register (type_module);
+
 	e_book_backend_ews_factory_register_type (type_module);
 }
 
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index 7773f1d..40605d8 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -35,34 +35,39 @@
 #include <glib/gstdio.h>
 #include <glib/gi18n-lib.h>
 
-#include "libedataserver/e-sexp.h"
-#include "libedataserver/e-data-server-util.h"
-#include "libedataserver/e-flag.h"
-#include "libedataserver/e-url.h"
-#include "libebook/e-contact.h"
-#include "libebook/e-destination.h"
-#include "libedata-book/e-book-backend-sexp.h"
-#include "libedata-book/e-data-book.h"
-#include "libedata-book/e-data-book-view.h"
-#include "e-book-backend-ews.h"
-#include "e-book-backend-sqlitedb.h"
+#include <libedataserver/e-data-server-util.h>
+#include <libedataserver/e-flag.h>
+#include <libedataserver/e-sexp.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-offline.h>
+#include <libedataserver/e-url.h>
+
+#include <libebook/e-contact.h>
+#include <libebook/e-destination.h>
+
+#include <libedata-book/e-book-backend-sexp.h>
+#include <libedata-book/e-data-book.h>
+#include <libedata-book/e-data-book-view.h>
+
 #include "lzx/ews-oal-decompress.h"
-#include "ews-oab-decoder.h"
 
 #include "server/e-ews-item-change.h"
 #include "server/e-ews-message.h"
 #include "server/e-ews-connection.h"
 #include "server/e-ews-item.h"
+#include "server/e-source-ews-folder.h"
 
 #include "utils/e-ews-query-to-restriction.h"
 
+#include "e-book-backend-ews.h"
+#include "e-book-backend-sqlitedb.h"
+#include "ews-oab-decoder.h"
+
 #define d(x) x
 
 #define EDB_ERROR(_code) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL)
 #define EDB_ERROR_EX(_code,_msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
 
-G_DEFINE_TYPE (EBookBackendEws, e_book_backend_ews, E_TYPE_BOOK_BACKEND)
-
 static gboolean ebews_fetch_items (EBookBackendEws *ebews,  GSList *items, gboolean store_to_cache, GSList **vcards, GCancellable *cancellable, GError **error);
 
 typedef struct {
@@ -97,7 +102,6 @@ struct _EBookBackendEwsPrivate {
 	GThread *dthread;
 	SyncDelta *dlock;
 
-	ECredentials *credentials;
 	GCancellable *cancellable;
 };
 
@@ -121,6 +125,47 @@ enum {
 #define PRIV_LOCK(p)   (g_static_rec_mutex_lock (&(p)->rec_mutex))
 #define PRIV_UNLOCK(p) (g_static_rec_mutex_unlock (&(p)->rec_mutex))
 
+/* Forward Declarations */
+static void	e_book_backend_ews_authenticator_init
+				(ESourceAuthenticatorInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	EBookBackendEws,
+	e_book_backend_ews,
+	E_TYPE_BOOK_BACKEND,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_book_backend_ews_authenticator_init))
+
+static CamelEwsSettings *
+book_backend_ews_get_collection_settings (EBookBackendEws *backend)
+{
+	ESource *source;
+	ESource *collection;
+	ESourceCamel *extension;
+	ESourceRegistry *registry;
+	CamelSettings *settings;
+	const gchar *extension_name;
+
+	source = e_backend_get_source (E_BACKEND (backend));
+	registry = e_book_backend_get_registry (E_BOOK_BACKEND (backend));
+
+	extension_name = e_source_camel_get_extension_name ("ews");
+	e_source_camel_generate_subtype ("ews", CAMEL_TYPE_EWS_SETTINGS);
+
+	/* The collection settings live in our parent data source. */
+	collection = e_source_registry_find_extension (
+		registry, source, extension_name);
+	g_return_val_if_fail (collection != NULL, NULL);
+
+	extension = e_source_get_extension (collection, extension_name);
+	settings = e_source_camel_get_settings (extension);
+
+	g_object_unref (collection);
+
+	return CAMEL_EWS_SETTINGS (settings);
+}
+
 static void
 convert_error_to_edb_error (GError **perror)
 {
@@ -158,12 +203,6 @@ convert_error_to_edb_error (GError **perror)
 	*perror = error;
 }
 
-static void
-ews_auth_required (EBookBackend *backend)
-{
-	e_book_backend_notify_auth_required (backend, TRUE, NULL);
-}
-
 static gboolean
 ews_remove_attachments (const gchar *attachment_dir)
 {
@@ -2358,7 +2397,7 @@ ebews_start_refreshing (EBookBackendEws *ebews)
 	PRIV_LOCK (priv);
 
 	if (e_backend_get_online (E_BACKEND (ebews)) &&
-	    priv->cnc != NULL&& priv->marked_for_offline)
+	    priv->cnc != NULL && priv->marked_for_offline)
 		fetch_deltas (ebews);
 
 	PRIV_UNLOCK (priv);
@@ -2410,14 +2449,20 @@ e_book_backend_ews_start_book_view (EBookBackend *backend,
 	GCancellable *cancellable;
 	GSList *ids = NULL, *mailboxes = NULL, *l, *contacts = NULL, *c;
 	EwsFolderId *fid;
+	ESource *source;
+	ESourceRegistry *registry;
+	ESourceEwsFolder *extension;
+	const gchar *extension_name;
 	GError *error = NULL;
 	gboolean includes_last_item;
-	ESource *source;
 
 	ebews = E_BOOK_BACKEND_EWS (backend);
 	priv = ebews->priv;
 	query = e_data_book_view_get_card_query (book_view);
 
+	registry = e_book_backend_get_registry (backend);
+	source = e_backend_get_source (E_BACKEND (backend));
+
 	e_data_book_view_ref (book_view);
 	e_data_book_view_notify_progress (book_view, -1, _("Searching..."));
 
@@ -2434,15 +2479,23 @@ e_book_backend_ews_start_book_view (EBookBackend *backend,
 		return;
 	}
 
-	if (!priv->cnc) {
-		error = EDB_ERROR (AUTHENTICATION_REQUIRED);
-		ews_auth_required (backend);
-		e_data_book_view_notify_complete (book_view, error);
-		e_data_book_view_unref (book_view);
-		g_error_free (error);
-		return;
+	if (priv->cnc == NULL) {
+		/* XXX Why doesn't start_book_view()
+		 *     get passed a GCancellable? */
+		e_source_registry_authenticate_sync (
+			registry, source,
+			E_SOURCE_AUTHENTICATOR (backend),
+			NULL, &error);
+		if (error != NULL) {
+			e_data_book_view_notify_complete (book_view, error);
+			e_data_book_view_unref (book_view);
+			g_error_free (error);
+			return;
+		}
 	}
 
+	g_return_if_fail (priv->cnc != NULL);
+
 	ebews_start_refreshing (ebews);
 
 	if (priv->ebsdb &&
@@ -2459,7 +2512,9 @@ e_book_backend_ews_start_book_view (EBookBackend *backend,
 		return;
 	}
 
-	source = e_backend_get_source (E_BACKEND (backend));
+	extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+	extension = e_source_get_extension (source, extension_name);
+
 	cancellable = g_cancellable_new ();
 
 	/* FIXME Need to convert the Ids from EwsLegacyId format to EwsId format using
@@ -2467,7 +2522,7 @@ e_book_backend_ews_start_book_view (EBookBackend *backend,
 	 * 2007 and 2007_SP1 */
 	fid = g_new0 (EwsFolderId, 1);
 	fid->id = g_strdup (priv->folder_id);
-	fid->change_key = e_source_get_duped_property (source, "change-key");
+	fid->change_key = e_source_ews_folder_dup_change_key (extension);
 	ids = g_slist_append (ids, fid);
 
 	/* We do not scan until we reach the last_item as it might be good enough to show first 100
@@ -2560,58 +2615,62 @@ e_book_backend_ews_load_source (EBookBackend *backend,
 {
 	EBookBackendEws *cbews;
 	EBookBackendEwsPrivate *priv;
+	CamelEwsSettings *settings;
+	ESourceExtension *extension;
 	const gchar *cache_dir, *email;
-	const gchar *folder_name;
-	const gchar *offline, *is_gal;
-	GError *err = NULL;
+	const gchar *display_name;
+	const gchar *extension_name;
+	const gchar *gal_uid;
+	const gchar *uid;
 
 	cbews = E_BOOK_BACKEND_EWS (backend);
 	priv = cbews->priv;
 
 	cache_dir = e_book_backend_get_cache_dir (backend);
-	email = e_source_get_property (source, "email");
-	is_gal = e_source_get_property (source, "gal");
+	settings = book_backend_ews_get_collection_settings (cbews);
+	email = camel_ews_settings_get_email (settings);
 
-	if (is_gal && !strcmp (is_gal, "1"))
-		priv->is_gal = TRUE;
+	uid = e_source_get_uid (source);
+	gal_uid = camel_ews_settings_get_gal_uid (settings);
+	priv->is_gal = (g_strcmp0 (uid, gal_uid) == 0);
 
-	if (!priv->is_gal) {
-		priv->folder_id = e_source_get_duped_property (source, "folder-id");
-		folder_name = e_source_peek_name (source);
+	display_name = e_source_get_display_name (source);
 
-		priv->ebsdb = e_book_backend_sqlitedb_new (cache_dir, email, priv->folder_id, folder_name, TRUE, &err);
-		if (err) {
-			g_propagate_error (perror, err);
-			return;
-		}
+	extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+	extension = e_source_get_extension (source, extension_name);
 
-		offline = e_source_get_property (source, "offline_sync");
-		if (offline  && g_str_equal (offline, "1"))
-			priv->marked_for_offline = TRUE;
-	} else {
-		priv->folder_id = e_source_get_duped_property (source, "oal_id");
+	priv->folder_id = e_source_ews_folder_dup_id (
+		E_SOURCE_EWS_FOLDER (extension));
 
-		/* If folder_id is present it means the GAL is marked for offline usage, we do not check for offline_sync property */
-		if (priv->folder_id) {
-			priv->folder_name = g_strdup (e_source_peek_name (source));
-			priv->oab_url = e_source_get_duped_property (source, "oab_url");
+	priv->ebsdb = e_book_backend_sqlitedb_new (
+		cache_dir, email, priv->folder_id,
+		display_name, TRUE, perror);
 
-			/* setup stagging dir, remove any old files from there */
-			priv->attachment_dir = g_build_filename (cache_dir, "attachments", NULL);
-			g_mkdir_with_parents (priv->attachment_dir, 0777);
+	if (priv->ebsdb == NULL)
+		return;
 
-			priv->ebsdb = e_book_backend_sqlitedb_new (cache_dir, email, priv->folder_id, priv->folder_name, TRUE, &err);
-			if (err) {
-				g_propagate_error (perror, err);
-				return;
-			}
-			priv->marked_for_offline = TRUE;
-			priv->is_writable = FALSE;
-		}
-	}
+	if (!priv->is_gal) {
+		extension_name = E_SOURCE_EXTENSION_OFFLINE;
+		extension = e_source_get_extension (source, extension_name);
 
-	if (e_backend_get_online (E_BACKEND (backend)))
-		e_book_backend_notify_auth_required (backend, TRUE, NULL);
+		priv->marked_for_offline =
+			e_source_offline_get_stay_synchronized (
+			E_SOURCE_OFFLINE (extension));
+
+	/* If folder_id is present it means the GAL is marked for
+	 * offline usage, we do not check for offline_sync property */
+	} else if (priv->folder_id != NULL) {
+		priv->folder_name = g_strdup (display_name);
+		priv->oab_url = camel_ews_settings_dup_oaburl (settings);
+
+		/* setup stagging dir, remove any old files from there */
+		priv->attachment_dir = g_build_filename (
+			cache_dir, "attachments", NULL);
+		g_mkdir_with_parents (priv->attachment_dir, 0777);
+
+		priv->marked_for_offline = TRUE;
+		priv->is_writable = FALSE;
+	}
 }
 
 static void
@@ -2624,80 +2683,6 @@ e_book_backend_ews_remove (EBookBackend *backend,
 }
 
 static void
-e_book_backend_ews_authenticate_user (EBookBackend *backend,
-                                      GCancellable *cancellable,
-                                      ECredentials *credentials)
-{
-	EBookBackendEws *ebews;
-	EBookBackendEwsPrivate *priv;
-	EEwsConnection *cnc = NULL;
-	ESource *esource;
-	GError *error = NULL;
-	GSList *folders = NULL, *ids = NULL;
-	EwsFolderId *fid = NULL;
-
-	const gchar *host_url;
-	const gchar *read_only;
-
-	ebews = E_BOOK_BACKEND_EWS (backend);
-	priv = ebews->priv;
-
-	if (!e_backend_get_online (E_BACKEND (backend))) {
-		e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
-		return;
-	}
-
-	if (priv->cnc) {
-		e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
-		return;
-	}
-
-	esource = e_backend_get_source (E_BACKEND (backend));
-	host_url = e_source_get_property (esource, "hosturl");
-	read_only = e_source_get_property (esource, "read_only");
-
-	cnc = e_ews_connection_new (host_url, e_credentials_peek (credentials, E_CREDENTIALS_KEY_USERNAME),
-					  e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD),
-					  NULL, NULL, &error);
-
-	if ((read_only && !strcmp (read_only, "true")) || priv->is_gal) {
-		priv->is_writable = FALSE;
-	} else
-		priv->is_writable = TRUE;
-
-	if (!error && cnc) {
-		/* a dummy request to make sure we have a authenticated connection */
-		fid = g_new0 (EwsFolderId, 1);
-		fid->id = g_strdup ("contacts");
-		fid->is_distinguished_id = TRUE;
-		ids = g_slist_append (ids, fid);
-		e_ews_connection_get_folder_sync (
-			cnc, EWS_PRIORITY_MEDIUM, "Default",
-			NULL, ids, &folders, cancellable, &error);
-
-		e_ews_folder_free_fid (fid);
-		g_slist_free (ids);
-		ids = NULL;
-	}
-
-	if (error) {
-		convert_error_to_edb_error (&error);
-
-		e_book_backend_notify_auth_required (backend, TRUE, priv->credentials);
-		e_book_backend_notify_opened (backend, error);
-		g_object_unref (cnc);
-		return;
-	}
-
-	priv->cnc = cnc;
-	priv->username = e_source_get_duped_property (esource, "username");
-	priv->password = g_strdup (e_credentials_peek (credentials, E_CREDENTIALS_KEY_PASSWORD));
-
-	e_book_backend_notify_opened (backend, EDB_ERROR (SUCCESS));
-	e_book_backend_notify_readonly (backend, !priv->is_writable);
-}
-
-static void
 e_book_backend_ews_notify_online_cb (EBookBackend *backend,
                                      GParamSpec *spec)
 {
@@ -2724,7 +2709,6 @@ e_book_backend_ews_notify_online_cb (EBookBackend *backend,
 
 			e_book_backend_notify_readonly (backend, !ebews->priv->is_writable);
 			e_book_backend_notify_online (backend, TRUE);
-			e_book_backend_notify_auth_required (backend, TRUE, NULL);
 		}
 	}
 }
@@ -2798,13 +2782,35 @@ e_book_backend_ews_open (EBookBackend *backend,
                          GCancellable *cancellable,
                          gboolean only_if_exists)
 {
-	GError *error = NULL;
+	EBookBackendEws *cbews;
+	ESourceRegistry *registry;
 	ESource *source;
+	GError *error = NULL;
 
+	cbews = E_BOOK_BACKEND_EWS (backend);
+
+	registry = e_book_backend_get_registry (backend);
 	source = e_backend_get_source (E_BACKEND (backend));
 	e_book_backend_ews_load_source (backend, source, only_if_exists, &error);
+
+	if (error == NULL) {
+		gboolean need_to_authenticate;
+
+		PRIV_LOCK (cbews->priv);
+		need_to_authenticate =
+			(cbews->priv->cnc == NULL) &&
+			(e_backend_get_online (E_BACKEND (backend)));
+		PRIV_UNLOCK (cbews->priv);
+
+		if (need_to_authenticate)
+			e_source_registry_authenticate_sync (
+				registry, source,
+				E_SOURCE_AUTHENTICATOR (backend),
+				cancellable, &error);
+	}
+
 	convert_error_to_edb_error (&error);
-	e_data_book_respond_open (book, opid, error);
+	e_book_backend_respond_opened (backend, book, opid, error);
 }
 
 /**
@@ -2891,9 +2897,6 @@ e_book_backend_ews_dispose (GObject *object)
 		priv->ebsdb = NULL;
 	}
 
-	e_credentials_free (priv->credentials);
-	priv->credentials = NULL;
-
 	g_static_rec_mutex_free (&priv->rec_mutex);
 
 	g_free (priv);
@@ -2902,6 +2905,98 @@ e_book_backend_ews_dispose (GObject *object)
 	G_OBJECT_CLASS (e_book_backend_ews_parent_class)->dispose (object);
 }
 
+static ESourceAuthenticationResult
+book_backend_ews_try_password_sync (ESourceAuthenticator *authenticator,
+                                    const GString *password,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+	EBookBackendEws *backend;
+	EEwsConnection *connection;
+	ESourceAuthenticationResult result;
+	CamelEwsSettings *ews_settings;
+	CamelNetworkSettings *network_settings;
+	EwsFolderId *fid = NULL;
+	GSList *folders = NULL;
+	GSList *ids = NULL;
+	gchar *hosturl;
+	gchar *user;
+	GError *local_error = NULL;
+
+	/* This tests the password by fetching the contacts folder. */
+
+	backend = E_BOOK_BACKEND_EWS (authenticator);
+	ews_settings = book_backend_ews_get_collection_settings (backend);
+	hosturl = camel_ews_settings_dup_hosturl (ews_settings);
+
+	network_settings = CAMEL_NETWORK_SETTINGS (ews_settings);
+	user = camel_network_settings_dup_user (network_settings);
+
+	connection = e_ews_connection_new (
+		hosturl, user, password->str, NULL, NULL, error);
+
+	if (connection == NULL) {
+		result = E_SOURCE_AUTHENTICATION_ERROR;
+		goto exit;
+	}
+
+	fid = g_new0 (EwsFolderId, 1);
+	fid->id = g_strdup ("contacts");
+	fid->is_distinguished_id = TRUE;
+	ids = g_slist_append (ids, fid);
+
+	e_ews_connection_get_folder_sync (
+		connection, EWS_PRIORITY_MEDIUM, "Default",
+		NULL, ids, &folders, cancellable, &local_error);
+
+	e_ews_folder_free_fid (fid);
+	g_slist_free (ids);
+	ids = NULL;
+
+	if (local_error == NULL) {
+
+		PRIV_LOCK (backend->priv);
+
+		if (backend->priv->cnc != NULL)
+			g_object_unref (backend->priv->cnc);
+		backend->priv->cnc = g_object_ref (connection);
+
+		/* Stash the username and password for later
+		 * reuse in Offline Address Book connections. */
+		g_free (backend->priv->username);
+		g_free (backend->priv->password);
+		backend->priv->username = g_strdup (user);
+		backend->priv->password = g_strdup (password->str);
+
+		PRIV_UNLOCK (backend->priv);
+
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+	} else {
+		gboolean auth_failed;
+
+		auth_failed = g_error_matches (
+			local_error, EWS_CONNECTION_ERROR,
+			EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED);
+
+		if (auth_failed) {
+			g_clear_error (&local_error);
+			result = E_SOURCE_AUTHENTICATION_REJECTED;
+		} else {
+			g_propagate_error (error, local_error);
+			result = E_SOURCE_AUTHENTICATION_ERROR;
+		}
+	}
+
+	g_object_unref (connection);
+
+exit:
+	g_free (hosturl);
+	g_free (user);
+
+	return result;
+}
+
 static void
 e_book_backend_ews_class_init (EBookBackendEwsClass *klass)
 {
@@ -2921,7 +3016,6 @@ e_book_backend_ews_class_init (EBookBackendEwsClass *klass)
 	parent_class->get_contact             = e_book_backend_ews_get_contact;
 	parent_class->get_contact_list        = e_book_backend_ews_get_contact_list;
 	parent_class->remove                  = e_book_backend_ews_remove;
-	parent_class->authenticate_user       = e_book_backend_ews_authenticate_user;
 	parent_class->start_book_view         = e_book_backend_ews_start_book_view;
 	parent_class->stop_book_view          = e_book_backend_ews_stop_book_view;
 
@@ -2929,6 +3023,12 @@ e_book_backend_ews_class_init (EBookBackendEwsClass *klass)
 }
 
 static void
+e_book_backend_ews_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = book_backend_ews_try_password_sync;
+}
+
+static void
 e_book_backend_ews_init (EBookBackendEws *backend)
 {
 	EBookBackendEws *bews;
diff --git a/src/addressbook/ews-oab-decoder.h b/src/addressbook/ews-oab-decoder.h
index d948966..cfc6551 100644
--- a/src/addressbook/ews-oab-decoder.h
+++ b/src/addressbook/ews-oab-decoder.h
@@ -22,8 +22,6 @@
 #ifndef _EWS_OAB_DECODER
 #define _EWS_OAB_DECODER
 
-#include <glib.h>
-#include <glib-object.h>
 #include <gio/gio.h>
 #include <libebook/e-contact.h>
 
diff --git a/src/calendar/e-cal-backend-ews-factory.c b/src/calendar/e-cal-backend-ews-factory.c
index 8647402..e9996d3 100644
--- a/src/calendar/e-cal-backend-ews-factory.c
+++ b/src/calendar/e-cal-backend-ews-factory.c
@@ -12,6 +12,9 @@
 #include <string.h>
 
 #include <libedata-cal/e-cal-backend-factory.h>
+
+#include "server/e-source-ews-folder.h"
+
 #include "e-cal-backend-ews.h"
 
 #define FACTORY_NAME "ews"
@@ -106,6 +109,8 @@ e_cal_backend_ews_todos_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+	e_source_ews_folder_type_register (type_module);
+
 	e_cal_backend_ews_events_factory_register_type (type_module);
 	e_cal_backend_ews_journal_factory_register_type (type_module);
 	e_cal_backend_ews_todos_factory_register_type (type_module);
diff --git a/src/calendar/e-cal-backend-ews-utils.c b/src/calendar/e-cal-backend-ews-utils.c
index edfd485..7177908 100644
--- a/src/calendar/e-cal-backend-ews-utils.c
+++ b/src/calendar/e-cal-backend-ews-utils.c
@@ -35,7 +35,6 @@
 #include <libecal/e-cal-recur.h>
 #include <libecal/e-cal-time-util.h>
 #include <libsoup/soup-misc.h>
-#include <libedataserver/e-source-list.h>
 
 #include "server/e-ews-connection.h"
 #include "server/e-ews-message.h"
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index c9d70a5..40c2e2e 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -27,25 +27,33 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+
 #include <glib/gstdio.h>
 #include <glib/gi18n-lib.h>
-#include "libedataserver/e-xml-hash-utils.h"
-#include "libedataserver/e-url.h"
+
+#include <camel/camel.h>
+
+#include <libedataserver/eds-version.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-xml-hash-utils.h>
+#include <libedataserver/e-url.h>
+
 #include <libedata-cal/e-cal-backend-cache.h>
 #include <libedata-cal/e-cal-backend-file-store.h>
 #include <libedata-cal/e-cal-backend-util.h>
+
 #include <libecal/e-cal-component.h>
 #include <libecal/e-cal-time-util.h>
+
 #include <libical/icaltz-util.h>
 #include <libical/icalcomponent.h>
 #include <libical/icalproperty.h>
 #include <libical/icalparameter.h>
-#include <camel/camel.h>
-#include <libedataserver/eds-version.h>
 
 #include "server/e-ews-item-change.h"
 #include "server/e-ews-message.h"
 #include "server/e-soap-response.h"
+#include "server/e-source-ews-folder.h"
 
 #include "utils/ews-camel-common.h"
 
@@ -65,7 +73,7 @@
 #define gmtime_r(tp,tmp) (gmtime(tp)?(*(tmp)=*gmtime(tp),(tmp)):0)
 #endif
 
-G_DEFINE_TYPE (ECalBackendEws, e_cal_backend_ews, E_TYPE_CAL_BACKEND)
+typedef struct _SyncItemsClosure SyncItemsClosure;
 
 /* Private part of the CalBackendEws structure */
 struct _ECalBackendEwsPrivate {
@@ -88,10 +96,19 @@ struct _ECalBackendEwsPrivate {
 	gboolean refreshing;
 	GHashTable *item_id_hash;
 
-	ECredentials *credentials;
 	GCancellable *cancellable;
 };
 
+struct _SyncItemsClosure {
+	ECalBackendEws *backend;
+	EEwsConnection *connection;
+	gchar *sync_state;
+	gboolean includes_last_item;
+	GSList *items_created;
+	GSList *items_deleted;
+	GSList *items_updated;
+};
+
 #define PRIV_LOCK(p)   (g_static_rec_mutex_lock (&(p)->rec_mutex))
 #define PRIV_UNLOCK(p) (g_static_rec_mutex_unlock (&(p)->rec_mutex))
 
@@ -117,13 +134,74 @@ struct _ECalBackendEwsPrivate {
 		}								\
 	} G_STMT_END
 
-#define PARENT_TYPE E_TYPE_CAL_BACKEND
-static ECalBackendClass *parent_class = NULL;
 static void ews_cal_sync_items_ready_cb (GObject *obj, GAsyncResult *res, gpointer user_data);
 static void ews_cal_component_get_item_id (ECalComponent *comp, gchar **itemid, gchar **changekey);
 static gboolean ews_start_sync	(gpointer data);
 static icaltimezone * e_cal_get_timezone_from_ical_component (ECalBackend *backend, icalcomponent *comp);
 
+/* Forward Declarations */
+static void	e_cal_backend_ews_authenticator_init
+				(ESourceAuthenticatorInterface *interface);
+
+G_DEFINE_TYPE_WITH_CODE (
+	ECalBackendEws,
+	e_cal_backend_ews,
+	E_TYPE_CAL_BACKEND,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_cal_backend_ews_authenticator_init))
+
+static void
+sync_items_closure_free (SyncItemsClosure *closure)
+{
+	g_object_unref (closure->backend);
+	g_object_unref (closure->connection);
+	g_free (closure->sync_state);
+
+	g_slist_free_full (
+		closure->items_created,
+		(GDestroyNotify) g_object_unref);
+
+	g_slist_free_full (
+		closure->items_updated,
+		(GDestroyNotify) g_object_unref);
+
+	g_slist_free_full (
+		closure->items_deleted,
+		(GDestroyNotify) g_free);
+
+	g_slice_free (SyncItemsClosure, closure);
+}
+
+static CamelEwsSettings *
+cal_backend_ews_get_collection_settings (ECalBackendEws *backend)
+{
+	ESource *source;
+	ESource *collection;
+	ESourceCamel *extension;
+	ESourceRegistry *registry;
+	CamelSettings *settings;
+	const gchar *extension_name;
+
+	source = e_backend_get_source (E_BACKEND (backend));
+	registry = e_cal_backend_get_registry (E_CAL_BACKEND (backend));
+
+	extension_name = e_source_camel_get_extension_name ("ews");
+	e_source_camel_generate_subtype ("ews", CAMEL_TYPE_EWS_SETTINGS);
+
+	/* The collection settings live in our parent data source. */
+	collection = e_source_registry_find_extension (
+		registry, source, extension_name);
+	g_return_val_if_fail (collection != NULL, NULL);
+
+	extension = e_source_get_extension (collection, extension_name);
+	settings = e_source_camel_get_settings (extension);
+
+	g_object_unref (collection);
+
+	return CAMEL_EWS_SETTINGS (settings);
+}
+
 static void
 convert_error_to_edc_error (GError **perror)
 {
@@ -201,8 +279,8 @@ e_cal_backend_ews_internal_get_timezone (ECalBackend *backend,
 	if (cbews->priv->store)
 		zone = (icaltimezone *) e_cal_backend_store_get_timezone (cbews->priv->store, tzid);
 
-	if (!zone && E_CAL_BACKEND_CLASS (parent_class)->internal_get_timezone)
-		zone = E_CAL_BACKEND_CLASS (parent_class)->internal_get_timezone (backend, tzid);
+	if (!zone && E_CAL_BACKEND_CLASS (e_cal_backend_ews_parent_class)->internal_get_timezone)
+		zone = E_CAL_BACKEND_CLASS (e_cal_backend_ews_parent_class)->internal_get_timezone (backend, tzid);
 
 	return zone;
 }
@@ -537,99 +615,38 @@ add_comps_to_item_id_hash (ECalBackendEws *cbews)
 	g_slist_free (comps);
 }
 
-static gboolean
-connect_to_server (ECalBackendEws *cbews,
-                   const gchar *username,
-                   const gchar *password,
-                   GError **error)
-{
-	ECalBackendEwsPrivate *priv;
-	ESource *esource;
-
-	priv = cbews->priv;
-	esource = e_backend_get_source (E_BACKEND (cbews));
-
-	PRIV_LOCK (priv);
-
-	if (e_backend_get_online (E_BACKEND (cbews)) &&
-	    priv->cnc == NULL && password != NULL) {
-		const gchar *host_url;
-		GSList *folders = NULL, *ids = NULL;
-		EwsFolderId *fid = NULL;
-		EEwsConnection *cnc = NULL;
-		GError *err = NULL;
-
-		/* If we can be called a second time while the first is still
-		 * "outstanding", we need a bit of a rethink... */
-		g_assert (!priv->opening_ctx && !priv->opening_cal);
-
-		priv->user_email = e_source_get_duped_property (esource, "email");
-
-		host_url = e_source_get_property (esource, "hosturl");
-		cnc = e_ews_connection_new (host_url, username, password,
-						  NULL, NULL, error);
-
-		fid = g_new0 (EwsFolderId, 1);
-		fid->id = g_strdup (priv->folder_id);
-		ids = g_slist_append (ids, fid);
-		e_ews_connection_get_folder_sync (
-			cnc, EWS_PRIORITY_MEDIUM, "Default", NULL,
-			ids, &folders, priv->cancellable, &err);
-
-		e_ews_folder_free_fid (fid);
-		g_slist_free (ids);
-		ids = NULL;
-
-		if (err) {
-			g_object_unref (cnc);
-			g_propagate_error (error, err);
-			PRIV_UNLOCK (priv);
-
-			e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbews), TRUE, priv->credentials);
-
-			return FALSE;
-		}
-
-		g_object_unref ((EEwsFolder *) folders->data);
-		g_slist_free (folders);
-		folders = NULL;
-
-		priv->cnc = cnc;
-
-		/* Trigger an update request, which will test our authentication */
-		ews_start_sync (cbews);
-		PRIV_UNLOCK (priv);
-		return TRUE;
-	}
-
-	PRIV_UNLOCK (priv);
-	return FALSE;
-}
-
-static gboolean
+static void
 e_cal_backend_ews_open (ECalBackend *backend,
                         EDataCal *cal,
-                        guint32 context,
+                        guint32 opid,
                         GCancellable *cancellable,
-                        gboolean only_if_exists,
-                        const gchar *username,
-                        const gchar *password,
-                        GError **error)
+                        gboolean only_if_exists)
 {
 	ECalBackendEws *cbews;
 	ECalBackendEwsPrivate *priv;
-	ESource *esource;
+	ESourceRegistry *registry;
+	ESource *source;
 	const gchar *cache_dir;
+	gboolean need_to_authenticate;
+	GError *error = NULL;
 
 	cbews = (ECalBackendEws *) backend;
 	priv = cbews->priv;
 
+	registry = e_cal_backend_get_registry (backend);
 	cache_dir = e_cal_backend_get_cache_dir (backend);
-	esource = e_backend_get_source (E_BACKEND (cbews));
+	source = e_backend_get_source (E_BACKEND (cbews));
 
 	PRIV_LOCK (priv);
+
 	if (!priv->store) {
-		priv->folder_id = e_source_get_duped_property (esource, "folder-id");
+		ESourceEwsFolder *extension;
+		const gchar *extension_name;
+
+		extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+		extension = e_source_get_extension (source, extension_name);
+		priv->folder_id = e_source_ews_folder_dup_id (extension);
+
 		priv->storage_path = g_build_filename (cache_dir, priv->folder_id, NULL);
 
 		priv->store = e_cal_backend_file_store_new (priv->storage_path);
@@ -637,82 +654,24 @@ e_cal_backend_ews_open (ECalBackend *backend,
 		add_comps_to_item_id_hash (cbews);
 
 		if (priv->default_zone)
-			e_cal_backend_store_set_default_timezone (priv->store, priv->default_zone);
-	}
-	PRIV_UNLOCK (priv);
-
-	if (connect_to_server (cbews, username, password, error)) {
-		priv->opening_cal = cal;
-		priv->opening_ctx = context;
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static void
-e_cal_backend_ews_open_compat (ECalBackend *backend,
-                               EDataCal *cal,
-                               guint32 opid,
-                               GCancellable *cancellable,
-                               gboolean only_if_exists)
-{
-	GError *error = NULL;
-	ECalBackendEws *cbews = E_CAL_BACKEND_EWS (backend);
-	ECalBackendEwsPrivate *priv = cbews->priv;
-	const gchar *user_name = NULL, *password = NULL;
-	gboolean ret;
-
-	if (priv->credentials)	{
-		user_name = e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME);
-		password = e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_PASSWORD);
-	}
-
-	ret = e_cal_backend_ews_open (backend, cal, opid, cancellable, only_if_exists, user_name,
-				password, &error);
-
-	if (!priv->credentials)
-		e_cal_backend_notify_auth_required (backend, TRUE, priv->credentials);
-
-	e_cal_backend_notify_opened (backend, NULL);
-	convert_error_to_edc_error (&error);
-	e_data_cal_respond_open (cal, opid, error);
-}
-
-static void
-e_cal_backend_ews_authenticate_user (ECalBackend *backend,
-                                     GCancellable *cancellable,
-                                     ECredentials *credentials)
-{
-	ECalBackendEws        *cbews;
-	ECalBackendEwsPrivate *priv;
-	GError *error = NULL;
-
-	cbews = E_CAL_BACKEND_EWS (backend);
-	priv  = cbews->priv;
-
-	PRIV_LOCK (priv);
-
-	e_credentials_free (priv->credentials);
-	priv->credentials = NULL;
-
-	if (!credentials || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
-		PRIV_UNLOCK (priv);
-		g_propagate_error (&error, EDC_ERROR (AuthenticationFailed));
-		e_cal_backend_notify_opened (backend, error);
-		return;
+			e_cal_backend_store_set_default_timezone (
+				priv->store, priv->default_zone);
 	}
 
-	priv->credentials = e_credentials_new_clone (credentials);
-
-	connect_to_server (cbews, e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME),
-			   e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_PASSWORD), &error);
+	need_to_authenticate =
+		(priv->cnc == NULL) &&
+		(e_backend_get_online (E_BACKEND (backend)));
 
 	PRIV_UNLOCK (priv);
 
+	if (need_to_authenticate)
+		e_source_registry_authenticate_sync (
+			registry, source,
+			E_SOURCE_AUTHENTICATOR (backend),
+			cancellable, &error);
+
 	convert_error_to_edc_error (&error);
-	e_cal_backend_notify_opened (backend, error);
+	e_cal_backend_respond_opened (backend, cal, opid, error);
 }
 
 static void
@@ -1486,7 +1445,6 @@ ews_create_object_cb (GObject *object,
 	icalproperty *icalprop;
 	icalcomponent *icalcomp;
 	guint n_attach;
-	gboolean result;
 	EEwsItem *item;
 
 	/* get a list of ids from server (single item) */
@@ -1508,7 +1466,7 @@ ews_create_object_cb (GObject *object,
 		items = g_slist_append (items, item_id->id);
 
 		/* get calender uid from server*/
-		result = e_ews_connection_get_items_sync (
+		e_ews_connection_get_items_sync (
 			cnc, EWS_PRIORITY_MEDIUM,
 			items,
 			"IdOnly",
@@ -3414,55 +3372,23 @@ exit:
 	g_free (sync_data->master_uid);
 	g_free (sync_data->sync_state);
 	g_free (sync_data);
-	g_object_unref (cbews);
 }
 
 static void
-ews_cal_sync_items_ready_cb (GObject *obj,
-                             GAsyncResult *res,
-                             gpointer user_data)
+cal_backend_ews_process_folder_items (ECalBackendEws *backend,
+                                      EEwsConnection *connection,
+                                      const gchar *sync_state,
+                                      gboolean includes_last_item,
+                                      GSList *items_created,
+                                      GSList *items_updated,
+                                      GSList *items_deleted)
 {
-	EEwsConnection *cnc;
-	ECalBackendEws *cbews;
 	ECalBackendEwsPrivate *priv;
-	GSList *items_created = NULL, *items_updated = NULL;
-	GSList *items_deleted = NULL, *l[2], *m, *cal_item_ids = NULL, *task_item_ids = NULL;
-	gchar *sync_state = NULL;
-	gboolean includes_last_item;
-	GError *error = NULL;
+	GSList *l[2], *m, *cal_item_ids = NULL, *task_item_ids = NULL;
 	struct _ews_sync_data *sync_data = NULL;
 	gint i;
 
-	cnc = (EEwsConnection *) obj;
-	cbews = (ECalBackendEws *) user_data;
-	priv = cbews->priv;
-
-	e_ews_connection_sync_folder_items_finish	(cnc, res, &sync_state, &includes_last_item,
-							 &items_created, &items_updated,
-							 &items_deleted, &error);
-
-	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
-	    g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_CANCELLED)) {
-		g_clear_error (&error);
-		g_object_unref (cbews);
-		return;
-	}
-
-	/*FIXME invoke a dummy request in authenticate user to ensure we have a valid connection to avoid this mess */
-	if (!g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED))
-		e_cal_backend_notify_readonly (E_CAL_BACKEND (cbews), FALSE);
-
-	if (error != NULL) {
-		g_warning ("Unable to Sync changes %s \n", error->message);
-
-		PRIV_LOCK (priv);
-		priv->refreshing = FALSE;
-		PRIV_UNLOCK (priv);
-
-		g_clear_error (&error);
-		g_object_unref (cbews);
-		return;
-	}
+	priv = backend->priv;
 
 	l[0] = items_created;
 	l[1] = items_updated;
@@ -3478,7 +3404,6 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 				cal_item_ids = g_slist_append (cal_item_ids, g_strdup (id->id));
 			else if (type == E_EWS_ITEM_TYPE_TASK)
 				task_item_ids = g_slist_append (task_item_ids, g_strdup (id->id));
-			g_object_unref (item);
 		}
 	}
 
@@ -3492,36 +3417,34 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 		PRIV_UNLOCK (priv);
 
 		if (comp)
-			ews_cal_delete_comp (cbews, comp, item_id);
-
-		g_free (m->data);
+			ews_cal_delete_comp (backend, comp, item_id);
 	}
 	e_cal_backend_store_thaw_changes (priv->store);
 
 	if (!cal_item_ids && !task_item_ids && !includes_last_item) {
 		e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, sync_state);
 		e_ews_connection_sync_folder_items (
-			g_object_ref (priv->cnc), EWS_PRIORITY_MEDIUM,
+			connection,
+			EWS_PRIORITY_MEDIUM,
 			sync_state, priv->folder_id,
 			"IdOnly", NULL,
 			EWS_MAX_FETCH_COUNT,
 			priv->cancellable,
 			ews_cal_sync_items_ready_cb,
-			g_object_ref (cbews));
-		g_free (sync_state);
+			g_object_ref (backend));
 		goto exit;
 	}
 
 	if (cal_item_ids || task_item_ids) {
 		sync_data = g_new0 (struct _ews_sync_data, 1);
-		sync_data->cbews = g_object_ref (cbews);
-		sync_data->sync_state = sync_state;
+		sync_data->cbews = g_object_ref (backend);
+		sync_data->sync_state = g_strdup (sync_state);
 		sync_data->sync_pending = !includes_last_item;
 	}
 
 	if (cal_item_ids)
 		e_ews_connection_get_items (
-			cnc,
+			connection,
 			EWS_PRIORITY_MEDIUM,
 			cal_item_ids,
 			"IdOnly",
@@ -3533,7 +3456,8 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 
 	if (task_item_ids)
 		e_ews_connection_get_items (
-			cnc, EWS_PRIORITY_MEDIUM,
+			connection,
+			EWS_PRIORITY_MEDIUM,
 			task_item_ids,
 			"AllProperties",
 			NULL,
@@ -3552,15 +3476,92 @@ exit:
 		g_slist_foreach (task_item_ids, (GFunc) g_free, NULL);
 		g_slist_free (task_item_ids);
 	}
+}
+
+static gboolean
+cal_backend_ews_sync_items_idle_cb (gpointer user_data)
+{
+	SyncItemsClosure *closure = user_data;
 
-	if (items_created)
-		g_slist_free (items_created);
-	if (items_updated)
-		g_slist_free (items_updated);
-	if (items_deleted)
-		g_slist_free (items_deleted);
+	cal_backend_ews_process_folder_items (
+		closure->backend,
+		closure->connection,
+		closure->sync_state,
+		closure->includes_last_item,
+		closure->items_created,
+		closure->items_updated,
+		closure->items_deleted);
 
-	g_object_unref (cbews);
+	return FALSE;
+}
+
+static void
+ews_cal_sync_items_ready_cb (GObject *source_object,
+                             GAsyncResult *result,
+                             gpointer user_data)
+{
+	ECalBackendEws *backend;
+	EEwsConnection *connection;
+	GSList *items_created = NULL;
+	GSList *items_updated = NULL;
+	GSList *items_deleted = NULL;
+	gboolean includes_last_item;
+	gchar *sync_state = NULL;
+	GError *error = NULL;
+
+	connection = E_EWS_CONNECTION (source_object);
+	backend = E_CAL_BACKEND_EWS (user_data);
+
+	e_ews_connection_sync_folder_items_finish (
+		connection, result,
+		&sync_state,
+		&includes_last_item,
+		&items_created,
+		&items_updated,
+		&items_deleted,
+		&error);
+
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		g_error_free (error);
+		g_object_unref (backend);
+		return;
+	}
+
+	/* XXX Why are there two different error codes for cancellation? */
+	if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_CANCELLED)) {
+		g_error_free (error);
+		g_object_unref (backend);
+		return;
+	}
+
+	if (!g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED))
+		e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), FALSE);
+
+	if (error == NULL) {
+		cal_backend_ews_process_folder_items (
+			backend, connection,
+			sync_state, includes_last_item,
+			items_created, items_updated, items_deleted);
+	} else {
+		g_warn_if_fail (items_created == NULL);
+		g_warn_if_fail (items_updated == NULL);
+		g_warn_if_fail (items_deleted == NULL);
+
+		PRIV_LOCK (backend->priv);
+		backend->priv->refreshing = FALSE;
+		PRIV_UNLOCK (backend->priv);
+
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+	}
+
+	g_slist_free_full (items_created, (GDestroyNotify) g_object_unref);
+	g_slist_free_full (items_updated, (GDestroyNotify) g_object_unref);
+	g_slist_free_full (items_deleted, (GDestroyNotify) g_free);
+
+	g_free (sync_state);
+
+	g_object_unref (backend);
 }
 
 static gboolean
@@ -3897,7 +3898,7 @@ e_cal_backend_ews_get_backend_property (ECalBackend *backend,
 		prop_value = e_cal_component_get_as_string (comp);
 		g_object_unref (comp);
 	} else {
-		E_CAL_BACKEND_CLASS (parent_class)->get_backend_property (backend, cal, opid, cancellable, prop_name);
+		E_CAL_BACKEND_CLASS (e_cal_backend_ews_parent_class)->get_backend_property (backend, cal, opid, cancellable, prop_name);
 		return;
 	}
 
@@ -3929,8 +3930,6 @@ e_cal_backend_ews_notify_online_cb (ECalBackend *backend,
 		priv->read_only = FALSE;
 		e_cal_backend_notify_online (backend, TRUE);
 		e_cal_backend_notify_readonly (backend, priv->read_only);
-		if (e_cal_backend_is_opened (backend))
-		      e_cal_backend_notify_auth_required (backend, TRUE, priv->credentials);
 	} else {
 		switch_offline (E_CAL_BACKEND_EWS (backend));
 		e_cal_backend_notify_readonly (backend, priv->read_only);
@@ -3963,8 +3962,7 @@ e_cal_backend_ews_dispose (GObject *object)
 		priv->cnc = NULL;
 	}
 
-	if (G_OBJECT_CLASS (parent_class)->dispose)
-		(* G_OBJECT_CLASS (parent_class)->dispose) (object);
+	G_OBJECT_CLASS (e_cal_backend_ews_parent_class)->dispose (object);
 }
 
 /* Finalize handler for the file backend */
@@ -4015,41 +4013,127 @@ e_cal_backend_ews_finalize (GObject *object)
 
 	g_hash_table_destroy (priv->item_id_hash);
 
-	e_credentials_free (priv->credentials);
-	priv->credentials = NULL;
-
 	g_free (priv);
 	cbews->priv = NULL;
 
-	if (G_OBJECT_CLASS (parent_class)->finalize)
-		(* G_OBJECT_CLASS (parent_class)->finalize) (object);
+	G_OBJECT_CLASS (e_cal_backend_ews_parent_class)->finalize (object);
 }
 
-/* Object initialization function for the file backend */
-static void
-e_cal_backend_ews_init (ECalBackendEws *cbews)
+static ESourceAuthenticationResult
+cal_backend_ews_try_password_sync (ESourceAuthenticator *authenticator,
+                                   const GString *password,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
-	ECalBackendEwsPrivate *priv;
+	ECalBackendEws *backend;
+	ECalBackendStore *store;
+	EEwsConnection *connection;
+	ESourceAuthenticationResult result;
+	CamelEwsSettings *ews_settings;
+	CamelNetworkSettings *network_settings;
+	GSList *items_created = NULL;
+	GSList *items_updated = NULL;
+	GSList *items_deleted = NULL;
+	gboolean includes_last_item = FALSE;
+	const gchar *sync_state;
+	gchar *sync_state_inout;
+	gchar *hosturl;
+	gchar *user;
+	GError *local_error = NULL;
 
-	priv = g_new0 (ECalBackendEwsPrivate, 1);
+	/* This tests the password by synchronizing the folder. */
 
-	/* create the mutex for thread safety */
-	g_static_rec_mutex_init (&priv->rec_mutex);
-	priv->item_id_hash = g_hash_table_new_full
-						(g_str_hash, g_str_equal,
-						 (GDestroyNotify) g_free,
-						 (GDestroyNotify) g_object_unref);
-	priv->default_zone = icaltimezone_get_utc_timezone ();
-	priv->cancellable = g_cancellable_new ();
+	backend = E_CAL_BACKEND_EWS (authenticator);
+	ews_settings = cal_backend_ews_get_collection_settings (backend);
+	hosturl = camel_ews_settings_dup_hosturl (ews_settings);
 
-	cbews->priv = priv;
+	network_settings = CAMEL_NETWORK_SETTINGS (ews_settings);
+	user = camel_network_settings_dup_user (network_settings);
 
-	g_signal_connect (
-		cbews, "notify::online",
-		G_CALLBACK (e_cal_backend_ews_notify_online_cb), NULL);
+	connection = e_ews_connection_new (
+		hosturl, user, password->str, NULL, NULL, error);
+
+	g_free (hosturl);
+	g_free (user);
+
+	if (connection == NULL)
+		return E_SOURCE_AUTHENTICATION_ERROR;
+
+	store = backend->priv->store;
+	sync_state = e_cal_backend_store_get_key_value (store, SYNC_KEY);
+	sync_state_inout = g_strdup (sync_state);
+
+	e_ews_connection_sync_folder_items_sync (
+		connection,
+		EWS_PRIORITY_MEDIUM,
+		&sync_state_inout,
+		backend->priv->folder_id,
+		"IdOnly", NULL,
+		EWS_MAX_FETCH_COUNT,
+		&includes_last_item,
+		&items_created,
+		&items_updated,
+		&items_deleted,
+		cancellable, &local_error);
+
+	if (local_error == NULL) {
+		SyncItemsClosure *closure;
+
+		/* We can now report the password was accepted.
+		 * Because a password dialog may be stuck in a busy
+		 * state, process the synchronization results from an
+		 * idle callback so we don't delay the authentication
+		 * session any longer than neccessary. */
+
+		/* This takes ownership of the item lists. */
+		closure = g_slice_new0 (SyncItemsClosure);
+		closure->backend = g_object_ref (backend);
+		closure->connection = g_object_ref (connection);
+		closure->includes_last_item = includes_last_item;
+		closure->items_created = items_created;
+		closure->items_deleted = items_deleted;
+		closure->items_updated = items_updated;
+
+		g_idle_add_full (
+			G_PRIORITY_DEFAULT_IDLE,
+			cal_backend_ews_sync_items_idle_cb, closure,
+			(GDestroyNotify) sync_items_closure_free);
+
+		PRIV_LOCK (backend->priv);
+		if (backend->priv->cnc != NULL)
+			g_object_unref (backend->priv->cnc);
+		backend->priv->cnc = g_object_ref (connection);
+		PRIV_UNLOCK (backend->priv);
+
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+	} else {
+		gboolean auth_failed;
+
+		/* Make sure we're not leaking anything. */
+		g_warn_if_fail (items_created == NULL);
+		g_warn_if_fail (items_updated == NULL);
+		g_warn_if_fail (items_deleted == NULL);
+
+		auth_failed = g_error_matches (
+			local_error, EWS_CONNECTION_ERROR,
+			EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED);
+
+		if (auth_failed) {
+			g_clear_error (&local_error);
+			result = E_SOURCE_AUTHENTICATION_REJECTED;
+		} else {
+			g_propagate_error (error, local_error);
+			result = E_SOURCE_AUTHENTICATION_ERROR;
+		}
+	}
+
+	g_free (sync_state_inout);
+	g_object_unref (connection);
+
+	return result;
 }
 
-/* Class initialization function for the ews backend */
 static void
 e_cal_backend_ews_class_init (ECalBackendEwsClass *class)
 {
@@ -4059,8 +4143,6 @@ e_cal_backend_ews_class_init (ECalBackendEwsClass *class)
 	object_class = (GObjectClass *) class;
 	backend_class = (ECalBackendClass *) class;
 
-	parent_class = g_type_class_peek_parent (class);
-
 	object_class->dispose = e_cal_backend_ews_dispose;
 	object_class->finalize = e_cal_backend_ews_finalize;
 
@@ -4073,8 +4155,7 @@ e_cal_backend_ews_class_init (ECalBackendEwsClass *class)
 	backend_class->add_timezone = e_cal_backend_ews_add_timezone;
 	backend_class->get_timezone = e_cal_backend_ews_get_timezone;
 
-	backend_class->open = e_cal_backend_ews_open_compat;
-	backend_class->authenticate_user = e_cal_backend_ews_authenticate_user;
+	backend_class->open = e_cal_backend_ews_open;
 	backend_class->refresh = e_cal_backend_ews_refresh;
 	backend_class->get_object = e_cal_backend_ews_get_object;
 	backend_class->get_object_list = e_cal_backend_ews_get_object_list;
@@ -4093,3 +4174,33 @@ e_cal_backend_ews_class_init (ECalBackendEwsClass *class)
 	/* backend_class->get_changes = e_cal_backend_ews_get_changes; */
 	backend_class->internal_get_timezone = e_cal_backend_ews_internal_get_timezone;
 }
+
+static void
+e_cal_backend_ews_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = cal_backend_ews_try_password_sync;
+}
+
+static void
+e_cal_backend_ews_init (ECalBackendEws *cbews)
+{
+	ECalBackendEwsPrivate *priv;
+
+	priv = g_new0 (ECalBackendEwsPrivate, 1);
+
+	/* create the mutex for thread safety */
+	g_static_rec_mutex_init (&priv->rec_mutex);
+	priv->item_id_hash = g_hash_table_new_full
+						(g_str_hash, g_str_equal,
+						 (GDestroyNotify) g_free,
+						 (GDestroyNotify) g_object_unref);
+	priv->default_zone = icaltimezone_get_utc_timezone ();
+	priv->cancellable = g_cancellable_new ();
+
+	cbews->priv = priv;
+
+	g_signal_connect (
+		cbews, "notify::online",
+		G_CALLBACK (e_cal_backend_ews_notify_online_cb), NULL);
+}
+
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index 36ae586..f50c061 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -45,12 +45,12 @@ which needs to be better organized via functions */
 #include <libical/icalcomponent.h>
 #include <libical/icalparser.h>
 
+#include "server/camel-ews-settings.h"
 #include "server/e-ews-connection.h"
 #include "server/e-ews-item-change.h"
 #include "server/e-ews-message.h"
 
 #include "utils/ews-camel-common.h"
-#include "utils/camel-ews-settings.h"
 
 #include "camel-ews-folder.h"
 #include "camel-ews-private.h"
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index be33b7b..f7881e3 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -38,12 +38,10 @@
 
 #include <libedataserver/e-flag.h>
 
+#include "server/camel-ews-settings.h"
 #include "server/e-ews-item-change.h"
 #include "server/e-ews-message.h"
 
-#include "utils/camel-ews-settings.h"
-#include "utils/ews-esource-utils.h"
-
 #include "camel-ews-folder.h"
 #include "camel-ews-store.h"
 #include "camel-ews-summary.h"
@@ -167,11 +165,9 @@ ews_store_construct (CamelService *service,
                      GError **error)
 {
 	CamelEwsStore *ews_store;
-	CamelEwsStorePrivate *priv;
 	gchar *summary_file, *session_storage_path;
 
 	ews_store = (CamelEwsStore *) service;
-	priv = ews_store->priv;
 
 	/* Disable virtual trash and junk folders. Exchange has real
 	 * folders for that */
diff --git a/src/camel/camel-ews-transport.c b/src/camel/camel-ews-transport.c
index 6cc575b..32f85ee 100644
--- a/src/camel/camel-ews-transport.c
+++ b/src/camel/camel-ews-transport.c
@@ -30,7 +30,8 @@
 
 #include <glib/gi18n-lib.h>
 
-#include "utils/camel-ews-settings.h"
+#include "server/camel-ews-settings.h"
+
 #include "utils/ews-camel-common.h"
 
 #include "camel-ews-store.h"
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index 701e81b..cf5f29f 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -30,11 +30,9 @@
 #include <glib/gi18n-lib.h>
 #include <glib/gstdio.h>
 
+#include "server/camel-ews-settings.h"
 #include "server/e-ews-message.h"
 
-#include "utils/camel-ews-settings.h"
-#include "utils/ews-esource-utils.h"
-
 #include "camel-ews-utils.h"
 
 #define SUBFOLDER_DIR_NAME     "subfolders"
@@ -320,44 +318,13 @@ camel_ews_utils_build_folder_info (CamelEwsStore *store,
 	return fi;
 }
 
-struct remove_esrc_data {
-	gchar *fid;
-	CamelURL *account_url;
-	EwsFolderType ftype;
-};
-
-static gboolean ews_do_remove_esource (gpointer user_data)
-{
-	struct remove_esrc_data *remove_data = user_data;
-
-	ews_esource_utils_remove_esource (remove_data->fid,
-					  remove_data->account_url,
-					  remove_data->ftype);
-
-	camel_url_free (remove_data->account_url);
-	g_free (remove_data->fid);
-	g_free (remove_data);
-
-	return FALSE;
-}
-
 static void
 sync_deleted_folders (CamelEwsStore *store,
                       GSList *deleted_folders)
 {
 	CamelEwsStoreSummary *ews_summary = store->summary;
-	CamelEwsSettings *ews_settings;
-	CamelSettings *settings;
-	CamelService *service;
-	const gchar *email;
 	GSList *l;
 
-	service = CAMEL_SERVICE (store);
-	settings = camel_service_get_settings (service);
-
-	ews_settings = CAMEL_EWS_SETTINGS (settings);
-	email = camel_ews_settings_get_email (ews_settings);
-
 	for (l = deleted_folders; l != NULL; l = g_slist_next (l)) {
 		const gchar *fid = l->data;
 		EwsFolderType ftype;
@@ -375,15 +342,6 @@ sync_deleted_folders (CamelEwsStore *store,
 			camel_store_folder_deleted ((CamelStore *) store, fi);
 
 			g_clear_error (&error);
-		} else {
-			struct remove_esrc_data *remove_data = g_new0 (struct remove_esrc_data, 1);
-
-			remove_data->fid = g_strdup (fid);
-			remove_data->account_url = camel_service_new_camel_url (service);
-			remove_data->ftype = ftype;
-
-			/* This uses GConf so has to be done in the main thread */
-			g_idle_add_full (G_PRIORITY_DEFAULT, ews_do_remove_esource, remove_data, NULL);
 		}
 	}
 }
@@ -425,11 +383,7 @@ sync_updated_folders (CamelEwsStore *store,
 		const EwsFolderId *fid, *pfid;
 
 		ftype = e_ews_folder_get_folder_type (ews_folder);
-		if (ftype == EWS_FOLDER_TYPE_CALENDAR ||
-		    ftype == EWS_FOLDER_TYPE_TASKS ||
-		    ftype == EWS_FOLDER_TYPE_CONTACTS) {
-			/* TODO Update esource */
-		} else if (ftype != EWS_FOLDER_TYPE_MAILBOX)
+		if (ftype != EWS_FOLDER_TYPE_MAILBOX)
 			continue;
 
 		fid = e_ews_folder_get_id (ews_folder);
@@ -516,58 +470,11 @@ add_folder_to_summary (CamelEwsStore *store,
 	camel_ews_store_summary_set_folder_unread (ews_summary, fid->id, unread);
 }
 
-struct add_esrc_data {
-	EEwsFolder *folder;
-	gchar *account_uri;
-	gchar *account_name;
-	gchar *username;
-	gchar *email_id;
-	gchar *hosturl;
-	gint refresh_timeout;
-};
-
-static gboolean ews_do_add_esource (gpointer user_data)
-{
-	struct add_esrc_data *add_data = user_data;
-
-	ews_esource_utils_add_esource (add_data->folder, add_data->account_uri,
-				       add_data->account_name,
-				       add_data->username, add_data->email_id,
-				       add_data->hosturl, add_data->refresh_timeout);
-
-	g_object_unref (add_data->folder);
-	g_free (add_data->account_uri);
-	g_free (add_data->account_name);
-	g_free (add_data->username);
-	g_free (add_data->email_id);
-	g_free (add_data->hosturl);
-	g_free (add_data);
-
-	return FALSE;
-}
-
 static void
 sync_created_folders (CamelEwsStore *ews_store,
                       GSList *created_folders)
 {
-	CamelNetworkSettings *network_settings;
-	CamelEwsSettings *ews_settings;
-	CamelSettings *settings;
-	CamelService *service;
 	GSList *l;
-	const gchar *email;
-	const gchar *hosturl;
-	const gchar *user;
-
-	service = CAMEL_SERVICE (ews_store);
-	settings = camel_service_get_settings (service);
-
-	ews_settings = CAMEL_EWS_SETTINGS (settings);
-	email = camel_ews_settings_get_email (ews_settings);
-	hosturl = camel_ews_settings_get_hosturl (ews_settings);
-
-	network_settings = CAMEL_NETWORK_SETTINGS (settings);
-	user = camel_network_settings_get_user (network_settings);
 
 	for (l = created_folders; l != NULL; l = g_slist_next (l)) {
 		EEwsFolder *folder = (EEwsFolder *) l->data;
@@ -576,27 +483,7 @@ sync_created_folders (CamelEwsStore *ews_store,
 		const EwsFolderId *fid;
 
 		ftype = e_ews_folder_get_folder_type (folder);
-		if (ftype == EWS_FOLDER_TYPE_CALENDAR ||
-		    ftype == EWS_FOLDER_TYPE_TASKS ||
-		    ftype == EWS_FOLDER_TYPE_CONTACTS) {
-			struct add_esrc_data *add_data = g_new0 (struct add_esrc_data, 1);
-			CamelURL *url = camel_service_new_camel_url (service);
-
-			add_data->folder = g_object_ref (folder);
-			add_data->account_uri = camel_url_to_string (url, CAMEL_URL_HIDE_PARAMS);
-			add_data->account_name = g_strdup (email);
-			add_data->username = g_strdup (user);
-			/* Duplicate... for now */
-			add_data->email_id = g_strdup (email);
-			add_data->hosturl = g_strdup (hosturl);
-			/* FIXME pass right refresh timeout */
-
-			camel_url_free (url);
-
-			/* This uses GConf so has to be done in the main thread */
-			g_idle_add_full (G_PRIORITY_DEFAULT, ews_do_add_esource, add_data, NULL);
-
-		} else	if (ftype != EWS_FOLDER_TYPE_MAILBOX)
+		if (ftype != EWS_FOLDER_TYPE_MAILBOX)
 			continue;
 
 		fid = e_ews_folder_get_id (folder);
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
new file mode 100644
index 0000000..2659d42
--- /dev/null
+++ b/src/modules/Makefile.am
@@ -0,0 +1,76 @@
+NULL =
+
+# module-ews-backend is for evolution-data-server
+
+eds_module_LTLIBRARIES = module-ews-backend.la
+
+module_ews_backend_la_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/src \
+	$(LIBEDATASERVER_CFLAGS) \
+	$(LIBEBACKEND_CFLAGS) \
+	$(SOUP_CFLAGS) \
+	$(NULL)
+
+module_ews_backend_la_SOURCES = \
+	module-ews-backend.c
+
+module_ews_backend_la_LIBADD = \
+	$(top_builddir)/src/server/libeews-1.2.la \
+	$(top_builddir)/src/utils/libewsutils.la \
+	$(LIBEDATASERVER_LIBS) \
+	$(LIBEBACKEND_LIBS) \
+	$(SOUP_LIBS) \
+	$(NULL)
+
+module_ews_backend_la_LDFLAGS = \
+	-module -avoid-version $(NO_UNDEFINED) \
+	$(NULL)
+
+# module-ews-mail-config is for evolution
+
+evo_module_LTLIBRARIES = module-ews-mail-config.la
+
+module_ews_mail_config_la_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/src \
+	$(EVOLUTION_MAIL_CFLAGS) \
+	$(NULL)
+
+module_ews_mail_config_la_SOURCES = \
+	module-ews-mail-config.c \
+	e-mail-config-ews-autodiscover.c \
+	e-mail-config-ews-autodiscover.h \
+	e-mail-config-ews-backend.c \
+	e-mail-config-ews-backend.h \
+	e-mail-config-ews-gal.c \
+	e-mail-config-ews-gal.h \
+	e-mail-config-ews-oal-combo-box.c \
+	e-mail-config-ews-oal-combo-box.h \
+	e-mail-config-ews-ooo-page.c \
+	e-mail-config-ews-ooo-page.h \
+	$(NULL)
+
+module_ews_mail_config_la_LIBADD = \
+	$(top_builddir)/src/server/libeews-1.2.la \
+	$(top_builddir)/src/utils/libewsutils.la \
+	$(EVOLUTION_MAIL_LIBS) \
+	$(NULL)
+
+module_ews_mail_config_la_LDFLAGS = \
+	-module -avoid-version $(NO_UNDEFINED)
+
+error_DATA = module-ews-mail-config.error
+
+%.error: %.error.xml
+	$(AM_V_GEN) LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp/notthere $< $@
+
+EXTRA_DIST = module-ews-mail-config.error.xml
+
+BUILT_SOURCES = $(error_DATA)
+
+CLEANFILES = $(BUILT_SOURCES)
+
+-include $(top_srcdir)/git.mk
diff --git a/src/modules/e-mail-config-ews-autodiscover.c b/src/modules/e-mail-config-ews-autodiscover.c
new file mode 100644
index 0000000..f301008
--- /dev/null
+++ b/src/modules/e-mail-config-ews-autodiscover.c
@@ -0,0 +1,345 @@
+/*
+ * e-mail-config-ews-autodiscover.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-ews-autodiscover.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <mail/e-mail-config-service-page.h>
+
+#include "server/e-ews-connection.h"
+
+#define E_MAIL_CONFIG_EWS_AUTODISCOVER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER, EMailConfigEwsAutodiscoverPrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailConfigEwsAutodiscoverPrivate {
+	EMailConfigServiceBackend *backend;
+};
+
+struct _AsyncContext {
+	EMailConfigEwsAutodiscover *autodiscover;
+	EActivity *activity;
+};
+
+enum {
+	PROP_0,
+	PROP_BACKEND
+};
+
+/* Forward Declarations */
+static void	e_mail_config_ews_autodiscover_authenticator_init
+				(ESourceAuthenticatorInterface *interface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailConfigEwsAutodiscover,
+	e_mail_config_ews_autodiscover,
+	GTK_TYPE_BUTTON,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_mail_config_ews_autodiscover_authenticator_init))
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+	if (async_context->autodiscover != NULL)
+		g_object_unref (async_context->autodiscover);
+
+	if (async_context->activity != NULL)
+		g_object_unref (async_context->activity);
+
+	g_slice_free (AsyncContext, async_context);
+}
+
+static void
+mail_config_ews_autodiscover_run_cb (GObject *source_object,
+                                     GAsyncResult *result,
+                                     gpointer user_data)
+{
+	AsyncContext *async_context = user_data;
+	EMailConfigEwsAutodiscover *autodiscover;
+	EAlertSink *alert_sink;
+	GError *error = NULL;
+
+	autodiscover = async_context->autodiscover;
+	alert_sink = e_activity_get_alert_sink (async_context->activity);
+
+	e_source_registry_authenticate_finish (
+		E_SOURCE_REGISTRY (source_object), result, &error);
+
+	if (e_activity_handle_cancellation (async_context->activity, error)) {
+		g_error_free (error);
+
+	} else if (error != NULL) {
+		e_alert_submit (
+			alert_sink,
+			"ews:autodiscovery-error",
+			error->message, NULL);
+		g_error_free (error);
+	}
+
+	gtk_widget_set_sensitive (GTK_WIDGET (autodiscover), TRUE);
+
+	async_context_free (async_context);
+}
+
+static void
+mail_config_ews_autodiscover_run (EMailConfigEwsAutodiscover *autodiscover)
+{
+	EActivity *activity;
+	EMailConfigServicePage *page;
+	EMailConfigServiceBackend *backend;
+	ESourceRegistry *registry;
+	ESource *source;
+	GCancellable *cancellable;
+	AsyncContext *async_context;
+
+	backend = e_mail_config_ews_autodiscover_get_backend (autodiscover);
+	page = e_mail_config_service_backend_get_page (backend);
+	source = e_mail_config_service_backend_get_source (backend);
+
+	registry = e_mail_config_service_page_get_registry (page);
+
+	activity = e_mail_config_service_page_new_activity (page);
+	cancellable = e_activity_get_cancellable (activity);
+
+	e_activity_set_text (activity, _("Querying Autodiscover service"));
+
+	gtk_widget_set_sensitive (GTK_WIDGET (autodiscover), FALSE);
+
+	async_context = g_slice_new0 (AsyncContext);
+	async_context->autodiscover = g_object_ref (autodiscover);
+	async_context->activity = activity;  /* takes ownership */
+
+	e_source_registry_authenticate (
+		registry, source,
+		E_SOURCE_AUTHENTICATOR (autodiscover),
+		cancellable, mail_config_ews_autodiscover_run_cb,
+		async_context);
+}
+
+static void
+mail_config_ews_autodiscover_set_backend (EMailConfigEwsAutodiscover *autodiscover,
+                                          EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+	g_return_if_fail (autodiscover->priv->backend == NULL);
+
+	autodiscover->priv->backend = g_object_ref (backend);
+}
+
+static void
+mail_config_ews_autodiscover_set_property (GObject *object,
+                                           guint property_id,
+                                           const GValue *value,
+                                           GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			mail_config_ews_autodiscover_set_backend (
+				E_MAIL_CONFIG_EWS_AUTODISCOVER (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_autodiscover_get_property (GObject *object,
+                                           guint property_id,
+                                           GValue *value,
+                                           GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_autodiscover_get_backend (
+				E_MAIL_CONFIG_EWS_AUTODISCOVER (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_autodiscover_dispose (GObject *object)
+{
+	EMailConfigEwsAutodiscoverPrivate *priv;
+
+	priv = E_MAIL_CONFIG_EWS_AUTODISCOVER_GET_PRIVATE (object);
+
+	if (priv->backend != NULL) {
+		g_object_unref (priv->backend);
+		priv->backend = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_autodiscover_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_ews_autodiscover_constructed (GObject *object)
+{
+	GtkButton *button;
+
+	button = GTK_BUTTON (object);
+	gtk_button_set_label (button, _("Fetch _URL"));
+	gtk_button_set_use_underline (button, TRUE);
+
+	/* Chain up tp parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_autodiscover_parent_class)->
+		constructed (object);
+}
+
+static void
+mail_config_ews_autodiscover_clicked (GtkButton *button)
+{
+	EMailConfigEwsAutodiscover *autodiscover;
+
+	autodiscover = E_MAIL_CONFIG_EWS_AUTODISCOVER (button);
+
+	mail_config_ews_autodiscover_run (autodiscover);
+}
+
+static ESourceAuthenticationResult
+mail_config_ews_autodiscover_try_password_sync (ESourceAuthenticator *auth,
+                                                const GString *password,
+                                                GCancellable *cancellable,
+                                                GError **error)
+{
+	EMailConfigEwsAutodiscover *autodiscover;
+	EMailConfigServiceBackend *backend;
+	EMailConfigServicePage *page;
+	CamelSettings *settings;
+	CamelEwsSettings *ews_settings;
+	ESourceAuthenticationResult result;
+	const gchar *email_address;
+	GError *local_error = NULL;
+
+	autodiscover = E_MAIL_CONFIG_EWS_AUTODISCOVER (auth);
+	backend = e_mail_config_ews_autodiscover_get_backend (autodiscover);
+	page = e_mail_config_service_backend_get_page (backend);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	email_address = e_mail_config_service_page_get_email_address (page);
+
+	ews_settings = CAMEL_EWS_SETTINGS (settings);
+
+	e_ews_autodiscover_ws_url_sync (
+		ews_settings, email_address, password->str,
+		cancellable, &local_error);
+
+	if (local_error == NULL) {
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+	} else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED)) {
+		result = E_SOURCE_AUTHENTICATION_REJECTED;
+		g_error_free (local_error);
+
+	} else {
+		result = E_SOURCE_AUTHENTICATION_ERROR;
+		g_propagate_error (error, local_error);
+	}
+
+	return result;
+}
+
+static void
+e_mail_config_ews_autodiscover_class_init (EMailConfigEwsAutodiscoverClass *class)
+{
+	GObjectClass *object_class;
+	GtkButtonClass *button_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigEwsAutodiscoverPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_ews_autodiscover_set_property;
+	object_class->get_property = mail_config_ews_autodiscover_get_property;
+	object_class->dispose = mail_config_ews_autodiscover_dispose;
+	object_class->constructed = mail_config_ews_autodiscover_constructed;
+
+	button_class = GTK_BUTTON_CLASS (class);
+	button_class->clicked = mail_config_ews_autodiscover_clicked;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_BACKEND,
+		g_param_spec_object (
+			"backend",
+			"Backend",
+			"Mail configuration backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_mail_config_ews_autodiscover_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync =
+		mail_config_ews_autodiscover_try_password_sync;
+}
+
+static void
+e_mail_config_ews_autodiscover_class_finalize (EMailConfigEwsAutodiscoverClass *class)
+{
+}
+
+static void
+e_mail_config_ews_autodiscover_init (EMailConfigEwsAutodiscover *autodiscover)
+{
+	autodiscover->priv =
+		E_MAIL_CONFIG_EWS_AUTODISCOVER_GET_PRIVATE (autodiscover);
+}
+
+void
+e_mail_config_ews_autodiscover_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_ews_autodiscover_register_type (type_module);
+}
+
+GtkWidget *
+e_mail_config_ews_autodiscover_new (EMailConfigServiceBackend *backend)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER,
+		"backend", backend, NULL);
+}
+
+EMailConfigServiceBackend *
+e_mail_config_ews_autodiscover_get_backend (EMailConfigEwsAutodiscover *autodiscover)
+{
+	g_return_val_if_fail (
+		E_IS_MAIL_CONFIG_EWS_AUTODISCOVER (autodiscover), NULL);
+
+	return autodiscover->priv->backend;
+}
+
diff --git a/src/modules/e-mail-config-ews-autodiscover.h b/src/modules/e-mail-config-ews-autodiscover.h
new file mode 100644
index 0000000..a6dd371
--- /dev/null
+++ b/src/modules/e-mail-config-ews-autodiscover.h
@@ -0,0 +1,71 @@
+/*
+ * e-mail-config-ews-autodiscover.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_EWS_AUTODISCOVER_H
+#define E_MAIL_CONFIG_EWS_AUTODISCOVER_H
+
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER \
+	(e_mail_config_ews_autodiscover_get_type ())
+#define E_MAIL_CONFIG_EWS_AUTODISCOVER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER, EMailConfigEwsAutodiscover))
+#define E_MAIL_CONFIG_EWS_AUTODISCOVER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER, EMailConfigEwsAutodiscoverClass))
+#define E_IS_MAIL_CONFIG_EWS_AUTODISCOVER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER))
+#define E_IS_MAIL_CONFIG_EWS_AUTODISCOVER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER))
+#define E_MAIL_CONFIG_EWS_AUTODISCOVER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_AUTODISCOVER, EMailConfigEwsAutodiscoverClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigEwsAutodiscover EMailConfigEwsAutodiscover;
+typedef struct _EMailConfigEwsAutodiscoverClass EMailConfigEwsAutodiscoverClass;
+typedef struct _EMailConfigEwsAutodiscoverPrivate EMailConfigEwsAutodiscoverPrivate;
+
+struct _EMailConfigEwsAutodiscover {
+	GtkButton parent;
+	EMailConfigEwsAutodiscoverPrivate *priv;
+};
+
+struct _EMailConfigEwsAutodiscoverClass {
+	GtkButtonClass parent_class;
+};
+
+GType		e_mail_config_ews_autodiscover_get_type
+					(void) G_GNUC_CONST;
+void		e_mail_config_ews_autodiscover_type_register
+					(GTypeModule *type_module);
+GtkWidget *	e_mail_config_ews_autodiscover_new
+					(EMailConfigServiceBackend *backend);
+EMailConfigServiceBackend *
+		e_mail_config_ews_autodiscover_get_backend
+					(EMailConfigEwsAutodiscover *autodiscover);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_EWS_AUTODISCOVER_H */
+
diff --git a/src/modules/e-mail-config-ews-backend.c b/src/modules/e-mail-config-ews-backend.c
new file mode 100644
index 0000000..7352269
--- /dev/null
+++ b/src/modules/e-mail-config-ews-backend.c
@@ -0,0 +1,352 @@
+/*
+ * e-mail-config-ews-backend.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-ews-backend.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <camel/camel.h>
+#include <libebackend/e-extension.h>
+#include <libedataserver/e-source-collection.h>
+
+#include <mail/e-mail-config-auth-check.h>
+#include <mail/e-mail-config-receiving-page.h>
+
+#include "server/camel-ews-settings.h"
+
+#include "e-mail-config-ews-autodiscover.h"
+
+#define E_MAIL_CONFIG_EWS_BACKEND_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_BACKEND, EMailConfigEwsBackendPrivate))
+
+struct _EMailConfigEwsBackendPrivate {
+	GtkWidget *user_entry;		/* not referenced */
+	GtkWidget *host_entry;		/* not referenced */
+	GtkWidget *url_button;		/* not referenced */
+	GtkWidget *oab_entry;		/* not referenced */
+	GtkWidget *auth_check;		/* not referenced */
+};
+
+G_DEFINE_DYNAMIC_TYPE (
+	EMailConfigEwsBackend,
+	e_mail_config_ews_backend,
+	E_TYPE_MAIL_CONFIG_SERVICE_BACKEND)
+
+static ESource *
+mail_config_ews_backend_new_collection (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServiceBackendClass *class;
+	ESourceBackend *extension;
+	ESource *source;
+	const gchar *extension_name;
+
+	/* This backend serves double duty.  One instance holds the
+	 * mail account source, another holds the mail transport source.
+	 * We can differentiate by examining the EMailConfigServicePage
+	 * the backend is associated with.  We return a new collection
+	 * for both the Receiving Page and Sending Page.  Although the
+	 * Sending Page instance ultimately gets discarded, it's still
+	 * needed to avoid creating an [Ews Backend] extension in the
+	 * mail transport source. */
+
+	class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
+
+	source = e_source_new (NULL, NULL, NULL);
+	extension_name = E_SOURCE_EXTENSION_COLLECTION;
+	extension = e_source_get_extension (source, extension_name);
+	e_source_backend_set_backend_name (extension, class->backend_name);
+
+	return source;
+}
+
+static void
+mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
+                                        GtkBox *parent)
+{
+	EMailConfigEwsBackendPrivate *priv;
+	EMailConfigServicePage *page;
+	ESource *source;
+	ESourceExtension *extension;
+	CamelSettings *settings;
+	GtkLabel *label;
+	GtkWidget *widget;
+	GtkWidget *container;
+	const gchar *extension_name;
+	const gchar *text;
+	gchar *markup;
+
+	priv = E_MAIL_CONFIG_EWS_BACKEND_GET_PRIVATE (backend);
+	page = e_mail_config_service_backend_get_page (backend);
+
+	/* This backend serves double duty.  One instance holds the
+	 * mail account source, another holds the mail transport source.
+	 * We can differentiate by examining the EMailConfigServicePage
+	 * the backend is associated with.  This method only applies to
+	 * the Receiving Page. */
+	if (!E_IS_MAIL_CONFIG_RECEIVING_PAGE (page))
+		return;
+
+	/* This needs to come _after_ the page type check so we don't
+	 * introduce a backend extension in the mail transport source. */
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	text = _("Configuration");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (parent), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	widget = gtk_grid_new ();
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (parent), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_label_new_with_mnemonic (_("User_name:"));
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 2, 1);
+	priv->user_entry = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new_with_mnemonic (_("_Host URL:"));
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+	priv->host_entry = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	widget = e_mail_config_ews_autodiscover_new (backend);
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 1, 1, 1);
+	priv->url_button = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new_with_mnemonic (_("OAB U_RL:"));
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 2, 1);
+	priv->oab_entry = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	text = _("Authentication");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_widget_set_margin_top (widget, 6);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (parent), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	widget = e_mail_config_auth_check_new (backend);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_box_pack_start (GTK_BOX (parent), widget, FALSE, FALSE, 0);
+	priv->auth_check = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		settings, "user",
+		priv->user_entry, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		settings, "hosturl",
+		priv->host_entry, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		settings, "oaburl",
+		priv->oab_entry, "text",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	/* Don't use G_BINDING_SYNC_CREATE here since the widget
+	 * chooses its initial mechanism more intelligently than
+	 * a simple property binding would. */
+	g_object_bind_property (
+		settings, "auth-mechanism",
+		priv->auth_check, "active-mechanism",
+		G_BINDING_BIDIRECTIONAL);
+
+	extension_name = E_SOURCE_EXTENSION_COLLECTION;
+	source = e_mail_config_service_backend_get_collection (backend);
+	extension = e_source_get_extension (source, extension_name);
+
+	/* The collection identity is the user name. */
+	g_object_bind_property (
+		settings, "user",
+		extension, "identity",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+}
+
+static void
+mail_config_ews_backend_setup_defaults (EMailConfigServiceBackend *backend)
+{
+	CamelSettings *settings;
+	EMailConfigServicePage *page;
+	const gchar *email_address;
+	gchar **parts = NULL;
+
+	page = e_mail_config_service_backend_get_page (backend);
+
+	/* This backend serves double duty.  One instance holds the
+	 * mail account source, another holds the mail transport source.
+	 * We can differentiate by examining the EMailConfigServicePage
+	 * the backend is associated with.  This method only applies to
+	 * the Receiving Page. */
+	if (!E_IS_MAIL_CONFIG_RECEIVING_PAGE (page))
+		return;
+
+	/* This needs to come _after_ the page type check so we don't
+	 * introduce a backend extension in the mail transport source. */
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	email_address = e_mail_config_service_page_get_email_address (page);
+	if (email_address != NULL)
+		parts = g_strsplit (email_address, "@", 2);
+
+	if (parts != NULL && g_strv_length (parts) >= 2) {
+		CamelEwsSettings *ews_settings;
+		CamelNetworkSettings *network_settings;
+		gchar *hosturl;
+
+		g_strstrip (parts[0]);  /* user name */
+		g_strstrip (parts[1]);  /* domain name */
+
+		hosturl = g_strdup_printf (
+			"https://exchange.%s/EWS/Exchange.asmx";, parts[1]);
+
+		ews_settings = CAMEL_EWS_SETTINGS (settings);
+		camel_ews_settings_set_hosturl (ews_settings, hosturl);
+
+		network_settings = CAMEL_NETWORK_SETTINGS (settings);
+		camel_network_settings_set_user (network_settings, parts[0]);
+
+		g_free (hosturl);
+	}
+
+	g_strfreev (parts);
+}
+
+static gboolean
+mail_config_ews_backend_check_complete (EMailConfigServiceBackend *backend)
+{
+	EMailConfigServicePage *page;
+	CamelSettings *settings;
+	CamelEwsSettings *ews_settings;
+	CamelNetworkSettings *network_settings;
+	const gchar *hosturl;
+	const gchar *user;
+
+	page = e_mail_config_service_backend_get_page (backend);
+
+	/* This backend serves double duty.  One instance holds the
+	 * mail account source, another holds the mail transport source.
+	 * We can differentiate by examining the EMailConfigServicePage
+	 * the backend is associated with.  This method only applies to
+	 * the Receiving Page. */
+	if (!E_IS_MAIL_CONFIG_RECEIVING_PAGE (page))
+		return TRUE;
+
+	/* This needs to come _after_ the page type check so we don't
+	 * introduce a backend extension in the mail transport source. */
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	ews_settings = CAMEL_EWS_SETTINGS (settings);
+	hosturl = camel_ews_settings_get_hosturl (ews_settings);
+
+	network_settings = CAMEL_NETWORK_SETTINGS (settings);
+	user = camel_network_settings_get_user (network_settings);
+
+	if (hosturl == NULL || *hosturl == '\0')
+		return FALSE;
+
+	if (user == NULL || *user == '\0')
+		return FALSE;
+
+	return TRUE;
+}
+
+static void
+e_mail_config_ews_backend_class_init (EMailConfigEwsBackendClass *class)
+{
+	EMailConfigServiceBackendClass *backend_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigEwsBackendPrivate));
+
+	backend_class = E_MAIL_CONFIG_SERVICE_BACKEND_CLASS (class);
+	backend_class->backend_name = "ews";
+	backend_class->new_collection = mail_config_ews_backend_new_collection;
+	backend_class->insert_widgets = mail_config_ews_backend_insert_widgets;
+	backend_class->setup_defaults = mail_config_ews_backend_setup_defaults;
+	backend_class->check_complete = mail_config_ews_backend_check_complete;
+}
+
+static void
+e_mail_config_ews_backend_class_finalize (EMailConfigEwsBackendClass *class)
+{
+}
+
+static void
+e_mail_config_ews_backend_init (EMailConfigEwsBackend *backend)
+{
+	backend->priv = E_MAIL_CONFIG_EWS_BACKEND_GET_PRIVATE (backend);
+}
+
+void
+e_mail_config_ews_backend_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_ews_backend_register_type (type_module);
+}
+
diff --git a/src/modules/e-mail-config-ews-backend.h b/src/modules/e-mail-config-ews-backend.h
new file mode 100644
index 0000000..7d5de45
--- /dev/null
+++ b/src/modules/e-mail-config-ews-backend.h
@@ -0,0 +1,66 @@
+/*
+ * e-mail-config-ews-backend.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_EWS_BACKEND_H
+#define E_MAIL_CONFIG_EWS_BACKEND_H
+
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_EWS_BACKEND \
+	(e_mail_config_ews_backend_get_type ())
+#define E_MAIL_CONFIG_EWS_BACKEND(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_BACKEND, EMailConfigEwsBackend))
+#define E_MAIL_CONFIG_EWS_BACKEND_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_BACKEND, EMailConfigEwsBackendClass))
+#define E_IS_MAIL_CONFIG_EWS_BACKEND(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_BACKEND))
+#define E_IS_MAIL_CONFIG_EWS_BACKEND_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_BACKEND))
+#define E_MAIL_CONFIG_EWS_BACKEND_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_BACKEND, EMailConfigEwsBackendClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigEwsBackend EMailConfigEwsBackend;
+typedef struct _EMailConfigEwsBackendClass EMailConfigEwsBackendClass;
+typedef struct _EMailConfigEwsBackendPrivate EMailConfigEwsBackendPrivate;
+
+struct _EMailConfigEwsBackend {
+	EMailConfigServiceBackend parent;
+	EMailConfigEwsBackendPrivate *priv;
+};
+
+struct _EMailConfigEwsBackendClass {
+	EMailConfigServiceBackendClass parent_class;
+};
+
+GType		e_mail_config_ews_backend_get_type
+						(void) G_GNUC_CONST;
+void		e_mail_config_ews_backend_type_register
+						(GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_EWS_BACKEND_H */
+
diff --git a/src/modules/e-mail-config-ews-gal.c b/src/modules/e-mail-config-ews-gal.c
new file mode 100644
index 0000000..3a6c263
--- /dev/null
+++ b/src/modules/e-mail-config-ews-gal.c
@@ -0,0 +1,389 @@
+/*
+ * e-mail-config-ews-gal.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-ews-gal.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <mail/e-mail-config-provider-page.h>
+
+#include "server/camel-ews-settings.h"
+
+#include "e-mail-config-ews-oal-combo-box.h"
+
+#define E_MAIL_CONFIG_EWS_GAL_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_GAL, EMailConfigEwsGalPrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailConfigEwsGalPrivate {
+	GtkWidget *toggle_button;	/* not referenced */
+	GtkWidget *combo_box;		/* not referenced */
+	GtkWidget *fetch_button;	/* not referenced */
+};
+
+struct _AsyncContext {
+	EMailConfigEwsGal *extension;
+	EActivity *activity;
+};
+
+G_DEFINE_DYNAMIC_TYPE (
+	EMailConfigEwsGal,
+	e_mail_config_ews_gal,
+	E_TYPE_EXTENSION)
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+	if (async_context->extension != NULL)
+		g_object_unref (async_context->extension);
+
+	if (async_context->activity != NULL)
+		g_object_unref (async_context->activity);
+
+	g_slice_free (AsyncContext, async_context);
+}
+
+static EMailConfigProviderPage *
+mail_config_ews_gal_get_provider_page (EMailConfigEwsGal *extension)
+{
+	EExtensible *extensible;
+
+	extensible = e_extension_get_extensible (E_EXTENSION (extension));
+
+	return E_MAIL_CONFIG_PROVIDER_PAGE (extensible);
+}
+
+static gboolean
+mail_config_ews_gal_string_to_boolean (GBinding *binding,
+                                       const GValue *source_value,
+                                       GValue *target_value,
+                                       gpointer unused)
+{
+	const gchar *v_string;
+	gboolean v_boolean;
+
+	v_string = g_value_get_string (source_value);
+	v_boolean = (v_string != NULL && *v_string != '\0');
+	g_value_set_boolean (target_value, v_boolean);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_ews_gal_oal_selected_to_active_id (GBinding *binding,
+                                               const GValue *source_value,
+                                               GValue *target_value,
+                                               gpointer unused)
+{
+	GObject *target_object;
+	GtkComboBox *combo_box;
+	const gchar *selected;
+	gchar *active_id;
+	gchar *active_text;
+
+	selected = g_value_get_string (source_value);
+
+	if (selected == NULL)
+		return FALSE;
+
+	/* Selected value is of the form "id:name". */
+	active_id = g_strdup (selected);
+	active_text = strrchr (active_id, ':');
+
+	if (active_text != NULL) {
+		*active_text++ = '\0';
+	} else {
+		g_free (active_id);
+		return FALSE;
+	}
+
+	target_object = g_binding_get_target (binding);
+	combo_box = GTK_COMBO_BOX (target_object);
+
+	/* The combo box might already have the OAL ID, in which case
+	 * we simply make it the active combo box row.  Otherwise we
+	 * have to add a new row and make it the active row. */
+	if (!gtk_combo_box_set_active_id (combo_box, active_id)) {
+		gtk_combo_box_text_append (
+			GTK_COMBO_BOX_TEXT (combo_box),
+			active_id, active_text);
+		gtk_combo_box_set_active_id (combo_box, active_id);
+	}
+
+	g_free (active_id);
+
+	return TRUE;
+}
+
+static gboolean
+mail_config_ews_gal_active_id_to_oal_selected (GBinding *binding,
+                                               const GValue *source_value,
+                                               GValue *target_value,
+                                               gpointer unused)
+{
+	GObject *source_object;
+	GtkComboBoxText *combo_box;
+	const gchar *active_id;
+	const gchar *active_text;
+	gchar *selected = NULL;
+
+	source_object = g_binding_get_source (binding);
+	combo_box = GTK_COMBO_BOX_TEXT (source_object);
+
+	active_id = g_value_get_string (source_value);
+	active_text = gtk_combo_box_text_get_active_text (combo_box);
+
+	if (active_id != NULL && active_text != NULL)
+		selected = g_strdup_printf ("%s:%s", active_id, active_text);
+
+	g_value_set_string (target_value, selected);
+
+	g_free (selected);
+
+	return TRUE;
+}
+
+static void
+mail_config_ews_gal_fetch_list_cb (GObject *source_object,
+                                   GAsyncResult *result,
+                                   gpointer user_data)
+{
+	AsyncContext *async_context = user_data;
+	EMailConfigEwsGal *extension;
+	EAlertSink *alert_sink;
+	GError *error = NULL;
+
+	extension = async_context->extension;
+	alert_sink = e_activity_get_alert_sink (async_context->activity);
+
+	e_mail_config_ews_oal_combo_box_update_finish (
+		E_MAIL_CONFIG_EWS_OAL_COMBO_BOX (source_object),
+		result, &error);
+
+	if (e_activity_handle_cancellation (async_context->activity, error)) {
+		g_error_free (error);
+
+	} else if (error != NULL) {
+		e_alert_submit (
+			alert_sink,
+			"ews:query-oal-error",
+			error->message, NULL);
+		g_error_free (error);
+	}
+
+	gtk_widget_set_sensitive (extension->priv->combo_box, TRUE);
+	gtk_widget_set_sensitive (extension->priv->fetch_button, TRUE);
+
+	async_context_free (async_context);
+}
+
+static void
+mail_config_ews_gal_fetch_list (EMailConfigEwsGal *extension)
+{
+	EActivity *activity;
+	EMailConfigProviderPage *page;
+	GtkWidget *combo_box;
+	GCancellable *cancellable;
+	AsyncContext *async_context;
+
+	combo_box = extension->priv->combo_box;
+
+	page = mail_config_ews_gal_get_provider_page (extension);
+
+	activity = e_mail_config_provider_page_new_activity (page);
+	cancellable = e_activity_get_cancellable (activity);
+
+	e_activity_set_text (activity, _("Locating offline address books"));
+
+	gtk_widget_set_sensitive (extension->priv->combo_box, FALSE);
+	gtk_widget_set_sensitive (extension->priv->fetch_button, FALSE);
+
+	async_context = g_slice_new0 (AsyncContext);
+	async_context->extension = g_object_ref (extension);
+	async_context->activity = activity;  /* takes ownership */
+
+	e_mail_config_ews_oal_combo_box_update (
+		E_MAIL_CONFIG_EWS_OAL_COMBO_BOX (combo_box),
+		cancellable, mail_config_ews_gal_fetch_list_cb,
+		async_context);
+}
+
+static void
+mail_config_ews_gal_fetch_button_clicked_cb (GtkButton *button,
+                                             EMailConfigEwsGal *extension)
+{
+	mail_config_ews_gal_fetch_list (extension);
+}
+
+static void
+mail_config_ews_gal_constructed (GObject *object)
+{
+	EMailConfigEwsGal *extension;
+	EMailConfigProviderPage *page;
+	EMailConfigServiceBackend *backend;
+	CamelSettings *settings;
+	GtkWidget *container;
+	GtkWidget *widget;
+	GtkLabel *label;
+	const gchar *text;
+	gchar *markup;
+
+	extension = E_MAIL_CONFIG_EWS_GAL (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_gal_parent_class)->
+		constructed (object);
+
+	page = mail_config_ews_gal_get_provider_page (extension);
+	backend = e_mail_config_provider_page_get_backend (page);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	/* A provider page is created for every available CamelStore
+	 * class.  We're only interested in the one for CamelEwsStore.
+	 * We determine this by the CamelSettings type returned. */
+	if (!CAMEL_IS_EWS_SETTINGS (settings))
+		return;
+
+	container = GTK_WIDGET (page);
+
+	text = _("Global Address List");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_widget_set_margin_top (widget, 6);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	widget = gtk_grid_new ();
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_object_bind_property_full (
+		settings, "oaburl",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE,
+		mail_config_ews_gal_string_to_boolean,
+		NULL,
+		NULL, (GDestroyNotify) NULL);
+
+	container = widget;
+
+	text = _("Cache o_ffline address book");
+	widget = gtk_check_button_new_with_mnemonic (text);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	extension->priv->toggle_button = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		settings, "oab-offline",
+		widget, "active",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE);
+
+	widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_box_set_spacing (GTK_BOX (widget), 6);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		settings, "oab-offline",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE);
+
+	container = widget;
+
+	text = _("Select ad_dress list:");
+	widget = gtk_label_new_with_mnemonic (text);
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	label = GTK_LABEL (widget);
+
+	widget = e_mail_config_ews_oal_combo_box_new (backend);
+	gtk_label_set_mnemonic_widget (label, widget);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	extension->priv->combo_box = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	g_object_bind_property_full (
+		settings, "oal-selected",
+		widget, "active-id",
+		G_BINDING_BIDIRECTIONAL |
+		G_BINDING_SYNC_CREATE,
+		mail_config_ews_gal_oal_selected_to_active_id,
+		mail_config_ews_gal_active_id_to_oal_selected,
+		NULL, (GDestroyNotify) NULL);
+
+	widget = gtk_button_new_with_label (_("Fetch List"));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	extension->priv->fetch_button = widget;  /* do not reference */
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget, "clicked",
+		G_CALLBACK (mail_config_ews_gal_fetch_button_clicked_cb),
+		extension);
+}
+
+static void
+e_mail_config_ews_gal_class_init (EMailConfigEwsGalClass *class)
+{
+	GObjectClass *object_class;
+	EExtensionClass *extension_class;
+
+	g_type_class_add_private (class, sizeof (EMailConfigEwsGalPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = mail_config_ews_gal_constructed;
+
+	extension_class = E_EXTENSION_CLASS (class);
+	extension_class->extensible_type = E_TYPE_MAIL_CONFIG_PROVIDER_PAGE;
+}
+
+static void
+e_mail_config_ews_gal_class_finalize (EMailConfigEwsGalClass *class)
+{
+}
+
+static void
+e_mail_config_ews_gal_init (EMailConfigEwsGal *extension)
+{
+	extension->priv = E_MAIL_CONFIG_EWS_GAL_GET_PRIVATE (extension);
+}
+
+void
+e_mail_config_ews_gal_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_ews_gal_register_type (type_module);
+}
+
diff --git a/src/modules/e-mail-config-ews-gal.h b/src/modules/e-mail-config-ews-gal.h
new file mode 100644
index 0000000..2ab1db7
--- /dev/null
+++ b/src/modules/e-mail-config-ews-gal.h
@@ -0,0 +1,65 @@
+/*
+ * e-mail-config-ews-gal.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_EWS_GAL_H
+#define E_MAIL_CONFIG_EWS_GAL_H
+
+#include <libebackend/e-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_EWS_GAL \
+	(e_mail_config_ews_gal_get_type ())
+#define E_MAIL_CONFIG_EWS_GAL(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_GAL, EMailConfigEwsGal))
+#define E_MAIL_CONFIG_EWS_GAL_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_GAL, EMailConfigEwsGalClass))
+#define E_IS_MAIL_CONFIG_EWS_GAL(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_GAL))
+#define E_IS_MAIL_CONFIG_EWS_GAL_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_GAL))
+#define E_MAIL_CONFIG_EWS_GAL_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_GAL, EMailConfigEwsGalClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigEwsGal EMailConfigEwsGal;
+typedef struct _EMailConfigEwsGalClass EMailConfigEwsGalClass;
+typedef struct _EMailConfigEwsGalPrivate EMailConfigEwsGalPrivate;
+
+struct _EMailConfigEwsGal {
+	EExtension parent;
+	EMailConfigEwsGalPrivate *priv;
+};
+
+struct _EMailConfigEwsGalClass {
+	EExtensionClass parent_class;
+};
+
+GType		e_mail_config_ews_gal_get_type	(void) G_GNUC_CONST;
+void		e_mail_config_ews_gal_type_register
+						(GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_EWS_GAL_H */
+
diff --git a/src/modules/e-mail-config-ews-oal-combo-box.c b/src/modules/e-mail-config-ews-oal-combo-box.c
new file mode 100644
index 0000000..5aa08a5
--- /dev/null
+++ b/src/modules/e-mail-config-ews-oal-combo-box.c
@@ -0,0 +1,365 @@
+/*
+ * e-mail-config-ews-oal-combo-box.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-ews-oal-combo-box.h"
+
+#include <mail/e-mail-config-service-page.h>
+
+#include "server/e-ews-connection.h"
+
+#define E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX, EMailConfigEwsOalComboBoxPrivate))
+
+struct _EMailConfigEwsOalComboBoxPrivate {
+	EMailConfigServiceBackend *backend;
+
+	/* The try_password() method deposits results here, and the
+	 * update_finish() function uses the results to re-populate
+	 * the combo box.  This avoids calling GTK+ functions from
+	 * multiple threads. */
+	GSList *oal_items;
+	GMutex *oal_items_lock;
+};
+
+enum {
+	PROP_0,
+	PROP_BACKEND
+};
+
+/* Forward Declarations */
+static void	e_mail_config_ews_oal_combo_box_authenticator_init
+				(ESourceAuthenticatorInterface *interface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailConfigEwsOalComboBox,
+	e_mail_config_ews_oal_combo_box,
+	GTK_TYPE_COMBO_BOX_TEXT,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_mail_config_ews_oal_combo_box_authenticator_init))
+
+static void
+mail_config_ews_oal_combo_box_set_backend (EMailConfigEwsOalComboBox *combo_box,
+                                           EMailConfigServiceBackend *backend)
+{
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+	g_return_if_fail (combo_box->priv->backend == NULL);
+
+	combo_box->priv->backend = g_object_ref (backend);
+}
+
+static void
+mail_config_ews_oal_combo_box_set_property (GObject *object,
+                                            guint property_id,
+                                            const GValue *value,
+                                            GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			mail_config_ews_oal_combo_box_set_backend (
+				E_MAIL_CONFIG_EWS_OAL_COMBO_BOX (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_oal_combo_box_get_property (GObject *object,
+                                            guint property_id,
+                                            GValue *value,
+                                            GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_BACKEND:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_oal_combo_box_get_backend (
+				E_MAIL_CONFIG_EWS_OAL_COMBO_BOX (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_oal_combo_box_dispose (GObject *object)
+{
+	EMailConfigEwsOalComboBoxPrivate *priv;
+
+	priv = E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_GET_PRIVATE (object);
+
+	if (priv->backend != NULL) {
+		g_object_ref (priv->backend);
+		priv->backend = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_oal_combo_box_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_ews_oal_combo_box_finalize (GObject *object)
+{
+	EMailConfigEwsOalComboBoxPrivate *priv;
+
+	priv = E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_GET_PRIVATE (object);
+
+	g_mutex_free (priv->oal_items_lock);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_oal_combo_box_parent_class)->
+		finalize (object);
+}
+
+static ESourceAuthenticationResult
+mail_config_ews_oal_combo_box_try_password_sync (ESourceAuthenticator *auth,
+                                                 const GString *password,
+                                                 GCancellable *cancellable,
+                                                 GError **error)
+{
+	EMailConfigEwsOalComboBox *combo_box;
+	EMailConfigServiceBackend *backend;
+	CamelSettings *settings;
+	CamelEwsSettings *ews_settings;
+	CamelNetworkSettings *network_settings;
+	ESourceAuthenticationResult result;
+	EEwsConnection *cnc;
+	GSList *oal_items = NULL;
+	const gchar *oab_url;
+	const gchar *user;
+	GError *local_error = NULL;
+
+	combo_box = E_MAIL_CONFIG_EWS_OAL_COMBO_BOX (auth);
+	backend = e_mail_config_ews_oal_combo_box_get_backend (combo_box);
+	settings = e_mail_config_service_backend_get_settings (backend);
+
+	ews_settings = CAMEL_EWS_SETTINGS (settings);
+	oab_url = camel_ews_settings_get_oaburl (ews_settings);
+
+	network_settings = CAMEL_NETWORK_SETTINGS (settings);
+	user = camel_network_settings_get_user (network_settings);
+
+	/* XXX This takes a GError but never fails, so skip it. */
+	cnc = e_ews_connection_new (
+		oab_url, user, password->str, NULL, NULL, NULL);
+
+	e_ews_connection_get_oal_list_sync (
+		cnc, &oal_items, cancellable, &local_error);
+
+	g_object_unref (cnc);
+
+	if (local_error == NULL) {
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+		/* Deposit results in the private struct for
+		 * the update_finish() function to pick up. */
+		g_mutex_lock (combo_box->priv->oal_items_lock);
+		g_slist_free_full (
+			combo_box->priv->oal_items,
+			(GDestroyNotify) ews_oal_free);
+		combo_box->priv->oal_items = oal_items;
+		g_mutex_unlock (combo_box->priv->oal_items_lock);
+
+	} else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED)) {
+		result = E_SOURCE_AUTHENTICATION_REJECTED;
+		g_error_free (local_error);
+
+	} else {
+		result = E_SOURCE_AUTHENTICATION_ERROR;
+		g_propagate_error (error, local_error);
+	}
+
+	return result;
+}
+
+static void
+e_mail_config_ews_oal_combo_box_class_init (EMailConfigEwsOalComboBoxClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigEwsOalComboBoxPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_ews_oal_combo_box_set_property;
+	object_class->get_property = mail_config_ews_oal_combo_box_get_property;
+	object_class->dispose = mail_config_ews_oal_combo_box_dispose;
+	object_class->finalize = mail_config_ews_oal_combo_box_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_BACKEND,
+		g_param_spec_object (
+			"backend",
+			"Backend",
+			"Service backend",
+			E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_mail_config_ews_oal_combo_box_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync =
+		mail_config_ews_oal_combo_box_try_password_sync;
+}
+
+static void
+e_mail_config_ews_oal_combo_box_class_finalize (EMailConfigEwsOalComboBoxClass *class)
+{
+}
+
+static void
+e_mail_config_ews_oal_combo_box_init (EMailConfigEwsOalComboBox *combo_box)
+{
+	combo_box->priv =
+		E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_GET_PRIVATE (combo_box);
+
+	combo_box->priv->oal_items_lock = g_mutex_new ();
+}
+
+void
+e_mail_config_ews_oal_combo_box_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_ews_oal_combo_box_register_type (type_module);
+}
+
+GtkWidget *
+e_mail_config_ews_oal_combo_box_new (EMailConfigServiceBackend *backend)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX,
+		"backend", backend, NULL);
+}
+
+EMailConfigServiceBackend *
+e_mail_config_ews_oal_combo_box_get_backend (EMailConfigEwsOalComboBox *combo_box)
+{
+	g_return_val_if_fail (
+		E_IS_MAIL_CONFIG_EWS_OAL_COMBO_BOX (combo_box), NULL);
+
+	return combo_box->priv->backend;
+}
+
+/* Helper for e_mail_config_ews_oal_combo_box_update() */
+static void
+mail_config_ews_oal_combo_box_update_cb (GObject *source_object,
+                                         GAsyncResult *result,
+                                         gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+	e_source_registry_authenticate_finish (
+		E_SOURCE_REGISTRY (source_object), result, &error);
+
+	if (error != NULL)
+		g_simple_async_result_take_error (simple, error);
+
+	g_simple_async_result_complete (simple);
+
+	g_object_unref (simple);
+}
+
+void
+e_mail_config_ews_oal_combo_box_update (EMailConfigEwsOalComboBox *combo_box,
+                                        GCancellable *cancellable,
+                                        GAsyncReadyCallback callback,
+                                        gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	EMailConfigServicePage *page;
+	EMailConfigServiceBackend *backend;
+	ESourceAuthenticator *authenticator;
+	ESourceRegistry *registry;
+	ESource *source;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_EWS_OAL_COMBO_BOX (combo_box));
+
+	backend = e_mail_config_ews_oal_combo_box_get_backend (combo_box);
+	page = e_mail_config_service_backend_get_page (backend);
+	source = e_mail_config_service_backend_get_source (backend);
+	registry = e_mail_config_service_page_get_registry (page);
+
+	authenticator = E_SOURCE_AUTHENTICATOR (combo_box);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (combo_box), callback, user_data,
+		e_mail_config_ews_oal_combo_box_update);
+
+	e_source_registry_authenticate (
+		registry, source, authenticator, cancellable,
+		mail_config_ews_oal_combo_box_update_cb, simple);
+}
+
+gboolean
+e_mail_config_ews_oal_combo_box_update_finish (EMailConfigEwsOalComboBox *combo_box,
+                                               GAsyncResult *result,
+                                               GError **error)
+{
+	GSimpleAsyncResult *simple;
+	GtkComboBoxText *combo_box_text;
+	GSList *list, *link;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (combo_box),
+		e_mail_config_ews_oal_combo_box_update), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+
+	/* Re-populate the combo box using the cached results. */
+
+	g_mutex_lock (combo_box->priv->oal_items_lock);
+	list = combo_box->priv->oal_items;
+	combo_box->priv->oal_items = NULL;
+	g_mutex_unlock (combo_box->priv->oal_items_lock);
+
+	combo_box_text = GTK_COMBO_BOX_TEXT (combo_box);
+	gtk_combo_box_text_remove_all (combo_box_text);
+
+	for (link = list; link != NULL; link = g_slist_next (link)) {
+		EwsOAL *oal = link->data;
+
+		gtk_combo_box_text_append (
+			combo_box_text, oal->id, oal->name);
+	}
+
+	g_slist_free_full (list, (GDestroyNotify) ews_oal_free);
+
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+
+	return TRUE;
+}
+
diff --git a/src/modules/e-mail-config-ews-oal-combo-box.h b/src/modules/e-mail-config-ews-oal-combo-box.h
new file mode 100644
index 0000000..8510044
--- /dev/null
+++ b/src/modules/e-mail-config-ews-oal-combo-box.h
@@ -0,0 +1,82 @@
+/*
+ * e-mail-config-ews-oal-combo-box.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_H
+#define E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_H
+
+#include <gtk/gtk.h>
+#include <mail/e-mail-config-service-backend.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX \
+	(e_mail_config_ews_oal_combo_box_get_type ())
+#define E_MAIL_CONFIG_EWS_OAL_COMBO_BOX(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX, EMailConfigEwsOalComboBox))
+#define E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX, EMailConfigEwsOalComboBoxClass))
+#define E_IS_MAIL_CONFIG_EWS_OAL_COMBO_BOX(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX))
+#define E_IS_MAIL_CONFIG_EWS_OAL_COMBO_BOX_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX))
+#define E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OAL_COMBO_BOX, EMailConfigEwsOalComboBoxClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigEwsOalComboBox EMailConfigEwsOalComboBox;
+typedef struct _EMailConfigEwsOalComboBoxClass EMailConfigEwsOalComboBoxClass;
+typedef struct _EMailConfigEwsOalComboBoxPrivate EMailConfigEwsOalComboBoxPrivate;
+
+struct _EMailConfigEwsOalComboBox {
+	GtkComboBoxText parent;
+	EMailConfigEwsOalComboBoxPrivate *priv;
+};
+
+struct _EMailConfigEwsOalComboBoxClass {
+	GtkComboBoxTextClass parent_class;
+};
+
+GType		e_mail_config_ews_oal_combo_box_get_type
+						(void) G_GNUC_CONST;
+void		e_mail_config_ews_oal_combo_box_type_register
+						(GTypeModule *type_module);
+GtkWidget *	e_mail_config_ews_oal_combo_box_new
+						(EMailConfigServiceBackend *backend);
+EMailConfigServiceBackend *
+		e_mail_config_ews_oal_combo_box_get_backend
+						(EMailConfigEwsOalComboBox *combo_box);
+void		e_mail_config_ews_oal_combo_box_update
+						(EMailConfigEwsOalComboBox *combo_box,
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_mail_config_ews_oal_combo_box_update_finish
+						(EMailConfigEwsOalComboBox *combo_box,
+						 GAsyncResult *result,
+						 GError **error);
+
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_EWS_OAL_COMBO_BOX_H */
+
diff --git a/src/modules/e-mail-config-ews-ooo-page.c b/src/modules/e-mail-config-ews-ooo-page.c
new file mode 100644
index 0000000..2cafd0a
--- /dev/null
+++ b/src/modules/e-mail-config-ews-ooo-page.c
@@ -0,0 +1,937 @@
+/*
+ * e-mail-config-ews-ooo-page.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-ews-ooo-page.h"
+
+#include <config.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+
+#include <misc/e-dateedit.h>
+#include <e-util/e-dialog-utils.h>
+
+#include "server/camel-ews-settings.h"
+#include "server/e-ews-connection.h"
+
+#define E_MAIL_CONFIG_EWS_OOO_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE, EMailConfigEwsOooPagePrivate))
+
+typedef enum {
+	EXTERNAL_AUDIENCE_NONE,
+	EXTERNAL_AUDIENCE_KNOWN,
+	EXTERNAL_AUDIENCE_ALL
+} ExternalAudience;
+
+struct _EMailConfigEwsOooPagePrivate {
+	ESource *account_source;
+	ESource *identity_source;
+
+	gboolean state;
+
+	/*to set duration or not*/
+	gboolean set_range;
+	GtkWidget *range_wt;
+
+	/*duration for out of office*/
+	time_t from_time;
+	time_t to_time;
+	EDateEdit *from_date;
+	EDateEdit *to_date;
+
+	/*External Audience type*/
+	gchar *audience;
+	gint audience_type;
+	GtkWidget *aud_box;
+
+	/*Internal and External messages*/
+	gchar *external_message;
+	gchar *internal_message;
+	GtkWidget *external_view;
+	GtkWidget *internal_view;
+
+	/*Update box*/
+	GtkWidget *stat_box;
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT_SOURCE,
+	PROP_IDENTITY_SOURCE
+};
+
+/* Forward Declarations */
+static void	e_mail_config_ews_ooo_page_interface_init
+					(EMailConfigPageInterface *interface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailConfigEwsOooPage,
+	e_mail_config_ews_ooo_page,
+	GTK_TYPE_BOX,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_ews_ooo_page_interface_init))
+
+static void
+update_audience_type (void)
+{
+#if 0  /* ACCOUNT_MGMT */
+	if (!g_ascii_strcasecmp (oof_data->audience, "None"))
+		oof_data->audience_type = EXTERNAL_AUDIENCE_NONE;
+	else if (!g_ascii_strcasecmp (oof_data->audience, "Known"))
+		oof_data->audience_type = EXTERNAL_AUDIENCE_KNOWN;
+	else
+		oof_data->audience_type = EXTERNAL_AUDIENCE_ALL;
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+update_audience (void)
+{
+#if 0  /* ACCOUNT_MGMT */
+	g_free (oof_data->audience);
+	oof_data->audience = NULL;
+
+	if (oof_data->audience_type == EXTERNAL_AUDIENCE_NONE)
+		oof_data->audience = g_strdup ("None");
+	else if (oof_data->audience_type == EXTERNAL_AUDIENCE_KNOWN)
+		oof_data->audience = g_strdup ("Known");
+	else
+		oof_data->audience = g_strdup ("All");
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+update_audience_cb (GtkComboBoxText *combo,
+                    gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	gint active;
+
+	active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+	if (active == oof_data->audience_type)
+		return;
+	else
+		oof_data->audience_type = active;
+
+	update_audience ();
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+update_int_msg_cb (GtkTextBuffer *buffer,
+                   gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	if (gtk_text_buffer_get_modified (buffer)) {
+		GtkTextIter start, end;
+		if (oof_data->internal_message)
+			g_free (oof_data->internal_message);
+		gtk_text_buffer_get_bounds (buffer, &start, &end);
+		oof_data->internal_message =  gtk_text_buffer_get_text (buffer, &start,
+							       &end, FALSE);
+		gtk_text_buffer_set_modified (buffer, FALSE);
+	}
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+update_ext_msg_cb (GtkTextBuffer *buffer,
+                   gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	if (gtk_text_buffer_get_modified (buffer)) {
+		GtkTextIter start, end;
+		if (oof_data->external_message)
+			g_free (oof_data->external_message);
+		gtk_text_buffer_get_bounds (buffer, &start, &end);
+		oof_data->external_message =  gtk_text_buffer_get_text (buffer, &start,
+							       &end, FALSE);
+		gtk_text_buffer_set_modified (buffer, FALSE);
+	}
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+toggled_state_cb (GtkToggleButton *button,
+                  gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	gboolean current_oof_state;
+
+	current_oof_state = gtk_toggle_button_get_active (button);
+	if (current_oof_state == oof_data->state)
+		return;
+	oof_data->state = current_oof_state;
+	gtk_widget_set_sensitive (oof_data->range_wt, current_oof_state);
+	gtk_widget_set_sensitive (oof_data->internal_view, current_oof_state);
+	gtk_widget_set_sensitive (oof_data->external_view, current_oof_state);
+	gtk_widget_set_sensitive ((GtkWidget *) oof_data->from_date, current_oof_state && oof_data->set_range);
+	gtk_widget_set_sensitive ((GtkWidget *) oof_data->to_date, current_oof_state && oof_data->set_range);
+	gtk_widget_set_sensitive (oof_data->aud_box, current_oof_state);
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+toggled_set_date_cb (GtkToggleButton *button,
+		     gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	gboolean current_state;
+
+	current_state = gtk_toggle_button_get_active (button);
+	if (current_state == oof_data->set_range)
+		return;
+
+	oof_data->set_range = current_state;
+	gtk_widget_set_sensitive ((GtkWidget *) oof_data->from_date, current_state);
+	gtk_widget_set_sensitive ((GtkWidget *) oof_data->to_date, current_state);
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+from_time_changed_cb (EDateEdit *date_tm,
+                      gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	if (e_date_edit_get_time (date_tm) < time (NULL)) {
+		e_notice (NULL, GTK_MESSAGE_WARNING, _("Cannot set Date-Time in Past"));
+		e_date_edit_set_time (date_tm, time (NULL) + 60);
+	} else if (e_date_edit_date_is_valid (date_tm) && e_date_edit_time_is_valid (date_tm)) {
+		oof_data->from_time = e_date_edit_get_time (date_tm);
+	}
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+to_time_changed_cb (EDateEdit *date_tm,
+                    gpointer data)
+{
+#if 0  /* ACCOUNT_MGMT */
+	if (e_date_edit_get_time (date_tm) < time (NULL)) {
+		e_notice (NULL, GTK_MESSAGE_WARNING, _("Cannot set Date-Time in Past"));
+		e_date_edit_set_time (date_tm, time (NULL) + 60);
+		return;
+	} else if (e_date_edit_date_is_valid (date_tm) && e_date_edit_time_is_valid (date_tm)) {
+		oof_data->to_time = e_date_edit_get_time (date_tm);
+	}
+	if (oof_data->from_time > oof_data->to_time)
+		e_notice (NULL, GTK_MESSAGE_WARNING, _("Select a valid time range"));
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+oof_data_new (void)
+{
+#if 0  /* ACCOUNT_MGMT */
+	oof_data = g_new0 (OOFData, 1);
+	oof_data->state = FALSE;
+	oof_data->set_range = FALSE;
+	oof_data->range_wt = NULL;
+	oof_data->audience_type = EXTERNAL_AUDIENCE_ALL;
+	oof_data->audience = NULL;
+	oof_data->external_message = NULL;
+	oof_data->internal_message = NULL;
+	oof_data->internal_view = NULL;
+	oof_data->external_view = NULL;
+	oof_data->from_time = 0;
+	oof_data->to_time = 0;
+	oof_data->from_date = NULL;
+	oof_data->to_date = NULL;
+	oof_data->stat_box = NULL;
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+destroy_oof_data (void)
+{
+#if 0  /* ACCOUNT_MGMT */
+	if (oof_data->audience) {
+		g_free (oof_data->audience);
+		oof_data->audience = NULL;
+	}
+
+	if (oof_data->external_message) {
+		g_free (oof_data->external_message);
+		oof_data->external_message = NULL;
+	}
+
+	if (oof_data->internal_message) {
+		g_free (oof_data->internal_message);
+		oof_data->internal_message = NULL;
+	}
+
+	if (oof_data) {
+		g_free (oof_data);
+		oof_data = NULL;
+	}
+#endif /* ACCOUNT_MGMT */
+}
+
+#if 0  /* ACCOUNT_MGMT */
+static gchar *
+get_password (CamelSettings *settings)
+{
+	gchar *key, *password = NULL;
+	CamelURL *url;
+
+	url = g_new0 (CamelURL, 1);
+	camel_settings_save_to_url (settings, url);
+	key = camel_url_to_string (url, CAMEL_URL_HIDE_PARAMS);
+	camel_url_free (url);
+
+	password = e_passwords_get_password ("Exchange Web Services", key);
+
+	g_free (key);
+	return password;
+}
+#endif /* ACCOUNT_MGMT */
+
+#if 0  /* ACCOUNT_MGMT */
+static EEwsConnection *
+get_connection (EMConfigTargetSettings *target)
+{
+	CamelEwsSettings *ews_settings;
+	CamelNetworkSettings *network_settings;
+	EEwsConnection *cnc;
+	const gchar *host_url;
+	const gchar *user;
+	gchar *email, *password;
+	GError *error = NULL;
+
+	ews_settings = CAMEL_EWS_SETTINGS (target->storage_settings);
+	network_settings = CAMEL_NETWORK_SETTINGS (target->storage_settings);
+
+	/* Create a new connection */
+	host_url = camel_ews_settings_get_hosturl (ews_settings);
+	user = camel_network_settings_get_user (network_settings);
+	password = get_password (target->storage_settings);
+	email = target->email_address;
+
+	cnc = e_ews_connection_new (host_url, user, password, NULL, NULL, &error);
+
+	if (!cnc) {
+		g_warning ("Error in connection: %s\n", error->message);
+		g_clear_error (&error);
+		return NULL;
+	}
+
+	e_ews_connection_set_mailbox (cnc, email);
+
+	g_free (password);
+	return cnc;
+}
+#endif /* ACCOUNT_MGMT */
+
+static void
+set_oof_error_to_frame (GtkWidget *oof_frame,
+                        GError *error)
+{
+#if 0  /* ACCOUNT_MGMT */
+	GtkHBox *error_box;
+	GtkLabel *error_msg;
+	GtkWidget *error_img;
+	gchar *message;
+
+	gtk_widget_destroy (oof_data->stat_box);
+
+	error_box = (GtkHBox*) g_object_new (GTK_TYPE_HBOX, NULL, "homogeneous", FALSE, "spacing", 6, NULL);
+	error_img = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_SMALL_TOOLBAR);
+	message = g_strdup_printf (_("Unable to fetch out of office settings: \n%s"), error->message);
+	error_msg = (GtkLabel *) gtk_label_new (message);
+	gtk_label_set_use_markup (error_msg, TRUE);
+	gtk_box_pack_start (GTK_BOX (error_box), GTK_WIDGET (error_img), FALSE, FALSE, 12);
+	gtk_box_pack_start (GTK_BOX (error_box), GTK_WIDGET (error_msg), FALSE, FALSE, 0);
+	gtk_container_add (GTK_CONTAINER (oof_frame), GTK_WIDGET (error_box));
+	gtk_widget_show_all (GTK_WIDGET (error_box));
+
+	g_free (message);
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+set_oof_settings_to_frame (GtkWidget *oof_frame)
+{
+#if 0  /* ACCOUNT_MGMT */
+	gtk_widget_destroy (oof_data->stat_box);
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+get_oof_settings_cb (GObject *object,
+                     GAsyncResult *res,
+                     gpointer user_data)
+{
+	EEwsConnection *cnc = E_EWS_CONNECTION (object);
+	GtkWidget *oof_frame = GTK_WIDGET (user_data);
+	OOFSettings *oof_settings = NULL;
+	GError *error = NULL;
+
+	e_ews_connection_get_oof_settings_finish (cnc, res, &oof_settings, &error);
+
+	if (error) {
+		g_warning ("Error Unable to get out of office settings: %s\n", error->message);
+		set_oof_error_to_frame (oof_frame, error);
+		g_object_unref (cnc);
+		g_clear_error (&error);
+		return;
+	}
+
+#if 0  /* ACCOUNT_MGMT */
+	if (!g_ascii_strcasecmp (oof_settings->state, "Disabled"))
+		oof_data->state = FALSE;
+	else
+		oof_data->state = TRUE;
+
+	oof_data->audience = g_strdup (oof_settings->ext_aud);
+	update_audience_type ();
+	if (!g_ascii_strcasecmp (oof_settings->state, "Scheduled")) {
+		oof_data->from_time = oof_settings->start_tm;
+		oof_data->to_time = oof_settings->end_tm;
+		oof_data->set_range = TRUE;
+	}
+	oof_data->internal_message = g_strdup (oof_settings->int_reply);
+	oof_data->external_message = g_strdup (oof_settings->ext_reply);
+#endif /* ACCOUNT_MGMT */
+
+	set_oof_settings_to_frame (oof_frame);
+	e_ews_connection_free_oof_settings (oof_settings);
+	g_object_unref (cnc);
+}
+
+#if 0  /* ACCOUNT_MGMT */
+static void
+set_oof_data_from_settings (EMConfigTargetSettings *target,
+                            GtkWidget *oof_frame)
+{
+	GCancellable *cancellable = NULL;
+	EEwsConnection *cnc = NULL;
+
+	cnc = get_connection (target);
+	if (!cnc)
+		return;
+
+	cancellable = g_cancellable_new ();
+
+	e_ews_connection_get_oof_settings (
+		cnc, EWS_PRIORITY_MEDIUM, cancellable,
+		get_oof_settings_cb, oof_frame);
+}
+#endif /* ACCOUNT_MGMT */
+
+static OOFSettings *
+get_settings_from_data (void)
+{
+	OOFSettings *oof_settings = NULL;
+
+	oof_settings = g_new0 (OOFSettings, 1);
+
+#if 0  /* ACCOUNT_MGMT */
+	if (oof_data->from_time >= oof_data->to_time || !oof_data->set_range) {
+		d (printf ("not a valid time range or set duration is not available"));
+		oof_data->from_time = 0;
+		oof_data->to_time = 0;
+	}
+
+	if (oof_data->state) {
+		if (oof_data->from_time && oof_data->to_time)
+			oof_settings->state = g_strdup ("Scheduled");
+		else
+			oof_settings->state = g_strdup ("Enabled");
+	} else
+		oof_settings->state = g_strdup ("Disabled");
+
+	oof_settings->ext_aud = g_strdup (oof_data->audience);
+	oof_settings->start_tm = oof_data->from_time;
+	oof_settings->end_tm = oof_data->to_time;
+	oof_settings->int_reply = g_strdup (oof_data->internal_message);
+	oof_settings->ext_reply = g_strdup (oof_data->external_message);
+#endif /* ACCOUNT_MGMT */
+
+	return oof_settings;
+}
+
+#if 0  /* ACCOUNT_MGMT */
+gboolean
+ews_set_oof_settings (EMConfigTargetSettings *target)
+{
+	GCancellable *cancellable = NULL;
+	OOFSettings *oof_settings = NULL;
+	EEwsConnection *cnc = NULL;
+	GError *error = NULL;
+	gboolean ret_val;
+
+	cnc = get_connection (target);
+	if (!cnc) {
+		destroy_oof_data ();
+		return FALSE;
+	}
+
+	cancellable = g_cancellable_new ();
+
+	oof_settings = get_settings_from_data ();
+
+	e_ews_connection_set_oof_settings_sync (
+		cnc, EWS_PRIORITY_MEDIUM,
+		oof_settings, cancellable, &error);
+
+	if (error) {
+		g_warning ("Error While setting out of office: %s\n", error->message);
+		g_clear_error (&error);
+		ret_val = FALSE;
+	} else
+		ret_val = TRUE;
+
+	destroy_oof_data ();
+	e_ews_connection_free_oof_settings (oof_settings);
+	g_object_unref (cnc);
+
+	return ret_val;
+}
+#endif /* ACCOUNT_MGMT */
+
+#if 0  /* ACCOUNT_MGMT */
+GtkWidget *
+ews_get_outo_office_widget (EMConfigTargetSettings *target_account)
+{
+	GtkFrame *frm_oof;
+	GtkHBox *stat_box;
+	GtkLabel *stat_msg;
+	GtkWidget *spinner, *label;
+	gchar *txt;
+
+	txt = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>", _("Out of Office"));
+	label = gtk_label_new (NULL);
+	gtk_label_set_markup ((GtkLabel *) label, txt);
+	g_free (txt);
+	frm_oof = (GtkFrame*) g_object_new (GTK_TYPE_FRAME, "label-widget", label, NULL);
+
+	oof_data_new ();
+
+	stat_box = (GtkHBox*) g_object_new (GTK_TYPE_HBOX, NULL, "homogeneous", FALSE, "spacing", 6, NULL);
+	spinner = gtk_spinner_new ();
+	stat_msg = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("Fetching out of office settings..."), "use-markup", TRUE, NULL);
+
+	oof_data->stat_box = GTK_WIDGET (stat_box);
+
+	gtk_box_pack_start (GTK_BOX (stat_box), GTK_WIDGET (spinner), FALSE, FALSE, 12);
+	gtk_box_pack_start (GTK_BOX (stat_box), GTK_WIDGET (stat_msg), FALSE, FALSE, 0);
+	gtk_spinner_start ((GtkSpinner *) spinner);
+	gtk_container_add (GTK_CONTAINER (frm_oof), GTK_WIDGET (stat_box));
+
+	set_oof_data_from_settings (target_account, (GtkWidget *) frm_oof);
+
+	return (GtkWidget *) frm_oof;
+}
+#endif /* ACCOUNT_MGMT */
+
+static void
+mail_config_ews_ooo_page_set_account_source (EMailConfigEwsOooPage *page,
+                                             ESource *account_source)
+{
+	g_return_if_fail (E_IS_SOURCE (account_source));
+	g_return_if_fail (page->priv->account_source == NULL);
+
+	page->priv->account_source = g_object_ref (account_source);
+}
+
+static void
+mail_config_ews_ooo_page_set_identity_source (EMailConfigEwsOooPage *page,
+                                              ESource *identity_source)
+{
+	g_return_if_fail (E_IS_SOURCE (identity_source));
+	g_return_if_fail (page->priv->identity_source == NULL);
+
+	page->priv->identity_source = g_object_ref (identity_source);
+}
+
+static void
+mail_config_ews_ooo_page_set_property (GObject *object,
+                                       guint property_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			mail_config_ews_ooo_page_set_account_source (
+				E_MAIL_CONFIG_EWS_OOO_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			mail_config_ews_ooo_page_set_identity_source (
+				E_MAIL_CONFIG_EWS_OOO_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_ooo_page_get_property (GObject *object,
+                                       guint property_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_ooo_page_get_account_source (
+				E_MAIL_CONFIG_EWS_OOO_PAGE (object)));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_ooo_page_get_identity_source (
+				E_MAIL_CONFIG_EWS_OOO_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_ooo_page_dispose (GObject *object)
+{
+	EMailConfigEwsOooPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_EWS_OOO_PAGE_GET_PRIVATE (object);
+
+	if (priv->account_source != NULL) {
+		g_object_unref (priv->account_source);
+		priv->account_source = NULL;
+	}
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_ooo_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_ews_ooo_page_constructed (GObject *object)
+{
+	EMailConfigEwsOooPage *page;
+	GtkWidget *widget;
+	GtkWidget *container;
+	const gchar *text;
+	gchar *markup;
+
+	GtkHBox *hbox_ext, *hbox_state;
+	GtkLabel *lbl_oof_desc, *from_label, *to_label;
+	GtkTable *tbl_oof_status;
+	GtkLabel *lbl_status, *lbl_external, *lbl_internal;
+	GtkRadioButton *radio_iof, *radio_oof;
+	GtkScrolledWindow *scrwnd_oof_int, *scrwnd_oof_ext;
+	GtkTextView *txtview_oof_int, *txtview_oof_ext;
+	GtkTextBuffer *buffer_int, *buffer_ext;
+	GtkWidget *from_date, *to_date, *aud_box, *set_range;
+
+	page = E_MAIL_CONFIG_EWS_OOO_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_ooo_page_parent_class)->
+		constructed (object);
+
+	text = _("Out of Office");
+	markup = g_markup_printf_escaped ("<b>%s</b>", text);
+	widget = gtk_label_new (markup);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+	g_free (markup);
+
+	widget = gtk_grid_new ();
+	gtk_widget_set_margin_left (widget, 12);
+	gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+	gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	text = _("The messages specified below will be automatically sent "
+		 "to each internal and external personal who sends a mail "
+		 "to you.");
+	widget = gtk_label_new (text);
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+	gtk_widget_show (widget);
+
+	/* XXX Crap starts here */
+
+	tbl_oof_status = (GtkTable*) g_object_new (GTK_TYPE_TABLE, "n-rows", 7, "n-columns", 2, "homogeneous", FALSE, "row-spacing", 6, "column-spacing", 6, NULL);
+	gtk_grid_attach (GTK_GRID (container), GTK_WIDGET (tbl_oof_status), 0, 1, 1, 1);
+	gtk_widget_show (GTK_WIDGET (tbl_oof_status));
+
+	lbl_status = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("Status:"), "use-markup", TRUE, NULL);
+	gtk_misc_set_alignment (GTK_MISC (lbl_status), 0, 0.5);
+	gtk_misc_set_padding (GTK_MISC (lbl_status), 0, 0);
+
+#if 0  /* ACCOUNT_MGMT */
+	if (oof_data->state) {
+#endif /* ACCOUNT_MGMT */
+		radio_oof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am _out of the office"), "use-underline", TRUE, NULL);
+		radio_iof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am _in the office"), "use-underline", TRUE, "group", radio_oof, NULL);
+#if 0  /* ACCOUNT_MGMT */
+	} else {
+		radio_iof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am _in the office"), "use-underline", TRUE, NULL);
+		radio_oof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am _out of the office"), "use-underline", TRUE, "group", radio_iof, NULL);
+	}
+#endif /* ACCOUNT_MGMT */
+	g_signal_connect (radio_oof, "toggled", G_CALLBACK (toggled_state_cb), NULL);
+
+	hbox_state = g_object_new (GTK_TYPE_HBOX, NULL, "homogeneous", FALSE, "spacing", 6, NULL);
+	gtk_box_pack_start (GTK_BOX (hbox_state), GTK_WIDGET (radio_iof), FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox_state), GTK_WIDGET (radio_oof), FALSE, FALSE, 12);
+
+	/*Check box for setting date*/
+	set_range = gtk_check_button_new_with_mnemonic (_("_Send only during this time period"));
+#if 0  /* ACCOUNT_MGMT */
+	oof_data->range_wt = set_range;
+	gtk_toggle_button_set_active ((GtkToggleButton*) set_range, oof_data->set_range);
+#endif /* ACCOUNT_MGMT */
+	g_signal_connect ((GtkToggleButton*) set_range, "toggled", G_CALLBACK (toggled_set_date_cb), NULL);
+
+
+	/*Selectable Dates*/
+	from_date = e_date_edit_new ();
+	to_date = e_date_edit_new ();
+
+#if 0  /* ACCOUNT_MGMT */
+	e_date_edit_set_time ((EDateEdit *) from_date, oof_data->from_time);
+	e_date_edit_set_time ((EDateEdit *) to_date, oof_data->to_time);
+
+	oof_data->from_date = (EDateEdit *) from_date;
+	oof_data->to_date = (EDateEdit *) to_date;
+#endif /* ACCOUNT_MGMT */
+
+	g_signal_connect (from_date, "changed", G_CALLBACK (from_time_changed_cb), NULL);
+	g_signal_connect (to_date, "changed", G_CALLBACK (to_time_changed_cb), NULL);
+
+	from_label = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("_From:"), "use-underline", TRUE, "use-markup", TRUE, NULL);
+	gtk_label_set_mnemonic_widget (from_label, GTK_WIDGET (from_date));
+	gtk_misc_set_alignment (GTK_MISC (from_label), 0, 0.5);
+	gtk_misc_set_padding (GTK_MISC (from_label), 0, 0);
+
+	to_label = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("_To:"), "use-markup", TRUE, "use-underline", TRUE, NULL);
+	gtk_label_set_mnemonic_widget (to_label, GTK_WIDGET (to_date));
+	gtk_misc_set_alignment (GTK_MISC (to_label), 0, 0.5);
+	gtk_misc_set_padding (GTK_MISC (to_label), 0, 0);
+
+	scrwnd_oof_int = (GtkScrolledWindow*) g_object_new (GTK_TYPE_SCROLLED_WINDOW, "hscrollbar-policy", GTK_POLICY_AUTOMATIC, "vscrollbar-policy", GTK_POLICY_AUTOMATIC, "shadow-type", GTK_SHADOW_IN, NULL);
+	txtview_oof_int = (GtkTextView*) g_object_new (GTK_TYPE_TEXT_VIEW, "justification", GTK_JUSTIFY_LEFT, "wrap-mode", GTK_WRAP_WORD, "editable", TRUE, NULL);
+
+	buffer_int = gtk_text_view_get_buffer (txtview_oof_int);
+#if 0  /* ACCOUNT_MGMT */
+	if (oof_data->internal_message) {
+		/* previuosly set message */
+		gtk_text_buffer_set_text (buffer_int, oof_data->internal_message, -1);
+		gtk_text_view_set_buffer (txtview_oof_int, buffer_int);
+	}
+#endif /* ACCOUNT_MGMT */
+	gtk_text_buffer_set_modified (buffer_int, FALSE);
+	gtk_container_add (GTK_CONTAINER (scrwnd_oof_int), GTK_WIDGET (txtview_oof_int));
+
+	lbl_internal = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("I_nternal:"), "use-underline", TRUE, "use-markup", TRUE, NULL);
+	gtk_label_set_mnemonic_widget (lbl_internal, GTK_WIDGET (txtview_oof_int));
+	gtk_widget_set_tooltip_text (GTK_WIDGET (lbl_internal), _("Message to be sent inside organization"));
+	gtk_misc_set_alignment (GTK_MISC (lbl_internal), 0, 0.5);
+	gtk_misc_set_padding (GTK_MISC (lbl_internal), 0, 0);
+
+	/*Select External Audience*/
+	hbox_ext = g_object_new (GTK_TYPE_HBOX, NULL, "homogeneous", FALSE, "spacing", 6, NULL);	
+	aud_box = gtk_combo_box_text_new ();
+	gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (aud_box), EXTERNAL_AUDIENCE_NONE, _("None"));
+	gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (aud_box), EXTERNAL_AUDIENCE_KNOWN, _("Known"));
+	gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (aud_box), EXTERNAL_AUDIENCE_ALL, _("All"));
+#if 0  /* ACCOUNT_MGMT */
+	gtk_combo_box_set_active (GTK_COMBO_BOX (aud_box), oof_data->audience_type);
+#endif /* ACCOUNT_MGMT */
+	gtk_widget_set_tooltip_text (GTK_WIDGET (aud_box), _("Send Message to"));
+
+#if 0  /* ACCOUNT_MGMT */
+	oof_data->aud_box = aud_box;
+#endif /* ACCOUNT_MGMT */
+	gtk_box_pack_start (GTK_BOX (hbox_ext), GTK_WIDGET (aud_box), FALSE, FALSE, 0);
+	g_signal_connect (GTK_COMBO_BOX (aud_box), "changed", G_CALLBACK (update_audience_cb), NULL);
+
+	scrwnd_oof_ext = (GtkScrolledWindow*) g_object_new (GTK_TYPE_SCROLLED_WINDOW, "hscrollbar-policy", GTK_POLICY_AUTOMATIC, "vscrollbar-policy", GTK_POLICY_AUTOMATIC, "shadow-type", GTK_SHADOW_IN, NULL);
+	gtk_box_pack_start (GTK_BOX (hbox_ext), GTK_WIDGET (scrwnd_oof_ext), TRUE, TRUE, 0);
+	txtview_oof_ext = (GtkTextView*) g_object_new (GTK_TYPE_TEXT_VIEW, "justification", GTK_JUSTIFY_LEFT, "wrap-mode", GTK_WRAP_WORD, "editable", TRUE, NULL);
+
+	buffer_ext = gtk_text_view_get_buffer (txtview_oof_ext);
+#if 0  /* ACCOUNT_MGMT */
+	if (oof_data->external_message) {
+		/* previuosly set message */
+		gtk_text_buffer_set_text (buffer_ext, oof_data->external_message, -1);
+		gtk_text_view_set_buffer (txtview_oof_ext, buffer_ext);
+
+	}
+#endif /* ACCOUNT_MGMT */
+	gtk_text_buffer_set_modified (buffer_ext, FALSE);
+	gtk_container_add (GTK_CONTAINER (scrwnd_oof_ext), GTK_WIDGET (txtview_oof_ext));
+
+	lbl_external = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("E_xternal:"), "use-underline", TRUE, "use-markup", TRUE, NULL);
+	gtk_label_set_mnemonic_widget (lbl_external, GTK_WIDGET (txtview_oof_ext));
+	gtk_widget_set_tooltip_text (GTK_WIDGET (lbl_external), _("Message to be sent outside organization"));
+	gtk_misc_set_alignment (GTK_MISC (lbl_external), 0, 0.5);
+	gtk_misc_set_padding (GTK_MISC (lbl_external), 0, 0);
+
+	g_signal_connect (buffer_int, "changed", G_CALLBACK (update_int_msg_cb), NULL);
+	g_signal_connect (buffer_ext, "changed", G_CALLBACK (update_ext_msg_cb), NULL);
+
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (lbl_status), 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (hbox_state), 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (set_range), 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (from_label), 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (from_date), 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (to_label), 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (to_date), 1, 2, 3, 4, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (lbl_internal), 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (scrwnd_oof_int), 1, 2, 4, 5, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (lbl_external), 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
+	gtk_table_attach (tbl_oof_status, GTK_WIDGET (hbox_ext), 1, 2, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
+
+#if 0  /* ACCOUNT_MGMT */
+	if (!oof_data->state) {
+		gtk_widget_set_sensitive ((GtkWidget *) set_range, FALSE);
+		gtk_widget_set_sensitive (GTK_WIDGET (txtview_oof_int), FALSE);
+		gtk_widget_set_sensitive (GTK_WIDGET (txtview_oof_ext), FALSE);
+		gtk_widget_set_sensitive ((GtkWidget *) from_date, FALSE);
+		gtk_widget_set_sensitive ((GtkWidget *) to_date, FALSE);
+		gtk_widget_set_sensitive (aud_box, FALSE);
+	}
+	if (!oof_data->set_range) {
+		gtk_widget_set_sensitive ((GtkWidget *) from_date, FALSE);
+		gtk_widget_set_sensitive ((GtkWidget *) to_date, FALSE);
+	}
+
+	oof_data->internal_view = GTK_WIDGET (txtview_oof_int);
+	oof_data->external_view = GTK_WIDGET (txtview_oof_ext);
+#endif /* ACCOUNT_MGMT */
+}
+
+static void
+e_mail_config_ews_ooo_page_class_init (EMailConfigEwsOooPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigEwsOooPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_ews_ooo_page_set_property;
+	object_class->get_property = mail_config_ews_ooo_page_get_property;
+	object_class->dispose = mail_config_ews_ooo_page_dispose;
+	object_class->constructed = mail_config_ews_ooo_page_constructed;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ACCOUNT_SOURCE,
+		g_param_spec_object (
+			"account-source",
+			"Account Source",
+			"Mail account source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IDENTITY_SOURCE,
+		g_param_spec_object (
+			"identity-source",
+			"Identity Source",
+			"Mail identity source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_ews_ooo_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("EWS Settings");
+	interface->sort_order = E_MAIL_CONFIG_EWS_OOO_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_ews_ooo_page_class_finalize (EMailConfigEwsOooPageClass *class)
+{
+}
+
+static void
+e_mail_config_ews_ooo_page_init (EMailConfigEwsOooPage *page)
+{
+	page->priv = E_MAIL_CONFIG_EWS_OOO_PAGE_GET_PRIVATE (page);
+}
+
+void
+e_mail_config_ews_ooo_page_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_mail_config_ews_ooo_page_register_type (type_module);
+}
+
+EMailConfigPage *
+e_mail_config_ews_ooo_page_new (ESource *account_source,
+                                ESource *identity_source)
+{
+	g_return_val_if_fail (E_IS_SOURCE (account_source), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE,
+		"account-source", account_source,
+		"identity-source", identity_source, NULL);
+}
+
+ESource *
+e_mail_config_ews_ooo_page_get_account_source (EMailConfigEwsOooPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_EWS_OOO_PAGE (page), NULL);
+
+	return page->priv->account_source;
+}
+
+ESource *
+e_mail_config_ews_ooo_page_get_identity_source (EMailConfigEwsOooPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_EWS_OOO_PAGE (page), NULL);
+
+	return page->priv->identity_source;
+}
+
diff --git a/src/modules/e-mail-config-ews-ooo-page.h b/src/modules/e-mail-config-ews-ooo-page.h
new file mode 100644
index 0000000..86e5cf9
--- /dev/null
+++ b/src/modules/e-mail-config-ews-ooo-page.h
@@ -0,0 +1,80 @@
+/*
+ * e-mail-config-ews-ooo-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* "OOO" = "Out of Office" */
+
+#ifndef E_MAIL_CONFIG_EWS_OOO_PAGE_H
+#define E_MAIL_CONFIG_EWS_OOO_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-source.h>
+
+#include <mail/e-mail-config-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE \
+	(e_mail_config_ews_ooo_page_get_type ())
+#define E_MAIL_CONFIG_EWS_OOO_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE, EMailConfigEwsOooPage))
+#define E_MAIL_CONFIG_EWS_OOO_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE, EMailConfigEwsOooPageClass))
+#define E_IS_MAIL_CONFIG_EWS_OOO_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE))
+#define E_IS_MAIL_CONFIG_EWS_OOO_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE))
+#define E_MAIL_CONFIG_EWS_OOO_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_OOO_PAGE, EMailConfigEwsOooPageClass))
+
+#define E_MAIL_CONFIG_EWS_OOO_PAGE_SORT_ORDER (550)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigEwsOooPage EMailConfigEwsOooPage;
+typedef struct _EMailConfigEwsOooPageClass EMailConfigEwsOooPageClass;
+typedef struct _EMailConfigEwsOooPagePrivate EMailConfigEwsOooPagePrivate;
+
+struct _EMailConfigEwsOooPage {
+	GtkBox parent;
+	EMailConfigEwsOooPagePrivate *priv;
+};
+
+struct _EMailConfigEwsOooPageClass {
+	GtkBoxClass parent_class;
+};
+
+GType		e_mail_config_ews_ooo_page_get_type
+						(void) G_GNUC_CONST;
+void		e_mail_config_ews_ooo_page_type_register
+						(GTypeModule *type_module);
+EMailConfigPage *
+		e_mail_config_ews_ooo_page_new	(ESource *account_source,
+						 ESource *identity_source);
+ESource *	e_mail_config_ews_ooo_page_get_account_source
+						(EMailConfigEwsOooPage *page);
+ESource *	e_mail_config_ews_ooo_page_get_identity_source
+						(EMailConfigEwsOooPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_EWS_OOO_PAGE_H */
+
diff --git a/src/modules/module-ews-backend.c b/src/modules/module-ews-backend.c
new file mode 100644
index 0000000..6fdb342
--- /dev/null
+++ b/src/modules/module-ews-backend.c
@@ -0,0 +1,822 @@
+/*
+ * module-ews-backend.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source-address-book.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-autocomplete.h>
+#include <libedataserver/e-source-calendar.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-collection.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-transport.h>
+#include <libedataserver/e-source-offline.h>
+
+#include <libebackend/e-collection-backend.h>
+#include <libebackend/e-collection-backend-factory.h>
+#include <libebackend/e-source-registry-server.h>
+
+#include "server/e-ews-connection.h"
+#include "server/e-source-ews-folder.h"
+
+/* Standard GObject macros */
+#define E_TYPE_EWS_BACKEND \
+	(e_ews_backend_get_type ())
+#define E_EWS_BACKEND(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_EWS_BACKEND, EEwsBackend))
+
+typedef struct _EEwsBackend EEwsBackend;
+typedef struct _EEwsBackendClass EEwsBackendClass;
+
+typedef struct _EEwsBackendFactory EEwsBackendFactory;
+typedef struct _EEwsBackendFactoryClass EEwsBackendFactoryClass;
+
+typedef struct _SyncFoldersClosure SyncFoldersClosure;
+
+struct _SyncFoldersClosure {
+	EEwsBackend *backend;
+	GSList *folders_created;
+	GSList *folders_deleted;
+	GSList *folders_updated;
+};
+
+struct _EEwsBackend {
+	ECollectionBackend parent;
+
+	/* Folder ID -> ESource */
+	GHashTable *folders;
+
+	ESource *gal_source;
+	gchar *oal_selected;
+
+	gchar *sync_state;
+	GMutex *sync_state_lock;
+};
+
+struct _EEwsBackendClass {
+	ECollectionBackendClass parent_class;
+};
+
+struct _EEwsBackendFactory {
+	ECollectionBackendFactory parent;
+};
+
+struct _EEwsBackendFactoryClass {
+	ECollectionBackendFactoryClass parent_class;
+};
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+/* Forward Declarations */
+GType e_ews_backend_get_type (void);
+GType e_ews_backend_factory_get_type (void);
+
+static void	e_ews_backend_authenticator_init
+				(ESourceAuthenticatorInterface *interface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EEwsBackend,
+	e_ews_backend,
+	E_TYPE_COLLECTION_BACKEND,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_ews_backend_authenticator_init))
+
+G_DEFINE_DYNAMIC_TYPE (
+	EEwsBackendFactory,
+	e_ews_backend_factory,
+	E_TYPE_COLLECTION_BACKEND_FACTORY)
+
+static void
+sync_folders_closure_free (SyncFoldersClosure *closure)
+{
+	g_object_unref (closure->backend);
+
+	/* List of EEwsFolder instances. */
+	g_slist_free_full (
+		closure->folders_created,
+		(GDestroyNotify) g_object_unref);
+
+	/* List of folder ID strings. */
+	g_slist_free_full (
+		closure->folders_deleted,
+		(GDestroyNotify) g_free);
+
+	/* List of EEwsFolder instances. */
+	g_slist_free_full (
+		closure->folders_updated,
+		(GDestroyNotify) g_object_unref);
+
+	g_slice_free (SyncFoldersClosure, closure);
+}
+
+static CamelEwsSettings *
+ews_backend_get_settings (EEwsBackend *backend)
+{
+	ESource *source;
+	ESourceCamel *extension;
+	CamelSettings *settings;
+	const gchar *extension_name;
+
+	source = e_backend_get_source (E_BACKEND (backend));
+	extension_name = e_source_camel_get_extension_name ("ews");
+	extension = e_source_get_extension (source, extension_name);
+	settings = e_source_camel_get_settings (extension);
+
+	return CAMEL_EWS_SETTINGS (settings);
+}
+
+static void
+ews_backend_queue_auth_session (ECollectionBackend *backend)
+{
+	ESourceRegistryServer *server;
+	EAuthenticationSession *session;
+	ESource *source;
+
+	server = e_collection_backend_ref_server (backend);
+	source = e_backend_get_source (E_BACKEND (backend));
+
+	session = e_authentication_session_new (
+		server, E_SOURCE_AUTHENTICATOR (backend),
+		e_source_get_uid (source));
+
+	e_source_registry_server_queue_auth_session (server, session);
+
+	g_object_unref (session);
+	g_object_unref (server);
+}
+
+static ESource *
+ews_backend_new_child (EEwsBackend *backend,
+                       EEwsFolder *folder)
+{
+	ECollectionBackend *collection_backend;
+	ESourceExtension *extension;
+	ESource *source;
+	const EwsFolderId *fid;
+	const gchar *display_name;
+	const gchar *extension_name;
+
+	fid = e_ews_folder_get_id (folder);
+
+	collection_backend = E_COLLECTION_BACKEND (backend);
+	source = e_collection_backend_new_child (collection_backend, fid->id);
+
+	display_name = e_ews_folder_get_name (folder);
+	e_source_set_display_name (source, display_name);
+
+	switch (e_ews_folder_get_folder_type (folder)) {
+		case EWS_FOLDER_TYPE_CALENDAR:
+			extension_name = E_SOURCE_EXTENSION_CALENDAR;
+			break;
+		case EWS_FOLDER_TYPE_TASKS:
+			extension_name = E_SOURCE_EXTENSION_TASK_LIST;
+			break;
+		case EWS_FOLDER_TYPE_CONTACTS:
+			extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+			break;
+		default:
+			g_object_unref (source);
+			g_return_val_if_reached (NULL);
+	}
+	extension = e_source_get_extension (source, extension_name);
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (extension), "ews");
+
+	extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+	extension = e_source_get_extension (source, extension_name);
+	e_source_ews_folder_set_id (
+		E_SOURCE_EWS_FOLDER (extension), fid->id);
+	e_source_ews_folder_set_change_key (
+		E_SOURCE_EWS_FOLDER (extension), fid->change_key);
+
+	extension_name = E_SOURCE_EXTENSION_OFFLINE;
+	extension = e_source_get_extension (source, extension_name);
+	e_source_offline_set_stay_synchronized (
+		E_SOURCE_OFFLINE (extension), TRUE);
+
+	return source;
+}
+
+static ESource *
+ews_backend_new_calendar (EEwsBackend *backend,
+                          EEwsFolder *folder)
+{
+	ESourceExtension *extension;
+	ESource *source;
+	const gchar *extension_name;
+
+	source = ews_backend_new_child (backend, folder);
+
+	/* XXX The Exchange server does not provide a color? */
+	extension_name = E_SOURCE_EXTENSION_CALENDAR;
+	extension = e_source_get_extension (source, extension_name);
+	e_source_selectable_set_color (
+		E_SOURCE_SELECTABLE (extension), "#EEBC60");
+
+	return source;
+}
+
+static ESource *
+ews_backend_new_task_list (EEwsBackend *backend,
+                           EEwsFolder *folder)
+{
+	ESourceExtension *extension;
+	ESource *source;
+	const gchar *extension_name;
+
+	source = ews_backend_new_child (backend, folder);
+
+	/* XXX The Exchange server does not provide a color? */
+	extension_name = E_SOURCE_EXTENSION_TASK_LIST;
+	extension = e_source_get_extension (source, extension_name);
+	e_source_selectable_set_color (
+		E_SOURCE_SELECTABLE (extension), "#EEBC60");
+
+	return source;
+}
+
+static ESource *
+ews_backend_new_address_book (EEwsBackend *backend,
+                              EEwsFolder *folder)
+{
+	/* No extra configuration to do. */
+	return ews_backend_new_child (backend, folder);
+}
+
+static void
+ews_backend_sync_created_folders (EEwsBackend *backend,
+                                  GSList *list)
+{
+	ECollectionBackend *collection_backend;
+	ESourceRegistryServer *server;
+	GSList *link;
+
+	collection_backend = E_COLLECTION_BACKEND (backend);
+	server = e_collection_backend_ref_server (collection_backend);
+
+	for (link = list; link != NULL; link = g_slist_next (link)) {
+		EEwsFolder *folder = E_EWS_FOLDER (link->data);
+		const EwsFolderId *fid;
+		ESource *source = NULL;
+
+		/* If we already know about this folder, skip it. */
+		fid = e_ews_folder_get_id (folder);
+		if (fid->id == NULL)
+			continue;  /* not a valid ID anyway */
+		if (g_hash_table_contains (backend->folders, fid->id))
+			continue;
+
+		switch (e_ews_folder_get_folder_type (folder)) {
+			case EWS_FOLDER_TYPE_CALENDAR:
+				source = ews_backend_new_calendar (
+					backend, folder);
+				break;
+			case EWS_FOLDER_TYPE_TASKS:
+				source = ews_backend_new_task_list (
+					backend, folder);
+				break;
+			case EWS_FOLDER_TYPE_CONTACTS:
+				source = ews_backend_new_address_book (
+					backend, folder);
+				break;
+			default:
+				break;
+		}
+
+		if (source != NULL) {
+			e_source_registry_server_add_source (server, source);
+			g_object_unref (source);
+		}
+	}
+
+	g_object_unref (server);
+}
+
+static void
+ews_backend_sync_deleted_folders (EEwsBackend *backend,
+                                  GSList *list)
+{
+	ECollectionBackend *collection_backend;
+	ESourceRegistryServer *server;
+	GSList *link;
+
+	collection_backend = E_COLLECTION_BACKEND (backend);
+	server = e_collection_backend_ref_server (collection_backend);
+
+	for (link = list; link != NULL; link = g_slist_next (link)) {
+		const gchar *folder_id = link->data;
+		ESource *source = NULL;
+
+		if (folder_id != NULL)
+			source = g_hash_table_lookup (
+				backend->folders, folder_id);
+
+		if (source == NULL)
+			continue;
+
+		/* This will trigger a "child-removed" signal and
+		 * our handler will remove the hash table entry. */
+		e_source_registry_server_remove_source (server, source);
+	}
+
+	g_object_unref (server);
+}
+
+static void
+ews_backend_add_gal_source (EEwsBackend *backend)
+{
+	ECollectionBackend *collection_backend;
+	ESourceAutocomplete *autocomplete_extension;
+	ESourceBackend *backend_extension;
+	ESourceEwsFolder *folder_extension;
+	ESourceOffline *offline_extension;
+	ESourceRegistryServer *server;
+	ESource *source = NULL;
+	CamelEwsSettings *settings;
+	const gchar *display_name;
+	const gchar *extension_name;
+	const gchar *gal_uid;
+	const gchar *oal_id;
+	const gchar *uid;
+	gchar *oal_selected;
+
+	settings = ews_backend_get_settings (backend);
+	collection_backend = E_COLLECTION_BACKEND (backend);
+
+	gal_uid = camel_ews_settings_get_gal_uid (settings);
+
+	if (gal_uid != NULL) {
+		server = e_collection_backend_ref_server (collection_backend);
+		source = e_source_registry_server_ref_source (server, gal_uid);
+		g_object_unref (server);
+
+		if (source != NULL) {
+			g_object_unref (source);
+			return;
+		}
+	}
+
+	oal_selected = camel_ews_settings_dup_oal_selected (settings);
+
+	/* This is supposed to be in the form: ID ':' NAME */
+	if (oal_selected != NULL) {
+		gchar *cp = strrchr (oal_selected, ':');
+		if (cp != NULL) {
+			*cp++ = '\0';
+			display_name = cp;
+			oal_id = oal_selected;
+		} else {
+			g_free (oal_selected);
+			oal_selected = NULL;
+		}
+	}
+
+	if (oal_selected == NULL) {
+		display_name = _("Global Address List");
+		oal_id = NULL;
+	}
+
+	g_free (backend->oal_selected);
+	backend->oal_selected = oal_selected;  /* takes ownership */
+
+	if (oal_id != NULL)
+		source = e_collection_backend_new_child (
+			collection_backend, oal_id);
+	else
+		source = e_collection_backend_new_child (
+			collection_backend, "Global Address List");
+
+	e_source_set_display_name (source, display_name);
+
+	extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+	backend_extension = e_source_get_extension (source, extension_name);
+	e_source_backend_set_backend_name (backend_extension, "ews");
+
+	extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
+	autocomplete_extension = e_source_get_extension (source, extension_name);
+	e_source_autocomplete_set_include_me (autocomplete_extension, TRUE);
+
+	extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+	folder_extension = e_source_get_extension (source, extension_name);
+	e_source_ews_folder_set_id (folder_extension, oal_id);
+
+	extension_name = E_SOURCE_EXTENSION_OFFLINE;
+	offline_extension = e_source_get_extension (source, extension_name);
+	e_source_offline_set_stay_synchronized (offline_extension, TRUE);
+
+	server = e_collection_backend_ref_server (collection_backend);
+	e_source_registry_server_add_source (server, source);
+	g_object_unref (server);
+
+	uid = e_source_get_uid (source);
+	camel_ews_settings_set_gal_uid (settings, uid);
+
+	g_object_unref (source);
+}
+
+static void
+ews_backend_source_changed_cb (ESource *source,
+                               EEwsBackend *backend)
+{
+	CamelEwsSettings *settings;
+	const gchar *oal_selected;
+	const gchar *gal_uid;
+
+	settings = ews_backend_get_settings (backend);
+	gal_uid = camel_ews_settings_get_gal_uid (settings);
+	oal_selected = camel_ews_settings_get_oal_selected (settings);
+
+	g_print ("OAL: '%s' vs '%s'\n", oal_selected, backend->oal_selected);
+
+	if (g_strcmp0 (oal_selected, backend->oal_selected) == 0)
+		return;
+
+	/* Remove the old Global Address List source if present. */
+	if (gal_uid != NULL) {
+		ECollectionBackend *collection_backend;
+		ESourceRegistryServer *server;
+
+		collection_backend = E_COLLECTION_BACKEND (backend);
+		server = e_collection_backend_ref_server (collection_backend);
+		source = e_source_registry_server_ref_source (server, gal_uid);
+
+		if (source != NULL) {
+			e_source_registry_server_remove_source (server, source);
+			g_object_unref (source);
+		}
+
+		camel_ews_settings_set_gal_uid (settings, NULL);
+	}
+
+	ews_backend_add_gal_source (backend);
+}
+
+static gboolean
+ews_backend_sync_folders_idle_cb (gpointer user_data)
+{
+	SyncFoldersClosure *closure = user_data;
+
+	/* FIXME Handle updated folders. */
+
+	ews_backend_sync_deleted_folders (
+		closure->backend, closure->folders_deleted);
+	ews_backend_sync_created_folders (
+		closure->backend, closure->folders_created);
+
+	return FALSE;
+}
+
+static void
+ews_backend_dispose (GObject *object)
+{
+	EEwsBackend *backend = E_EWS_BACKEND (object);
+
+	g_hash_table_remove_all (backend->folders);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_ews_backend_parent_class)->dispose (object);
+}
+
+static void
+ews_backend_finalize (GObject *object)
+{
+	EEwsBackend *backend = E_EWS_BACKEND (object);
+
+	g_hash_table_destroy (backend->folders);
+
+	g_free (backend->oal_selected);
+
+	g_free (backend->sync_state);
+	g_mutex_free (backend->sync_state_lock);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_ews_backend_parent_class)->finalize (object);
+}
+
+static void
+ews_backend_populate (ECollectionBackend *backend)
+{
+	ESource *source;
+
+	/* We test authentication passwords by attempting to synchronize
+	 * the folder hierarchy.  Since we want to synchronize the folder
+	 * hierarchy immediately on startup, schedule an authentication
+	 * session first thing. */
+	ews_backend_queue_auth_session (backend);
+
+	ews_backend_add_gal_source (E_EWS_BACKEND (backend));
+
+	source = e_backend_get_source (E_BACKEND (backend));
+
+	g_signal_connect (
+		source, "changed",
+		G_CALLBACK (ews_backend_source_changed_cb), backend);
+}
+
+static void
+ews_backend_child_added (ECollectionBackend *backend,
+                         ESource *child_source)
+{
+	EEwsBackend *ews_backend;
+	ESource *collection_source;
+	const gchar *extension_name;
+	gboolean is_mail = FALSE;
+
+	ews_backend = E_EWS_BACKEND (backend);
+
+	collection_source = e_backend_get_source (E_BACKEND (backend));
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
+	is_mail |= e_source_has_extension (child_source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	is_mail |= e_source_has_extension (child_source, extension_name);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
+	is_mail |= e_source_has_extension (child_source, extension_name);
+
+	/* Synchronize mail-related display names with the collection. */
+	if (is_mail)
+		g_object_bind_property (
+			collection_source, "display-name",
+			child_source, "display-name",
+			G_BINDING_SYNC_CREATE);
+
+	/* Synchronize mail-related user with the collection identity. */
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	if (is_mail && e_source_has_extension (child_source, extension_name)) {
+		ESourceAuthentication *auth_child_extension;
+		ESourceCollection *collection_extension;
+
+		extension_name = E_SOURCE_EXTENSION_COLLECTION;
+		collection_extension = e_source_get_extension (
+			collection_source, extension_name);
+
+		extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+		auth_child_extension = e_source_get_extension (
+			child_source, extension_name);
+
+		g_object_bind_property (
+			collection_extension, "identity",
+			auth_child_extension, "user",
+			G_BINDING_SYNC_CREATE);
+	}
+
+	/* We track EWS folders in a hash table by folder ID. */
+	extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+	if (e_source_has_extension (child_source, extension_name)) {
+		ESourceEwsFolder *extension;
+		gchar *folder_id;
+
+		extension = e_source_get_extension (
+			child_source, extension_name);
+		folder_id = e_source_ews_folder_dup_id (extension);
+		if (folder_id != NULL)
+			g_hash_table_insert (
+				ews_backend->folders, folder_id,
+				g_object_ref (child_source));
+	}
+
+	/* Chain up to parent's child_added() method. */
+	E_COLLECTION_BACKEND_CLASS (e_ews_backend_parent_class)->
+		child_added (backend, child_source);
+}
+
+static void
+ews_backend_child_removed (ECollectionBackend *backend,
+                           ESource *child_source)
+{
+	EEwsBackend *ews_backend;
+	const gchar *extension_name;
+
+	ews_backend = E_EWS_BACKEND (backend);
+
+	/* We track EWS folders in a hash table by folder ID. */
+	extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+	if (e_source_has_extension (child_source, extension_name)) {
+		ESourceEwsFolder *extension;
+		const gchar *folder_id;
+
+		extension = e_source_get_extension (
+			child_source, extension_name);
+		folder_id = e_source_ews_folder_get_id (extension);
+		if (folder_id != NULL)
+			g_hash_table_remove (
+				ews_backend->folders, folder_id);
+	}
+
+	/* Chain up to parent's child_removed() method. */
+	E_COLLECTION_BACKEND_CLASS (e_ews_backend_parent_class)->
+		child_removed (backend, child_source);
+}
+
+static ESourceAuthenticationResult
+ews_backend_try_password_sync (ESourceAuthenticator *authenticator,
+                               const GString *password,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+	EEwsBackend *backend;
+	EEwsConnection *connection;
+	ESource *source;
+	ESourceCollection *collection_extension;
+	ESourceAuthenticationResult result;
+	CamelEwsSettings *settings;
+	GSList *folders_created = NULL;
+	GSList *folders_updated = NULL;
+	GSList *folders_deleted = NULL;
+	gboolean includes_last_folder = FALSE;
+	const gchar *extension_name;
+	gchar *sync_state;
+	gchar *hosturl;
+	gchar *user;
+	GError *local_error = NULL;
+
+	/* This tests the password by updating the folder hierarchy. */
+
+	backend = E_EWS_BACKEND (authenticator);
+	source = e_backend_get_source (E_BACKEND (backend));
+
+	settings = ews_backend_get_settings (backend);
+	hosturl = camel_ews_settings_dup_hosturl (settings);
+
+	extension_name = E_SOURCE_EXTENSION_COLLECTION;
+	collection_extension = e_source_get_extension (source, extension_name);
+	user = e_source_collection_dup_identity (collection_extension);
+
+	connection = e_ews_connection_new (
+		hosturl, user, password->str, NULL, NULL, error);
+
+	g_free (hosturl);
+	g_free (user);
+
+	if (connection == NULL)
+		return E_SOURCE_AUTHENTICATION_ERROR;
+
+	g_mutex_lock (backend->sync_state_lock);
+	sync_state = g_strdup (backend->sync_state);
+	g_mutex_unlock (backend->sync_state_lock);
+
+	/* XXX I think this leaks the old sync_state value when
+	 *     it replaces it with the new sync_state value. */
+	e_ews_connection_sync_folder_hierarchy_sync (
+		connection, EWS_PRIORITY_MEDIUM,
+		&sync_state, &includes_last_folder,
+		&folders_created, &folders_updated, &folders_deleted,
+		cancellable, &local_error);
+
+	g_object_unref (connection);
+
+	if (local_error == NULL) {
+		SyncFoldersClosure *closure;
+
+		/* We can now report the password was accepted.
+		 * Because a password dialog may be stuck in a busy
+		 * state, process the synchronization results from an
+		 * idle callback so we don't delay the authentication
+		 * session any longer than necessary. */
+
+		/* This takes ownership of the folder lists. */
+		closure = g_slice_new0 (SyncFoldersClosure);
+		closure->backend = g_object_ref (backend);
+		closure->folders_created = folders_created;
+		closure->folders_deleted = folders_deleted;
+		closure->folders_updated = folders_updated;
+
+		g_idle_add_full (
+			G_PRIORITY_DEFAULT_IDLE,
+			ews_backend_sync_folders_idle_cb, closure,
+			(GDestroyNotify) sync_folders_closure_free);
+
+		g_mutex_lock (backend->sync_state_lock);
+		g_free (backend->sync_state);
+		backend->sync_state = sync_state;
+		g_mutex_unlock (backend->sync_state_lock);
+
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+	} else {
+		gboolean auth_failed;
+
+		/* Make sure we're not leaking anything. */
+		g_warn_if_fail (folders_created == NULL);
+		g_warn_if_fail (folders_updated == NULL);
+		g_warn_if_fail (folders_deleted == NULL);
+
+		auth_failed = g_error_matches (
+			local_error, EWS_CONNECTION_ERROR,
+			EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED);
+
+		if (auth_failed) {
+			g_clear_error (&local_error);
+			result = E_SOURCE_AUTHENTICATION_REJECTED;
+		} else {
+			g_propagate_error (error, local_error);
+			result = E_SOURCE_AUTHENTICATION_ERROR;
+		}
+
+		g_free (sync_state);
+	}
+
+	return result;
+}
+
+static void
+e_ews_backend_class_init (EEwsBackendClass *class)
+{
+	GObjectClass *object_class;
+	ECollectionBackendClass *backend_class;
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = ews_backend_dispose;
+	object_class->finalize = ews_backend_finalize;
+
+	backend_class = E_COLLECTION_BACKEND_CLASS (class);
+	backend_class->populate = ews_backend_populate;
+	backend_class->child_added = ews_backend_child_added;
+	backend_class->child_removed = ews_backend_child_removed;
+}
+
+static void
+e_ews_backend_class_finalize (EEwsBackendClass *class)
+{
+}
+
+static void
+e_ews_backend_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = ews_backend_try_password_sync;
+}
+
+static void
+e_ews_backend_init (EEwsBackend *backend)
+{
+	backend->folders = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) g_object_unref);
+
+	backend->sync_state_lock = g_mutex_new ();
+
+	/* This generates an ESourceCamel subtype for CamelEwsSettings. */
+	e_source_camel_generate_subtype ("ews", CAMEL_TYPE_EWS_SETTINGS);
+}
+
+static void
+e_ews_backend_factory_class_init (EEwsBackendFactoryClass *class)
+{
+	ECollectionBackendFactoryClass *factory_class;
+
+	factory_class = E_COLLECTION_BACKEND_FACTORY_CLASS (class);
+	factory_class->factory_name = "ews";
+	factory_class->backend_type = E_TYPE_EWS_BACKEND;
+}
+
+static void
+e_ews_backend_factory_class_finalize (EEwsBackendFactoryClass *class)
+{
+}
+
+static void
+e_ews_backend_factory_init (EEwsBackendFactory *factory)
+{
+}
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+	e_ews_backend_register_type (type_module);
+	e_ews_backend_factory_register_type (type_module);
+
+	e_source_ews_folder_type_register (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+
diff --git a/src/modules/module-ews-mail-config.c b/src/modules/module-ews-mail-config.c
new file mode 100644
index 0000000..5748f77
--- /dev/null
+++ b/src/modules/module-ews-mail-config.c
@@ -0,0 +1,43 @@
+/*
+ * module-ews-mail-config.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-config-ews-autodiscover.h"
+#include "e-mail-config-ews-backend.h"
+#include "e-mail-config-ews-gal.h"
+#include "e-mail-config-ews-oal-combo-box.h"
+#include "e-mail-config-ews-ooo-page.h"
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+	e_mail_config_ews_autodiscover_type_register (type_module);
+	e_mail_config_ews_backend_type_register (type_module);
+	e_mail_config_ews_gal_type_register (type_module);
+	e_mail_config_ews_oal_combo_box_type_register (type_module);
+	e_mail_config_ews_ooo_page_type_register (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+
diff --git a/src/modules/module-ews-mail-config.error.xml b/src/modules/module-ews-mail-config.error.xml
new file mode 100644
index 0000000..3ac5023
--- /dev/null
+++ b/src/modules/module-ews-mail-config.error.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<error-list domain="ews">
+
+  <error type="warning" id="autodiscovery-error">
+    <primary>Autodiscovery query failed.</primary>
+    <secondary>The reported error was &quot;{0}&quot;.</secondary>
+  </error>
+
+  <error type="warning" id="query-oal-error">
+    <primary>Failed to locate offline address books.</primary>
+    <secondary>The reported error was &quot;{0}&quot;.</secondary>
+  </error>
+
+</error-list>
\ No newline at end of file
diff --git a/src/server/Makefile.am b/src/server/Makefile.am
index 580967e..fc84f82 100644
--- a/src/server/Makefile.am
+++ b/src/server/Makefile.am
@@ -42,6 +42,8 @@ libeews_1_2_la_CPPFLAGS = \
 	$(NULL)
 
 libeews_1_2_la_SOURCES = \
+	camel-ews-settings.h \
+	camel-ews-settings.c \
 	ews-errors.h \
 	ews-errors.c \
 	ews-marshal.h \
@@ -57,6 +59,8 @@ libeews_1_2_la_SOURCES = \
 	e-soap-message.h \
 	e-soap-response.c \
 	e-soap-response.h \
+	e-source-ews-folder.c \
+	e-source-ews-folder.h \
 	$(NULL)
 
 libeews_1_2_la_LIBADD = \
diff --git a/src/utils/camel-ews-settings.c b/src/server/camel-ews-settings.c
similarity index 89%
rename from src/utils/camel-ews-settings.c
rename to src/server/camel-ews-settings.c
index ff9e81d..6ac8645 100644
--- a/src/utils/camel-ews-settings.c
+++ b/src/server/camel-ews-settings.c
@@ -18,6 +18,8 @@
 
 #include "camel-ews-settings.h"
 
+#include <libedataserver/e-data-server-util.h>
+
 #define CAMEL_EWS_SETTINGS_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
 	((obj), CAMEL_TYPE_EWS_SETTINGS, CamelEwsSettingsPrivate))
@@ -29,6 +31,7 @@ struct _CamelEwsSettingsPrivate {
 	gboolean filter_junk_inbox;
 	gboolean oab_offline;
 	gchar *email;
+	gchar *gal_uid;
 	gchar *hosturl;
 	gchar *oaburl;
 	gchar *oal_selected;
@@ -41,6 +44,7 @@ enum {
 	PROP_EMAIL,
 	PROP_FILTER_JUNK,
 	PROP_FILTER_JUNK_INBOX,
+	PROP_GAL_UID,
 	PROP_HOST,
 	PROP_HOSTURL,
 	PROP_OABURL,
@@ -95,6 +99,12 @@ ews_settings_set_property (GObject *object,
 				g_value_get_boolean (value));
 			return;
 
+		case PROP_GAL_UID:
+			camel_ews_settings_set_gal_uid (
+				CAMEL_EWS_SETTINGS (object),
+				g_value_get_string (value));
+			return;
+
 		case PROP_HOST:
 			camel_network_settings_set_host (
 				CAMEL_NETWORK_SETTINGS (object),
@@ -189,6 +199,13 @@ ews_settings_get_property (GObject *object,
 				CAMEL_EWS_SETTINGS (object)));
 			return;
 
+		case PROP_GAL_UID:
+			g_value_take_string (
+				value,
+				camel_ews_settings_dup_gal_uid (
+				CAMEL_EWS_SETTINGS (object)));
+			return;
+
 		case PROP_HOST:
 			g_value_take_string (
 				value,
@@ -259,6 +276,7 @@ ews_settings_finalize (GObject *object)
 	g_mutex_free (priv->property_lock);
 
 	g_free (priv->email);
+	g_free (priv->gal_uid);
 	g_free (priv->hosturl);
 	g_free (priv->oaburl);
 	g_free (priv->oal_selected);
@@ -333,6 +351,18 @@ camel_ews_settings_class_init (CamelEwsSettingsClass *class)
 			G_PARAM_CONSTRUCT |
 			G_PARAM_STATIC_STRINGS));
 
+	g_object_class_install_property (
+		object_class,
+		PROP_GAL_UID,
+		g_param_spec_string (
+			"gal-uid",
+			"GAL UID",
+			"Global Address List data source UID",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+
 	/* Inherited from CamelNetworkSettings. */
 	g_object_class_override_property (
 		object_class,
@@ -486,7 +516,7 @@ camel_ews_settings_set_email (CamelEwsSettings *settings,
 	g_mutex_lock (settings->priv->property_lock);
 
 	g_free (settings->priv->email);
-	settings->priv->email = g_strdup (email);
+	settings->priv->email = e_util_strdup_strip (email);
 
 	g_mutex_unlock (settings->priv->property_lock);
 
@@ -574,6 +604,48 @@ camel_ews_settings_set_filter_junk_inbox (CamelEwsSettings *settings,
 }
 
 const gchar *
+camel_ews_settings_get_gal_uid (CamelEwsSettings *settings)
+{
+	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+	return settings->priv->gal_uid;
+}
+
+gchar *
+camel_ews_settings_dup_gal_uid (CamelEwsSettings *settings)
+{
+	const gchar *protected;
+	gchar *duplicate;
+
+	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+	g_mutex_lock (settings->priv->property_lock);
+
+	protected = camel_ews_settings_get_gal_uid (settings);
+	duplicate = g_strdup (protected);
+
+	g_mutex_unlock (settings->priv->property_lock);
+
+	return duplicate;
+}
+
+void
+camel_ews_settings_set_gal_uid (CamelEwsSettings *settings,
+                                const gchar *gal_uid)
+{
+	g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+	g_mutex_lock (settings->priv->property_lock);
+
+	g_free (settings->priv->gal_uid);
+	settings->priv->gal_uid = e_util_strdup_strip (gal_uid);
+
+	g_mutex_unlock (settings->priv->property_lock);
+
+	g_object_notify (G_OBJECT (settings), "gal-uid");
+}
+
+const gchar *
 camel_ews_settings_get_hosturl (CamelEwsSettings *settings)
 {
 	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
@@ -608,7 +680,7 @@ camel_ews_settings_set_hosturl (CamelEwsSettings *settings,
 	g_mutex_lock (settings->priv->property_lock);
 
 	g_free (settings->priv->hosturl);
-	settings->priv->hosturl = g_strdup (hosturl);
+	settings->priv->hosturl = e_util_strdup_strip (hosturl);
 
 	g_mutex_unlock (settings->priv->property_lock);
 
@@ -650,7 +722,7 @@ camel_ews_settings_set_oaburl (CamelEwsSettings *settings,
 	g_mutex_lock (settings->priv->property_lock);
 
 	g_free (settings->priv->oaburl);
-	settings->priv->oaburl = g_strdup (oaburl);
+	settings->priv->oaburl = e_util_strdup_strip (oaburl);
 
 	g_mutex_unlock (settings->priv->property_lock);
 
@@ -711,7 +783,7 @@ camel_ews_settings_set_oal_selected (CamelEwsSettings *settings,
 	g_mutex_lock (settings->priv->property_lock);
 
 	g_free (settings->priv->oal_selected);
-	settings->priv->oal_selected = g_strdup (oal_selected);
+	settings->priv->oal_selected = e_util_strdup_strip (oal_selected);
 
 	g_mutex_unlock (settings->priv->property_lock);
 
diff --git a/src/utils/camel-ews-settings.h b/src/server/camel-ews-settings.h
similarity index 93%
rename from src/utils/camel-ews-settings.h
rename to src/server/camel-ews-settings.h
index d976fbc..55a5700 100644
--- a/src/utils/camel-ews-settings.h
+++ b/src/server/camel-ews-settings.h
@@ -75,6 +75,10 @@ gboolean	camel_ews_settings_get_filter_junk_inbox
 void		camel_ews_settings_set_filter_junk_inbox
 						(CamelEwsSettings *settings,
 						 gboolean filter_junk_inbox);
+const gchar *	camel_ews_settings_get_gal_uid	(CamelEwsSettings *settings);
+gchar *		camel_ews_settings_dup_gal_uid	(CamelEwsSettings *settings);
+void		camel_ews_settings_set_gal_uid	(CamelEwsSettings *settings,
+						 const gchar *gal_uid);
 const gchar *	camel_ews_settings_get_hosturl	(CamelEwsSettings *settings);
 gchar *		camel_ews_settings_dup_hosturl	(CamelEwsSettings *settings);
 void		camel_ews_settings_set_hosturl	(CamelEwsSettings *settings,
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index a2116e8..2987666 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -35,6 +35,7 @@
 #include <libical/ical.h>
 #include "e-ews-connection.h"
 #include <libedataserver/e-flag.h>
+#include <libedataserver/e-data-server-util.h>
 #include "e-ews-message.h"
 #include "e-ews-item-change.h"
 #include "ews-marshal.h"
@@ -1124,6 +1125,27 @@ ews_connection_authenticate (SoupSession *sess,
 }
 
 void
+ews_oal_free (EwsOAL *oal)
+{
+	if (oal != NULL) {
+		g_free (oal->id);
+		g_free (oal->dn);
+		g_free (oal->name);
+		g_free (oal);
+	}
+}
+
+void
+ews_oal_details_free (EwsOALDetails *details)
+{
+	if (details != NULL) {
+		g_free (details->sha);
+		g_free (details->filename);
+		g_free (details);
+	}
+}
+
+void
 ews_user_id_free (EwsUserId *id)
 {
 	if (id)
@@ -1271,7 +1293,7 @@ e_ews_connection_new (const gchar *uri,
 }
 
 static xmlDoc *
-e_ews_autodiscover_ws_xml (const gchar *email)
+e_ews_autodiscover_ws_xml (const gchar *email_address)
 {
 	xmlDoc *doc;
 	xmlNode *node;
@@ -1285,7 +1307,7 @@ e_ews_autodiscover_ws_xml (const gchar *email)
 
 	node = xmlNewChild(node, ns, (xmlChar *)"Request", NULL);
 	xmlNewChild(node, ns, (xmlChar *)"EMailAddress",
-			    (xmlChar *) email);
+			    (xmlChar *) email_address);
 	xmlNewChild(node, ns, (xmlChar *)"AcceptableResponseSchema",
 			    (xmlChar *)"http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a";);
 
@@ -1295,29 +1317,31 @@ e_ews_autodiscover_ws_xml (const gchar *email)
 struct _autodiscover_data {
 	EEwsConnection *cnc;
 	xmlOutputBuffer *buf;
-	GSimpleAsyncResult *simple;
 	SoupMessage *msgs[4];
-	EEwsAutoDiscoverCallback cb;
-	gpointer cbdata;
+
+	GCancellable *cancellable;
+	gulong cancel_id;
+
+	/* Results */
+	gchar *as_url;
+	gchar *oab_url;
 };
 
-/* Called in the context e_ews_autodiscover_ws_url() was called from,
- * with the final result. */
-static void autodiscover_done_cb (GObject *cnc, GAsyncResult *res,
-				  gpointer user_data)
+static void
+autodiscover_data_free (struct _autodiscover_data *ad)
 {
-	struct _autodiscover_data *ad = user_data;
-	EwsUrls *urls = NULL;
-	GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
-	GError *error = NULL;
+	g_object_unref (ad->cnc);
+	xmlOutputBufferClose (ad->buf);
 
-	if (!g_simple_async_result_propagate_error (simple, &error))
-		urls = g_simple_async_result_get_op_res_gpointer (simple);
+	if (ad->cancellable != NULL) {
+		g_cancellable_disconnect (ad->cancellable, ad->cancel_id);
+		g_object_unref (ad->cancellable);
+	}
 
-	xmlOutputBufferClose (ad->buf);
+	g_free (ad->as_url);
+	g_free (ad->oab_url);
 
-	ad->cb (urls, ad->cbdata, error);
-	g_free (ad);
+	g_slice_free (struct _autodiscover_data, ad);
 }
 
 static void
@@ -1335,6 +1359,13 @@ ews_dump_raw_soup_response (SoupMessage *msg)
 
 }
 
+static void
+autodiscover_cancelled_cb (GCancellable *cancellable,
+                           SoupSession *soup_session)
+{
+	soup_session_abort (soup_session);
+}
+
 /* Called when each soup message completes */
 static void
 autodiscover_response_cb (SoupSession *session,
@@ -1342,15 +1373,17 @@ autodiscover_response_cb (SoupSession *session,
                           gpointer data)
 
 {
-	GError *error = NULL;
-	struct _autodiscover_data *ad = data;
+	GSimpleAsyncResult *simple = data;
+	struct _autodiscover_data *ad;
 	EwsUrls *urls = NULL;
 	guint status = msg->status_code;
 	xmlDoc *doc;
 	xmlNode *node;
 	gint idx;
 	gboolean success = FALSE;
-	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	ad = g_simple_async_result_get_op_res_gpointer (simple);
 
 	for (idx = 0; idx < 4; idx++) {
 		if (ad->msgs[idx] == msg)
@@ -1363,38 +1396,29 @@ autodiscover_response_cb (SoupSession *session,
 
 	ad->msgs[idx] = NULL;
 
-	/* Take 'simple' from 'ad' before actual call
-	   to g_simple_async_result_complete_in_idle(),
-	   for cases where the 'ad' is freed in autodiscover_done_cb()
-	   before this function finishes. Suggested by Dan Winship.
-	*/
-	simple = ad->simple;
-
 	if (status != 200) {
 		g_set_error (
-			     &error, EWS_CONNECTION_ERROR,
-			     status,
-			     _("Code: %d - Unexpected response from server"),
-			     status);
+			&error, SOUP_HTTP_ERROR, status,
+			"%d %s", status, msg->reason_phrase);
 		goto failed;
 	}
 
 	ews_dump_raw_soup_response (msg);
-	doc = xmlReadMemory (msg->response_body->data, msg->response_body->length,
-			     "autodiscover.xml", NULL, 0);
+	doc = xmlReadMemory (
+		msg->response_body->data,
+		msg->response_body->length,
+		"autodiscover.xml", NULL, 0);
 	if (!doc) {
 		g_set_error (
-			     &error, EWS_CONNECTION_ERROR,
-			     -1,
-			     _("Failed to parse autodiscover response XML"));
+			&error, EWS_CONNECTION_ERROR, -1,
+			_("Failed to parse autodiscover response XML"));
 		goto failed;
 	}
 	node = xmlDocGetRootElement (doc);
 	if (strcmp((char *)node->name, "Autodiscover")) {
 		g_set_error (
-			     &error, EWS_CONNECTION_ERROR,
-			     -1,
-			     _("Failed to find <Autodiscover> element\n"));
+			&error, EWS_CONNECTION_ERROR, -1,
+			_("Failed to find <Autodiscover> element"));
 		goto failed;
 	}
 	for (node = node->children; node; node = node->next) {
@@ -1404,9 +1428,8 @@ autodiscover_response_cb (SoupSession *session,
 	}
 	if (!node) {
 		g_set_error (
-			     &error, EWS_CONNECTION_ERROR,
-			     -1,
-			     _("Failed to find <Response> element\n"));
+			&error, EWS_CONNECTION_ERROR, -1,
+			_("Failed to find <Response> element"));
 		goto failed;
 	}
 	for (node = node->children; node; node = node->next) {
@@ -1416,9 +1439,8 @@ autodiscover_response_cb (SoupSession *session,
 	}
 	if (!node) {
 		g_set_error (
-			     &error, EWS_CONNECTION_ERROR,
-			     -1,
-			     _("Failed to find <Account> element\n"));
+			&error, EWS_CONNECTION_ERROR, -1,
+			_("Failed to find <Account> element"));
 		goto failed;
 	}
 
@@ -1435,9 +1457,9 @@ autodiscover_response_cb (SoupSession *session,
 		g_free (urls->as_url);
 		g_free (urls->oab_url);
 		g_free (urls);
-		g_set_error	(&error, EWS_CONNECTION_ERROR,
-				-1,
-				_("Failed to find <ASUrl> and <OABUrl> in autodiscover response"));
+		g_set_error (
+			&error, EWS_CONNECTION_ERROR, -1,
+			_("Failed to find <ASUrl> and <OABUrl> in autodiscover response"));
 		goto failed;
 	}
 
@@ -1446,18 +1468,21 @@ autodiscover_response_cb (SoupSession *session,
 		if (ad->msgs[idx]) {
 			SoupMessage *m = ad->msgs[idx];
 			ad->msgs[idx] = NULL;
-			soup_session_cancel_message (ad->cnc->priv->soup_session,
-						     m, SOUP_STATUS_CANCELLED);
+			soup_session_cancel_message (
+				ad->cnc->priv->soup_session,
+				m, SOUP_STATUS_CANCELLED);
 		}
 	}
 
-	g_simple_async_result_set_op_res_gpointer (ad->simple, urls, NULL);
-	g_simple_async_result_complete_in_idle (ad->simple);
-	/* the 'simple' holds reference on 'cnc' and this function
-	   is called in a dedicated thread, which 'cnc' joins on dispose,
-	   thus to avoid race condition, unref the object in its own thread */
-	ews_unref_in_thread (G_OBJECT (simple));
-	return;
+	ad->as_url = urls->as_url;
+	urls->as_url = NULL;
+
+	ad->oab_url = urls->oab_url;
+	urls->oab_url = NULL;
+
+	g_free (urls);
+
+	goto exit;
 
 failed:
 	for (idx = 0; idx < 4; idx++) {
@@ -1473,12 +1498,11 @@ failed:
 	 * and in some cases (stupid firewalls causing timeouts)
 	 * that's going to be the least interesting one. We probably
 	 * want the *first* error */
-	g_simple_async_result_set_from_error (ad->simple, error);
-	g_simple_async_result_complete_in_idle (ad->simple);
-	/* the 'simple' holds reference on 'cnc' and this function
-	   is called in a dedicated thread, which 'cnc' joins on dispose,
-	   thus to avoid race condition, unref the object in its own thread */
-	ews_unref_in_thread (G_OBJECT (simple));
+	g_simple_async_result_take_error (simple, error);
+
+exit:
+	g_simple_async_result_complete_in_idle (simple);
+	g_object_unref (simple);
 }
 
 static void post_restarted (SoupMessage *msg, gpointer data)
@@ -1501,20 +1525,28 @@ e_ews_get_msg_for_url (const gchar *url,
 {
 	SoupMessage *msg;
 
-	msg = soup_message_new (buf?"POST":"GET", url);
-	soup_message_headers_append (msg->request_headers,
-				     "User-Agent", "libews/0.1");
+	if (url == NULL)
+		return NULL;
+
+	msg = soup_message_new (buf != NULL ? "POST" : "GET", url);
 
-	if (buf) {
-		soup_message_set_request (msg, "text/xml; charset=utf-8", SOUP_MEMORY_COPY,
-					  (gchar *) buf->buffer->content,
-					  buf->buffer->use);
-		g_signal_connect (msg, "restarted",
-				  G_CALLBACK (post_restarted), buf);
+	soup_message_headers_append (
+		msg->request_headers,
+		"User-Agent", "libews/0.1");
+
+	if (buf != NULL) {
+		soup_message_set_request (
+			msg, "text/xml; charset=utf-8", SOUP_MEMORY_COPY,
+			(gchar *) buf->buffer->content, buf->buffer->use);
+		g_signal_connect (
+			msg, "restarted",
+			G_CALLBACK (post_restarted), buf);
 	}
 
 	if (g_getenv ("EWS_DEBUG") && (atoi (g_getenv ("EWS_DEBUG")) >= 1)) {
-		soup_buffer_free (soup_message_body_flatten (SOUP_MESSAGE (msg)->request_body));
+		soup_buffer_free (
+			soup_message_body_flatten (
+			SOUP_MESSAGE (msg)->request_body));
 		/* print request's body */
 		printf ("\n The request headers");
 		printf ("\n ===================");
@@ -1526,38 +1558,78 @@ e_ews_get_msg_for_url (const gchar *url,
 	return msg;
 }
 
+gboolean
+e_ews_autodiscover_ws_url_sync (CamelEwsSettings *settings,
+                                const gchar *email_address,
+                                const gchar *password,
+                                GCancellable *cancellable,
+                                GError **error)
+{
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	gboolean success;
+
+	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), FALSE);
+	g_return_val_if_fail (email_address != NULL, FALSE);
+	g_return_val_if_fail (password != NULL, FALSE);
+
+	closure = e_async_closure_new ();
+
+	e_ews_autodiscover_ws_url (
+		settings, email_address, password, cancellable,
+		e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_autodiscover_ws_url_finish (settings, result, error);
+
+	e_async_closure_free (closure);
+
+	return success;
+}
+
 void
-e_ews_autodiscover_ws_url (EEwsAutoDiscoverCallback cb,
-                           gpointer cbdata,
-                           const gchar *email,
+e_ews_autodiscover_ws_url (CamelEwsSettings *settings,
+                           const gchar *email_address,
                            const gchar *password,
-                           const gchar *ews_url,
-                           const gchar *username)
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
 {
+	CamelNetworkSettings *network_settings;
+	GSimpleAsyncResult *simple;
 	struct _autodiscover_data *ad;
 	xmlOutputBuffer *buf;
-	GError *error = NULL;
 	gchar *url1, *url2, *url3, *url4;
 	gchar *domain;
 	xmlDoc *doc;
 	EEwsConnection *cnc;
+	SoupURI *soup_uri = NULL;
 	gboolean use_secure = TRUE;
+	const gchar *host_url;
+	const gchar *user;
+	GError *error = NULL;
 
-	if (!password || !email) {
-		g_set_error (&error, EWS_CONNECTION_ERROR,
-			     -1, _("Both email and password must be provided"));
-		goto err;
-	}
-
-	domain = strchr (email, '@');
-	if (!(domain && *domain)) {
-		g_set_error (&error, EWS_CONNECTION_ERROR,
-			     -1, _("Wrong email id"));
-		goto err;
+	g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+	g_return_if_fail (email_address != NULL);
+	g_return_if_fail (password != NULL);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (settings), callback,
+		user_data, e_ews_autodiscover_ws_url);
+
+	domain = strchr (email_address, '@');
+	if (domain == NULL || *domain == '\0') {
+		g_simple_async_result_set_error (
+			simple, EWS_CONNECTION_ERROR, -1,
+			"%s", _("Email address is missing a domain part"));
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
+		return;
 	}
 	domain++;
 
-	doc = e_ews_autodiscover_ws_xml (email);
+	doc = e_ews_autodiscover_ws_xml (email_address);
 	buf = xmlAllocOutputBuffer (NULL);
 	xmlNodeDumpOutput (buf, doc, xmlDocGetRootElement (doc), 0, 1, NULL);
 	xmlOutputBufferFlush (buf);
@@ -1566,31 +1638,43 @@ e_ews_autodiscover_ws_url (EEwsAutoDiscoverCallback cb,
 	url2 = NULL;
 	url3 = NULL;
 	url4 = NULL;
-	if (ews_url) {
-		SoupURI *uri = soup_uri_new (ews_url);
 
-		if (uri) {
-			use_secure = g_strcmp0 (soup_uri_get_scheme (uri), "https") == 0;
+	host_url = camel_ews_settings_get_hosturl (settings);
+	if (host_url != NULL)
+		soup_uri = soup_uri_new (host_url);
 
-			url1 = g_strdup_printf ("http%s://%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", soup_uri_get_host (uri));
-			url2 = g_strdup_printf ("http%s://autodiscover.%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", soup_uri_get_host (uri));
-			soup_uri_free (uri);
-		}
+	if (soup_uri != NULL) {
+		const gchar *host = soup_uri_get_host (soup_uri);
+		const gchar *scheme = soup_uri_get_scheme (soup_uri);
+
+		use_secure = g_strcmp0 (scheme, "https") == 0;
+
+		url1 = g_strdup_printf ("http%s://%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", host);
+		url2 = g_strdup_printf ("http%s://autodiscover.%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", host);
+
+		soup_uri_free (soup_uri);
 	}
 
 	url3 = g_strdup_printf ("http%s://%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", domain);
 	url4 = g_strdup_printf ("http%s://autodiscover.%s/autodiscover/autodiscover.xml", use_secure ? "s" : "", domain);
 
-	cnc = e_ews_connection_new (url3, (username && *username) ? username : email, password, NULL, NULL, &error);
-	if (!cnc) {
+	network_settings = CAMEL_NETWORK_SETTINGS (settings);
+	user = camel_network_settings_get_user (network_settings);
+	if (user == NULL || *user == '\0')
+		user = email_address;
+
+	cnc = e_ews_connection_new (url3, user, password, NULL, NULL, &error);
+	if (cnc == NULL) {
 		g_free (url1);
 		g_free (url2);
 		g_free (url3);
 		g_free (url4);
 		xmlOutputBufferClose (buf);
 		xmlFreeDoc (doc);
-	err:
-		cb (NULL, cbdata, error);
+
+		g_simple_async_result_take_error (simple, error);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
 		return;
 	}
 
@@ -1602,34 +1686,46 @@ e_ews_autodiscover_ws_url (EEwsAutoDiscoverCallback cb,
 	 * to time out. So run both queries in parallel and let the fastest
 	 * (successful) one win.
 	 */
-	ad = g_new0 (struct _autodiscover_data, 1);
-	ad->cb = cb;
-	ad->cbdata = cbdata;
-	ad->cnc = cnc;
-	ad->buf = buf;
-	ad->simple = g_simple_async_result_new (G_OBJECT (cnc), autodiscover_done_cb,
-					    ad, e_ews_autodiscover_ws_url);
-	ad->msgs[0] = url1 ? e_ews_get_msg_for_url (url1, buf) : NULL;
-	ad->msgs[1] = url2 ? e_ews_get_msg_for_url (url2, buf) : NULL;
-	ad->msgs[2] = url3 ? e_ews_get_msg_for_url (url3, buf) : NULL;
-	ad->msgs[3] = url4 ? e_ews_get_msg_for_url (url4, buf) : NULL;
+	ad = g_slice_new0 (struct _autodiscover_data);
+	ad->cnc = cnc;  /* takes ownership */
+	ad->buf = buf;  /* takes ownership */
+
+	if (G_IS_CANCELLABLE (cancellable)) {
+		ad->cancellable = g_object_ref (cancellable);
+		ad->cancel_id = g_cancellable_connect (
+			ad->cancellable,
+			G_CALLBACK (autodiscover_cancelled_cb),
+			g_object_ref (cnc->priv->soup_session),
+			(GDestroyNotify) g_object_unref);
+	}
+
+	g_simple_async_result_set_op_res_gpointer (
+		simple, ad, (GDestroyNotify) autodiscover_data_free);
+
+	/* Passing a NULL URL string returns NULL. */
+	ad->msgs[0] = e_ews_get_msg_for_url (url1, buf);
+	ad->msgs[1] = e_ews_get_msg_for_url (url2, buf);
+	ad->msgs[2] = e_ews_get_msg_for_url (url3, buf);
+	ad->msgs[3] = e_ews_get_msg_for_url (url4, buf);
 
 	/* These have to be submitted only after they're both set in ad->msgs[]
 	 * or there will be races with fast completion */
-	if (ad->msgs[0])
-		soup_session_queue_message (cnc->priv->soup_session, ad->msgs[0],
-					    autodiscover_response_cb, ad);
-	if (ad->msgs[1])
-		soup_session_queue_message (cnc->priv->soup_session, ad->msgs[1],
-					    autodiscover_response_cb, ad);
-	if (ad->msgs[2])
-		soup_session_queue_message (cnc->priv->soup_session, ad->msgs[2],
-					    autodiscover_response_cb, ad);
-	if (ad->msgs[3])
-		soup_session_queue_message (cnc->priv->soup_session, ad->msgs[3],
-					    autodiscover_response_cb, ad);
-
-	g_object_unref (cnc); /* the GSimpleAsyncResult holds it now */
+	if (ad->msgs[0] != NULL)
+		soup_session_queue_message (
+			cnc->priv->soup_session, ad->msgs[0],
+			autodiscover_response_cb, simple);
+	if (ad->msgs[1] != NULL)
+		soup_session_queue_message (
+			cnc->priv->soup_session, ad->msgs[1],
+			autodiscover_response_cb, simple);
+	if (ad->msgs[2] != NULL)
+		soup_session_queue_message (
+			cnc->priv->soup_session, ad->msgs[2],
+			autodiscover_response_cb, simple);
+	if (ad->msgs[3] != NULL)
+		soup_session_queue_message (
+			cnc->priv->soup_session, ad->msgs[3],
+			autodiscover_response_cb, simple);
 
 	xmlFreeDoc (doc);
 	g_free (url1);
@@ -1638,15 +1734,46 @@ e_ews_autodiscover_ws_url (EEwsAutoDiscoverCallback cb,
 	g_free (url4);
 }
 
-struct _oal_req_data {
-	EEwsConnection *cnc;
+gboolean
+e_ews_autodiscover_ws_url_finish (CamelEwsSettings *settings,
+                                  GAsyncResult *result,
+                                  GError **error)
+{
 	GSimpleAsyncResult *simple;
-	SoupMessage *msg;
-	GCancellable *cancellable;
-	gulong cancel_handler_id;
+	struct _autodiscover_data *ad;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (settings),
+		e_ews_autodiscover_ws_url), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+	ad = g_simple_async_result_get_op_res_gpointer (simple);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+
+	g_warn_if_fail (ad->as_url != NULL);
+	g_warn_if_fail (ad->oab_url != NULL);
+
+	camel_ews_settings_set_hosturl (settings, ad->as_url);
+	camel_ews_settings_set_oaburl (settings, ad->oab_url);
+
+	return TRUE;
+}
+
+struct _oal_req_data {
+	SoupSession *soup_session;
+	SoupMessage *soup_message;
 	gchar *oal_id;
 	gchar *oal_element;
 
+	GSList *oals;
+	GSList *elements;
+
+	GCancellable *cancellable;
+	gulong cancel_id;
+
 	/* for dowloading oal file */
 	gchar *cache_filename;
 	GError *error;
@@ -1656,6 +1783,28 @@ struct _oal_req_data {
 	gsize received_size;
 };
 
+static void
+oal_req_data_free (struct _oal_req_data *data)
+{
+	/* The SoupMessage is owned by the SoupSession. */
+	g_object_ref (data->soup_session);
+
+	g_free (data->oal_id);
+	g_free (data->oal_element);
+
+	g_slist_free_full (data->oals, (GDestroyNotify) ews_oal_free);
+	g_slist_free_full (data->elements, (GDestroyNotify) ews_oal_details_free);
+
+	if (data->cancellable != NULL) {
+		g_cancellable_disconnect (data->cancellable, data->cancel_id);
+		g_object_unref (data->cancellable);
+	}
+
+	g_free (data->cache_filename);
+
+	g_slice_free (struct _oal_req_data, data);
+}
+
 static gchar *
 get_property (xmlNodePtr node_ptr,
               const gchar *name)
@@ -1725,56 +1874,65 @@ parse_oal_full_details (xmlNode *node,
 }
 
 static void
-oal_response_cb (SoupSession *session,
-                 SoupMessage *msg,
+oal_response_cb (SoupSession *soup_session,
+                 SoupMessage *soup_message,
                  gpointer user_data)
 {
-	GError *error = NULL;
-	guint status = msg->status_code;
+	GSimpleAsyncResult *simple;
+	struct _oal_req_data *data;
 	xmlDoc *doc;
 	xmlNode *node;
-	struct _oal_req_data *data = (struct _oal_req_data *) user_data;
-	GSList *oals = NULL;
 
-	if (status != 200) {
-		g_set_error (&error, EWS_CONNECTION_ERROR, status,
-			     _("Code: %d - Unexpected response from server"),
-			     status);
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+	data = g_simple_async_result_get_op_res_gpointer (simple);
+
+	if (soup_message->status_code != 200) {
+		g_simple_async_result_set_error (
+			simple, SOUP_HTTP_ERROR,
+			soup_message->status_code,
+			"%d %s",
+			soup_message->status_code,
+			soup_message->reason_phrase);
 		goto exit;
 	}
-	ews_dump_raw_soup_response (msg);
 
-	doc = xmlReadMemory (msg->response_body->data, msg->response_body->length,
-			     "oab.xml", NULL, 0);
-	if (!doc) {
-		g_set_error (&error, EWS_CONNECTION_ERROR,
-			     -1, _("Failed to parse oab XML"));
+	ews_dump_raw_soup_response (soup_message);
+
+	doc = xmlReadMemory (
+		soup_message->response_body->data,
+		soup_message->response_body->length,
+		"oab.xml", NULL, 0);
+	if (doc == NULL) {
+		g_simple_async_result_set_error (
+			simple, EWS_CONNECTION_ERROR, -1,
+			"%s", _("Failed to parse oab XML"));
 		goto exit;
 	}
 
 	node = xmlDocGetRootElement (doc);
-	if (strcmp((char *)node->name, "OAB")) {
-		g_set_error (&error, EWS_CONNECTION_ERROR, -1,
-			     _("Failed to find <OAB> element\n"));
+	if (strcmp ((gchar *) node->name, "OAB") != 0) {
+		g_simple_async_result_set_error (
+			simple, EWS_CONNECTION_ERROR, -1,
+			"%s", _("Failed to find <OAB> element\n"));
 		goto exit;
 	}
 
 	for (node = node->children; node; node = node->next) {
-		if (node->type == XML_ELEMENT_NODE && !strcmp((char *)node->name, "OAL")) {
-			if (!data->oal_id) {
+		if (node->type == XML_ELEMENT_NODE && strcmp((gchar *) node->name, "OAL") == 0) {
+			if (data->oal_id != NULL) {
 				EwsOAL *oal = g_new0 (EwsOAL, 1);
 
 				oal->id = get_property (node, "id");
 				oal->dn = get_property (node, "dn");
 				oal->name = get_property (node, "name");
 
-				oals = g_slist_prepend (oals, oal);
+				data->oals = g_slist_prepend (data->oals, oal);
 			} else {
 				gchar *id = get_property (node, "id");
 
-				if (!strcmp (id, data->oal_id)) {
+				if (strcmp (id, data->oal_id) == 0) {
 					/* parse details of full_details file */
-					oals = parse_oal_full_details (node, data->oal_element);
+					data->elements = parse_oal_full_details (node, data->oal_element);
 
 					g_free (id);
 					break;
@@ -1785,31 +1943,48 @@ oal_response_cb (SoupSession *session,
 		}
 	}
 
-	oals = g_slist_reverse (oals);
-	g_simple_async_result_set_op_res_gpointer (data->simple, oals, NULL);
+	data->oals = g_slist_reverse (data->oals);
 
 exit:
-	if (data->cancellable)
-		g_signal_handler_disconnect (data->cancellable, data->cancel_handler_id);
-
-	if (error) {
-		g_simple_async_result_set_from_error (data->simple, error);
-		g_clear_error (&error);
-	}
-
-	g_simple_async_result_complete_in_idle (data->simple);
-	g_free (data->oal_id);
-	g_free (data->oal_element);
-	g_free (data);
+	g_simple_async_result_complete_in_idle (simple);
+	g_object_unref (simple);
 }
 
 static void
 ews_cancel_msg (GCancellable *cancellable,
-                gpointer user_data)
+                struct _oal_req_data *data)
 {
-	struct _oal_req_data *data = (struct _oal_req_data *) user_data;
+	soup_session_cancel_message (
+		data->soup_session,
+		data->soup_message,
+		SOUP_STATUS_CANCELLED);
+}
+
+gboolean
+e_ews_connection_get_oal_list_sync (EEwsConnection *cnc,
+                                    GSList **oals,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	gboolean success;
+
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+
+	closure = e_async_closure_new ();
+
+	e_ews_connection_get_oal_list (
+		cnc, cancellable, e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_connection_get_oal_list_finish (
+		cnc, result, oals, error);
 
-	soup_session_cancel_message (data->cnc->priv->soup_session, SOUP_MESSAGE (data->msg), SOUP_STATUS_CANCELLED);
+	e_async_closure_free (closure);
+
+	return success;
 }
 
 void
@@ -1819,28 +1994,37 @@ e_ews_connection_get_oal_list (EEwsConnection *cnc,
                                gpointer user_data)
 {
 	GSimpleAsyncResult *simple;
-	SoupMessage *msg;
+	SoupSession *soup_session;
+	SoupMessage *soup_message;
 	struct _oal_req_data *data;
 
-	g_return_if_fail (cnc != NULL);
+	g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
 
-	msg = e_ews_get_msg_for_url (cnc->priv->uri, NULL);
+	soup_session = cnc->priv->soup_session;
+	soup_message = e_ews_get_msg_for_url (cnc->priv->uri, NULL);
 
-	simple = g_simple_async_result_new (G_OBJECT (cnc),
-				      callback,
-				      user_data,
-				      e_ews_connection_get_oal_list);
-	data = g_new0 (struct _oal_req_data, 1);
-	data->cnc = cnc;
-	data->simple = simple;
-	data->cancellable = cancellable;
-	data->msg = msg;
+	data = g_slice_new0 (struct _oal_req_data);
+	data->soup_session = g_object_ref (soup_session);
+	data->soup_message = soup_message;  /* the session owns this */
+
+	if (G_IS_CANCELLABLE (cancellable)) {
+		data->cancellable = g_object_ref (cancellable);
+		data->cancel_id = g_cancellable_connect (
+			data->cancellable,
+			G_CALLBACK (ews_cancel_msg),
+			data, (GDestroyNotify) NULL);
+	}
 
-	if (cancellable)
-		data->cancel_handler_id = g_cancellable_connect	(cancellable,
-								 G_CALLBACK (ews_cancel_msg), (gpointer) data, NULL);
-	soup_session_queue_message (cnc->priv->soup_session, msg,
-				    oal_response_cb, data);
+	simple = g_simple_async_result_new (
+		G_OBJECT (cnc), callback, user_data,
+		e_ews_connection_get_oal_list);
+
+	g_simple_async_result_set_op_res_gpointer (
+		simple, data, (GDestroyNotify) oal_req_data_free);
+
+	soup_session_queue_message (
+		soup_session, soup_message,
+		oal_response_cb, simple);
 }
 
 gboolean
@@ -1850,8 +2034,9 @@ e_ews_connection_get_oal_list_finish (EEwsConnection *cnc,
                                       GError **error)
 {
 	GSimpleAsyncResult *simple;
+	struct _oal_req_data *data;
 
-	g_return_val_if_fail (cnc != NULL, FALSE);
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
 
 	g_return_val_if_fail (
 		g_simple_async_result_is_valid (
@@ -1859,15 +2044,61 @@ e_ews_connection_get_oal_list_finish (EEwsConnection *cnc,
 		FALSE);
 
 	simple = G_SIMPLE_ASYNC_RESULT (result);
+	data = g_simple_async_result_get_op_res_gpointer (simple);
 
 	if (g_simple_async_result_propagate_error (simple, error))
 		return FALSE;
 
-	*oals= g_simple_async_result_get_op_res_gpointer (simple);
+	if (oals != NULL) {
+		*oals = data->oals;
+		data->oals = NULL;
+	}
 
 	return TRUE;
 }
 
+/**
+ * e_ews_connection_get_oal_detail 
+ * @cnc: 
+ * @oal_id: 
+ * @oal_element: 
+ * @elements: "Full" "Diff" "Template" are the possible values.
+ * @cancellable: 
+ * @error: 
+ * 
+ * 
+ * Returns: 
+ **/
+gboolean
+e_ews_connection_get_oal_detail_sync (EEwsConnection *cnc,
+                                      const gchar *oal_id,
+                                      const gchar *oal_element,
+                                      GSList **elements,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	gboolean success;
+
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+
+	closure = e_async_closure_new ();
+
+	e_ews_connection_get_oal_detail (
+		cnc, oal_id, oal_element, cancellable,
+		e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_connection_get_oal_detail_finish (
+		cnc, result, elements, error);
+
+	e_async_closure_free (closure);
+
+	return success;
+}
+
 void
 e_ews_connection_get_oal_detail (EEwsConnection *cnc,
                                  const gchar *oal_id,
@@ -1877,31 +2108,39 @@ e_ews_connection_get_oal_detail (EEwsConnection *cnc,
                                  gpointer user_data)
 {
 	GSimpleAsyncResult *simple;
-	SoupMessage *msg;
+	SoupSession *soup_session;
+	SoupMessage *soup_message;
 	struct _oal_req_data *data;
 
-	g_return_if_fail (cnc != NULL);
+	g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
 
-	msg = e_ews_get_msg_for_url (cnc->priv->uri, NULL);
+	soup_session = cnc->priv->soup_session;
+	soup_message = e_ews_get_msg_for_url (cnc->priv->uri, NULL);
 
-	simple = g_simple_async_result_new (G_OBJECT (cnc),
-				      callback,
-				      user_data,
-				      e_ews_connection_get_oal_detail);
-	data = g_new0 (struct _oal_req_data, 1);
-	data->cnc = cnc;
-	data->simple = simple;
-	data->cancellable = cancellable;
-	data->msg = msg;
+	data = g_slice_new0 (struct _oal_req_data);
+	data->soup_session = g_object_ref (soup_session);
+	data->soup_message = soup_message;  /* the session owns this */
 	data->oal_id = g_strdup (oal_id);
 	data->oal_element = g_strdup (oal_element);
 
-	if (cancellable)
-		data->cancel_handler_id = g_cancellable_connect	(cancellable,
-								 G_CALLBACK (ews_cancel_msg), (gpointer) data, NULL);
-	soup_session_queue_message (cnc->priv->soup_session, msg,
-				    oal_response_cb, data);
+	if (G_IS_CANCELLABLE (cancellable)) {
+		data->cancellable = g_object_ref (cancellable);
+		data->cancel_id = g_cancellable_connect (
+			data->cancellable,
+			G_CALLBACK (ews_cancel_msg),
+			data, (GDestroyNotify) NULL);
+	}
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (cnc), callback, user_data,
+		e_ews_connection_get_oal_detail);
 
+	g_simple_async_result_set_op_res_gpointer (
+		simple, data, (GDestroyNotify) oal_req_data_free);
+
+	soup_session_queue_message (
+		soup_session, soup_message,
+		oal_response_cb, simple);
 }
 
 gboolean
@@ -1911,6 +2150,7 @@ e_ews_connection_get_oal_detail_finish (EEwsConnection *cnc,
                                         GError **error)
 {
 	GSimpleAsyncResult *simple;
+	struct _oal_req_data *data;
 
 	g_return_val_if_fail (cnc != NULL, FALSE);
 	g_return_val_if_fail (
@@ -1919,95 +2159,48 @@ e_ews_connection_get_oal_detail_finish (EEwsConnection *cnc,
 		FALSE);
 
 	simple = G_SIMPLE_ASYNC_RESULT (result);
+	data = g_simple_async_result_get_op_res_gpointer (simple);
 
 	if (g_simple_async_result_propagate_error (simple, error))
 		return FALSE;
 
-	*elements = g_simple_async_result_get_op_res_gpointer (simple);
+	if (elements != NULL) {
+		*elements = data->elements;
+		data->elements = NULL;
+	}
 
 	return TRUE;
 
 }
 
-/**
- * e_ews_connection_get_oal_detail_sync:
- * @cnc: 
- * @oal_id: 
- * @oal_element: 
- * @elements: "Full" "Diff" "Template" are the possible values.
- * @cancellable: 
- * @error: 
- * 
- * 
- * Returns: 
- **/
-gboolean
-e_ews_connection_get_oal_detail_sync (EEwsConnection *cnc,
-                                      const gchar *oal_id,
-                                      const gchar *oal_element,
-                                      GSList **elements,
-                                      GCancellable *cancellable,
-                                      GError **error)
-{
-	EwsSyncData *sync_data;
-	gboolean result;
-
-	g_return_val_if_fail (cnc != NULL, FALSE);
-
-	sync_data = g_new0 (EwsSyncData, 1);
-	sync_data->eflag = e_flag_new ();
-
-	e_ews_connection_get_oal_detail (
-		cnc, oal_id, oal_element,
-		cancellable,
-		ews_sync_reply_cb,
-		sync_data);
-
-	e_flag_wait (sync_data->eflag);
-
-	result = e_ews_connection_get_oal_detail_finish
-						(cnc, sync_data->res,
-						 elements, error);
-
-	e_flag_free (sync_data->eflag);
-	g_object_unref (sync_data->res);
-	g_free (sync_data);
-
-	return result;
-}
-
 static void
-oal_download_response_cb (SoupSession *session,
-                          SoupMessage *msg,
+oal_download_response_cb (SoupSession *soup_session,
+                          SoupMessage *soup_message,
                           gpointer user_data)
 {
-	GError *error = NULL;
-	guint status = msg->status_code;
-	struct _oal_req_data *data = (struct _oal_req_data *) user_data;
+	GSimpleAsyncResult *simple;
+	struct _oal_req_data *data;
 
-	if (status != 200) {
-		g_set_error (&error, EWS_CONNECTION_ERROR, status,
-			     _("Code: %d - Unexpected response from server"),
-			     status);
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+	data = g_simple_async_result_get_op_res_gpointer (simple);
+
+	if (soup_message->status_code != 200) {
+		g_simple_async_result_set_error (
+			simple, SOUP_HTTP_ERROR,
+			soup_message->status_code,
+			"%d %s",
+			soup_message->status_code,
+			soup_message->reason_phrase);
 		g_unlink (data->cache_filename);
-		goto exit;
+
 	} else if (data->error != NULL) {
-		g_propagate_error (&error, data->error);
+		g_simple_async_result_take_error (simple, data->error);
+		data->error = NULL;
 		g_unlink (data->cache_filename);
-		goto exit;
 	}
 
-	g_simple_async_result_set_op_res_gpointer (data->simple, NULL, NULL);
-
-exit:
-	if (error) {
-		g_simple_async_result_set_from_error (data->simple, error);
-		g_clear_error (&error);
-	}
-
-	g_simple_async_result_complete_in_idle (data->simple);
-	g_free (data->cache_filename);
-	g_free (data);
+	g_simple_async_result_complete_in_idle (simple);
+	g_object_unref (simple);
 }
 
 static void
@@ -2069,6 +2262,37 @@ ews_soup_got_chunk (SoupMessage *msg,
 	}
 }
 
+gboolean
+e_ews_connection_download_oal_file_sync (EEwsConnection *cnc,
+                                         const gchar *cache_filename,
+                                         EwsProgressFn progress_fn,
+                                         gpointer progress_data,
+                                         GCancellable *cancellable,
+                                         GError **error)
+{
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	gboolean success;
+
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+
+	closure = e_async_closure_new ();
+
+	e_ews_connection_download_oal_file (
+		cnc, cache_filename,
+		progress_fn, progress_data, cancellable,
+		e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_connection_download_oal_file_finish (
+		cnc, result, error);
+
+	e_async_closure_free (closure);
+
+	return success;
+}
+
 void
 e_ews_connection_download_oal_file (EEwsConnection *cnc,
                                     const gchar *cache_filename,
@@ -2079,38 +2303,52 @@ e_ews_connection_download_oal_file (EEwsConnection *cnc,
                                     gpointer user_data)
 {
 	GSimpleAsyncResult *simple;
-	SoupMessage *msg;
+	SoupSession *soup_session;
+	SoupMessage *soup_message;
 	struct _oal_req_data *data;
 
-	g_return_if_fail (cnc != NULL);
+	g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
 
-	msg = e_ews_get_msg_for_url (cnc->priv->uri, NULL);
+	soup_session = cnc->priv->soup_session;
+	soup_message = e_ews_get_msg_for_url (cnc->priv->uri, NULL);
 
-	simple = g_simple_async_result_new (G_OBJECT (cnc),
-			callback,
-			user_data,
-			e_ews_connection_download_oal_file);
-	data = g_new0 (struct _oal_req_data, 1);
-	data->cnc = cnc;
-	data->simple = simple;
-	data->cancellable = cancellable;
-	data->msg = SOUP_MESSAGE (msg);
+	data = g_slice_new0 (struct _oal_req_data);
+	data->soup_session = g_object_ref (soup_session);
+	data->soup_message = soup_message;  /* the session owns this */
 	data->cache_filename = g_strdup (cache_filename);
 	data->progress_fn = progress_fn;
 	data->progress_data = progress_data;
 
-	if (cancellable)
-		data->cancel_handler_id = g_cancellable_connect	(cancellable,
-						G_CALLBACK (ews_cancel_msg), (gpointer) data, NULL);
+	if (G_IS_CANCELLABLE (cancellable)) {
+		data->cancellable = g_object_ref (cancellable);
+		data->cancel_id = g_cancellable_connect (
+			data->cancellable,
+			G_CALLBACK (ews_cancel_msg),
+			data, (GDestroyNotify) NULL);
+	}
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (cnc), callback, user_data,
+		e_ews_connection_download_oal_file);
 
-	soup_message_body_set_accumulate (SOUP_MESSAGE (msg)->response_body,
-					  FALSE);
-	g_signal_connect (msg, "got-headers", G_CALLBACK (ews_soup_got_headers), data);
-	g_signal_connect (msg, "got-chunk", G_CALLBACK (ews_soup_got_chunk), data);
-	g_signal_connect (msg, "restarted", G_CALLBACK (ews_soup_restarted), data);
+	g_simple_async_result_set_op_res_gpointer (
+		simple, data, (GDestroyNotify) oal_req_data_free);
+
+	soup_message_body_set_accumulate (soup_message->response_body, FALSE);
+
+	g_signal_connect (
+		soup_message, "got-headers",
+		G_CALLBACK (ews_soup_got_headers), data);
+	g_signal_connect (
+		soup_message, "got-chunk",
+		G_CALLBACK (ews_soup_got_chunk), data);
+	g_signal_connect (
+		soup_message, "restarted",
+		G_CALLBACK (ews_soup_restarted), data);
 
-	soup_session_queue_message	(cnc->priv->soup_session, SOUP_MESSAGE (msg),
-					 oal_download_response_cb, data);
+	soup_session_queue_message (
+		soup_session, soup_message,
+		oal_download_response_cb, simple);
 }
 
 gboolean
@@ -2122,50 +2360,14 @@ e_ews_connection_download_oal_file_finish (EEwsConnection *cnc,
 
 	g_return_val_if_fail (cnc != NULL, FALSE);
 	g_return_val_if_fail (
-			g_simple_async_result_is_valid (
-				result, G_OBJECT (cnc), e_ews_connection_download_oal_file),
-			FALSE);
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (cnc),
+		e_ews_connection_download_oal_file), FALSE);
 
 	simple = G_SIMPLE_ASYNC_RESULT (result);
 
-	if (g_simple_async_result_propagate_error (simple, error))
-		return FALSE;
-
-	return TRUE;
-}
-
-gboolean
-e_ews_connection_download_oal_file_sync (EEwsConnection *cnc,
-                                         const gchar *cache_filename,
-                                         EwsProgressFn progress_fn,
-                                         gpointer progress_data,
-                                         GCancellable *cancellable,
-                                         GError **error)
-{
-	EwsSyncData *sync_data;
-	gboolean result;
-
-	g_return_val_if_fail (cnc != NULL, FALSE);
-
-	sync_data = g_new0 (EwsSyncData, 1);
-	sync_data->eflag = e_flag_new ();
-
-	e_ews_connection_download_oal_file (
-		cnc, cache_filename,
-		progress_fn, progress_data,
-		cancellable, ews_sync_reply_cb, sync_data);
-
-	e_flag_wait (sync_data->eflag);
-
-	result = e_ews_connection_download_oal_file_finish
-						(cnc, sync_data->res,
-						 error);
-
-	e_flag_free (sync_data->eflag);
-	g_object_unref (sync_data->res);
-	g_free (sync_data);
-
-	return result;
+	/* Assume success unless a GError is set. */
+	return !g_simple_async_result_propagate_error (simple, error);
 }
 
 void
@@ -5359,7 +5561,6 @@ e_ews_connection_set_oof_settings_finish (EEwsConnection *cnc,
                                           GError **error)
 {
 	GSimpleAsyncResult *simple;
-	EwsAsyncData *async_data;
 
 	g_return_val_if_fail (cnc != NULL, FALSE);
 	g_return_val_if_fail (
@@ -5368,7 +5569,6 @@ e_ews_connection_set_oof_settings_finish (EEwsConnection *cnc,
 		FALSE);
 
 	simple = G_SIMPLE_ASYNC_RESULT (result);
-	async_data = g_simple_async_result_get_op_res_gpointer (simple);
 
 	if (g_simple_async_result_propagate_error (simple, error))
 		return FALSE;
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index a7d7eb2..5a29b6b 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -31,6 +31,7 @@
 #include "ews-errors.h"
 #include "e-ews-folder.h"
 #include "e-ews-item.h"
+#include "camel-ews-settings.h"
 
 G_BEGIN_DECLS
 
@@ -179,6 +180,9 @@ typedef struct {
 	gchar *ext_reply;	/*External Reply */
 } OOFSettings;
 
+void		ews_oal_free			(EwsOAL *oal);
+void		ews_oal_details_free		(EwsOALDetails *details);
+
 GType		e_ews_connection_get_type	(void);
 EEwsConnection *e_ews_connection_new		(const gchar *uri,
 						 const gchar *username,
@@ -194,13 +198,21 @@ void		e_ews_connection_authenticate	(EEwsConnection *cnc,
 						 const gchar *passwd,
 						 GError *error);
 
-typedef void (*EEwsAutoDiscoverCallback) (EwsUrls *urls, gpointer user_data, GError *error);
-void		e_ews_autodiscover_ws_url	(EEwsAutoDiscoverCallback callback,
-						 gpointer cbdata,
-						 const gchar *email,
+gboolean	e_ews_autodiscover_ws_url_sync	(CamelEwsSettings *settings,
+						 const gchar *email_address,
 						 const gchar *password,
-						 const gchar *ews_url,
-						 const gchar *username);
+						 GCancellable *cancellable,
+						 GError **error);
+void		e_ews_autodiscover_ws_url	(CamelEwsSettings *settings,
+						 const gchar *email_address,
+						 const gchar *password,
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_ews_autodiscover_ws_url_finish
+						(CamelEwsSettings *settings,
+						 GAsyncResult *result,
+						 GError **error);
 void		e_ews_connection_set_mailbox	(EEwsConnection *cnc,
 						 const gchar *email);
 
@@ -683,6 +695,11 @@ GSList *	e_ews_connection_get_attachments_sync
 						 GCancellable *cancellable,
 						 GError **error);
 
+gboolean	e_ews_connection_get_oal_list_sync
+						(EEwsConnection *cnc,
+						 GSList **oals,
+						 GCancellable *cancellable,
+						 GError **error);
 void		e_ews_connection_get_oal_list	(EEwsConnection *cnc,
 						 GCancellable *cancellable,
 						 GAsyncReadyCallback callback,
@@ -692,7 +709,13 @@ gboolean	e_ews_connection_get_oal_list_finish
 						 GAsyncResult *result,
 						 GSList **oals,
 						 GError **error);
-
+gboolean	e_ews_connection_get_oal_detail_sync
+						(EEwsConnection *cnc,
+						 const gchar *oal_id,
+						 const gchar *oal_element,
+						 GSList **elements,
+						 GCancellable *cancellable,
+						 GError **error);
 void		e_ews_connection_get_oal_detail	(EEwsConnection *cnc,
 						 const gchar *oal_id,
 						 const gchar *oal_element,
@@ -704,13 +727,6 @@ gboolean	e_ews_connection_get_oal_detail_finish
 						 GAsyncResult *result,
 						 GSList **elements,
 						 GError **error);
-gboolean	e_ews_connection_get_oal_detail_sync
-						(EEwsConnection *cnc,
-						 const gchar *oal_id,
-						 const gchar *oal_element,
-						 GSList **elements,
-						 GCancellable *cancellable,
-						 GError **error);
 
 void		e_ews_connection_get_free_busy	(EEwsConnection *cnc,
 						 gint pri,
@@ -732,25 +748,24 @@ gboolean	e_ews_connection_get_free_busy_sync
 						 GSList **free_busy,
 						 GCancellable *cancellable,
 						 GError **error);
-
-void		e_ews_connection_download_oal_file
+gboolean	e_ews_connection_download_oal_file_sync
 						(EEwsConnection *cnc,
 						 const gchar *cache_filename,
 						 EwsProgressFn progress_fn,
 						 gpointer progress_data,
 						 GCancellable *cancellable,
-						 GAsyncReadyCallback callback,
-						 gpointer user_data);
-gboolean	e_ews_connection_download_oal_file_finish
-						(EEwsConnection *cnc,
-						 GAsyncResult *result,
 						 GError **error);
-gboolean	e_ews_connection_download_oal_file_sync
+void		e_ews_connection_download_oal_file
 						(EEwsConnection *cnc,
 						 const gchar *cache_filename,
 						 EwsProgressFn progress_fn,
 						 gpointer progress_data,
 						 GCancellable *cancellable,
+						 GAsyncReadyCallback cb,
+						 gpointer user_data);
+gboolean	e_ews_connection_download_oal_file_finish
+						(EEwsConnection *cnc,
+						 GAsyncResult *result,
 						 GError **error);
 
 void		e_ews_connection_get_delegate	(EEwsConnection *cnc,
diff --git a/src/server/e-source-ews-folder.c b/src/server/e-source-ews-folder.c
new file mode 100644
index 0000000..cb79f8b
--- /dev/null
+++ b/src/server/e-source-ews-folder.c
@@ -0,0 +1,254 @@
+/*
+ * e-source-ews-folder.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-source-ews-folder.h"
+
+#define E_SOURCE_EWS_FOLDER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SOURCE_EWS_FOLDER, ESourceEwsFolderPrivate))
+
+struct _ESourceEwsFolderPrivate {
+	GMutex *property_lock;
+	gchar *change_key;
+	gchar *id;
+};
+
+enum {
+	PROP_0,
+	PROP_CHANGE_KEY,
+	PROP_ID
+};
+
+G_DEFINE_DYNAMIC_TYPE (
+	ESourceEwsFolder,
+	e_source_ews_folder,
+	E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_ews_folder_set_property (GObject *object,
+                                guint property_id,
+                                const GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CHANGE_KEY:
+			e_source_ews_folder_set_change_key (
+				E_SOURCE_EWS_FOLDER (object),
+				g_value_get_string (value));
+			return;
+
+		case PROP_ID:
+			e_source_ews_folder_set_id (
+				E_SOURCE_EWS_FOLDER (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_ews_folder_get_property (GObject *object,
+                                guint property_id,
+                                GValue *value,
+                                GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CHANGE_KEY:
+			g_value_take_string (
+				value,
+				e_source_ews_folder_dup_change_key (
+				E_SOURCE_EWS_FOLDER (object)));
+			return;
+
+		case PROP_ID:
+			g_value_take_string (
+				value,
+				e_source_ews_folder_dup_id (
+				E_SOURCE_EWS_FOLDER (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_ews_folder_finalize (GObject *object)
+{
+	ESourceEwsFolderPrivate *priv;
+
+	priv = E_SOURCE_EWS_FOLDER_GET_PRIVATE (object);
+
+	g_mutex_free (priv->property_lock);
+
+	g_free (priv->change_key);
+	g_free (priv->id);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_source_ews_folder_parent_class)->finalize (object);
+}
+
+static void
+e_source_ews_folder_class_init (ESourceEwsFolderClass *class)
+{
+	GObjectClass *object_class;
+	ESourceExtensionClass *extension_class;
+
+	g_type_class_add_private (class, sizeof (ESourceEwsFolderPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = source_ews_folder_set_property;
+	object_class->get_property = source_ews_folder_get_property;
+	object_class->finalize = source_ews_folder_finalize;
+
+	extension_class = E_SOURCE_EXTENSION_CLASS (class);
+	extension_class->name = E_SOURCE_EXTENSION_EWS_FOLDER;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_CHANGE_KEY,
+		g_param_spec_string (
+			"change-key",
+			"Change Key",
+			"Essentially an entity tag, "
+			"used when submitting changes",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS |
+			E_SOURCE_PARAM_SETTING));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_ID,
+		g_param_spec_string (
+			"id",
+			"ID",
+			"The server-assigned folder ID",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS |
+			E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_ews_folder_class_finalize (ESourceEwsFolderClass *class)
+{
+}
+
+static void
+e_source_ews_folder_init (ESourceEwsFolder *extension)
+{
+	extension->priv = E_SOURCE_EWS_FOLDER_GET_PRIVATE (extension);
+	extension->priv->property_lock = g_mutex_new ();
+}
+
+void
+e_source_ews_folder_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_source_ews_folder_register_type (type_module);
+}
+
+const gchar *
+e_source_ews_folder_get_change_key (ESourceEwsFolder *extension)
+{
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), NULL);
+
+	return extension->priv->change_key;
+}
+
+gchar *
+e_source_ews_folder_dup_change_key (ESourceEwsFolder *extension)
+{
+	const gchar *protected;
+	gchar *duplicate;
+
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), NULL);
+
+	g_mutex_lock (extension->priv->property_lock);
+
+	protected = e_source_ews_folder_get_id (extension);
+	duplicate = g_strdup (protected);
+
+	g_mutex_unlock (extension->priv->property_lock);
+
+	return duplicate;
+}
+
+void
+e_source_ews_folder_set_change_key (ESourceEwsFolder *extension,
+                                    const gchar *change_key)
+{
+	g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
+
+	g_mutex_lock (extension->priv->property_lock);
+
+	g_free (extension->priv->change_key);
+	extension->priv->change_key = g_strdup (change_key);
+
+	g_mutex_unlock (extension->priv->property_lock);
+
+	g_object_notify (G_OBJECT (extension), "change-key");
+}
+
+const gchar *
+e_source_ews_folder_get_id (ESourceEwsFolder *extension)
+{
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), NULL);
+
+	return extension->priv->id;
+}
+
+gchar *
+e_source_ews_folder_dup_id (ESourceEwsFolder *extension)
+{
+	const gchar *protected;
+	gchar *duplicate;
+
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), NULL);
+
+	g_mutex_lock (extension->priv->property_lock);
+
+	protected = e_source_ews_folder_get_id (extension);
+	duplicate = g_strdup (protected);
+
+	g_mutex_unlock (extension->priv->property_lock);
+
+	return duplicate;
+}
+
+void
+e_source_ews_folder_set_id (ESourceEwsFolder *extension,
+                            const gchar *id)
+{
+	g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
+
+	g_mutex_lock (extension->priv->property_lock);
+
+	g_free (extension->priv->id);
+	extension->priv->id = g_strdup (id);
+
+	g_mutex_unlock (extension->priv->property_lock);
+
+	g_object_notify (G_OBJECT (extension), "id");
+}
+
diff --git a/src/server/e-source-ews-folder.h b/src/server/e-source-ews-folder.h
new file mode 100644
index 0000000..3dd30e4
--- /dev/null
+++ b/src/server/e-source-ews-folder.h
@@ -0,0 +1,78 @@
+/*
+ * e-source-ews-folder.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_SOURCE_EWS_FOLDER_H
+#define E_SOURCE_EWS_FOLDER_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_EWS_FOLDER \
+	(e_source_ews_folder_get_type ())
+#define E_SOURCE_EWS_FOLDER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SOURCE_EWS_FOLDER, ESourceEwsFolder))
+#define E_SOURCE_EWS_FOLDER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SOURCE_EWS_FOLDER, ESourceEwsFolderClass))
+#define E_IS_SOURCE_EWS_FOLDER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SOURCE_EWS_FOLDER))
+#define E_IS_SOURCE_EWS_FOLDER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SOURCE_EWS_FOLDER))
+#define E_SOURCE_EWS_FOLDER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SOURCE_EWS_FOLDER, ESourceEwsFolderClass))
+
+#define E_SOURCE_EXTENSION_EWS_FOLDER "Exchange Web Services Folder"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceEwsFolder ESourceEwsFolder;
+typedef struct _ESourceEwsFolderClass ESourceEwsFolderClass;
+typedef struct _ESourceEwsFolderPrivate ESourceEwsFolderPrivate;
+
+struct _ESourceEwsFolder {
+	ESourceExtension parent;
+	ESourceEwsFolderPrivate *priv;
+};
+
+struct _ESourceEwsFolderClass {
+	ESourceExtensionClass parent_class;
+};
+
+GType		e_source_ews_folder_get_type	(void) G_GNUC_CONST;
+void		e_source_ews_folder_type_register
+						(GTypeModule *type_module);
+const gchar *	e_source_ews_folder_get_change_key
+						(ESourceEwsFolder *extension);
+gchar *		e_source_ews_folder_dup_change_key
+						(ESourceEwsFolder *extension);
+void		e_source_ews_folder_set_change_key
+						(ESourceEwsFolder *extension,
+						 const gchar *change_key);
+const gchar *	e_source_ews_folder_get_id	(ESourceEwsFolder *extension);
+gchar *		e_source_ews_folder_dup_id	(ESourceEwsFolder *extension);
+void		e_source_ews_folder_set_id	(ESourceEwsFolder *extension,
+						 const gchar *id);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_EWS_FOLDER_H */
+
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index 0d5e8d8..642cf2f 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -17,10 +17,6 @@ libewsutils_la_CPPFLAGS = \
 	$(NULL)
 
 libewsutils_la_SOURCES = \
-	camel-ews-settings.c \
-	camel-ews-settings.h \
-	ews-esource-utils.h \
-	ews-esource-utils.c \
 	e-sqlite3-vfs.c \
 	e-sqlite3-vfs.h \
 	ews-camel-common.c \



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