[evolution-ews] Bug #656376 - Support for delegation



commit 7ee6fd6bf09a5a13e4da36712d7d6f85dbb18ed2
Author: Milan Crha <mcrha redhat com>
Date:   Fri Aug 3 11:56:43 2012 +0200

    Bug #656376 - Support for delegation

 po/POTFILES.in                                     |    1 +
 src/calendar/e-cal-backend-ews.c                   |    2 +-
 src/camel/camel-ews-store-summary.c                |    3 +-
 src/camel/camel-ews-store-summary.h                |    3 +
 src/camel/camel-ews-store.c                        |    2 +-
 src/camel/camel-ews-utils.c                        |    2 +-
 src/configuration/Makefile.am                      |    4 +
 src/configuration/e-ews-config-utils.c             |    3 +-
 src/configuration/e-ews-config-utils.h             |    3 +-
 src/configuration/e-ews-edit-folder-permissions.c  |    2 +-
 src/configuration/e-ews-search-user.c              |   25 +-
 .../e-mail-config-ews-delegates-page.c             | 1743 ++++++++++++++++++++
 .../e-mail-config-ews-delegates-page.h             |   83 +
 src/configuration/e-mail-config-ews-notebook.c     |    8 +
 src/configuration/module-ews-configuration.c       |    2 +
 .../module-ews-configuration.error.xml             |    5 +
 src/server/e-ews-connection.c                      |  598 ++++++-
 src/server/e-ews-connection.h                      |  102 +-
 src/server/e-ews-item.c                            |    9 +-
 src/server/e-ews-item.h                            |    3 +-
 src/server/e-soap-response.c                       |    8 +
 src/server/e-soap-response.h                       |    2 +
 src/server/tests/test-getdelegate.c                |   24 +-
 23 files changed, 2526 insertions(+), 111 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6066ad0..ae9a67f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,7 @@ src/configuration/e-ews-search-user.c
 src/configuration/e-mail-config-ews-autodiscover.c
 src/configuration/e-mail-config-ews-backend.c
 src/configuration/e-mail-config-ews-gal.c
