[evolution-ews] Bug #685795 - Be able to open mailbox of other user



commit 6775f24d51250a75b2079587e09a53ddd0ce1e05
Author: Milan Crha <mcrha redhat com>
Date:   Wed Nov 14 16:29:21 2012 +0100

    Bug #685795 - Be able to open mailbox of other user

 src/addressbook/e-book-backend-ews.c          |   34 +++++++
 src/calendar/e-cal-backend-ews.c              |   45 +++++++++
 src/camel/camel-ews-folder.c                  |   62 +++++++++++--
 src/camel/camel-ews-store.c                   |  101 ++++++++++++++++----
 src/collection/e-ews-backend.c                |   70 ++++++++++++--
 src/configuration/e-mail-config-ews-backend.c |   73 ++++++++++++++
 src/server/camel-ews-settings.c               |  126 ++++++++++++++++++++++++-
 src/server/camel-ews-settings.h               |   13 +++
 src/server/e-ews-connection.c                 |  100 +++++++++++---------
 src/server/e-ews-connection.h                 |    5 +-
 src/server/e-ews-message.c                    |   19 ++++
 src/server/e-ews-message.h                    |    1 +
 src/server/e-ews-oof-settings.c               |   10 +-
 13 files changed, 568 insertions(+), 91 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index ff27bd0..0cc4d59 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -2287,6 +2287,30 @@ cleanup:
 	return TRUE;
 }
 
+static void
+ebews_forget_all_contacts (EBookBackendEws *ebews)
+{
+	EBookBackend *backend;
+	GSList *ids = NULL;
+
+	g_return_if_fail (E_IS_BOOK_BACKEND_EWS (ebews));
+
+	backend = E_BOOK_BACKEND (ebews);
+	g_return_if_fail (backend != NULL);
+
+	ids = e_book_backend_sqlitedb_search_uids (ebews->priv->summary, ebews->priv->folder_id, NULL, NULL, NULL);
+	if (ids) {
+		GSList *id;
+
+		e_book_backend_sqlitedb_remove_contacts (ebews->priv->summary, ebews->priv->folder_id, ids, NULL);
+		for (id = ids; id; id = id->next) {
+			e_book_backend_notify_remove (backend, id->data);
+		}
+
+		g_slist_free_full (ids, g_free);
+	}
+}
+
 static gboolean
 ebews_start_sync (gpointer data)
 {
@@ -2329,6 +2353,16 @@ ebews_start_sync (gpointer data)
 
 		g_free (old_sync_state);
 
+		if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+			g_clear_error (&error);
+			e_book_backend_sqlitedb_set_sync_data (priv->summary, priv->folder_id, NULL, &error);
+			ebews_forget_all_contacts (ebews);
+
+			e_ews_connection_sync_folder_items_sync (priv->cnc, EWS_PRIORITY_MEDIUM, NULL, priv->folder_id, "IdOnly", NULL, EWS_MAX_FETCH_COUNT,
+				&sync_state, &includes_last_item, &items_created, &items_updated, &items_deleted,
+				priv->cancellable, &error);
+		}
+
 		if (error)
 			break;
 
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 5c61f66..a475fbb 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -3419,6 +3419,31 @@ cal_backend_ews_process_folder_items (ECalBackendEws *cbews,
 	g_slist_free (task_item_ids);
 }
 
+static void
+cbews_forget_all_components (ECalBackendEws *cbews)
+{
+	ECalBackend *backend;
+	GSList *ids, *ii;
+
+	g_return_if_fail (E_IS_CAL_BACKEND_EWS (cbews));
+
+	backend = E_CAL_BACKEND (cbews);
+	g_return_if_fail (backend != NULL);
+
+	ids = e_cal_backend_store_get_component_ids (cbews->priv->store);
+	for (ii = ids; ii; ii = ii->next) {
+		ECalComponentId *id = ii->data;
+
+		if (!id)
+			continue;
+
+		e_cal_backend_store_remove_component (cbews->priv->store, id->uid, id->rid);
+		e_cal_backend_notify_component_removed (backend, id, NULL, NULL);
+	}
+
+	g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+}
+
 static gpointer
 ews_start_sync_thread (gpointer data)
 {
@@ -3454,6 +3479,16 @@ ews_start_sync_thread (gpointer data)
 			priv->cancellable,
 			&error);
 
+		if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+			g_clear_error (&error);
+			e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, NULL);
+			cbews_forget_all_components (cbews);
+
+			e_ews_connection_sync_folder_items_sync (priv->cnc, EWS_PRIORITY_MEDIUM, NULL, priv->folder_id, "IdOnly", NULL, EWS_MAX_FETCH_COUNT,
+				&new_sync_state, &includes_last_item, &items_created, &items_updated, &items_deleted,
+				priv->cancellable, &error);
+		}
+
 		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
 		    g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_CANCELLED)) {
 			break;
@@ -4009,6 +4044,16 @@ cal_backend_ews_try_password_sync (ESourceAuthenticator *authenticator,
 		&items_deleted,
 		cancellable, &local_error);
 
+	if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+		g_clear_error (&local_error);
+		e_cal_backend_store_put_key_value (store, SYNC_KEY, NULL);
+		cbews_forget_all_components (backend);
+
+		e_ews_connection_sync_folder_items_sync (connection, EWS_PRIORITY_MEDIUM, NULL, backend->priv->folder_id, "IdOnly", NULL, 1,
+			&new_sync_state, &includes_last_item, &items_created, &items_updated, &items_deleted,
+			cancellable, &local_error);
+	}
+
 	if (local_error == NULL) {
 		PRIV_LOCK (backend->priv);
 		if (backend->priv->user_email)
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index 90f342b..e73621e 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -1371,6 +1371,45 @@ exit:
 	}
 }
 