+src/configuration/e-mail-config-ews-delegates-page.c
 src/configuration/e-mail-config-ews-ooo-page.c
 src/configuration/module-ews-configuration.error.xml
 src/server/e-ews-connection.c
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 1e8995e..8e08256 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -3133,7 +3133,7 @@ add_item_to_cache (ECalBackendEws *cbews,
 			if (!attendee->mailbox)
 				continue;
 
-			if (g_strcmp0 (attendee->mailbox->mb_type, "EX") == 0) {
+			if (g_strcmp0 (attendee->mailbox->routing_type, "EX") == 0) {
 				e_ews_connection_ex_to_smtp_sync (
 					cnc, EWS_PRIORITY_MEDIUM,
 					attendee->mailbox->name, attendee->mailbox->email, &email,
diff --git a/src/camel/camel-ews-store-summary.c b/src/camel/camel-ews-store-summary.c
index ba2203e..5c16c86 100644
--- a/src/camel/camel-ews-store-summary.c
+++ b/src/camel/camel-ews-store-summary.c
@@ -759,7 +759,8 @@ camel_ews_store_summary_get_folder_id_from_folder_type (CamelEwsStoreSummary *ew
 		guint64 folder_flags;
 
 		folder_flags = camel_ews_store_summary_get_folder_flags (ews_summary, id, NULL);
-		if ((folder_flags & CAMEL_FOLDER_TYPE_MASK) == folder_type) {
+		if ((folder_flags & CAMEL_FOLDER_TYPE_MASK) == folder_type &&
+		    (folder_flags & CAMEL_FOLDER_SYSTEM) != 0) {
 			folder_id = id;
 			l->data = NULL;
 			break;
diff --git a/src/camel/camel-ews-store-summary.h b/src/camel/camel-ews-store-summary.h
index 3bbc1c8..2f9b10e 100644
--- a/src/camel/camel-ews-store-summary.h
+++ b/src/camel/camel-ews-store-summary.h
@@ -22,6 +22,9 @@
 	(G_TYPE_INSTANCE_GET_CLASS \
 	((obj), CAMEL_TYPE_EWS_STORE_SUMMARY, CamelEwsStoreSummaryClass))
 
+/* the last possible value from CAMEL_FOLDER_TYPE_MASK range */
+#define CAMEL_EWS_FOLDER_TYPE_JOURNAL (((CAMEL_FOLDER_TYPE_MASK >> CAMEL_FOLDER_TYPE_BIT) - 1) << CAMEL_FOLDER_TYPE_BIT)
+
 G_BEGIN_DECLS
 
 typedef struct _CamelEwsStoreSummary CamelEwsStoreSummary;
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index ba3ff6f..59a554c 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -287,7 +287,7 @@ static SystemFolder system_folder[] = {
 	{"deleteditems", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_TRASH},
 	{"drafts", CAMEL_FOLDER_SYSTEM},
 	{"inbox", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_INBOX},
-	{"journal", CAMEL_FOLDER_SYSTEM},
+	{"journal", CAMEL_FOLDER_SYSTEM | CAMEL_EWS_FOLDER_TYPE_JOURNAL},
 	{"notes", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_MEMOS},
 	{"outbox", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_OUTBOX},
 	{"sentitems", CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_SENT},
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index 63dacc5..ba14fc4 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -690,7 +690,7 @@ form_email_string_from_mb (EEwsConnection *cnc,
 		GString *str;
 		gchar *email = NULL;
 
-		if (g_strcmp0 (mb->mb_type, "EX") == 0) {
+		if (g_strcmp0 (mb->routing_type, "EX") == 0) {
 			e_ews_connection_ex_to_smtp_sync (
 				cnc, EWS_PRIORITY_MEDIUM,
 				mb->name, mb->email, &email,
diff --git a/src/configuration/Makefile.am b/src/configuration/Makefile.am
index b5c384f..9c059ae 100644
--- a/src/configuration/Makefile.am
+++ b/src/configuration/Makefile.am
@@ -7,6 +7,7 @@ module_ews_configuration_la_CPPFLAGS = \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/src \
 	$(EVOLUTION_MAIL_CFLAGS) \
+	$(EVOLUTION_SHELL_CFLAGS) \
 	$(NULL)
 
 module_ews_configuration_la_SOURCES = \
@@ -25,6 +26,8 @@ module_ews_configuration_la_SOURCES = \
 	e-mail-config-ews-notebook.h \
 	e-mail-config-ews-oal-combo-box.c \
 	e-mail-config-ews-oal-combo-box.h \
+	e-mail-config-ews-delegates-page.c \
+	e-mail-config-ews-delegates-page.h \
 	e-mail-config-ews-ooo-page.c \
 	e-mail-config-ews-ooo-page.h \
 	e-ews-config-ui-extension.c \
@@ -41,6 +44,7 @@ module_ews_configuration_la_LIBADD = \
 	$(top_builddir)/src/server/libeews-1.2.la \
 	$(top_builddir)/src/utils/libewsutils.la \
 	$(EVOLUTION_MAIL_LIBS) \
+	$(EVOLUTION_SHELL_LIBS) \
 	$(NULL)
 
 module_ews_configuration_la_LDFLAGS = \
diff --git a/src/configuration/e-ews-config-utils.c b/src/configuration/e-ews-config-utils.c
index c2ed8e9..ccc6dd2 100644
--- a/src/configuration/e-ews-config-utils.c
+++ b/src/configuration/e-ews-config-utils.c
@@ -368,8 +368,7 @@ e_ews_config_utils_authenticator_init (EEwsConfigUtilsAuthenticator *authenticat
 }
 
 EEwsConnection	*
-e_ews_config_utils_open_connection_for (GtkWindow *parent,
-					ESourceRegistry *registry,
+e_ews_config_utils_open_connection_for (ESourceRegistry *registry,
 					ESource *source,
 					CamelEwsSettings *ews_settings,
 					GCancellable *cancellable,
diff --git a/src/configuration/e-ews-config-utils.h b/src/configuration/e-ews-config-utils.h
index e4f1207..57b559e 100644
--- a/src/configuration/e-ews-config-utils.h
+++ b/src/configuration/e-ews-config-utils.h
@@ -49,8 +49,7 @@ void			e_ews_config_utils_run_in_thread_with_feedback_modal	(GtkWindow *parent,
 										 gpointer user_data,
 										 GDestroyNotify free_user_data);
 
-EEwsConnection	*	e_ews_config_utils_open_connection_for			(GtkWindow *parent,
-										 ESourceRegistry *registry,
+EEwsConnection	*	e_ews_config_utils_open_connection_for			(ESourceRegistry *registry,
 										 ESource *source,
 										 CamelEwsSettings *ews_settings,
 										 GCancellable *cancellable,
diff --git a/src/configuration/e-ews-edit-folder-permissions.c b/src/configuration/e-ews-edit-folder-permissions.c
index c272d7b..da85ff0 100644
--- a/src/configuration/e-ews-edit-folder-permissions.c
+++ b/src/configuration/e-ews-edit-folder-permissions.c
@@ -681,7 +681,7 @@ read_folder_permissions_thread (GObject *dialog,
 	g_return_if_fail (widgets->source != NULL);
 	g_return_if_fail (widgets->ews_settings != NULL);
 
-	widgets->conn = e_ews_config_utils_open_connection_for (GTK_WINDOW (dialog),
+	widgets->conn = e_ews_config_utils_open_connection_for (
 		widgets->registry,
 		widgets->source,
 		widgets->ews_settings,
diff --git a/src/configuration/e-ews-search-user.c b/src/configuration/e-ews-search-user.c
index 7ec355b..285fbf3 100644
--- a/src/configuration/e-ews-search-user.c
+++ b/src/configuration/e-ews-search-user.c
@@ -112,7 +112,8 @@ struct EEwsSearchIdleData
 	GCancellable *cancellable;
 
 	GObject *dialog;
-	GSList *found_users; /* struct EEwsSearchUser * */
+	GSList *found_users; /* struct EEwsSearchUser *, for 'Mailbox' MailboxType */
+	guint found_contacts; /* how many other than 'Mailbox' were found */
 	gboolean includes_last_item;
 };
 
@@ -200,7 +201,15 @@ search_finish_idle (gpointer user_data)
 		}
 
 		if (!added) {
-			gtk_label_set_text (GTK_LABEL (pgu->info_label), _("No users found"));
+			if (sid->found_contacts > 0) {
+				gchar *str;
+				str = g_strdup_printf (ngettext ("No users found, only one contact", "No users found, only %d contacts",
+					sid->found_contacts), sid->found_contacts);
+				gtk_label_set_text (GTK_LABEL (pgu->info_label), str);
+				g_free (str);
+			} else {
+				gtk_label_set_text (GTK_LABEL (pgu->info_label), _("No users found"));
+			}
 		} else if (sid->includes_last_item) {
 			gchar *str;
 			str = g_strdup_printf (ngettext ("Found one user", "Found %d users", added), added);
@@ -208,7 +217,9 @@ search_finish_idle (gpointer user_data)
 			g_free (str);
 		} else {
 			gchar *str;
-			str = g_strdup_printf (ngettext ("Found more than 100 users, but showing only first %d", "Found more than 100 users, but showing only first %d", added), added);
+			str = g_strdup_printf (ngettext (
+				"Found more than 100 users, but showing only first %d",
+				"Found more than 100 users, but showing only first %d", added), added);
 			gtk_label_set_text (GTK_LABEL (pgu->info_label), str);
 			g_free (str);
 		}
@@ -236,11 +247,16 @@ search_thread (gpointer user_data)
 			&sid->includes_last_item, sid->cancellable, &error)) {
 			GSList *iter;
 
+			sid->found_contacts = 0;
+
 			for (iter = mailboxes; iter != NULL; iter = iter->next) {
 				EwsMailbox *mb = iter->data;
 
-				if (!mb || !mb->email || !*mb->email)
+				if (!mb || !mb->email || !*mb->email
+				    || g_strcmp0 (mb->mailbox_type, "Mailbox") != 0) {
+					sid->found_contacts++;
 					continue;
+				}
 
 				sid->found_users = g_slist_prepend (sid->found_users,
 					e_ews_search_user_new (mb->name, mb->email));
@@ -424,6 +440,7 @@ create_users_tree_view (GtkWidget *dialog,
 	return pgu->tree_view;
 }
 
+/* for non-NULL @info populates also permission levels for given user */
 gboolean
 e_ews_search_user_modal (GtkWindow *parent,
 			 EEwsConnection *conn,
diff --git a/src/configuration/e-mail-config-ews-delegates-page.c b/src/configuration/e-mail-config-ews-delegates-page.c
new file mode 100644
index 0000000..fcd036c
--- /dev/null
+++ b/src/configuration/e-mail-config-ews-delegates-page.c
@@ -0,0 +1,1743 @@
+/*
+ * e-mail-config-ews-delegates-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 <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 <libevolution-utils/e-alert-sink.h>
+#include <libevolution-utils/e-alert-dialog.h>
+#include <misc/e-activity-bar.h>
+#include <misc/e-alert-bar.h>
+#include <mail/e-mail-backend.h>
+
+#include "server/camel-ews-settings.h"
+#include "server/e-ews-connection.h"
+#include "server/e-ews-oof-settings.h"
+#include "camel/camel-ews-store.h"
+
+#include "e-ews-config-utils.h"
+#include "e-ews-search-user.h"
+#include "e-mail-config-ews-delegates-page.h"
+
+#define E_MAIL_CONFIG_EWS_DELEGATES_PAGE_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE, EMailConfigEwsDelegatesPagePrivate))
+
+typedef struct _AsyncContext AsyncContext;
+
+struct _EMailConfigEwsDelegatesPagePrivate {
+	ESourceRegistry *registry;
+	ESource *account_source;
+	ESource *identity_source;
+	ESource *collection_source;
+	EEwsConnection *connection;
+
+	/* The try_password() method deposits results here.
+	 * This avoids calling GTK+ functions from multiple threads. */
+	GSList *orig_delegates; /* EwsDelegateInfo * */
+	GSList *new_delegates; /* EwsDelegateInfo * */
+	EwsDelegateDeliver deliver_to;
+	GMutex delegates_lock;
+
+	GtkWidget *users_tree_view;			/* not referenced */
+	GtkWidget *add_button;				/* not referenced */
+	GtkWidget *remove_button;			/* not referenced */
+	GtkWidget *properties_button;			/* not referenced */
+	GtkWidget *deliver_copy_me_radio;		/* not referenced */
+	GtkWidget *deliver_delegates_only_radio;	/* not referenced */
+	GtkWidget *deliver_delegates_and_me_radio;	/* not referenced */
+};
+
+struct _AsyncContext {
+	EMailConfigEwsDelegatesPage *page;
+	EActivity *activity;
+};
+
+enum {
+	PROP_0,
+	PROP_ACCOUNT_SOURCE,
+	PROP_COLLECTION_SOURCE,
+	PROP_IDENTITY_SOURCE,
+	PROP_REGISTRY
+};
+
+/* Forward Declarations */
+static void	e_mail_config_ews_delegates_page_interface_init
+					(EMailConfigPageInterface *interface);
+static void	e_mail_config_ews_delegates_page_authenticator_init
+					(ESourceAuthenticatorInterface *interface);
+static void	add_to_tree_view	(EMailConfigEwsDelegatesPage *page,
+					 EwsDelegateInfo *di,
+					 gboolean select);
+static gboolean	page_contains_user	(EMailConfigEwsDelegatesPage *page,
+					 const gchar *primary_smtp,
+					 GtkTreeIter *piter);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailConfigEwsDelegatesPage,
+	e_mail_config_ews_delegates_page,
+	E_TYPE_MAIL_CONFIG_ACTIVITY_PAGE,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_CONFIG_PAGE,
+		e_mail_config_ews_delegates_page_interface_init)
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_mail_config_ews_delegates_page_authenticator_init))
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+	if (async_context->page != NULL)
+		g_object_unref (async_context->page);
+
+	if (async_context->activity != NULL)
+		g_object_unref (async_context->activity);
+
+	g_slice_free (AsyncContext, async_context);
+}
+
+static CamelSettings *
+mail_config_ews_delegates_page_get_settings (EMailConfigEwsDelegatesPage *page)
+{
+	ESource *source;
+	ESourceCamel *extension;
+	const gchar *extension_name;
+
+	source = e_mail_config_ews_delegates_page_get_collection_source (page);
+
+	extension_name = e_source_camel_get_extension_name ("ews");
+	extension = e_source_get_extension (source, extension_name);
+
+	return e_source_camel_get_settings (extension);
+}
+
+static const gchar *
+mail_config_ews_delegates_page_get_mailbox (EMailConfigEwsDelegatesPage *page)
+{
+	ESourceRegistry *registry;
+	ESource *collection_source;
+	GList *list, *link;
+	const gchar *collection_uid;
+	const gchar *extension_name;
+	const gchar *mailbox = NULL;
+
+	/* Find the mail identity source that belongs to
+	 * our collection and return its email address. */
+
+	collection_source =
+		e_mail_config_ews_delegates_page_get_collection_source (page);
+	collection_uid = e_source_get_uid (collection_source);
+
+	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
+	registry = e_mail_config_ews_delegates_page_get_registry (page);
+	list = e_source_registry_list_sources (registry, extension_name);
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		ESource *source = E_SOURCE (link->data);
+		ESourceMailIdentity *extension;
+		const gchar *parent_uid;
+
+		parent_uid = e_source_get_parent (source);
+		if (g_strcmp0 (parent_uid, collection_uid) != 0)
+			continue;
+
+		extension = e_source_get_extension (source, extension_name);
+		mailbox = e_source_mail_identity_get_address (extension);
+		break;
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+	return mailbox;
+}
+
+static void
+enable_delegates_page_widgets (EMailConfigEwsDelegatesPage *page,
+			       gboolean enable)
+{
+	gboolean has_users = FALSE;
+
+	g_return_if_fail (page != NULL);
+
+	if (enable)
+		has_users = page->priv->new_delegates != NULL;
+
+	gtk_widget_set_sensitive (page->priv->users_tree_view, enable && has_users);
+	gtk_widget_set_sensitive (page->priv->add_button, enable);
+	gtk_widget_set_sensitive (page->priv->deliver_copy_me_radio, enable && has_users);
+	gtk_widget_set_sensitive (page->priv->deliver_delegates_only_radio, enable && has_users);
+	gtk_widget_set_sensitive (page->priv->deliver_delegates_and_me_radio, enable && has_users);
+
+	if (enable) {
+		GtkTreeSelection *selection;
+
+		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (page->priv->users_tree_view));
+		enable = gtk_tree_selection_count_selected_rows (selection) == 1;
+	}
+
+	gtk_widget_set_sensitive (page->priv->remove_button, enable);
+	gtk_widget_set_sensitive (page->priv->properties_button, enable);
+}
+
+static EwsDelegateInfo *
+copy_delegate_info (const EwsDelegateInfo *src)
+{
+	EwsDelegateInfo *di;
+
+	g_return_val_if_fail (src != NULL, NULL);
+
+	di = g_new0 (EwsDelegateInfo, 1);
+	di->user_id = g_new0 (EwsUserId, 1);
+	di->user_id->sid = g_strdup (src->user_id->sid);
+	di->user_id->primary_smtp = g_strdup (src->user_id->primary_smtp);
+	di->user_id->display_name = g_strdup (src->user_id->display_name);
+	di->user_id->distinguished_user = g_strdup (src->user_id->distinguished_user);
+	di->user_id->external_user = g_strdup (src->user_id->external_user);
+	di->calendar = src->calendar;
+	di->tasks = src->tasks;
+	di->inbox = src->inbox;
+	di->contacts = src->contacts;
+	di->notes = src->notes;
+	di->journal = src->journal;
+	di->meetingcopies = src->meetingcopies;
+	di->view_priv_items = src->view_priv_items;
+
+	return di;
+}
+
+static void
+mail_config_ews_delegates_page_refresh_cb (GObject *source_object,
+					   GAsyncResult *result,
+					   gpointer user_data)
+{
+	ESourceRegistry *registry;
+	AsyncContext *async_context;
+	EAlertSink *alert_sink;
+	GError *error = NULL;
+
+	registry = E_SOURCE_REGISTRY (source_object);
+	async_context = (AsyncContext *) user_data;
+
+	alert_sink = e_activity_get_alert_sink (async_context->activity);
+
+	e_source_registry_authenticate_finish (registry, 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-delegates-error",
+			error->message, NULL);
+		g_error_free (error);
+
+	} else {
+		EMailConfigEwsDelegatesPage *page = async_context->page;
+		GtkWidget *radio = page->priv->deliver_copy_me_radio;
+		GtkTreeModel *model;
+		const GSList *iter;
+
+		g_mutex_lock (&page->priv->delegates_lock);
+
+		switch (page->priv->deliver_to) {
+		case EwsDelegateDeliver_DelegatesOnly:
+			radio = page->priv->deliver_delegates_only_radio;
+			break;
+		case EwsDelegateDeliver_DelegatesAndMe:
+			radio = page->priv->deliver_delegates_and_me_radio;
+			break;
+		case EwsDelegateDeliver_DelegatesAndSendInformationToMe:
+			radio = page->priv->deliver_copy_me_radio;
+			break;
+		}
+
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);
+
+		model = gtk_tree_view_get_model (GTK_TREE_VIEW (page->priv->users_tree_view));
+		gtk_list_store_clear (GTK_LIST_STORE (model));
+
+		for (iter = page->priv->orig_delegates; iter; iter = iter->next) {
+			const EwsDelegateInfo *orig_di = iter->data;
+			EwsDelegateInfo *di;
+
+			if (!orig_di) {
+				g_warn_if_reached ();
+				continue;
+			}
+
+			di = copy_delegate_info (orig_di);
+
+			add_to_tree_view (page, di, FALSE);
+		}
+
+		g_mutex_unlock (&page->priv->delegates_lock);
+
+		enable_delegates_page_widgets (page, page->priv->connection != NULL);
+	}
+
+	async_context_free (async_context);
+}
+
+static void
+mail_config_ews_delegates_page_set_account_source (EMailConfigEwsDelegatesPage *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_delegates_page_set_collection_source (EMailConfigEwsDelegatesPage *page,
+						      ESource *collection_source)
+{
+	g_return_if_fail (E_IS_SOURCE (collection_source));
+	g_return_if_fail (page->priv->collection_source == NULL);
+
+	page->priv->collection_source = g_object_ref (collection_source);
+}
+
+static void
+mail_config_ews_delegates_page_set_identity_source (EMailConfigEwsDelegatesPage *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_delegates_page_set_registry (EMailConfigEwsDelegatesPage *page,
+					     ESourceRegistry *registry)
+{
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+	g_return_if_fail (page->priv->registry == NULL);
+
+	page->priv->registry = g_object_ref (registry);
+}
+
+static void
+mail_config_ews_delegates_page_set_property (GObject *object,
+					     guint property_id,
+					     const GValue *value,
+					     GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_ACCOUNT_SOURCE:
+			mail_config_ews_delegates_page_set_account_source (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_COLLECTION_SOURCE:
+			mail_config_ews_delegates_page_set_collection_source (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			mail_config_ews_delegates_page_set_identity_source (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_REGISTRY:
+			mail_config_ews_delegates_page_set_registry (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object),
+				g_value_get_object (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_delegates_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_delegates_page_get_account_source (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object)));
+			return;
+
+		case PROP_COLLECTION_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_delegates_page_get_collection_source (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object)));
+			return;
+
+		case PROP_IDENTITY_SOURCE:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_delegates_page_get_identity_source (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object)));
+			return;
+
+		case PROP_REGISTRY:
+			g_value_set_object (
+				value,
+				e_mail_config_ews_delegates_page_get_registry (
+				E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_ews_delegates_page_dispose (GObject *object)
+{
+	EMailConfigEwsDelegatesPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_EWS_DELEGATES_PAGE_GET_PRIVATE (object);
+
+	if (priv->registry != NULL) {
+		g_object_unref (priv->registry);
+		priv->registry = NULL;
+	}
+
+	if (priv->account_source != NULL) {
+		g_object_unref (priv->account_source);
+		priv->account_source = NULL;
+	}
+
+	if (priv->collection_source != NULL) {
+		g_object_unref (priv->collection_source);
+		priv->collection_source = NULL;
+	}
+
+	if (priv->identity_source != NULL) {
+		g_object_unref (priv->identity_source);
+		priv->identity_source = NULL;
+	}
+
+	if (priv->connection) {
+		g_object_unref (priv->connection);
+		priv->connection = NULL;
+	}
+
+	g_slist_free_full (priv->orig_delegates, (GDestroyNotify) ews_delegate_info_free);
+	priv->orig_delegates = NULL;
+
+	g_slist_free_full (priv->new_delegates, (GDestroyNotify) ews_delegate_info_free);
+	priv->new_delegates = NULL;
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_delegates_page_parent_class)->
+		dispose (object);
+}
+
+static void
+mail_config_ews_delegates_page_finalize (GObject *object)
+{
+	EMailConfigEwsDelegatesPagePrivate *priv;
+
+	priv = E_MAIL_CONFIG_EWS_DELEGATES_PAGE_GET_PRIVATE (object);
+
+	g_mutex_clear (&priv->delegates_lock);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_delegates_page_parent_class)->
+		finalize (object);
+}
+
+static void
+delegates_tree_selection_changed_cb (GtkTreeSelection *selection,
+				     EMailConfigEwsDelegatesPage *page)
+{
+	g_return_if_fail (selection != NULL);
+	g_return_if_fail (page != NULL);
+
+	enable_delegates_page_widgets (page, page->priv->connection != NULL);
+}
+
+static GtkWidget *
+add_permission_level_combo_row (GtkGrid *grid,
+				gint row,
+				const gchar *icon_name,
+				const gchar *label_text,
+				EwsPermissionLevel preselect)
+{
+	GtkWidget *image = NULL, *label;
+	GtkComboBoxText *combo;
+	gint index = 0;
+
+	g_return_val_if_fail (grid != NULL, NULL);
+	g_return_val_if_fail (label_text != NULL, NULL);
+	g_return_val_if_fail (preselect != EwsPermissionLevel_Unknown, NULL);
+
+	combo = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new ());
+	gtk_combo_box_text_append_text (combo, C_("PermissionsLevel", "None"));
+	gtk_combo_box_text_append_text (combo, C_("PermissionsLevel", "Reviewer (can read items)"));
+	gtk_combo_box_text_append_text (combo, C_("PermissionsLevel", "Author (can read and create items)"));
+	gtk_combo_box_text_append_text (combo, C_("PermissionsLevel", "Editor (can read, create and modify items)"));
+
+	switch (preselect) {
+	case EwsPermissionLevel_Unknown:
+		break;
+	case EwsPermissionLevel_None:
+		index = 0;
+		break;
+	case EwsPermissionLevel_Reviewer:
+		index = 1;
+		break;
+	case EwsPermissionLevel_Author:
+		index = 2;
+		break;
+	case EwsPermissionLevel_Editor:
+		index = 3;
+		break;
+	case EwsPermissionLevel_Custom:
+		gtk_combo_box_text_append_text (combo, C_("PermissionsLevel", "Custom"));
+		index = 4;
+		break;
+	}
+
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index);
+	g_object_set (G_OBJECT (combo),
+		"valign", GTK_ALIGN_CENTER,
+		NULL);
+
+	if (icon_name)
+		image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+	label = gtk_label_new_with_mnemonic (label_text);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (combo));
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+	if (image)
+		gtk_grid_attach (grid, image, 0, row, 1, 1);
+	gtk_grid_attach (grid, label, 1, row, 1, 1);
+	gtk_grid_attach (grid, GTK_WIDGET (combo), 2, row, 1, 1);
+
+	return GTK_WIDGET (combo);
+}
+
+static EwsPermissionLevel
+get_permission_level_from_combo (GtkWidget *combo)
+{
+	EwsPermissionLevel res = EwsPermissionLevel_Unknown;
+
+	g_return_val_if_fail (GTK_IS_COMBO_BOX_TEXT (combo), res);
+
+	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo))) {
+	case 0:
+		res = EwsPermissionLevel_None;
+		break;
+	case 1:
+		res = EwsPermissionLevel_Reviewer;
+		break;
+	case 2:
+		res = EwsPermissionLevel_Author;
+		break;
+	case 3:
+		res = EwsPermissionLevel_Editor;
+		break;
+	case 4:
+		res = EwsPermissionLevel_Custom;
+		break;
+	default:
+		g_warn_if_reached ();
+		break;
+	}
+
+	return res;
+}
+
+static void
+enable_cal_copies_by_combo_index (GtkComboBox *combo,
+				  GtkWidget *check)
+{
+	gtk_widget_set_sensitive (check, gtk_combo_box_get_active (combo) >= 3);
+}
+
+static void
+show_delegate_properties_modal (EMailConfigEwsDelegatesPage *page,
+				EwsDelegateInfo *di)
+{
+	GtkWidget *dialog, *widget, *content_area;
+	GtkGrid *grid;
+	GtkWidget *lev_calendar, *lev_tasks, *lev_inbox, *lev_contacts, *lev_notes, *lev_journal;
+	GtkWidget *check_cal_copies, *check_see_private_items;
+	GtkWindow *parent;
+	const gchar *name;
+	gchar *text;
+	gint row = 0;
+
+	g_return_if_fail (page != NULL);
+	g_return_if_fail (di != NULL);
+
+	name = di->user_id->display_name;
+	if (!name)
+		name = di->user_id->primary_smtp;
+
+	parent = e_ews_config_utils_get_widget_toplevel_window (GTK_WIDGET (page));
+	dialog = gtk_dialog_new_with_buttons (_("Delegate permissions"), parent,
+		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+		GTK_STOCK_OK, GTK_RESPONSE_OK,
+		NULL);
+
+	widget = gtk_grid_new ();
+	grid = GTK_GRID (widget);
+	g_object_set (G_OBJECT (grid),
+		"row-spacing", 6,
+		"column-spacing", 6,
+		"orientation", GTK_ORIENTATION_VERTICAL,
+		"border-width", 12,
+		NULL);
+
+	row = 0;
+
+	lev_calendar = add_permission_level_combo_row (grid, row, "x-office-calendar", _("C_alendar"), di->calendar);
+	row++;
+
+	check_cal_copies = gtk_check_button_new_with_mnemonic (_("_Delegate receives copies of meeting-related messages sent to me"));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_cal_copies), di->meetingcopies);
+	gtk_grid_attach (grid, check_cal_copies, 1, row, 2, 1);
+	row++;
+
+	lev_tasks = add_permission_level_combo_row (grid, row, "evolution-tasks", _("_Tasks"), di->tasks);
+	row++;
+
+	lev_inbox = add_permission_level_combo_row (grid, row, "mail-inbox", _("_Inbox"), di->inbox);
+	row++;
+
+	lev_contacts = add_permission_level_combo_row (grid, row, "x-office-address-book", _("C_ontacts"), di->contacts);
+	row++;
+
+	lev_notes = add_permission_level_combo_row (grid, row, "evolution-memos", _("_Notes"), di->notes);
+	row++;
+
+	lev_journal = add_permission_level_combo_row (grid, row, NULL, _("_Journal"), di->journal);
+	row++;
+
+	text = g_strdup_printf (_("Delegate '%s' has the following permissions"), name);
+	widget = gtk_frame_new (text);
+	gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (grid));
+	g_free (text);
+
+	grid = GTK_GRID (gtk_grid_new ());
+	g_object_set (G_OBJECT (grid),
+		"row-spacing", 6,
+		"orientation", GTK_ORIENTATION_VERTICAL,
+		"border-width", 12,
+		NULL);
+
+	row = 0;
+
+	gtk_grid_attach (grid, widget, 0, row, 1, 1);
+	row++;
+
+	check_see_private_items = gtk_check_button_new_with_mnemonic (_("Delegate can see my _private items"));
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_see_private_items), di->view_priv_items);
+	gtk_grid_attach (grid, check_see_private_items, 0, row, 1, 1);
+	row++;
+
+	gtk_widget_show_all (GTK_WIDGET (grid));
+
+	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+	gtk_container_add (GTK_CONTAINER (content_area), GTK_WIDGET (grid));
+
+	g_signal_connect (lev_calendar, "changed", G_CALLBACK (enable_cal_copies_by_combo_index), check_cal_copies);
+	enable_cal_copies_by_combo_index (GTK_COMBO_BOX (lev_calendar), check_cal_copies);
+
+	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+		di->meetingcopies = gtk_widget_get_sensitive (check_cal_copies) &&
+			gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_cal_copies));
+
+		di->view_priv_items = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_see_private_items));
+
+		#define update_perm_level(_member, _combo) {			\
+			EwsPermissionLevel level;				\
+										\
+			level = get_permission_level_from_combo (_combo);	\
+			if (di->_member != level) {				\
+				di->_member = level;				\
+			}							\
+		}
+
+		update_perm_level (calendar, lev_calendar);
+		update_perm_level (tasks, lev_tasks);
+		update_perm_level (inbox, lev_inbox);
+		update_perm_level (contacts, lev_contacts);
+		update_perm_level (notes, lev_notes);
+		update_perm_level (journal, lev_journal);
+
+		#undef update_perm_level
+
+		if (!page_contains_user (page, di->user_id->primary_smtp, NULL))
+			add_to_tree_view (page, copy_delegate_info (di), TRUE);
+	}
+
+	gtk_widget_destroy (dialog);
+}
+
+static void
+retrieve_user_permissions_idle_cb (GObject *ppage,
+				   gpointer pdi,
+				   GCancellable *cancellable,
+				   GError **perror)
+{
+	EMailConfigEwsDelegatesPage *page = E_MAIL_CONFIG_EWS_DELEGATES_PAGE (ppage);
+	EwsDelegateInfo *di = pdi;
+
+	g_return_if_fail (page != NULL);
+	g_return_if_fail (di != NULL);
+
+	show_delegate_properties_modal (page, di);
+}
+
+static EwsPermissionLevel
+get_level_from_permissions (const GSList *permissions,
+			    const gchar *primary_smtp)
+{
+	EwsPermissionLevel level = EwsPermissionLevel_None;
+	const GSList *iter;
+
+	g_return_val_if_fail (primary_smtp != NULL, level);
+
+	for (iter = permissions; iter; iter = iter->next) {
+		EEwsPermission *perm = iter->data;
+
+		if (!perm || !perm->primary_smtp)
+			continue;
+
+		if (g_ascii_strcasecmp (primary_smtp, perm->primary_smtp) == 0) {
+			const gchar *level_name = e_ews_permission_rights_to_level_name (perm->rights);
+
+			if (g_strcmp0 (level_name, "None") == 0)
+				level = EwsPermissionLevel_None;
+			else if (g_strcmp0 (level_name, "Reviewer") == 0)
+				level = EwsPermissionLevel_Reviewer;
+			else if (g_strcmp0 (level_name, "Author") == 0)
+				level = EwsPermissionLevel_Author;
+			else if (g_strcmp0 (level_name, "Editor") == 0)
+				level = EwsPermissionLevel_Editor;
+			else
+				level = EwsPermissionLevel_Custom;
+			break;
+		}
+	}
+
+	return level;
+}
+
+static gboolean
+get_folder_permissions_sync (EEwsConnection *conn,
+			     const gchar *distinguished_folder_name,
+			     CamelEwsStoreSummary *ews_summary,
+			     GSList **permissions,
+			     GCancellable *cancellable,
+			     GError **error)
+{
+	gboolean res;
+	EwsFolderId *folder_id;
+	gchar *fid = NULL, *change_key;
+	guint32 folder_type = ~0;
+
+	if (g_strcmp0 (distinguished_folder_name, "calendar") == 0) {
+		folder_type = CAMEL_FOLDER_TYPE_EVENTS;
+	} else if (g_strcmp0 (distinguished_folder_name, "tasks") == 0) {
+		folder_type = CAMEL_FOLDER_TYPE_TASKS;
+	} else if (g_strcmp0 (distinguished_folder_name, "inbox") == 0) {
+		folder_type = CAMEL_FOLDER_TYPE_INBOX;
+	} else if (g_strcmp0 (distinguished_folder_name, "contacts") == 0) {
+		folder_type = CAMEL_FOLDER_TYPE_CONTACTS;
+	} else if (g_strcmp0 (distinguished_folder_name, "notes") == 0) {
+		folder_type = CAMEL_FOLDER_TYPE_MEMOS;
+	} else if (g_strcmp0 (distinguished_folder_name, "journal") == 0) {
+		folder_type = CAMEL_EWS_FOLDER_TYPE_JOURNAL;
+	} else {
+		g_return_val_if_reached (FALSE);
+	}
+
+	fid = camel_ews_store_summary_get_folder_id_from_folder_type (ews_summary, folder_type);
+	if (!fid)
+		return FALSE;
+
+	change_key = camel_ews_store_summary_get_change_key (ews_summary, fid, NULL);
+	folder_id = e_ews_folder_id_new (fid, change_key, FALSE);
+
+	res = e_ews_connection_get_folder_permissions_sync (
+		conn, G_PRIORITY_DEFAULT, folder_id, permissions, cancellable, error);
+
+	e_ews_folder_id_free (folder_id);
+	g_free (change_key);
+	g_free (fid);
+
+	return res;
+}
+
+static void
+retrieve_user_permissions_thread_cb (GObject *ppage,
+				     gpointer pdi,
+				     GCancellable *cancellable,
+				     GError **perror)
+{
+	EMailConfigEwsDelegatesPage *page = E_MAIL_CONFIG_EWS_DELEGATES_PAGE (ppage);
+	EwsDelegateInfo *di = pdi;
+	EShell *shell;
+	EMailBackend *backend;
+	ESource *source;
+	CamelSession *session;
+	CamelService *service;
+	CamelEwsStoreSummary *ews_summary;
+	EEwsConnection *conn;
+	GSList *permissions;
+	GError *local_error = NULL;
+
+	g_return_if_fail (page != NULL);
+	g_return_if_fail (di != NULL);
+
+	shell = e_shell_get_default ();
+	backend = E_MAIL_BACKEND (e_shell_get_backend_by_name (shell, "mail"));
+	g_return_if_fail (backend != NULL);
+
+	session = CAMEL_SESSION (e_mail_backend_get_session (backend));
+	source = e_mail_config_ews_delegates_page_get_account_source (page);
+	service = camel_session_get_service (session, e_source_get_uid (source));
+
+	g_return_if_fail (service != NULL);
+	g_return_if_fail (CAMEL_IS_EWS_STORE (service));
+
+	ews_summary = CAMEL_EWS_STORE (service)->summary;
+
+	if (page->priv->connection)
+		conn = g_object_ref (page->priv->connection);
+	else
+		conn = e_ews_config_utils_open_connection_for (
+			e_mail_config_ews_delegates_page_get_registry (page),
+			e_mail_config_ews_delegates_page_get_collection_source (page),
+			CAMEL_EWS_SETTINGS (mail_config_ews_delegates_page_get_settings (page)),
+			cancellable, perror);
+
+	if (!conn)
+		return;
+
+	permissions = NULL;
+
+	#define get_permissions_for(_member, _folder_name)							\
+		if (!local_error && !g_cancellable_is_cancelled (cancellable) &&				\
+		    get_folder_permissions_sync (conn, _folder_name, ews_summary,				\
+			&permissions, cancellable, &local_error)) {						\
+			di->_member = get_level_from_permissions (permissions, di->user_id->primary_smtp);	\
+														\
+			g_slist_free_full (permissions, (GDestroyNotify) e_ews_permission_free);		\
+			permissions = NULL;									\
+		} else {											\
+			di->_member = EwsPermissionLevel_None;							\
+		}
+
+	get_permissions_for (calendar, "calendar");
+	get_permissions_for (tasks, "tasks");
+	get_permissions_for (inbox, "inbox");
+	get_permissions_for (contacts, "contacts");
+	get_permissions_for (notes, "notes");
+	get_permissions_for (journal, "journal");
+
+	#undef get_permissions_for
+
+	if (local_error)
+		g_propagate_error (perror, local_error);
+
+	if (di->calendar == EwsPermissionLevel_None)
+		di->calendar = EwsPermissionLevel_Editor;
+
+	if (di->tasks == EwsPermissionLevel_None)
+		di->tasks = EwsPermissionLevel_Editor;
+
+	g_object_unref (conn);
+}
+
+enum {
+	COL_NAME,
+	COL_DELEGATE_INFO
+};
+
+static gboolean
+page_contains_user (EMailConfigEwsDelegatesPage *page,
+		    const gchar *primary_smtp,
+		    GtkTreeIter *piter)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean found = FALSE;
+
+	g_return_val_if_fail (page != NULL, FALSE);
+	g_return_val_if_fail (primary_smtp != NULL, FALSE);
+
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW (page->priv->users_tree_view));
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			EwsDelegateInfo *info = NULL;
+
+			gtk_tree_model_get (model, &iter, COL_DELEGATE_INFO, &info, -1);
+
+			found = info &&
+				g_ascii_strcasecmp (info->user_id->primary_smtp, primary_smtp) == 0;
+		} while (!found && gtk_tree_model_iter_next (model, &iter));
+	}
+
+	if (piter)
+		*piter = iter;
+
+	return found;
+}
+
+static void
+add_to_tree_view (EMailConfigEwsDelegatesPage *page,
+		  EwsDelegateInfo *di,
+		  gboolean select)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_if_fail (page != NULL);
+	g_return_if_fail (di != NULL);
+
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW (page->priv->users_tree_view));
+	if (page_contains_user (page, di->user_id->primary_smtp, &iter)) {
+		ews_delegate_info_free (di);
+	} else {
+		const gchar *name;
+
+		name = di->user_id->display_name;
+		if (!name)
+			name = di->user_id->primary_smtp;
+
+		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+			COL_NAME, name,
+			COL_DELEGATE_INFO, di,
+			-1);
+
+		page->priv->new_delegates = g_slist_append (page->priv->new_delegates, di);
+	}
+
+	if (select) {
+		GtkTreeSelection *selection;
+
+		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (page->priv->users_tree_view));
+		gtk_tree_selection_select_iter (selection, &iter);
+	}
+}
+
+static void
+add_button_clicked_cb (EMailConfigEwsDelegatesPage *page)
+{
+	GtkWindow *parent;
+	gchar *display_name = NULL, *email = NULL;
+
+	g_return_if_fail (page != NULL);
+
+	parent = e_ews_config_utils_get_widget_toplevel_window (GTK_WIDGET (page));
+
+	if (e_ews_search_user_modal (parent, page->priv->connection, NULL, &display_name, &email)) {
+		if (email && *email) {
+			EwsDelegateInfo *di;
+
+			di = g_new0 (EwsDelegateInfo, 1);
+			di->user_id = g_new0 (EwsUserId, 1);
+			di->user_id->display_name = display_name;
+			di->user_id->primary_smtp = email;
+			di->meetingcopies = TRUE;
+			di->view_priv_items = FALSE;
+
+			if (page_contains_user (page, email, NULL))
+				add_to_tree_view (page, di, TRUE);
+			else
+				e_ews_config_utils_run_in_thread_with_feedback_modal (parent, G_OBJECT (page),
+					_("Retrieving current user permissions, please wait..."),
+					retrieve_user_permissions_thread_cb,
+					retrieve_user_permissions_idle_cb,
+					di, (GDestroyNotify) ews_delegate_info_free);
+
+			display_name = NULL;
+			email = NULL;
+		}
+	}
+
+	g_free (display_name);
+	g_free (email);
+}
+
+static void
+remove_button_clicked_cb (EMailConfigEwsDelegatesPage *page)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_if_fail (page != NULL);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (page->priv->users_tree_view));
+	if (selection && gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		GtkTreeIter select;
+		gboolean can_select = FALSE;
+		EwsDelegateInfo *di = NULL;
+
+		select = iter;
+		can_select = gtk_tree_model_iter_next (model, &select);
+		if (!can_select) {
+			select = iter;
+			can_select = gtk_tree_model_iter_previous (model, &select);
+		}
+
+		if (can_select)
+			gtk_tree_selection_select_iter (selection, &select);
+
+		gtk_tree_model_get (model, &iter, COL_DELEGATE_INFO, &di, -1);
+		gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+
+		page->priv->new_delegates = g_slist_remove (page->priv->new_delegates, di);
+		ews_delegate_info_free (di);
+
+		enable_delegates_page_widgets (page, page->priv->connection != NULL);
+	}
+}
+
+static void
+properties_button_clicked_cb (EMailConfigEwsDelegatesPage *page)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	g_return_if_fail (page != NULL);
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (page->priv->users_tree_view));
+	if (selection && gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		EwsDelegateInfo *di = NULL;
+
+		gtk_tree_model_get (model, &iter, COL_DELEGATE_INFO, &di, -1);
+
+		if (di) {
+			g_return_if_fail (di->calendar != EwsPermissionLevel_Unknown);
+
+			show_delegate_properties_modal (page, di);
+		}
+	}
+}
+
+static GtkWidget *
+create_users_tree_view (EMailConfigEwsDelegatesPage *page)
+{
+	GtkTreeView *tree_view;
+	GtkTreeSelection *selection;
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+	gint pos;
+
+	g_return_val_if_fail (page != NULL, NULL);
+
+	tree_view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (
+		GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER))));
+	gtk_tree_view_set_headers_visible (tree_view, FALSE);
+
+	renderer = gtk_cell_renderer_text_new ();
+	g_object_set (renderer, "editable", FALSE, NULL);
+	pos = gtk_tree_view_insert_column_with_attributes (tree_view, -1, _("Name"), renderer, "text", COL_NAME, NULL);
+	column = gtk_tree_view_get_column (tree_view, pos - 1);
+	gtk_tree_view_column_set_expand (column, TRUE);
+
+	selection = gtk_tree_view_get_selection (tree_view);
+	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+	g_signal_connect (selection, "changed", G_CALLBACK (delegates_tree_selection_changed_cb), page);
+
+	g_signal_connect_swapped (tree_view, "row-activated", G_CALLBACK (properties_button_clicked_cb), page);
+
+	page->priv->users_tree_view = GTK_WIDGET (tree_view);
+
+	return page->priv->users_tree_view;
+}
+
+static void
+mail_config_ews_delegates_page_constructed (GObject *object)
+{
+	EMailConfigEwsDelegatesPage *page;
+	GtkGrid *grid;
+	GtkWidget *widget, *button, *hvgrid;
+	GSList *radio_group;
+	gchar *markup;
+	gint row = 0;
+
+	page = E_MAIL_CONFIG_EWS_DELEGATES_PAGE (object);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_mail_config_ews_delegates_page_parent_class)->
+		constructed (object);
+
+	gtk_box_set_spacing (GTK_BOX (page), 12);
+
+	markup = g_markup_printf_escaped ("<b>%s</b>", _("Delegates"));
+	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 ();
+	g_object_set (G_OBJECT (widget),
+		"row-homogeneous", FALSE,
+		"row-spacing", 6,
+		"column-homogeneous", FALSE,
+		"column-spacing", 6,
+		"margin-left", 12,
+		"vexpand", FALSE,
+		"valign", GTK_ALIGN_START,
+		NULL);
+	gtk_box_pack_start (GTK_BOX (page), widget, FALSE, FALSE, 0);
+
+	grid = GTK_GRID (widget);
+
+	widget = gtk_label_new (
+		_("Delegates can send items on your behalf, including creating and "
+		  "responding to meeting requests. If you want to grant folder "
+		  "permissions without giving send-on-behalf-of permissions, close this "
+		  "dialog box, right-click the folder, click Permissions and change the options there."));
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (grid, widget, 0, row, 2, 1);
+
+	row++;
+
+	widget = gtk_scrolled_window_new (NULL, NULL);
+	gtk_container_add (GTK_CONTAINER (widget), create_users_tree_view (page));
+	g_object_set (G_OBJECT (widget),
+		"hexpand", TRUE,
+		"vexpand", TRUE,
+		"shadow-type", GTK_SHADOW_IN,
+		NULL);
+
+	gtk_grid_attach (grid, widget, 0, row, 1, 1);
+
+	hvgrid = gtk_grid_new ();
+	gtk_orientable_set_orientation (GTK_ORIENTABLE (hvgrid), GTK_ORIENTATION_VERTICAL);
+	gtk_grid_set_row_spacing (GTK_GRID (hvgrid), 6);
+	gtk_grid_set_column_homogeneous (GTK_GRID (hvgrid), TRUE);
+	g_object_set (G_OBJECT (hvgrid),
+		"hexpand", FALSE,
+		"vexpand", FALSE,
+		"halign", GTK_ALIGN_END,
+		NULL);
+
+	button = gtk_button_new_from_stock (GTK_STOCK_ADD);
+	page->priv->add_button = button;
+	gtk_container_add (GTK_CONTAINER (hvgrid), button);
+
+	button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
+	page->priv->remove_button = button;
+	gtk_container_add (GTK_CONTAINER (hvgrid), button);
+
+	button = gtk_button_new_from_stock (GTK_STOCK_PROPERTIES);
+	page->priv->properties_button = button;
+	gtk_container_add (GTK_CONTAINER (hvgrid), button);
+
+	gtk_grid_attach (grid, hvgrid, 1, row, 1, 1);
+
+	row++;
+
+	widget = gtk_label_new (
+		_("Deliver meeting requests addressed to me and responses to meeting "
+		  "requests where I am the organizer to:"));
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_grid_attach (grid, widget, 0, row, 2, 1);
+
+	row++;
+
+	/* new-line break, because GtkRadioButton doesn't allow wrapping of the inner label */
+	widget = gtk_radio_button_new_with_mnemonic (NULL, _("My delegates only, but _send a copy of meeting requests\nand responses to me (recommended)"));
+	page->priv->deliver_copy_me_radio = widget;
+	radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	gtk_grid_attach (grid, widget, 0, row, 2, 1);
+
+	row++;
+
+	widget = gtk_radio_button_new_with_mnemonic (radio_group, _("My d_elegates only"));
+	page->priv->deliver_delegates_only_radio = widget;
+	radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	gtk_grid_attach (grid, widget, 0, row, 2, 1);
+
+	row++;
+
+	widget = gtk_radio_button_new_with_mnemonic (radio_group, _("My delegates a_nd me"));
+	page->priv->deliver_delegates_and_me_radio = widget;
+	radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	gtk_grid_attach (grid, widget, 0, row, 2, 1);
+
+	g_signal_connect_swapped (page->priv->add_button,
+		"clicked", G_CALLBACK (add_button_clicked_cb), page);
+	g_signal_connect_swapped (page->priv->remove_button,
+		"clicked", G_CALLBACK (remove_button_clicked_cb), page);
+	g_signal_connect_swapped (page->priv->properties_button,
+		"clicked", G_CALLBACK (properties_button_clicked_cb), page);
+
+	enable_delegates_page_widgets (page, FALSE);
+
+	gtk_widget_show_all (GTK_WIDGET (grid));
+
+	e_mail_config_ews_delegates_page_refresh (page);
+}
+
+#define REMOVED_SLIST_KEY	"ews-delegate-removed-slist"
+#define ADDED_SLIST_KEY		"ews-delegate-added-slist"
+#define CANCELLABLE_KEY		"ews-delegate-cancellable"
+
+static void
+mail_config_ews_delegates_page_add_delegate_cb (GObject *source_object,
+						GAsyncResult *result,
+						gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+	e_ews_connection_add_delegate_finish (
+		E_EWS_CONNECTION (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);
+}
+
+static void
+mail_config_ews_delegates_page_remove_delegate_cb (GObject *source_object,
+						   GAsyncResult *result,
+						   gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+	e_ews_connection_remove_delegate_finish (
+		E_EWS_CONNECTION (source_object), result, &error);
+
+	if (error != NULL) {
+		g_simple_async_result_take_error (simple, error);
+		g_simple_async_result_complete (simple);
+	} else {
+		GCancellable *cancellable;
+		GSList *list;
+
+		cancellable = g_object_get_data (G_OBJECT (simple), CANCELLABLE_KEY);
+		list = g_object_get_data (G_OBJECT (simple), ADDED_SLIST_KEY);
+		if (list) {
+			e_ews_connection_add_delegate (
+				E_EWS_CONNECTION (source_object), G_PRIORITY_DEFAULT, NULL, list,
+				cancellable, mail_config_ews_delegates_page_add_delegate_cb, g_object_ref (simple));
+		} else {
+			g_simple_async_result_complete (simple);
+		}
+	}
+
+	g_object_unref (simple);
+}
+
+static void
+mail_config_ews_delegates_page_update_delegate_cb (GObject *source_object,
+						   GAsyncResult *result,
+						   gpointer user_data)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+	e_ews_connection_update_delegate_finish (
+		E_EWS_CONNECTION (source_object), result, &error);
+
+	if (error != NULL) {
+		g_simple_async_result_take_error (simple, error);
+		g_simple_async_result_complete (simple);
+	} else {
+		GCancellable *cancellable;
+		GSList *list;
+
+		cancellable = g_object_get_data (G_OBJECT (simple), CANCELLABLE_KEY);
+		list = g_object_get_data (G_OBJECT (simple), REMOVED_SLIST_KEY);
+		if (list) {
+			e_ews_connection_remove_delegate (
+				E_EWS_CONNECTION (source_object), G_PRIORITY_DEFAULT, NULL, list,
+				cancellable, mail_config_ews_delegates_page_remove_delegate_cb, g_object_ref (simple));
+		} else {
+			list = g_object_get_data (G_OBJECT (simple), ADDED_SLIST_KEY);
+			if (list) {
+				e_ews_connection_add_delegate (
+					E_EWS_CONNECTION (source_object), G_PRIORITY_DEFAULT, NULL, list,
+					cancellable, mail_config_ews_delegates_page_add_delegate_cb, g_object_ref (simple));
+			} else {
+				g_simple_async_result_complete (simple);
+			}
+		}
+	}
+
+	g_object_unref (simple);
+}
+
+static gboolean
+delegate_infos_equal (const EwsDelegateInfo *di1,
+		       const EwsDelegateInfo *di2)
+{
+	if (!di1 || !di2)
+		return di1 == di2;
+
+	return g_strcmp0 (di1->user_id->primary_smtp, di2->user_id->primary_smtp) == 0 &&
+		di1->calendar == di2->calendar &&
+		di1->tasks == di2->tasks &&
+		di1->inbox == di2->inbox &&
+		di1->contacts == di2->contacts &&
+		di1->notes == di2->notes &&
+		di1->journal == di2->journal &&
+		(di1->meetingcopies ? 1 : 0) == (di2->meetingcopies ? 1 : 0) &&
+		(di1->view_priv_items ? 1 : 0) == (di2->view_priv_items ? 1 : 0);
+}
+
+static void
+mail_config_ews_delegates_page_submit (EMailConfigPage *page,
+				       GCancellable *cancellable,
+				       GAsyncReadyCallback callback,
+                                       gpointer user_data)
+{
+	EMailConfigEwsDelegatesPagePrivate *priv;
+	GSimpleAsyncResult *simple;
+	EwsDelegateDeliver deliver_to;
+	GSList *added = NULL, *updated = NULL, *removed = NULL, *iter;
+	GHashTable *oldies;
+	GHashTableIter titer;
+	gpointer key, value;
+
+	priv = E_MAIL_CONFIG_EWS_DELEGATES_PAGE_GET_PRIVATE (page);
+
+	g_mutex_lock (&priv->delegates_lock);
+
+	if (!priv->connection) {
+		g_mutex_unlock (&priv->delegates_lock);
+
+		simple = g_simple_async_result_new (
+			G_OBJECT (page), callback, user_data,
+			mail_config_ews_delegates_page_submit);
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+
+		return;
+	}
+
+	oldies = g_hash_table_new (g_str_hash, g_str_equal);
+	for (iter = priv->orig_delegates; iter; iter = iter->next) {
+		EwsDelegateInfo *di = iter->data;
+
+		if (!di) {
+			g_warn_if_reached ();
+			continue;
+		}
+
+		g_hash_table_insert (oldies, di->user_id->primary_smtp, di);
+	}
+
+	for (iter = priv->new_delegates; iter; iter = iter->next) {
+		EwsDelegateInfo *di = iter->data;
+		EwsDelegateInfo *orig_di;
+
+		if (!di) {
+			g_warn_if_reached ();
+			continue;
+		}
+
+		orig_di = g_hash_table_lookup (oldies, di->user_id->primary_smtp);
+		if (!orig_di) {
+			added = g_slist_prepend (added, di);
+		} else {
+			if (!delegate_infos_equal (orig_di, di))
+				updated = g_slist_prepend (updated, di);
+			g_hash_table_remove (oldies, di->user_id->primary_smtp);
+		}
+	}
+
+	g_hash_table_iter_init (&titer, oldies);
+	while (g_hash_table_iter_next (&titer, &key, &value)) {
+		EwsDelegateInfo *di = value;
+
+		removed = g_slist_prepend (removed, di->user_id);
+	}
+
+	g_hash_table_destroy (oldies);
+
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->deliver_copy_me_radio)))
+		deliver_to = EwsDelegateDeliver_DelegatesAndSendInformationToMe;
+	else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->deliver_delegates_only_radio)))
+		deliver_to = EwsDelegateDeliver_DelegatesOnly;
+	else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->deliver_delegates_and_me_radio)))
+		deliver_to = EwsDelegateDeliver_DelegatesAndMe;
+	else
+		deliver_to = EwsDelegateDeliver_DelegatesAndSendInformationToMe;
+
+	if (deliver_to == priv->deliver_to && !added && !updated && !removed) {
+		/* nothing changed, bye bye */
+		g_mutex_unlock (&priv->delegates_lock);
+
+		simple = g_simple_async_result_new (
+			G_OBJECT (page), callback, user_data,
+			mail_config_ews_delegates_page_submit);
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+
+		return;
+	}
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (page), callback, user_data,
+		mail_config_ews_delegates_page_submit);
+
+	g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+	g_object_set_data_full (G_OBJECT (simple), REMOVED_SLIST_KEY, removed, (GDestroyNotify) g_slist_free);
+	g_object_set_data_full (G_OBJECT (simple), ADDED_SLIST_KEY, added, (GDestroyNotify) g_slist_free);
+	if (cancellable)
+		g_object_set_data_full (G_OBJECT (simple), CANCELLABLE_KEY, g_object_ref (cancellable), g_object_unref);
+
+	if (deliver_to != priv->deliver_to || updated) {
+		e_ews_connection_update_delegate (
+			priv->connection, G_PRIORITY_DEFAULT, NULL, deliver_to, updated,
+			cancellable, mail_config_ews_delegates_page_update_delegate_cb, g_object_ref (simple));
+	} else if (removed) {
+		e_ews_connection_remove_delegate (
+			priv->connection, G_PRIORITY_DEFAULT, NULL, removed,
+			cancellable, mail_config_ews_delegates_page_remove_delegate_cb, g_object_ref (simple));
+	} else {
+		g_warn_if_fail (added != NULL);
+
+		e_ews_connection_add_delegate (
+			priv->connection, G_PRIORITY_DEFAULT, NULL, added,
+			cancellable, mail_config_ews_delegates_page_add_delegate_cb, g_object_ref (simple));
+	}
+
+	g_object_unref (simple);
+
+	g_mutex_unlock (&priv->delegates_lock);
+}
+
+static gboolean
+mail_config_ews_delegates_page_submit_finish (EMailConfigPage *page,
+					      GAsyncResult *result,
+                                              GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (
+		result, G_OBJECT (page),
+		mail_config_ews_delegates_page_submit), FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	/* Assume success unless a GError is set. */
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static gint
+sort_by_display_name_cb (gconstpointer a,
+			 gconstpointer b)
+{
+	const EwsDelegateInfo *dia, *dib;
+	const gchar *aname, *bname;
+
+	if (!a || !b)
+		return GPOINTER_TO_INT (a) - GPOINTER_TO_INT (b);
+
+	dia = a;
+	dib = b;
+
+	aname = dia->user_id->display_name;
+	if (!aname)
+		aname = dia->user_id->primary_smtp;
+
+	bname = dib->user_id->display_name;
+	if (!bname)
+		bname = dib->user_id->primary_smtp;
+
+	if (!aname || !bname)
+		return GPOINTER_TO_INT (aname) - GPOINTER_TO_INT (bname);
+
+	return g_utf8_collate (aname, bname);
+}
+
+static ESourceAuthenticationResult
+mail_config_ews_delegates_page_try_password_sync (ESourceAuthenticator *auth,
+						  const GString *password,
+						  GCancellable *cancellable,
+						  GError **error)
+{
+	EMailConfigEwsDelegatesPage *page;
+	CamelSettings *settings;
+	CamelEwsSettings *ews_settings;
+	ESourceAuthenticationResult result;
+	EwsDelegateDeliver deliver_to;
+	GSList *delegates;
+	const gchar *hosturl;
+	const gchar *mailbox;
+	GError *local_error = NULL;
+
+	page = E_MAIL_CONFIG_EWS_DELEGATES_PAGE (auth);
+	mailbox = mail_config_ews_delegates_page_get_mailbox (page);
+	settings = mail_config_ews_delegates_page_get_settings (page);
+
+	ews_settings = CAMEL_EWS_SETTINGS (settings);
+	hosturl = camel_ews_settings_get_hosturl (ews_settings);
+
+	if (page->priv->connection)
+		g_object_unref (page->priv->connection);
+	page->priv->connection = e_ews_connection_new (hosturl, ews_settings);
+	e_ews_connection_set_password (page->priv->connection, password->str);
+	e_ews_connection_set_mailbox (page->priv->connection, mailbox);
+
+	if (e_ews_connection_get_delegate_sync (page->priv->connection, G_PRIORITY_DEFAULT, NULL, TRUE,
+		&deliver_to, &delegates, cancellable, &local_error) ||
+	    g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND)) {
+		if (local_error) {
+			deliver_to = EwsDelegateDeliver_DelegatesAndSendInformationToMe;
+			delegates = NULL;
+			g_clear_error (&local_error);
+		}
+
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+
+		/* The page takes ownership of the settings. */
+		g_mutex_lock (&page->priv->delegates_lock);
+		g_slist_free_full (page->priv->orig_delegates, (GDestroyNotify) ews_delegate_info_free);
+
+		page->priv->deliver_to = deliver_to;
+		page->priv->orig_delegates = g_slist_sort (delegates, sort_by_display_name_cb);
+		g_mutex_unlock (&page->priv->delegates_lock);
+
+	} else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED)) {
+		result = E_SOURCE_AUTHENTICATION_REJECTED;
+		g_clear_object (&page->priv->connection);
+		g_error_free (local_error);
+
+	} else {
+		result = E_SOURCE_AUTHENTICATION_ERROR;
+		g_clear_object (&page->priv->connection);
+		g_propagate_error (error, local_error);
+	}
+
+	return result;
+}
+
+static void
+e_mail_config_ews_delegates_page_class_init (EMailConfigEwsDelegatesPageClass *class)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (
+		class, sizeof (EMailConfigEwsDelegatesPagePrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_config_ews_delegates_page_set_property;
+	object_class->get_property = mail_config_ews_delegates_page_get_property;
+	object_class->dispose = mail_config_ews_delegates_page_dispose;
+	object_class->finalize = mail_config_ews_delegates_page_finalize;
+	object_class->constructed = mail_config_ews_delegates_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_object_class_install_property (
+		object_class,
+		PROP_COLLECTION_SOURCE,
+		g_param_spec_object (
+			"collection-source",
+			"Collection Source",
+			"Collection source being edited",
+			E_TYPE_SOURCE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+
+	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_object_class_install_property (
+		object_class,
+		PROP_REGISTRY,
+		g_param_spec_object (
+			"registry",
+			"Registry",
+			"Data source registry",
+			E_TYPE_SOURCE_REGISTRY,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_mail_config_ews_delegates_page_interface_init (EMailConfigPageInterface *interface)
+{
+	interface->title = _("Delegates");
+	interface->sort_order = E_MAIL_CONFIG_EWS_DELEGATES_PAGE_SORT_ORDER;
+	interface->submit = mail_config_ews_delegates_page_submit;
+	interface->submit_finish = mail_config_ews_delegates_page_submit_finish;
+}
+
+static void
+e_mail_config_ews_delegates_page_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = mail_config_ews_delegates_page_try_password_sync;
+}
+
+static void
+e_mail_config_ews_delegates_page_class_finalize (EMailConfigEwsDelegatesPageClass *class)
+{
+}
+
+static void
+e_mail_config_ews_delegates_page_init (EMailConfigEwsDelegatesPage *page)
+{
+	page->priv = E_MAIL_CONFIG_EWS_DELEGATES_PAGE_GET_PRIVATE (page);
+
+	g_mutex_init (&page->priv->delegates_lock);
+}
+
+void
+e_mail_config_ews_delegates_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_delegates_page_register_type (type_module);
+}
+
+EMailConfigPage *
+e_mail_config_ews_delegates_page_new (ESourceRegistry *registry,
+				      ESource *account_source,
+                                      ESource *identity_source,
+                                      ESource *collection_source)
+{
+	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (account_source), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+	g_return_val_if_fail (E_IS_SOURCE (collection_source), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE,
+		"registry", registry,
+		"account-source", account_source,
+		"identity-source", identity_source,
+		"collection-source", collection_source,
+		NULL);
+}
+
+void
+e_mail_config_ews_delegates_page_refresh (EMailConfigEwsDelegatesPage *page)
+{
+	ESourceAuthenticator *authenticator;
+	ESourceRegistry *registry;
+	ESource *source;
+	EActivity *activity;
+	GCancellable *cancellable;
+	AsyncContext *async_context;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE (page));
+
+	registry = e_mail_config_ews_delegates_page_get_registry (page);
+	source = e_mail_config_ews_delegates_page_get_collection_source (page);
+	authenticator = E_SOURCE_AUTHENTICATOR (page);
+
+	activity = e_mail_config_activity_page_new_activity (
+		E_MAIL_CONFIG_ACTIVITY_PAGE (page));
+	cancellable = e_activity_get_cancellable (activity);
+
+	e_activity_set_text (
+		activity, _("Retrieving \"Delegates\" settings"));
+
+	async_context = g_slice_new0 (AsyncContext);
+	async_context->page = g_object_ref (page);
+	async_context->activity = activity;  /* takes ownership */
+
+	e_source_registry_authenticate (
+		registry, source, authenticator, cancellable,
+		mail_config_ews_delegates_page_refresh_cb, async_context);
+}
+
+ESourceRegistry *
+e_mail_config_ews_delegates_page_get_registry (EMailConfigEwsDelegatesPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE (page), NULL);
+
+	return page->priv->registry;
+}
+
+ESource *
+e_mail_config_ews_delegates_page_get_account_source (EMailConfigEwsDelegatesPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE (page), NULL);
+
+	return page->priv->account_source;
+}
+
+ESource *
+e_mail_config_ews_delegates_page_get_identity_source (EMailConfigEwsDelegatesPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE (page), NULL);
+
+	return page->priv->identity_source;
+}
+
+ESource *
+e_mail_config_ews_delegates_page_get_collection_source (EMailConfigEwsDelegatesPage *page)
+{
+	g_return_val_if_fail (E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE (page), NULL);
+
+	return page->priv->collection_source;
+}
diff --git a/src/configuration/e-mail-config-ews-delegates-page.h b/src/configuration/e-mail-config-ews-delegates-page.h
new file mode 100644
index 0000000..a0571be
--- /dev/null
+++ b/src/configuration/e-mail-config-ews-delegates-page.h
@@ -0,0 +1,83 @@
+/*
+ * e-mail-config-ews-delegates-page.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_EWS_DELEGATES_PAGE_H
+#define E_MAIL_CONFIG_EWS_DELEGATES_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libedataserver/libedataserver.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-activity-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE \
+	(e_mail_config_ews_delegates_page_get_type ())
+#define E_MAIL_CONFIG_EWS_DELEGATES_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE, EMailConfigEwsDelegatesPage))
+#define E_MAIL_CONFIG_EWS_DELEGATES_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE, EMailConfigEwsDelegatesPageClass))
+#define E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE))
+#define E_IS_MAIL_CONFIG_EWS_DELEGATES_PAGE_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE))
+#define E_MAIL_CONFIG_EWS_DELEGATES_PAGE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_CONFIG_EWS_DELEGATES_PAGE, EMailConfigEwsDelegatesPageClass))
+
+#define E_MAIL_CONFIG_EWS_DELEGATES_PAGE_SORT_ORDER (551)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigEwsDelegatesPage EMailConfigEwsDelegatesPage;
+typedef struct _EMailConfigEwsDelegatesPageClass EMailConfigEwsDelegatesPageClass;
+typedef struct _EMailConfigEwsDelegatesPagePrivate EMailConfigEwsDelegatesPagePrivate;
+
+struct _EMailConfigEwsDelegatesPage {
+	EMailConfigActivityPage parent;
+	EMailConfigEwsDelegatesPagePrivate *priv;
+};
+
+struct _EMailConfigEwsDelegatesPageClass {
+	EMailConfigActivityPageClass parent_class;
+};
+
+GType		e_mail_config_ews_delegates_page_get_type	(void) G_GNUC_CONST;
+void		e_mail_config_ews_delegates_page_type_register	(GTypeModule *type_module);
+EMailConfigPage *
+		e_mail_config_ews_delegates_page_new		(ESourceRegistry *registry,
+								 ESource *account_source,
+								 ESource *identity_source,
+								 ESource *collection_source);
+void		e_mail_config_ews_delegates_page_refresh	(EMailConfigEwsDelegatesPage *page);
+ESourceRegistry *
+		e_mail_config_ews_delegates_page_get_registry	(EMailConfigEwsDelegatesPage *page);
+ESource *	e_mail_config_ews_delegates_page_get_account_source
+								(EMailConfigEwsDelegatesPage *page);
+ESource *	e_mail_config_ews_delegates_page_get_identity_source
+								(EMailConfigEwsDelegatesPage *page);
+ESource *	e_mail_config_ews_delegates_page_get_collection_source
+								(EMailConfigEwsDelegatesPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_EWS_DELEGATES_PAGE_H */
diff --git a/src/configuration/e-mail-config-ews-notebook.c b/src/configuration/e-mail-config-ews-notebook.c
index dd21013..012a0b5 100644
--- a/src/configuration/e-mail-config-ews-notebook.c
+++ b/src/configuration/e-mail-config-ews-notebook.c
@@ -20,6 +20,7 @@
 
 #include <mail/e-mail-config-notebook.h>
 
+#include "e-mail-config-ews-delegates-page.h"
 #include "e-mail-config-ews-ooo-page.h"
 
 G_DEFINE_DYNAMIC_TYPE (
@@ -81,6 +82,13 @@ mail_config_ews_notebook_constructed (GObject *object)
 			identity_source,
 			collection_source);
 		e_mail_config_notebook_add_page (notebook, page);
+
+		page = e_mail_config_ews_delegates_page_new (
+			registry,
+			account_source,
+			identity_source,
+			collection_source);
+		e_mail_config_notebook_add_page (notebook, page);
 	}
 }
 
diff --git a/src/configuration/module-ews-configuration.c b/src/configuration/module-ews-configuration.c
index f71a263..050110e 100644
--- a/src/configuration/module-ews-configuration.c
+++ b/src/configuration/module-ews-configuration.c
@@ -23,6 +23,7 @@
 #include "e-mail-config-ews-gal.h"
 #include "e-mail-config-ews-notebook.h"
 #include "e-mail-config-ews-oal-combo-box.h"
+#include "e-mail-config-ews-delegates-page.h"
 #include "e-mail-config-ews-ooo-page.h"
 
 #include "e-ews-config-ui-extension.h"
@@ -42,6 +43,7 @@ e_module_load (GTypeModule *type_module)
 	e_mail_config_ews_gal_type_register (type_module);
 	e_mail_config_ews_notebook_type_register (type_module);
 	e_mail_config_ews_oal_combo_box_type_register (type_module);