+static void
+ews_folder_forget_all_mails (CamelEwsFolder *ews_folder)
+{
+	CamelFolder *folder;
+	CamelFolderChangeInfo *changes;
+	GPtrArray *known_uids;
+	gint ii;
+
+	g_return_if_fail (CAMEL_IS_EWS_FOLDER (ews_folder));
+
+	folder = CAMEL_FOLDER (ews_folder);
+	g_return_if_fail (folder != NULL);
+
+	known_uids = camel_folder_summary_get_array (folder->summary);
+	if (!known_uids)
+		return;
+
+	changes = camel_folder_change_info_new ();
+
+	camel_folder_summary_lock (folder->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	for (ii = 0; ii < known_uids->len; ii++) {
+		const gchar *uid = g_ptr_array_index (known_uids, ii);
+
+		camel_folder_change_info_remove_uid (changes, uid);
+		camel_folder_summary_remove_uid (folder->summary, uid);
+		ews_data_cache_remove (ews_folder->cache, "cur", uid, NULL);
+	}
+	camel_folder_summary_unlock (folder->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	if (camel_folder_change_info_changed (changes)) {
+		camel_folder_summary_touch (folder->summary);
+		camel_folder_summary_save_to_db (folder->summary, NULL);
+		camel_folder_changed (folder, changes);
+	}
+
+	camel_folder_change_info_free (changes);
+	camel_folder_summary_free_array (known_uids);
+}
+
 static gboolean
 ews_refresh_info_sync (CamelFolder *folder,
                        GCancellable *cancellable,
@@ -1425,14 +1464,21 @@ ews_refresh_info_sync (CamelFolder *folder,
 		GSList *items_deleted = NULL;
 		guint32 total, unread;
 
-		e_ews_connection_sync_folder_items_sync (
-			cnc, EWS_PRIORITY_MEDIUM,
-			sync_state, id,
-			"IdOnly", NULL,
-			EWS_MAX_FETCH_COUNT,
-			&sync_state, &includes_last_item,
-			&items_created, &items_updated,
-			&items_deleted, cancellable, &local_error);
+		e_ews_connection_sync_folder_items_sync (cnc, EWS_PRIORITY_MEDIUM, sync_state, id, "IdOnly", NULL, EWS_MAX_FETCH_COUNT,
+			&sync_state, &includes_last_item, &items_created, &items_updated, &items_deleted,
+			cancellable, &local_error);
+
+		if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+			g_clear_error (&local_error);
+			g_free (((CamelEwsSummary *) folder->summary)->sync_state);
+			((CamelEwsSummary *) folder->summary)->sync_state = NULL;
+			sync_state = NULL;
+			ews_folder_forget_all_mails (ews_folder);
+
+			e_ews_connection_sync_folder_items_sync (cnc, EWS_PRIORITY_MEDIUM, NULL, id, "IdOnly", NULL, EWS_MAX_FETCH_COUNT,
+				&sync_state, &includes_last_item, &items_created, &items_updated, &items_deleted,
+				cancellable, &local_error);
+		}
 
 		if (local_error) {
 			camel_ews_store_maybe_disconnect (ews_store, local_error);
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index e88f398..3301689 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -493,6 +493,39 @@ ews_store_set_flags (CamelEwsStore *ews_store,
 	}
 }
 
+static void
+ews_store_forget_all_folders (CamelEwsStore *ews_store)
+{
+	CamelStore *store;
+	CamelSubscribable *subscribable;
+	GSList *folders, *l;
+
+	g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
+
+	store = CAMEL_STORE (ews_store);
+	subscribable = CAMEL_SUBSCRIBABLE (ews_store);
+	folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL);
+
+	if (!folders)
+		return;
+
+	for (l = folders; l != NULL; l = g_slist_next (l)) {
+		CamelFolderInfo *fi;
+		EEwsFolderType ftype;
+
+		ftype = camel_ews_store_summary_get_folder_type (ews_store->summary, l->data, NULL);
+		if (ftype != E_EWS_FOLDER_TYPE_MAILBOX)
+			continue;
+
+		fi = camel_ews_utils_build_folder_info (ews_store, l->data);
+		camel_subscribable_folder_unsubscribed (subscribable, fi);
+		camel_store_folder_deleted (store, fi);
+		camel_folder_info_free (fi);
+	}
+
+	g_slist_free_full (folders, g_free);
+}
+
 static CamelAuthenticationResult
 ews_authenticate_sync (CamelService *service,
                        const gchar *mechanism,
@@ -512,7 +545,7 @@ ews_authenticate_sync (CamelService *service,
 	gboolean initial_setup = FALSE;
 	const gchar *password;
 	gchar *hosturl;
-	gchar *sync_state = NULL;
+	gchar *old_sync_state = NULL, *new_sync_state = NULL;
 	GError *local_error = NULL, *folder_err = NULL;
 	gint n = 0;
 
@@ -547,16 +580,30 @@ ews_authenticate_sync (CamelService *service,
 	 *     since we have to do that eventually anyway. */
 
 	/*use old sync_state from summary*/
-	sync_state = camel_ews_store_summary_get_string_val (ews_store->summary, "sync_state", NULL);
-	if (!sync_state)
+	old_sync_state = camel_ews_store_summary_get_string_val (ews_store->summary, "sync_state", NULL);
+	if (!old_sync_state)
 		initial_setup = TRUE;
 
-	e_ews_connection_sync_folder_hierarchy_sync (
-		connection, EWS_PRIORITY_MEDIUM,
-		&sync_state, &includes_last_folder,
-		&folders_created, &folders_updated, &folders_deleted,
+	e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, old_sync_state,
+		&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
 		cancellable, &local_error);
 
+	g_free (old_sync_state);
+	old_sync_state = NULL;
+
+	if (!initial_setup && g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+		g_clear_error (&local_error);
+		ews_store_forget_all_folders (ews_store);
+		camel_ews_store_summary_store_string_val (ews_store->summary, "sync_state", "");
+		camel_ews_store_summary_clear (ews_store->summary);
+
+		initial_setup = TRUE;
+
+		e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, NULL,
+			&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
+			cancellable, &local_error);
+	}
+
 	if (local_error == NULL) {
 		g_mutex_lock (&ews_store->priv->connection_lock);
 		if (ews_store->priv->connection != NULL)
@@ -566,7 +613,7 @@ ews_authenticate_sync (CamelService *service,
 
 		/* This consumes all allocated result data. */
 		ews_update_folder_hierarchy (
-			ews_store, sync_state, includes_last_folder,
+			ews_store, new_sync_state, includes_last_folder,
 			folders_created, folders_deleted, folders_updated);
 	} else {
 		g_mutex_lock (&ews_store->priv->connection_lock);
@@ -576,7 +623,7 @@ ews_authenticate_sync (CamelService *service,
 		}
 		g_mutex_unlock (&ews_store->priv->connection_lock);
 
-		g_free (sync_state);
+		g_free (new_sync_state);
 
 		/* Make sure we're not leaking anything. */
 		g_warn_if_fail (folders_created == NULL);
@@ -827,7 +874,7 @@ ews_get_folder_info_sync (CamelStore *store,
 	CamelEwsStorePrivate *priv;
 	CamelFolderInfo *fi = NULL;
 	EEwsConnection *connection;
-	gchar *sync_state;
+	gchar *old_sync_state, *new_sync_state = NULL;
 	gboolean initial_setup = FALSE;
 	GSList *folders_created = NULL, *folders_updated = NULL;
 	GSList *folders_deleted = NULL;
@@ -855,14 +902,14 @@ ews_get_folder_info_sync (CamelStore *store,
 		goto offline;
 	}
 
-	sync_state = camel_ews_store_summary_get_string_val (ews_store->summary, "sync_state", NULL);
-	if (!sync_state)
+	old_sync_state = camel_ews_store_summary_get_string_val (ews_store->summary, "sync_state", NULL);
+	if (!old_sync_state)
 		initial_setup = TRUE;
 
-	if (!initial_setup && flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) {
+	if (!initial_setup && (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) != 0) {
 		time_t now = time (NULL);
 
-		g_free (sync_state);
+		g_free (old_sync_state);
 		if (now - priv->last_refresh_time > FINFO_REFRESH_INTERVAL && ews_refresh_finfo (ews_store))
 			ews_store->priv->last_refresh_time = time (NULL);
 
@@ -872,11 +919,25 @@ ews_get_folder_info_sync (CamelStore *store,
 
 	connection = camel_ews_store_ref_connection (ews_store);
 
-	success = e_ews_connection_sync_folder_hierarchy_sync (
-		connection, EWS_PRIORITY_MEDIUM,
-		&sync_state, &includes_last_folder,
-		&folders_created, &folders_updated,
-		&folders_deleted, cancellable, &local_error);
+	success = e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, old_sync_state,
+		&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
+		cancellable, &local_error);
+
+	g_free (old_sync_state);
+	old_sync_state = NULL;
+
+	if (!initial_setup && g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+		g_clear_error (&local_error);
+		ews_store_forget_all_folders (ews_store);
+		camel_ews_store_summary_store_string_val (ews_store->summary, "sync_state", "");
+		camel_ews_store_summary_clear (ews_store->summary);
+
+		initial_setup = TRUE;
+
+		success = e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, NULL,
+			&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
+			cancellable, &local_error);
+	}
 
 	g_object_unref (connection);
 
@@ -895,7 +956,7 @@ ews_get_folder_info_sync (CamelStore *store,
 		return NULL;
 	}
 	ews_update_folder_hierarchy (
-		ews_store, sync_state, includes_last_folder,
+		ews_store, new_sync_state, includes_last_folder,
 		folders_created, folders_deleted, folders_updated);
 	g_mutex_unlock (&priv->get_finfo_lock);
 
diff --git a/src/collection/e-ews-backend.c b/src/collection/e-ews-backend.c
index 774881b..a6cee3e 100644
--- a/src/collection/e-ews-backend.c
+++ b/src/collection/e-ews-backend.c
@@ -1085,6 +1085,36 @@ ews_backend_sync_folders_thread (GSimpleAsyncResult *simple,
 		g_simple_async_result_take_error (simple, error);
 }
 
+static void
+ews_backend_delete_each_source_cb (gpointer data,
+				   gpointer user_data)
+{
+	ESource *source = data;
+	ECollectionBackend *backend = user_data;
+
+	e_collection_backend_delete_resource_sync (backend, source, NULL, NULL);
+}
+
+static void
+ews_backend_forget_all_sources (EEwsBackend *backend)
+{
+	GList *sources;
+
+	g_return_if_fail (E_IS_EWS_BACKEND (backend));
+
+	sources = e_collection_backend_list_calendar_sources (E_COLLECTION_BACKEND (backend));
+	g_list_foreach (sources, ews_backend_delete_each_source_cb, backend);
+	g_list_free_full (sources, g_object_unref);
+
+	sources = e_collection_backend_list_contacts_sources (E_COLLECTION_BACKEND (backend));
+	g_list_foreach (sources, ews_backend_delete_each_source_cb, backend);
+	g_list_free_full (sources, g_object_unref);
+
+	sources = e_collection_backend_list_mail_sources (E_COLLECTION_BACKEND (backend));
+	g_list_foreach (sources, ews_backend_delete_each_source_cb, backend);
+	g_list_free_full (sources, g_object_unref);
+}
+
 gboolean
 e_ews_backend_sync_folders_sync (EEwsBackend *backend,
                                  GCancellable *cancellable,
@@ -1095,8 +1125,9 @@ e_ews_backend_sync_folders_sync (EEwsBackend *backend,
 	GSList *folders_updated = NULL;
 	GSList *folders_deleted = NULL;
 	gboolean includes_last_folder = FALSE;
-	gchar *sync_state;
+	gchar *old_sync_state, *new_sync_state = NULL;
 	gboolean success;
+	GError *local_error = NULL;
 
 	g_return_val_if_fail (E_IS_EWS_BACKEND (backend), FALSE);
 
@@ -1111,16 +1142,33 @@ e_ews_backend_sync_folders_sync (EEwsBackend *backend,
 	backend->priv->need_update_folders = FALSE;
 
 	g_mutex_lock (&backend->priv->sync_state_lock);
-	sync_state = g_strdup (backend->priv->sync_state);
+	old_sync_state = g_strdup (backend->priv->sync_state);
 	g_mutex_unlock (&backend->priv->sync_state_lock);
 
-	/* XXX I think this leaks the old sync_state value when
-	 *     it replaces it with the new sync_state value. */
-	success = e_ews_connection_sync_folder_hierarchy_sync (
-		connection, EWS_PRIORITY_MEDIUM,
-		&sync_state, &includes_last_folder,
-		&folders_created, &folders_updated, &folders_deleted,
-		cancellable, error);
+	success = e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, old_sync_state,
+		&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
+		cancellable, &local_error);
+
+	if (old_sync_state && g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
+		g_clear_error (&local_error);
+
+		g_mutex_lock (&backend->priv->sync_state_lock);
+		g_free (backend->priv->sync_state);
+		backend->priv->sync_state = NULL;
+		g_mutex_unlock (&backend->priv->sync_state_lock);
+
+		ews_backend_forget_all_sources (backend);
+
+		success = e_ews_connection_sync_folder_hierarchy_sync (connection, EWS_PRIORITY_MEDIUM, NULL,
+			&new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted,
+			cancellable, &local_error);
+	} else if (local_error) {
+		g_propagate_error (error, local_error);
+		local_error = NULL;
+	}
+
+	g_free (old_sync_state);
+	old_sync_state = NULL;
 
 	if (success) {
 		SyncFoldersClosure *closure;
@@ -1140,7 +1188,7 @@ e_ews_backend_sync_folders_sync (EEwsBackend *backend,
 
 		g_mutex_lock (&backend->priv->sync_state_lock);
 		g_free (backend->priv->sync_state);
-		backend->priv->sync_state = g_strdup (sync_state);
+		backend->priv->sync_state = g_strdup (new_sync_state);
 		g_mutex_unlock (&backend->priv->sync_state_lock);
 
 	} else {
@@ -1152,7 +1200,7 @@ e_ews_backend_sync_folders_sync (EEwsBackend *backend,
 		backend->priv->need_update_folders = TRUE;
 	}
 
-	g_free (sync_state);
+	g_free (new_sync_state);
 
 	g_object_unref (connection);
 
diff --git a/src/configuration/e-mail-config-ews-backend.c b/src/configuration/e-mail-config-ews-backend.c
index b3eb40e..0ef4f30 100644
--- a/src/configuration/e-mail-config-ews-backend.c
+++ b/src/configuration/e-mail-config-ews-backend.c
@@ -33,6 +33,8 @@
 #include "server/camel-ews-settings.h"
 
 #include "e-mail-config-ews-autodiscover.h"
+#include "e-ews-config-utils.h"
+#include "e-ews-search-user.h"
 
 #define E_MAIL_CONFIG_EWS_BACKEND_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -44,6 +46,7 @@ struct _EMailConfigEwsBackendPrivate {
 	GtkWidget *url_button;		/* not referenced */
 	GtkWidget *oab_entry;		/* not referenced */
 	GtkWidget *auth_check;		/* not referenced */
+	GtkWidget *impersonate_user_entry; /* not referenced */
 };
 
 G_DEFINE_DYNAMIC_TYPE (
@@ -79,6 +82,31 @@ mail_config_ews_backend_new_collection (EMailConfigServiceBackend *backend)
 }
 
 static void
+search_for_impersonate_user_clicked_cb (GtkButton *button,
+					EMailConfigServiceBackend *backend)
+{
+	EMailConfigEwsBackendPrivate *priv;
+	CamelSettings *settings;
+	EEwsConnection *conn;
+	GtkWindow *parent;
+	gchar *email = NULL;
+
+	g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
+
+	priv = E_MAIL_CONFIG_EWS_BACKEND_GET_PRIVATE (backend);
+	settings = e_mail_config_service_backend_get_settings (backend);
+	conn = e_ews_connection_new (gtk_entry_get_text (GTK_ENTRY (priv->host_entry)), CAMEL_EWS_SETTINGS (settings));
+	parent = e_ews_config_utils_get_widget_toplevel_window (GTK_WIDGET (button));
+
+	if (e_ews_search_user_modal (parent, conn, NULL, NULL, &email)) {
+		gtk_entry_set_text (GTK_ENTRY (priv->impersonate_user_entry), email);
+	}
+
+	g_object_unref (conn);
+	g_free (email);
+}
+
+static void
 mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
                                         GtkBox *parent)
 {
@@ -174,6 +202,51 @@ mail_config_ews_backend_insert_widgets (EMailConfigServiceBackend *backend,
 	priv->oab_entry = widget;  /* do not reference */
 	gtk_widget_show (widget);
 
+	widget = gtk_check_button_new_with_mnemonic (_("Open _Mailbox of other user"));
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1);
+	gtk_widget_show (widget);
+
+	if (camel_ews_settings_get_use_impersonation (CAMEL_EWS_SETTINGS (settings))) {
+		const gchar *impersonate_user = camel_ews_settings_get_impersonate_user (CAMEL_EWS_SETTINGS (settings));
+
+		if (impersonate_user && !*impersonate_user) {
+			camel_ews_settings_set_impersonate_user (CAMEL_EWS_SETTINGS (settings), NULL);
+			camel_ews_settings_set_use_impersonation (CAMEL_EWS_SETTINGS (settings), FALSE);
+		}
+	}
+
+	g_object_bind_property (
+		settings, "use-impersonation",
+		widget, "active",
+		G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+	widget = gtk_entry_new ();
+	gtk_widget_set_hexpand (widget, TRUE);
+	gtk_grid_attach (GTK_GRID (container), widget, 1, 4, 1, 1);
+	gtk_widget_show (widget);
+	priv->impersonate_user_entry = widget;  /* do not reference */
+
+	g_object_bind_property (
+		settings, "impersonate-user",
+		widget, "text",
+		G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+	g_object_bind_property (
+		settings, "use-impersonation",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE);
+
+	widget = gtk_button_new_with_mnemonic (_("S_earch..."));
+	gtk_grid_attach (GTK_GRID (container), widget, 2, 4, 1, 1);
+	gtk_widget_show (widget);
+
+	g_object_bind_property (
+		priv->impersonate_user_entry, "sensitive",
+		widget, "sensitive",
+		G_BINDING_SYNC_CREATE);
+
+	g_signal_connect (widget, "clicked", G_CALLBACK (search_for_impersonate_user_clicked_cb), backend);
+
 	text = _("Authentication");
 	markup = g_markup_printf_escaped ("<b>%s</b>", text);
 	widget = gtk_label_new (markup);
diff --git a/src/server/camel-ews-settings.c b/src/server/camel-ews-settings.c
index 67d200e..7d06a0d 100644
--- a/src/server/camel-ews-settings.c
+++ b/src/server/camel-ews-settings.c
@@ -34,12 +34,14 @@ struct _CamelEwsSettingsPrivate {
 	gboolean filter_junk;
 	gboolean filter_junk_inbox;
 	gboolean oab_offline;
+	gboolean use_impersonation;
 	gchar *email;
 	gchar *gal_uid;
 	gchar *hosturl;
 	gchar *oaburl;
 	gchar *oal_selected;
 	guint timeout;
+	gchar *impersonate_user;
 };
 
 enum {
@@ -58,7 +60,9 @@ enum {
 	PROP_PORT,
 	PROP_SECURITY_METHOD,
 	PROP_TIMEOUT,
-	PROP_USER
+	PROP_USER,
+	PROP_USE_IMPERSONATION,
+	PROP_IMPERSONATE_USER
 };
 
 G_DEFINE_TYPE_WITH_CODE (
@@ -164,6 +168,18 @@ ews_settings_set_property (GObject *object,
 				CAMEL_NETWORK_SETTINGS (object),
 				g_value_get_string (value));
 			return;
+
+		case PROP_USE_IMPERSONATION:
+			camel_ews_settings_set_use_impersonation (
+				CAMEL_EWS_SETTINGS (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_IMPERSONATE_USER:
+			camel_ews_settings_set_impersonate_user (
+				CAMEL_EWS_SETTINGS (object),
+				g_value_get_string (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -280,6 +296,20 @@ ews_settings_get_property (GObject *object,
 				camel_network_settings_dup_user (
 				CAMEL_NETWORK_SETTINGS (object)));
 			return;
+
+		case PROP_USE_IMPERSONATION:
+			g_value_set_boolean (
+				value,
+				camel_ews_settings_get_use_impersonation (
+				CAMEL_EWS_SETTINGS (object)));
+			return;
+
+		case PROP_IMPERSONATE_USER:
+			g_value_take_string (
+				value,
+				camel_ews_settings_dup_impersonate_user (
+				CAMEL_EWS_SETTINGS (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -299,6 +329,7 @@ ews_settings_finalize (GObject *object)
 	g_free (priv->hosturl);
 	g_free (priv->oaburl);
 	g_free (priv->oal_selected);
+	g_free (priv->impersonate_user);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (camel_ews_settings_parent_class)->finalize (object);
@@ -465,6 +496,30 @@ camel_ews_settings_class_init (CamelEwsSettingsClass *class)
 		object_class,
 		PROP_USER,
 		"user");
+
+	g_object_class_install_property (
+		object_class,
+		PROP_USE_IMPERSONATION,
+		g_param_spec_boolean (
+			"use-impersonation",
+			"Use Impersonation",
+			"Use Impersonation",
+			FALSE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_IMPERSONATE_USER,
+		g_param_spec_string (
+			"impersonate-user",
+			"Impersonate User",
+			"Impersonate User",
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -879,3 +934,72 @@ camel_ews_settings_set_timeout (CamelEwsSettings *settings,
 
 	g_object_notify (G_OBJECT (settings), "timeout");
 }
+
+gboolean
+camel_ews_settings_get_use_impersonation (CamelEwsSettings *settings)
+{
+	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), FALSE);
+
+	return settings->priv->use_impersonation;
+}
+
+void
+camel_ews_settings_set_use_impersonation (CamelEwsSettings *settings,
+					  gboolean use_impersonation)
+{
+	g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+	if ((settings->priv->use_impersonation ? 1 : 0) == (use_impersonation ? 1 : 0))
+		return;
+
+	settings->priv->use_impersonation = use_impersonation;
+
+	g_object_notify (G_OBJECT (settings), "use-impersonation");
+}
+
+const gchar *
+camel_ews_settings_get_impersonate_user (CamelEwsSettings *settings)
+{
+	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+	return settings->priv->impersonate_user;
+}
+
+gchar *
+camel_ews_settings_dup_impersonate_user (CamelEwsSettings *settings)
+{
+	const gchar *protected;
+	gchar *duplicate;
+
+	g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), NULL);
+
+	g_mutex_lock (&settings->priv->property_lock);
+
+	protected = camel_ews_settings_get_impersonate_user (settings);
+	duplicate = g_strdup (protected);
+
+	g_mutex_unlock (&settings->priv->property_lock);
+
+	return duplicate;
+}
+
+void
+camel_ews_settings_set_impersonate_user (CamelEwsSettings *settings,
+					 const gchar *impersonate_user)
+{
+	g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+	g_mutex_lock (&settings->priv->property_lock);
+
+	if (g_strcmp0 (settings->priv->impersonate_user, impersonate_user) == 0) {
+		g_mutex_unlock (&settings->priv->property_lock);
+		return;
+	}
+
+	g_free (settings->priv->impersonate_user);
+	settings->priv->impersonate_user = e_util_strdup_strip (impersonate_user);
+
+	g_mutex_unlock (&settings->priv->property_lock);
+
+	g_object_notify (G_OBJECT (settings), "impersonate-user");
+}
diff --git a/src/server/camel-ews-settings.h b/src/server/camel-ews-settings.h
index 5fe4bbd..e2b12b9 100644
--- a/src/server/camel-ews-settings.h
+++ b/src/server/camel-ews-settings.h
@@ -102,6 +102,19 @@ void		camel_ews_settings_set_oal_selected
 guint		camel_ews_settings_get_timeout	(CamelEwsSettings *settings);
 void		camel_ews_settings_set_timeout	(CamelEwsSettings *settings,
 						 guint timeout);
+gboolean	camel_ews_settings_get_use_impersonation
+						(CamelEwsSettings *settings);
+void		camel_ews_settings_set_use_impersonation
+						(CamelEwsSettings *settings,
+						 gboolean use_impersonation);
+const gchar *	camel_ews_settings_get_impersonate_user
+						(CamelEwsSettings *settings);
+gchar *		camel_ews_settings_dup_impersonate_user
+						(CamelEwsSettings *settings);
+void		camel_ews_settings_set_impersonate_user
+						(CamelEwsSettings *settings,
+						 const gchar *impersonate_user);
+
 G_END_DECLS
 
 #endif /* CAMEL_EWS_SETTINGS_H */
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 9a49017..b9c74ff 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -85,6 +85,7 @@ struct _EEwsConnectionPrivate {
 	gchar *uri;
 	gchar *password;
 	gchar *email;
+	gchar *impersonate_user;
 
 	GSList *jobs;
 	GSList *active_job_queue;
@@ -1310,6 +1311,7 @@ ews_connection_finalize (GObject *object)
 	g_free (priv->password);
 	g_free (priv->email);
 	g_free (priv->hash_key);
+	g_free (priv->impersonate_user);
 
 	g_mutex_clear (&priv->password_lock);
 	g_rec_mutex_clear (&priv->queue_lock);
@@ -1633,6 +1635,17 @@ e_ews_connection_new (const gchar *uri,
 	cnc->priv->uri = g_strdup (uri);
 	cnc->priv->hash_key = hash_key;  /* takes ownership */
 
+	g_free (cnc->priv->impersonate_user);
+	if (camel_ews_settings_get_use_impersonation (settings)) {
+		cnc->priv->impersonate_user = camel_ews_settings_dup_impersonate_user (settings);
+		if (cnc->priv->impersonate_user && !*cnc->priv->impersonate_user) {
+			g_free (cnc->priv->impersonate_user);
+			cnc->priv->impersonate_user = NULL;
+		}
+	} else {
+		cnc->priv->impersonate_user = NULL;
+	}
+
 	g_object_bind_property_full (
 		settings, "auth-mechanism",
 		cnc->priv->soup_session, "use-ntlm",
@@ -1715,6 +1728,14 @@ e_ews_connection_set_password (EEwsConnection *cnc,
 	g_object_notify (G_OBJECT (cnc), "password");
 }
 
+const gchar *
+e_ews_connection_get_impersonate_user (EEwsConnection *cnc)
+{
+	g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), NULL);
+
+	return cnc->priv->impersonate_user;
+}
+
 CamelEwsSettings *
 e_ews_connection_ref_settings (EEwsConnection *cnc)
 {
@@ -3049,7 +3070,7 @@ e_ews_connection_sync_folder_items (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "SyncFolderItems", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "SyncFolderItems", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 	e_soap_message_start_element (msg, "ItemShape", "messages", NULL);
 	e_ews_message_write_string_parameter (msg, "BaseShape", NULL, default_props);
 
@@ -3245,7 +3266,7 @@ e_ews_connection_find_folder_items (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "FindItem", "Traversal", "Shallow", EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "FindItem", "Traversal", "Shallow", EWS_EXCHANGE_2007_SP1);
 	e_soap_message_start_element (msg, "ItemShape", "messages", NULL);
 	e_ews_message_write_string_parameter (msg, "BaseShape", NULL, default_props);
 
@@ -3368,7 +3389,7 @@ e_ews_connection_sync_folder_hierarchy (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "SyncFolderHierarchy", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "SyncFolderHierarchy", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 	e_soap_message_start_element (msg, "FolderShape", "messages", NULL);
 	e_ews_message_write_string_parameter (msg, "BaseShape", NULL, "AllProperties");
 	e_soap_message_end_element (msg);
@@ -3430,7 +3451,8 @@ e_ews_connection_sync_folder_hierarchy_finish (EEwsConnection *cnc,
 gboolean
 e_ews_connection_sync_folder_hierarchy_sync (EEwsConnection *cnc,
                                              gint pri,
-                                             gchar **sync_state,
+					     const gchar *old_sync_state,
+                                             gchar **new_sync_state,
                                              gboolean *includes_last_folder,
                                              GSList **folders_created,
                                              GSList **folders_updated,
@@ -3447,13 +3469,13 @@ e_ews_connection_sync_folder_hierarchy_sync (EEwsConnection *cnc,
 	closure = e_async_closure_new ();
 
 	e_ews_connection_sync_folder_hierarchy (
-		cnc, pri, *sync_state, cancellable,
+		cnc, pri, old_sync_state, cancellable,
 		e_async_closure_callback, closure);
 
 	result = e_async_closure_wait (closure);
 
 	success = e_ews_connection_sync_folder_hierarchy_finish (
-		cnc, result, sync_state,
+		cnc, result, new_sync_state,
 		includes_last_folder,
 		folders_created,
 		folders_updated,
@@ -3486,7 +3508,7 @@ e_ews_connection_get_items (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "GetItem", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetItem", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	if (progress_fn && progress_data)
 		e_soap_message_set_progress_fn (msg, progress_fn, progress_data);
@@ -3708,8 +3730,7 @@ e_ews_connection_delete_items (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "DeleteItem",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "DeleteItem",
 		"DeleteType", ews_delete_type_to_str (delete_type), EWS_EXCHANGE_2007_SP1);
 
 	if (send_cancels)
@@ -3765,8 +3786,7 @@ e_ews_connection_delete_item (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "DeleteItem",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "DeleteItem",
 		"DeleteType", ews_delete_type_to_str (delete_type), EWS_EXCHANGE_2007_SP1);
 
 	if (send_cancels)
@@ -3921,8 +3941,7 @@ e_ews_connection_update_items (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "UpdateItem",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "UpdateItem",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	if (conflict_res)
@@ -4074,8 +4093,7 @@ e_ews_connection_create_items (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "CreateItem",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "CreateItem",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	if (msg_disposition)
@@ -4230,7 +4248,7 @@ e_ews_connection_resolve_names (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "ResolveNames", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "ResolveNames", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_add_attribute (msg, "SearchScope", get_search_scope_str (scope), NULL, NULL);
 
@@ -4508,7 +4526,7 @@ e_ews_connection_expand_dl (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "ExpandDL", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "ExpandDL", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "Mailbox", "messages", NULL);
 
@@ -4652,8 +4670,7 @@ e_ews_connection_update_folder (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "UpdateFolder",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "UpdateFolder",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "FolderChanges", "messages", NULL);
@@ -4777,8 +4794,7 @@ e_ews_connection_move_folder (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "MoveFolder",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "MoveFolder",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "ToFolderId", "messages", NULL);
@@ -4882,8 +4898,7 @@ e_ews_connection_get_folder (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "GetFolder",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetFolder",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "FolderShape", "messages", NULL);
@@ -4992,7 +5007,7 @@ e_ews_connection_create_folder (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "CreateFolder", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "CreateFolder", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "ParentFolderId", "messages", NULL);
 
@@ -5137,12 +5152,10 @@ e_ews_connection_move_items (EEwsConnection *cnc,
 	g_return_if_fail (cnc != NULL);
 
 	if (docopy)
-		msg = e_ews_message_new_with_header (
-			cnc->priv->uri, "CopyItem",
+		msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "CopyItem",
 			NULL, NULL, EWS_EXCHANGE_2007_SP1);
 	else
-		msg = e_ews_message_new_with_header (
-			cnc->priv->uri, "MoveItem",
+		msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "MoveItem",
 			NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "ToFolderId", "messages", NULL);
@@ -5306,7 +5319,7 @@ e_ews_connection_delete_folder (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "DeleteFolder", "DeleteType", delete_type, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "DeleteFolder", "DeleteType", delete_type, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "FolderIds", "messages", NULL);
 
@@ -5533,7 +5546,7 @@ e_ews_connection_create_attachments (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "CreateAttachment", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "CreateAttachment", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "ParentItemId", "messages", NULL);
 	e_soap_message_add_attribute (msg, "Id", parent->id, NULL, NULL);
@@ -5700,7 +5713,7 @@ e_ews_connection_delete_attachments (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "DeleteAttachment", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "DeleteAttachment", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	/* start interation over all items to get the attachemnts */
 	e_soap_message_start_element (msg, "AttachmentIds", "messages", NULL);
@@ -5876,7 +5889,7 @@ e_ews_connection_get_attachments (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "GetAttachment", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetAttachment", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	/* not sure why I need it, need to check */
 	if (progress_fn && progress_data)
@@ -6119,8 +6132,7 @@ e_ews_connection_get_free_busy (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "GetUserAvailabilityRequest",
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetUserAvailabilityRequest",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	free_busy_cb (msg, free_busy_user_data);
@@ -6398,7 +6410,7 @@ 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 ? "true" : "false", EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetDelegate", "IncludePermissions", include_permissions ? "true" : "false", EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "Mailbox", "messages", NULL);
 
@@ -6567,7 +6579,7 @@ e_ews_connection_add_delegate (EEwsConnection *cnc,
 	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);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "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);
@@ -6689,7 +6701,7 @@ e_ews_connection_remove_delegate (EEwsConnection *cnc,
 	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);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "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);
@@ -6791,7 +6803,7 @@ e_ews_connection_update_delegate (EEwsConnection *cnc,
 
 	g_return_if_fail (cnc != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "UpdateDelegate", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "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);
@@ -6976,9 +6988,7 @@ e_ews_connection_get_folder_permissions (EEwsConnection *cnc,
 	g_return_if_fail (cnc != NULL);
 	g_return_if_fail (folder_id != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "GetFolder",
-		NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetFolder", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "FolderShape", "messages", NULL);
 	e_ews_message_write_string_parameter (msg, "BaseShape", NULL, "IdOnly");
@@ -7088,9 +7098,7 @@ e_ews_connection_set_folder_permissions (EEwsConnection *cnc,
 	g_return_if_fail (folder_id != NULL);
 	g_return_if_fail (permissions != NULL);
 
-	msg = e_ews_message_new_with_header (
-		cnc->priv->uri, "UpdateFolder",
-		NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "UpdateFolder", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "FolderChanges", "messages", NULL);
 	e_ews_message_start_item_change (
@@ -7329,7 +7337,7 @@ e_ews_connection_get_password_expiration (EEwsConnection *cnc,
 	GSimpleAsyncResult *simple;
 	EwsAsyncData *async_data;
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "GetPasswordExpirationDate", NULL, NULL, EWS_EXCHANGE_2010_SP2);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetPasswordExpirationDate", NULL, NULL, EWS_EXCHANGE_2010_SP2);
 	e_ews_message_write_string_parameter (msg, "MailboxSmtpAddress", NULL, mail_id ? mail_id : cnc->priv->email);
 	e_ews_message_write_footer (msg);
 
@@ -7484,7 +7492,7 @@ e_ews_connection_get_folder_info (EEwsConnection *cnc,
 	g_return_if_fail (cnc != NULL);
 	g_return_if_fail (folder_id != NULL);
 
-	msg = e_ews_message_new_with_header (cnc->priv->uri, "GetFolder", NULL, NULL, EWS_EXCHANGE_2007_SP1);
+	msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "GetFolder", NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (msg, "FolderShape", "messages", NULL);
 	e_ews_message_write_string_parameter (msg, "BaseShape", NULL, "Default");
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index 2fa5180..93b571f 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -203,6 +203,8 @@ const gchar *	e_ews_connection_get_password	(EEwsConnection *cnc);
 gchar *		e_ews_connection_dup_password	(EEwsConnection *cnc);
 void		e_ews_connection_set_password	(EEwsConnection *cnc,
 						 const gchar *password);
+const gchar *	e_ews_connection_get_impersonate_user
+						(EEwsConnection *cnc);
 CamelEwsSettings *
 		e_ews_connection_ref_settings	(EEwsConnection *cnc);
 SoupSession *	e_ews_connection_ref_soup_session
@@ -461,7 +463,8 @@ gboolean	e_ews_connection_sync_folder_hierarchy_finish
 gboolean	e_ews_connection_sync_folder_hierarchy_sync
 						(EEwsConnection *cnc,
 						 gint pri,
-						 gchar **sync_state,
+						 const gchar *old_sync_state,
+						 gchar **new_sync_state,
 						 gboolean *includes_last_folder,
 						 GSList **folders_created,
 						 GSList **folders_updated,
diff --git a/src/server/e-ews-message.c b/src/server/e-ews-message.c
index 7ca0464..994d264 100644
--- a/src/server/e-ews-message.c
+++ b/src/server/e-ews-message.c
@@ -31,6 +31,7 @@
 
 ESoapMessage *
 e_ews_message_new_with_header (const gchar *uri,
+			       const gchar *impersonate_user,
                                const gchar *method_name,
                                const gchar *attribute_name,
                                const gchar *attribute_value,
@@ -78,6 +79,24 @@ e_ews_message_new_with_header (const gchar *uri,
 	e_soap_message_add_attribute (msg, "Version", server_ver, NULL, NULL);
 	e_soap_message_end_element (msg);
 
+	if (impersonate_user && *impersonate_user) {
+		e_soap_message_start_element (msg, "ExchangeImpersonation", "types",
+			"http://schemas.microsoft.com/exchange/services/2006/types";);
+
+		e_soap_message_start_element (msg, "ConnectingSID", "types", NULL);
+
+		if (strchr (impersonate_user, '@') != 0)
+			e_soap_message_start_element (msg, "PrimarySmtpAddress", "types", NULL);
+		else
+			e_soap_message_start_element (msg, "PrincipalName", "types", NULL);
+		e_soap_message_write_string (msg, impersonate_user);
+		e_soap_message_end_element (msg); /* PrimarySmtpAddress or PrincipalName */
+
+		e_soap_message_end_element (msg); /* ConnectingSID */
+
+		e_soap_message_end_element (msg); /* ExchangeImpersonation */
+	}
+
 	e_soap_message_end_header (msg);
 
 	e_soap_message_start_body (msg);
diff --git a/src/server/e-ews-message.h b/src/server/e-ews-message.h
index c616706..1c62526 100644
--- a/src/server/e-ews-message.h
+++ b/src/server/e-ews-message.h
@@ -37,6 +37,7 @@ typedef enum {
 } EwsServerVersion;
 
 ESoapMessage *	e_ews_message_new_with_header	(const gchar *uri,
+						 const gchar *impersonate_user,
 						 const gchar *method_name,
 						 const gchar *attribute_name,
 						 const gchar *attribute_value,
diff --git a/src/server/e-ews-oof-settings.c b/src/server/e-ews-oof-settings.c
index 3b382aa..a69d97b 100644
--- a/src/server/e-ews-oof-settings.c
+++ b/src/server/e-ews-oof-settings.c
@@ -456,17 +456,18 @@ ews_oof_settings_initable_init_async (GAsyncInitable *initable,
 	EEwsOofSettings *settings;
 	EEwsConnection *connection;
 	ESoapMessage *message;
-	const gchar *uri;
+	const gchar *uri, *impersonate_user;
 	const gchar *mailbox;
 
 	settings = E_EWS_OOF_SETTINGS (initable);
 	connection = e_ews_oof_settings_get_connection (settings);
 
 	uri = e_ews_connection_get_uri (connection);
+	impersonate_user = e_ews_connection_get_impersonate_user (connection);
 	mailbox = e_ews_connection_get_mailbox (connection);
 
 	message = e_ews_message_new_with_header (
-		uri, "GetUserOofSettingsRequest",
+		uri, impersonate_user, "GetUserOofSettingsRequest",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	e_soap_message_start_element (message, "Mailbox", NULL, NULL);
@@ -949,7 +950,7 @@ e_ews_oof_settings_submit (EEwsOofSettings *settings,
 	GDateTime *date_time;
 	const gchar *mailbox;
 	const gchar *string;
-	const gchar *uri;
+	const gchar *uri, *impersonate_user;
 	gchar *internal_reply;
 	gchar *external_reply;
 	gchar *start_time;
@@ -960,6 +961,7 @@ e_ews_oof_settings_submit (EEwsOofSettings *settings,
 	connection = e_ews_oof_settings_get_connection (settings);
 	mailbox = e_ews_connection_get_mailbox (connection);
 	uri = e_ews_connection_get_uri (connection);
+	impersonate_user = e_ews_connection_get_impersonate_user (connection);
 
 	internal_reply = e_ews_oof_settings_dup_internal_reply (settings);
 	external_reply = e_ews_oof_settings_dup_external_reply (settings);
@@ -973,7 +975,7 @@ e_ews_oof_settings_submit (EEwsOofSettings *settings,
 	g_date_time_unref (date_time);
 
 	message = e_ews_message_new_with_header (
-		uri, "SetUserOofSettingsRequest",
+		uri, impersonate_user, "SetUserOofSettingsRequest",
 		NULL, NULL, EWS_EXCHANGE_2007_SP1);
 
 	/* <Mailbox> */



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