+	e_mail_config_ews_delegates_page_type_register (type_module);
 	e_mail_config_ews_ooo_page_type_register (type_module);
 	e_ews_config_ui_extension_type_register (type_module);
 
diff --git a/src/configuration/module-ews-configuration.error.xml b/src/configuration/module-ews-configuration.error.xml
index 9016291..eaa6802 100644
--- a/src/configuration/module-ews-configuration.error.xml
+++ b/src/configuration/module-ews-configuration.error.xml
@@ -16,4 +16,9 @@
     <_secondary>The reported error was &quot;{0}&quot;.</_secondary>
   </error>
 
+  <error type="warning" id="query-delegates-error">
+    <_primary>Failed to retrieve &quot;Delegates&quot; settings.</_primary>
+    <_secondary>The reported error was &quot;{0}&quot;.</_secondary>
+  </error>
+
 </error-list>
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 6ebaf0e..1ba41dc 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -117,6 +117,7 @@ struct _EwsAsyncData {
 	GSList *items;
 	gchar *sync_state;
 	gboolean includes_last_item;
+	EwsDelegateDeliver deliver_to;
 };
 
 struct _EwsNode {
@@ -1514,10 +1515,9 @@ ews_oal_details_free (EwsOALDetails *details)
 void
 ews_user_id_free (EwsUserId *id)
 {
-	if (id)
-	{
+	if (id) {
 		g_free (id->sid);
-		g_free (id->primary_smtp_add);
+		g_free (id->primary_smtp);
 		g_free (id->display_name);
 		g_free (id->distinguished_user);
 		g_free (id->external_user);
@@ -1525,6 +1525,16 @@ ews_user_id_free (EwsUserId *id)
 	}
 }
 
+void
+ews_delegate_info_free (EwsDelegateInfo *info)
+{
+	if (!info)
+		return;
+
+	ews_user_id_free (info->user_id);
+	g_free (info);
+}
+
 /* Connection APIS */
 
 /**
@@ -4230,7 +4240,7 @@ ews_connection_resolve_by_name (EEwsConnection *cnc,
 
 	for (miter = mailboxes; miter; miter = miter->next) {
 		const EwsMailbox *mailbox = miter->data;
-		if (mailbox->email && *mailbox->email && g_strcmp0 (mailbox->mb_type, "EX") != 0
+		if (mailbox->email && *mailbox->email && g_strcmp0 (mailbox->routing_type, "EX") != 0
 		    && ((!is_user_name && g_str_has_prefix (mailbox->email, usename) && mailbox->email[len] == '@') ||
 		    (is_user_name && g_str_equal (usename, mailbox->name)))) {
 			*smtp_address = g_strdup (mailbox->email);
@@ -4305,7 +4315,7 @@ e_ews_connection_ex_to_smtp_sync (EEwsConnection *cnc,
 	/* only one mailbox matches */
 	if (mailboxes && !mailboxes->next && mailboxes->data) {
 		const EwsMailbox *mailbox = mailboxes->data;
-		if (mailbox->email && *mailbox->email && g_strcmp0 (mailbox->mb_type, "EX") != 0) {
+		if (mailbox->email && *mailbox->email && g_strcmp0 (mailbox->routing_type, "EX") != 0) {
 			*smtp_address = g_strdup (mailbox->email);
 		} else if (contacts && !contacts->next && contacts->data) {
 			const EwsResolveContact *resolved = contacts->data;
@@ -6040,20 +6050,20 @@ e_ews_connection_get_free_busy_sync (EEwsConnection *cnc,
 }
 
 static EwsPermissionLevel
-get_permission_from_string (gchar *permission)
+get_permission_from_string (const gchar *permission)
 {
-	g_return_val_if_fail (permission != NULL, NONE);
+	g_return_val_if_fail (permission != NULL, EwsPermissionLevel_Unknown);
 
 	if (!g_ascii_strcasecmp (permission, "Editor"))
-		return EWS_PERM_EDITOR;
+		return EwsPermissionLevel_Editor;
 	else if (!g_ascii_strcasecmp (permission, "Author"))
-		return EWS_PERM_AUTHOR;
+		return EwsPermissionLevel_Author;
 	else if (!g_ascii_strcasecmp (permission, "Reviewer"))
-		return EWS_PERM_REVIEWER;
+		return EwsPermissionLevel_Reviewer;
 	else if (!g_ascii_strcasecmp (permission, "Custom"))
-		return CUSTOM;
+		return EwsPermissionLevel_Custom;
 	else
-		return NONE;
+		return EwsPermissionLevel_None;
 
 }
 
@@ -6066,11 +6076,15 @@ ews_handle_delegate_user_param (ESoapParameter *param,
 	gchar *value;
 
 	node = e_soap_parameter_get_first_child_by_name (param, "DelegateUser");
-
-	data = g_new (EwsDelegateInfo, 1);
-	data->user_id = g_new0 (EwsUserId, 1);
+	if (!node)
+		return;
 
 	subparam = e_soap_parameter_get_first_child_by_name (node, "UserId");
+	if (!subparam)
+		return;
+
+	data = g_new0 (EwsDelegateInfo, 1);
+	data->user_id = g_new0 (EwsUserId, 1);
 
 	/*Parse User Id*/
 
@@ -6078,50 +6092,71 @@ ews_handle_delegate_user_param (ESoapParameter *param,
 	data->user_id->sid = e_soap_parameter_get_string_value (child);
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "PrimarySmtpAddress");
-	data->user_id->primary_smtp_add = e_soap_parameter_get_string_value (child);
+	data->user_id->primary_smtp = e_soap_parameter_get_string_value (child);
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "DisplayName");
 	data->user_id->display_name = e_soap_parameter_get_string_value (child);
 
 	subparam = e_soap_parameter_get_first_child_by_name (node, "DelegatePermissions");
-	/*Parse Delegate Permissions*/
 
+	/*Parse Delegate Permissions*/
 	child = e_soap_parameter_get_first_child_by_name (subparam, "CalendarFolderPermissionLevel");
-	data->calendar = get_permission_from_string (e_soap_parameter_get_string_value (child));
+	if (child) {
+		value = e_soap_parameter_get_string_value (child);
+		data->calendar = get_permission_from_string (value);
+		g_free (value);
+	}
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "ContactsFolderPermissionLevel");
-	data->contact = get_permission_from_string (e_soap_parameter_get_string_value (child));
+	if (child) {
+		value = e_soap_parameter_get_string_value (child);
+		data->contacts = get_permission_from_string (value);
+		g_free (value);
+	}
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "InboxFolderPermissionLevel");
-	data->inbox = get_permission_from_string (e_soap_parameter_get_string_value (child));
+	if (child) {
+		value = e_soap_parameter_get_string_value (child);
+		data->inbox = get_permission_from_string (value);
+		g_free (value);
+	}
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "TasksFolderPermissionLevel");
-	data->tasks = get_permission_from_string (e_soap_parameter_get_string_value (child));
+	if (child) {
+		value = e_soap_parameter_get_string_value (child);
+		data->tasks = get_permission_from_string (value);
+		g_free (value);
+	}
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "NotesFolderPermissionLevel");
-	data->notes = get_permission_from_string (e_soap_parameter_get_string_value (child));
+	if (child) {
+		value = e_soap_parameter_get_string_value (child);
+		data->notes = get_permission_from_string (value);
+		g_free (value);
+	}
 
 	child = e_soap_parameter_get_first_child_by_name (subparam, "JournalFolderPermissionLevel");
-	data->journal = get_permission_from_string (e_soap_parameter_get_string_value (child));
+	if (child) {
+		value = e_soap_parameter_get_string_value (child);
+		data->journal = get_permission_from_string (value);
+		g_free (value);
+	}
 
 	subparam = e_soap_parameter_get_first_child_by_name (node, "ReceiveCopiesOfMeetingMessages");
-
-	value = e_soap_parameter_get_string_value (subparam);
-	if (!g_ascii_strcasecmp (value, "true"))
-		data->meetingcopies = TRUE;
+	if (subparam) {
+		value = e_soap_parameter_get_string_value (subparam);
+		data->meetingcopies = g_strcmp0 (value, "true") == 0;
+		g_free (value);
+	}
 
 	subparam = e_soap_parameter_get_first_child_by_name (node, "ViewPrivateItems");
-
-	value = e_soap_parameter_get_string_value (subparam);
-	if (!g_ascii_strcasecmp (value, "true"))
-		data->view_priv_items = TRUE;
-	else
-		data->view_priv_items = FALSE;
+	if (subparam) {
+		value = e_soap_parameter_get_string_value (subparam);
+		data->view_priv_items = g_strcmp0 (value, "true") == 0;
+		g_free (value);
+	}
 
 	async_data->items = g_slist_append (async_data->items, data);
-	async_data->items_created = g_slist_append (async_data->items_created, data);
-
-	return;
 }
 
 static void
@@ -6131,12 +6166,45 @@ get_delegate_response_cb (ESoapResponse *response,
 	EwsAsyncData *async_data;
 	ESoapParameter *param;
 	ESoapParameter *subparam;
+	gchar *value;
 	GError *error = NULL;
 
 	async_data = g_simple_async_result_get_op_res_gpointer (simple);
 
+	if (ews_get_response_status (e_soap_response_get_parameter (response), &error))
+		param = e_soap_response_get_first_parameter_by_name (
+			response, "DeliverMeetingRequests", &error);
+	else
+		param = NULL;
+
+	/* Sanity check */
+	g_return_if_fail (
+		(param != NULL && error == NULL) ||
+		(param == NULL && error != NULL));
+
+	if (error != NULL) {
+		g_simple_async_result_take_error (simple, error);
+		return;
+	}
+
+	value = e_soap_parameter_get_string_value (param);
+	if (g_strcmp0 (value, "DelegatesOnly") == 0)
+		async_data->deliver_to = EwsDelegateDeliver_DelegatesOnly;
+	else if (g_strcmp0 (value, "DelegatesAndMe") == 0)
+		async_data->deliver_to = EwsDelegateDeliver_DelegatesAndMe;
+	else if (g_strcmp0 (value, "DelegatesAndSendInformationToMe") == 0)
+		async_data->deliver_to = EwsDelegateDeliver_DelegatesAndSendInformationToMe;
+	else {
+		g_message ("%s: Unknown deliver-to value '%s'", G_STRFUNC, value ? value : "[null]");
+		async_data->deliver_to = EwsDelegateDeliver_DelegatesAndSendInformationToMe;
+	}
+	g_free (value);
+
 	param = e_soap_response_get_first_parameter_by_name (
-		response, "ResponseMessages", &error);
+		response, "ResponseMessages", NULL);
+	/* it's OK to not have set any delegate */
+	if (!param)
+		return;
 
 	/* Sanity check */
 	g_return_if_fail (
@@ -6165,22 +6233,11 @@ get_delegate_response_cb (ESoapResponse *response,
 	}
 }
 
-/**
- * e_ews_connection_get_delegate:
- * @cnc:
- * @pri:
- * @mail_id: mail is for which delegate is requested
- * @include permission: "true", "false"
- * @delete_type: "HardDelete", "SoftDelete", "MoveToDeletedItems"
- * @cancellable:
- * @callback:
- * @user_data:
- **/
 void
 e_ews_connection_get_delegate (EEwsConnection *cnc,
                                gint pri,
                                const gchar *mail_id,
-                               const gchar *include_permissions,
+                               gboolean include_permissions,
                                GCancellable *cancellable,
                                GAsyncReadyCallback callback,
                                gpointer user_data)
@@ -6191,11 +6248,11 @@ e_ews_connection_get_delegate (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "GetDelegate", "IncludePermissions", include_permissions, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, "GetDelegate", "IncludePermissions", include_permissions ? "true" : "false", EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "Mailbox", "messages", NULL);
 
-	e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, mail_id);
+	e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, mail_id ? mail_id : cnc->priv->email);
 
 	e_soap_message_end_element (msg);
 
@@ -6219,13 +6276,16 @@ e_ews_connection_get_delegate (EEwsConnection *cnc,
 gboolean
 e_ews_connection_get_delegate_finish (EEwsConnection *cnc,
                                       GAsyncResult *result,
-                                      EwsDelegateInfo **get_delegate,
+				      EwsDelegateDeliver *deliver_to,
+				      GSList **delegates, /* EwsDelegateInfo * */
                                       GError **error)
 {
 	GSimpleAsyncResult *simple;
 	EwsAsyncData *async_data;
 
 	g_return_val_if_fail (cnc != NULL, FALSE);
+	g_return_val_if_fail (delegates != NULL, FALSE);
+	g_return_val_if_fail (deliver_to != NULL, FALSE);
 	g_return_val_if_fail (
 		g_simple_async_result_is_valid (
 		result, G_OBJECT (cnc), e_ews_connection_get_delegate),
@@ -6236,27 +6296,21 @@ e_ews_connection_get_delegate_finish (EEwsConnection *cnc,
 
 	if (g_simple_async_result_propagate_error (simple, error))
 		return FALSE;
-	*get_delegate = (EwsDelegateInfo *) async_data->items_created->data;
-	g_slist_free (async_data->items_created);
+
+	*deliver_to = async_data->deliver_to;
+	*delegates = async_data->items;
+	async_data->items = NULL;
 
 	return TRUE;
 }
 
-/**
- * e_ews_connection_get_delegate:
- * @cnc:
- * @pri:
- * @mail_id: mail id for which delegate requested
- * @include_permissions: "true", "false"
- * @cancellable:
- * @error:
- **/
 gboolean
 e_ews_connection_get_delegate_sync (EEwsConnection *cnc,
                                     gint pri,
                                     const gchar *mail_id,
-                                    const gchar *include_permissions,
-                                    EwsDelegateInfo **get_delegate,
+                                    gboolean include_permissions,
+				    EwsDelegateDeliver *deliver_to,
+				    GSList **delegates, /* EwsDelegateInfo * */
                                     GCancellable *cancellable,
                                     GError **error)
 {
@@ -6265,6 +6319,8 @@ e_ews_connection_get_delegate_sync (EEwsConnection *cnc,
 	gboolean success;
 
 	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (deliver_to != NULL, FALSE);
+	g_return_val_if_fail (delegates != NULL, FALSE);
 
 	closure = e_async_closure_new ();
 
@@ -6276,7 +6332,417 @@ e_ews_connection_get_delegate_sync (EEwsConnection *cnc,
 	result = e_async_closure_wait (closure);
 
 	success = e_ews_connection_get_delegate_finish (
-		cnc, result, get_delegate, error);
+		cnc, result, deliver_to, delegates, error);
+
+	e_async_closure_free (closure);
+
+	return success;
+}
+
+static void
+update_delegate_response_cb (ESoapResponse *response,
+                             GSimpleAsyncResult *simple)
+{
+	ESoapParameter *param;
+	ESoapParameter *subparam;
+	GError *error = NULL;
+
+	if (ews_get_response_status (e_soap_response_get_parameter (response), &error)) {
+		param = e_soap_response_get_first_parameter_by_name (
+			response, "ResponseMessages", NULL);
+		/* that's OK to not receive any ResponseMessages here */
+		if (!param)
+			return;
+	} else
+		param = NULL;
+
+	/* Sanity check */
+	g_return_if_fail (
+		(param != NULL && error == NULL) ||
+		(param == NULL && error != NULL));
+
+	if (error != NULL) {
+		g_simple_async_result_take_error (simple, error);
+		return;
+	}
+
+	subparam = e_soap_parameter_get_first_child (param);
+
+	while (subparam != NULL) {
+		if (!ews_get_response_status (subparam, &error)) {
+			g_simple_async_result_take_error (simple, error);
+			return;
+		}
+
+		subparam = e_soap_parameter_get_next_child (param);
+	}
+}
+
+static void
+set_delegate_permission (ESoapMessage *msg,
+			 const gchar *elem_name,
+			 EwsPermissionLevel perm_level)
+{
+	const gchar *level_name = NULL;
+
+	if (perm_level == EwsPermissionLevel_None)
+		level_name = "None";
+	else if (perm_level == EwsPermissionLevel_Reviewer)
+		level_name = "Reviewer";
+	else if (perm_level == EwsPermissionLevel_Author)
+		level_name = "Author";
+	else if (perm_level == EwsPermissionLevel_Editor)
+		level_name = "Editor";
+
+	if (!level_name)
+		return;
+
+	e_ews_message_write_string_parameter (msg, elem_name, NULL, level_name);
+}
+
+void
+e_ews_connection_add_delegate (EEwsConnection *cnc,
+			       gint pri,
+			       const gchar *mail_id,
+			       const GSList *delegates, /* EwsDelegateInfo * */
+			       GCancellable *cancellable,
+			       GAsyncReadyCallback callback,
+			       gpointer user_data)
+{
+	ESoapMessage *msg;
+	GSimpleAsyncResult *simple;
+	EwsAsyncData *async_data;
+	const GSList *iter;
+
+	g_return_if_fail (cnc != NULL);
+	g_return_if_fail (delegates != NULL);
+
+	msg = e_ews_message_new_with_header (cnc->priv->uri, "AddDelegate", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+
+	e_soap_message_start_element (msg, "Mailbox", "messages", NULL);
+	e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, mail_id ? mail_id : cnc->priv->email);
+	e_soap_message_end_element (msg);
+
+	e_soap_message_start_element (msg, "DelegateUsers", "messages", NULL);
+	for (iter = delegates; iter; iter = iter->next) {
+		const EwsDelegateInfo *di = iter->data;
+
+		if (!di)
+			continue;
+
+		e_soap_message_start_element (msg, "DelegateUser", NULL, NULL);
+
+		e_soap_message_start_element (msg, "UserId", NULL, NULL);
+		e_ews_message_write_string_parameter (msg, "PrimarySmtpAddress", NULL, di->user_id->primary_smtp);
+		e_soap_message_end_element (msg); /* UserId */
+
+		e_soap_message_start_element (msg, "DelegatePermissions", NULL, NULL);
+		set_delegate_permission (msg, "CalendarFolderPermissionLevel", di->calendar);
+		set_delegate_permission (msg, "TasksFolderPermissionLevel", di->tasks);
+		set_delegate_permission (msg, "InboxFolderPermissionLevel", di->inbox);
+		set_delegate_permission (msg, "ContactsFolderPermissionLevel", di->contacts);
+		set_delegate_permission (msg, "NotesFolderPermissionLevel", di->notes);
+		set_delegate_permission (msg, "JournalFolderPermissionLevel", di->journal);
+		e_soap_message_end_element (msg); /* DelegatePermissions */
+
+		e_ews_message_write_string_parameter (msg, "ReceiveCopiesOfMeetingMessages", NULL,
+			di->meetingcopies ? "true" : "false");
+		e_ews_message_write_string_parameter (msg, "ViewPrivateItems", NULL,
+			di->view_priv_items ? "true" : "false");
+
+		e_soap_message_end_element (msg); /* DelegateUser */
+	}
+
+	e_soap_message_end_element (msg); /* DelegateUsers */
+
+	e_ews_message_write_footer (msg);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (cnc), callback, user_data,
+		e_ews_connection_add_delegate);
+
+	async_data = g_new0 (EwsAsyncData, 1);
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_data, (GDestroyNotify) async_data_free);
+
+	e_ews_connection_queue_request (
+		cnc, msg, update_delegate_response_cb,
+		pri, cancellable, simple);
+
+	g_object_unref (simple);
+}
+
+gboolean
+e_ews_connection_add_delegate_finish (EEwsConnection *cnc,
+				      GAsyncResult *result,
+				      GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	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_add_delegate),
+		FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
+gboolean
+e_ews_connection_add_delegate_sync (EEwsConnection *cnc,
+				    gint pri,
+				    const gchar *mail_id,
+				    const GSList *delegates, /* EwsDelegateInfo * */
+				    GCancellable *cancellable,
+                                    GError **error)
+{
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	gboolean success;
+
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (delegates != NULL, FALSE);
+
+	closure = e_async_closure_new ();
+
+	e_ews_connection_add_delegate (
+		cnc, pri, mail_id, delegates, cancellable,
+		e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_connection_add_delegate_finish (cnc, result, error);
+
+	e_async_closure_free (closure);
+
+	return success;
+}
+
+void
+e_ews_connection_remove_delegate (EEwsConnection *cnc,
+				  gint pri,
+				  const gchar *mail_id,
+				  const GSList *delegate_ids, /* EwsUserId * */
+				  GCancellable *cancellable,
+				  GAsyncReadyCallback callback,
+				  gpointer user_data)
+{
+	ESoapMessage *msg;
+	GSimpleAsyncResult *simple;
+	EwsAsyncData *async_data;
+	const GSList *iter;
+
+	g_return_if_fail (cnc != NULL);
+	g_return_if_fail (delegate_ids != NULL);
+
+	msg = e_ews_message_new_with_header (cnc->priv->uri, "RemoveDelegate", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+
+	e_soap_message_start_element (msg, "Mailbox", "messages", NULL);
+	e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, mail_id ? mail_id : cnc->priv->email);
+	e_soap_message_end_element (msg);
+
+	e_soap_message_start_element (msg, "UserIds", "messages", NULL);
+	for (iter = delegate_ids; iter; iter = iter->next) {
+		const EwsUserId *user_id = iter->data;
+
+		if (!user_id)
+			continue;
+
+		e_soap_message_start_element (msg, "UserId", NULL, NULL);
+		e_ews_message_write_string_parameter (msg, "PrimarySmtpAddress", NULL, user_id->primary_smtp);
+		e_soap_message_end_element (msg); /* UserId */
+	}
+
+	e_soap_message_end_element (msg); /* UserIds */
+
+	e_ews_message_write_footer (msg);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (cnc), callback, user_data,
+		e_ews_connection_remove_delegate);
+
+	async_data = g_new0 (EwsAsyncData, 1);
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_data, (GDestroyNotify) async_data_free);
+
+	e_ews_connection_queue_request (
+		cnc, msg, update_delegate_response_cb,
+		pri, cancellable, simple);
+
+	g_object_unref (simple);
+}
+
+gboolean
+e_ews_connection_remove_delegate_finish (EEwsConnection *cnc,
+					 GAsyncResult *result,
+					 GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	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_remove_delegate),
+		FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
+gboolean
+e_ews_connection_remove_delegate_sync (EEwsConnection *cnc,
+				       gint pri,
+                                       const gchar *mail_id,
+				       const GSList *delegate_ids, /* EwsUserId * */
+                                       GCancellable *cancellable,
+                                       GError **error)
+{
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	gboolean success;
+
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+	g_return_val_if_fail (delegate_ids != NULL, FALSE);
+
+	closure = e_async_closure_new ();
+
+	e_ews_connection_remove_delegate (
+		cnc, pri, mail_id, delegate_ids, cancellable,
+		e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_connection_remove_delegate_finish (cnc, result, error);
+
+	e_async_closure_free (closure);
+
+	return success;
+}
+
+void
+e_ews_connection_update_delegate (EEwsConnection *cnc,
+				  gint pri,
+				  const gchar *mail_id,
+				  EwsDelegateDeliver deliver_to,
+				  const GSList *delegates, /* EwsDelegateInfo * */
+				  GCancellable *cancellable,
+				  GAsyncReadyCallback callback,
+				  gpointer user_data)
+{
+	ESoapMessage *msg;
+	GSimpleAsyncResult *simple;
+	EwsAsyncData *async_data;
+	const GSList *iter;
+
+	g_return_if_fail (cnc != NULL);
+
+	msg = e_ews_message_new_with_header (cnc->priv->uri, "UpdateDelegate", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+
+	e_soap_message_start_element (msg, "Mailbox", "messages", NULL);
+	e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, mail_id ? mail_id : cnc->priv->email);
+	e_soap_message_end_element (msg);
+
+	if (delegates) {
+		e_soap_message_start_element (msg, "DelegateUsers", "messages", NULL);
+		for (iter = delegates; iter; iter = iter->next) {
+			const EwsDelegateInfo *di = iter->data;
+
+			if (!di)
+				continue;
+
+			e_soap_message_start_element (msg, "DelegateUser", NULL, NULL);
+
+			e_soap_message_start_element (msg, "UserId", NULL, NULL);
+			e_ews_message_write_string_parameter (msg, "PrimarySmtpAddress", NULL, di->user_id->primary_smtp);
+			e_soap_message_end_element (msg); /* UserId */
+
+			e_soap_message_start_element (msg, "DelegatePermissions", NULL, NULL);
+			set_delegate_permission (msg, "CalendarFolderPermissionLevel", di->calendar);
+			set_delegate_permission (msg, "TasksFolderPermissionLevel", di->tasks);
+			set_delegate_permission (msg, "InboxFolderPermissionLevel", di->inbox);
+			set_delegate_permission (msg, "ContactsFolderPermissionLevel", di->contacts);
+			set_delegate_permission (msg, "NotesFolderPermissionLevel", di->notes);
+			set_delegate_permission (msg, "JournalFolderPermissionLevel", di->journal);
+			e_soap_message_end_element (msg); /* DelegatePermissions */
+
+			e_ews_message_write_string_parameter (msg, "ReceiveCopiesOfMeetingMessages", NULL,
+				di->meetingcopies ? "true" : "false");
+			e_ews_message_write_string_parameter (msg, "ViewPrivateItems", NULL,
+				di->view_priv_items ? "true" : "false");
+
+			e_soap_message_end_element (msg); /* DelegateUser */
+		}
+
+		e_soap_message_end_element (msg); /* DelegateUsers */
+	}
+
+	e_ews_message_write_string_parameter (msg, "DeliverMeetingRequests", "messages",
+		deliver_to == EwsDelegateDeliver_DelegatesOnly ? "DelegatesOnly" :
+		deliver_to == EwsDelegateDeliver_DelegatesAndMe ? "DelegatesAndMe" :
+		"DelegatesAndSendInformationToMe");
+
+	e_ews_message_write_footer (msg);
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (cnc), callback, user_data,
+		e_ews_connection_update_delegate);
+
+	async_data = g_new0 (EwsAsyncData, 1);
+	g_simple_async_result_set_op_res_gpointer (
+		simple, async_data, (GDestroyNotify) async_data_free);
+
+	e_ews_connection_queue_request (
+		cnc, msg, update_delegate_response_cb,
+		pri, cancellable, simple);
+
+	g_object_unref (simple);
+}
+
+gboolean
+e_ews_connection_update_delegate_finish (EEwsConnection *cnc,
+					 GAsyncResult *result,
+					 GError **error)
+{
+	GSimpleAsyncResult *simple;
+
+	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_update_delegate),
+		FALSE);
+
+	simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	return !g_simple_async_result_propagate_error (simple, error);
+}
+
+gboolean
+e_ews_connection_update_delegate_sync (EEwsConnection *cnc,
+				       gint pri,
+                                       const gchar *mail_id,
+				       EwsDelegateDeliver deliver_to,
+				       const GSList *delegates, /* EwsDelegateInfo * */
+                                       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_update_delegate (
+		cnc, pri, mail_id, deliver_to, delegates, cancellable,
+		e_async_closure_callback, closure);
+
+	result = e_async_closure_wait (closure);
+
+	success = e_ews_connection_update_delegate_finish (cnc, result, error);
 
 	e_async_closure_free (closure);
 
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index cec2f09..5660747 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -119,28 +119,35 @@ typedef struct {
 	gchar *filename;
 } EwsOALDetails;
 
-typedef struct{
+typedef struct {
 	gchar *sid;
-	gchar *primary_smtp_add;
+	gchar *primary_smtp;
 	gchar *display_name;
 	gchar *distinguished_user;
 	gchar *external_user;
-}EwsUserId;
+} EwsUserId;
 
-typedef enum{
-	NONE,
-	EWS_PERM_EDITOR,
-	EWS_PERM_REVIEWER,
-	EWS_PERM_AUTHOR,
-	CUSTOM
-}EwsPermissionLevel;
+typedef enum {
+	EwsPermissionLevel_Unknown = 0,
+	EwsPermissionLevel_None,
+	EwsPermissionLevel_Reviewer,
+	EwsPermissionLevel_Author,
+	EwsPermissionLevel_Editor,
+	EwsPermissionLevel_Custom
+} EwsPermissionLevel;
 
-typedef struct{
+typedef struct {
 	EwsUserId *user_id;
-	EwsPermissionLevel calendar, contact, inbox, tasks, notes, journal;
+	EwsPermissionLevel calendar, tasks, inbox, contacts, notes, journal;
 	gboolean meetingcopies;
 	gboolean view_priv_items;
-}EwsDelegateInfo;
+} EwsDelegateInfo;
+
+typedef enum {
+	EwsDelegateDeliver_DelegatesOnly,
+	EwsDelegateDeliver_DelegatesAndMe,
+	EwsDelegateDeliver_DelegatesAndSendInformationToMe
+} EwsDelegateDeliver;
 
 typedef enum {
 	NORMAL_FIELD_URI,
@@ -218,6 +225,7 @@ void		e_ews_connection_set_mailbox	(EEwsConnection *cnc,
 						 const gchar *email);
 
 void		ews_user_id_free		(EwsUserId *id);
+void		ews_delegate_info_free		(EwsDelegateInfo *info);
 
 void		e_ews_connection_sync_folder_items
 						(EEwsConnection *cnc,
@@ -781,21 +789,81 @@ gboolean	e_ews_connection_download_oal_file_finish
 void		e_ews_connection_get_delegate	(EEwsConnection *cnc,
 						 gint pri,
 						 const gchar *mail_id,
-						 const gchar *include_permissions,
+						 gboolean include_permissions,
 						 GCancellable *cancellable,
 						 GAsyncReadyCallback callback,
 						 gpointer user_data);
 gboolean	e_ews_connection_get_delegate_finish
 						(EEwsConnection *cnc,
 						 GAsyncResult *result,
-						 EwsDelegateInfo **get_delegate,
+						 EwsDelegateDeliver *deliver_to,
+						 GSList **delegates, /* EwsDelegateInfo * */
 						 GError **error);
 gboolean	e_ews_connection_get_delegate_sync
 						(EEwsConnection *cnc,
 						 gint pri,
 						 const gchar *mail_id,
-						 const gchar *include_permissions,
-						 EwsDelegateInfo **get_delegate,
+						 gboolean include_permissions,
+						 EwsDelegateDeliver *deliver_to,
+						 GSList **delegates, /* EwsDelegateInfo * */
+						 GCancellable *cancellable,
+						 GError **error);
+void		e_ews_connection_add_delegate	(EEwsConnection *cnc,
+						 gint pri,
+						 const gchar *mail_id,
+						 const GSList *delegates, /* EwsDelegateInfo * */
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_ews_connection_add_delegate_finish
+						(EEwsConnection *cnc,
+						 GAsyncResult *result,
+						 GError **error);
+gboolean	e_ews_connection_add_delegate_sync
+						(EEwsConnection *cnc,
+						 gint pri,
+						 const gchar *mail_id,
+						 const GSList *delegates, /* EwsDelegateInfo * */
+						 GCancellable *cancellable,
+						 GError **error);
+void		e_ews_connection_remove_delegate
+						(EEwsConnection *cnc,
+						 gint pri,
+						 const gchar *mail_id,
+						 const GSList *delegate_ids, /* EwsUserId * */
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_ews_connection_remove_delegate_finish
+						(EEwsConnection *cnc,
+						 GAsyncResult *result,
+						 GError **error);
+gboolean	e_ews_connection_remove_delegate_sync
+						(EEwsConnection *cnc,
+						 gint pri,
+						 const gchar *mail_id,
+						 const GSList *delegate_ids, /* EwsUserId * */
+						 GCancellable *cancellable,
+						 GError **error);
+void		e_ews_connection_update_delegate
+						(EEwsConnection *cnc,
+						 gint pri,
+						 const gchar *mail_id,
+						 EwsDelegateDeliver deliver_to,
+						 const GSList *delegates, /* EwsDelegateInfo * */
+						 GCancellable *cancellable,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_ews_connection_update_delegate_finish
+						(EEwsConnection *cnc,
+						 GAsyncResult *result,
+						 GError **error);
+gboolean	e_ews_connection_update_delegate_sync
+						(EEwsConnection *cnc,
+						 gint pri,
+						 const gchar *mail_id,
+						 EwsDelegateDeliver deliver_to,
+						 const GSList *delegates, /* EwsDelegateInfo * */
 						 GCancellable *cancellable,
 						 GError **error);
 void		e_ews_connection_get_folder_permissions
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index 2266396..9a2a91b 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -1393,7 +1393,11 @@ e_ews_item_mailbox_from_soap_param (ESoapParameter *param)
 
 	subparam = e_soap_parameter_get_first_child_by_name (param, "RoutingType");
 	if (subparam)
-		mb->mb_type = e_soap_parameter_get_string_value (subparam);
+		mb->routing_type = e_soap_parameter_get_string_value (subparam);
+
+	subparam = e_soap_parameter_get_first_child_by_name (param, "MailboxType");
+	if (subparam)
+		mb->mailbox_type = e_soap_parameter_get_string_value (subparam);
 
 	if (!mb->email && !mb->name) {
 		e_ews_mailbox_free (mb);
@@ -1411,7 +1415,8 @@ e_ews_mailbox_free (EwsMailbox *mailbox)
 
 	g_free (mailbox->name);
 	g_free (mailbox->email);
-	g_free (mailbox->mb_type);
+	g_free (mailbox->routing_type);
+	g_free (mailbox->mailbox_type);
 
 	if (mailbox->item_id) {
 		g_free (mailbox->item_id->id);
diff --git a/src/server/e-ews-item.h b/src/server/e-ews-item.h
index cd2bfab..448c746 100644
--- a/src/server/e-ews-item.h
+++ b/src/server/e-ews-item.h
@@ -76,7 +76,8 @@ typedef struct {
 typedef struct {
 	gchar *name;
 	gchar *email;
-	gchar *mb_type;
+	gchar *routing_type;
+	gchar *mailbox_type;
 	EwsId *item_id;
 } EwsMailbox;
 
diff --git a/src/server/e-soap-response.c b/src/server/e-soap-response.c
index 07e05c4..114b759 100644
--- a/src/server/e-soap-response.c
+++ b/src/server/e-soap-response.c
@@ -487,6 +487,14 @@ e_soap_response_get_parameters (ESoapResponse *response)
 	return (const GList *) response->priv->parameters;
 }
 
+ESoapParameter *
+e_soap_response_get_parameter (ESoapResponse *response)
+{
+	g_return_val_if_fail (E_IS_SOAP_RESPONSE (response), NULL);
+
+	return response->priv->xml_method;
+}
+
 /**
  * e_soap_response_get_first_parameter:
  * @response: the #ESoapResponse object.
diff --git a/src/server/e-soap-response.h b/src/server/e-soap-response.h
index a570eef..a9ddc0d 100644
--- a/src/server/e-soap-response.h
+++ b/src/server/e-soap-response.h
@@ -79,6 +79,8 @@ gchar *		e_soap_parameter_get_property	(ESoapParameter *param,
 
 const GList *	e_soap_response_get_parameters	(ESoapResponse *response);
 ESoapParameter *
+		e_soap_response_get_parameter	(ESoapResponse *response);
+ESoapParameter *
 		e_soap_response_get_first_parameter
 						(ESoapResponse *response);
 ESoapParameter *
diff --git a/src/server/tests/test-getdelegate.c b/src/server/tests/test-getdelegate.c
index cab3e31..0eae7bf 100644
--- a/src/server/tests/test-getdelegate.c
+++ b/src/server/tests/test-getdelegate.c
@@ -46,25 +46,25 @@ get_delegate_cb (GObject *object,
 {
 	EEwsConnection *cnc = E_EWS_CONNECTION (object);
 	GError *error = NULL;
-	EwsDelegateInfo *get_delegate;
+	GSList *delegates = NULL;
+	EwsDelegateDeliver deliver_to;
 
-	e_ews_connection_get_delegate_finish	(cnc, res, &get_delegate,
-						 &error);
+	e_ews_connection_get_delegate_finish (cnc, res, &deliver_to, &delegates, &error);
 
 	if (error != NULL) {
 		g_warning ("Unable to get delegate: %s \n", error->message);
 		g_clear_error (&error);
 		goto quit;
 	}
-	if (get_delegate !=NULL && get_delegate->user_id != NULL)
-		g_print ("Delegate is %s", get_delegate->user_id->display_name);
-
-quit:
-	if (get_delegate)
-	{
-		ews_user_id_free (get_delegate->user_id);
-		g_free (get_delegate);
+
+	if (delegates != NULL && delegates->data) {
+		EwsDelegateInfo *info = delegates->data;
+		if (info->user_id != NULL)
+			g_print ("Delegate is %s\n", get_delegate->user_id->display_name);
 	}
+
+ quit:
+	g_slist_free_full (delegates, (GDestroyNotify) ews_delegate_info_free);
 	g_main_loop_quit (main_loop);
 }
 
@@ -96,7 +96,7 @@ op_test_get_delegate ()
 
 	e_ews_connection_get_delegate (
 		cnc, EWS_PRIORITY_MEDIUM, "abc xyz com",
-		"true", cancellable,
+		TRUE, cancellable,
 		get_delegate_cb, NULL);
 
 }



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