[evolution-mapi] Bug #601382 - Support for subscribe to other user's folder



commit 14377ea958dbd54627bf7cc786a88e758dab5865
Author: Milan Crha <mcrha redhat com>
Date:   Tue Jan 17 16:20:21 2012 +0100

    Bug #601382 - Support for subscribe to other user's folder

 configure.ac                                       |    1 +
 po/POTFILES.in                                     |    2 +
 src/account-setup-eplugin/Makefile.am              |    8 +-
 .../e-mapi-account-listener.c                      |  216 +----
 .../e-mapi-account-listener.h                      |    2 -
 .../e-mapi-account-settings.c                      |  172 +++-
 src/account-setup-eplugin/e-mapi-account-setup.c   |  280 +++++-
 src/account-setup-eplugin/e-mapi-account-setup.h   |   18 +-
 .../e-mapi-subscribe-foreign-folder.c              |  647 ++++++++++++
 .../e-mapi-subscribe-foreign-folder.h              |   34 +
 .../org-gnome-exchange-mapi.eplug.xml              |    1 +
 src/addressbook/e-book-backend-mapi-contacts.c     |  111 ++-
 src/calendar/e-cal-backend-mapi.c                  |  123 ++--
 src/camel/camel-mapi-folder.c                      |  178 +++--
 src/camel/camel-mapi-store-summary.c               |   28 +-
 src/camel/camel-mapi-store-summary.h               |    6 +-
 src/camel/camel-mapi-store.c                       |  382 +++++++-
 src/camel/camel-mapi-store.h                       |    8 +-
 src/libexchangemapi/e-mapi-cal-utils.c             |   13 +-
 src/libexchangemapi/e-mapi-connection.c            | 1047 +++++++++++++-------
 src/libexchangemapi/e-mapi-connection.h            |   78 +-
 src/libexchangemapi/e-mapi-folder.c                |  332 ++++++-
 src/libexchangemapi/e-mapi-folder.h                |   57 +-
 23 files changed, 2813 insertions(+), 931 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f8bddf9..46ae992 100644
--- a/configure.ac
+++ b/configure.ac
@@ -109,6 +109,7 @@ dnl ********************************
 dnl Check for evolution-data-server 
 dnl ********************************
 PKG_CHECK_MODULES(EVOLUTION_DATA_SERVER, evolution-data-server-$EDS_PACKAGE >= eds_minimum_version)
+PKG_CHECK_MODULES(LIBEDATASERVERUI, libedataserverui-3.0 >= eds_minimum_version)
 PKG_CHECK_MODULES(LIBEDATASERVER, libedataserver-$EDS_PACKAGE >= eds_minimum_version)
 PKG_CHECK_MODULES(LIBEBACKEND, libebackend-$EDS_PACKAGE >= eds_minimum_version)
 PKG_CHECK_MODULES(LIBECAL, libecal-$EDS_PACKAGE >= eds_minimum_version)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index de222c0..1cdc8dc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,6 +1,7 @@
 src/account-setup-eplugin/e-mapi-account-listener.c
 src/account-setup-eplugin/e-mapi-account-setup.c
 src/account-setup-eplugin/e-mapi-account-settings.c
+src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c
 src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
 src/addressbook/e-book-backend-mapi.c
 src/addressbook/e-book-backend-mapi-contacts.c
@@ -12,3 +13,4 @@ src/camel/camel-mapi-store.c
 src/camel/camel-mapi-transport.c
 src/libexchangemapi/e-mapi-cal-utils.c
 src/libexchangemapi/e-mapi-connection.c
+src/libexchangemapi/e-mapi-folder.c
diff --git a/src/account-setup-eplugin/Makefile.am b/src/account-setup-eplugin/Makefile.am
index 76af68c..6058f40 100644
--- a/src/account-setup-eplugin/Makefile.am
+++ b/src/account-setup-eplugin/Makefile.am
@@ -1,8 +1,10 @@
 AM_CPPFLAGS = -I .					\
 	-DEVOLUTION_GLADEDIR=\""$(gladedir)"\" 		\
 	-DCONNECTOR_GLADEDIR=\""$(gladedir)"\" 		\
+	-I$(top_srcdir)/src/				\
 	-I$(top_srcdir)/src/libexchangemapi/		\
 	$(EVOLUTION_PLUGIN_CFLAGS)			\
+	$(LIBEDATASERVERUI_CFLAGS)			\
 	$(CAMEL_CFLAGS)					\
 	$(LIBECAL_CFLAGS)				\
 	$(LIBMAPI_CFLAGS)
@@ -19,11 +21,15 @@ liborg_gnome_exchange_mapi_la_SOURCES = 	\
 	e-mapi-account-setup.h			\
 	e-mapi-account-settings.c		\
 	e-mapi-account-listener.c		\
-	e-mapi-account-listener.h
+	e-mapi-account-listener.h		\
+	e-mapi-subscribe-foreign-folder.c	\
+	e-mapi-subscribe-foreign-folder.h
 
 liborg_gnome_exchange_mapi_la_LIBADD = 			\
 	$(top_builddir)/src/libexchangemapi/libexchangemapi-1.0.la \
+	$(top_builddir)/src/camel/libcamelmapi.la	\
 	$(EVOLUTION_PLUGIN_LIBS)			\
+	$(LIBEDATASERVERUI_LIBS)			\
 	$(CAMEL_LIBS) 					\
 	$(LIBECAL_LIBS)					\
 	$(LIBMAPI_LIBS)
diff --git a/src/account-setup-eplugin/e-mapi-account-listener.c b/src/account-setup-eplugin/e-mapi-account-listener.c
index 85ebe54..5ea1c8b 100644
--- a/src/account-setup-eplugin/e-mapi-account-listener.c
+++ b/src/account-setup-eplugin/e-mapi-account-listener.c
@@ -217,14 +217,6 @@ find_source_by_fid (GSList *sources, const gchar *fid)
 	return NULL;
 }
 
-#define CALENDAR_SOURCES	"/apps/evolution/calendar/sources"
-#define TASK_SOURCES		"/apps/evolution/tasks/sources"
-#define JOURNAL_SOURCES		"/apps/evolution/memos/sources"
-#define SELECTED_CALENDARS	"/apps/evolution/calendar/display/selected_calendars"
-#define SELECTED_TASKS		"/apps/evolution/calendar/tasks/selected_tasks"
-#define SELECTED_JOURNALS	"/apps/evolution/calendar/memos/selected_memos"
-#define ADDRESSBOOK_SOURCES     "/apps/evolution/addressbook/sources"
-
 static void
 add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type, CamelURL *url, CamelSettings *settings, mapi_id_t trash_fid)
 {
@@ -249,13 +241,13 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
 	kerberos = camel_mapi_settings_get_kerberos (mapi_settings) ? "required" : NULL;
 	stay_synchronized = camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (settings));
 
-	if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT) {
+	if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT) {
 		conf_key = CALENDAR_SOURCES;
 		source_selection_key = SELECTED_CALENDARS;
-	} else if (folder_type == MAPI_FOLDER_TYPE_TASK) {
+	} else if (folder_type == E_MAPI_FOLDER_TYPE_TASK) {
 		conf_key = TASK_SOURCES;
 		source_selection_key = SELECTED_TASKS;
-	} else if (folder_type == MAPI_FOLDER_TYPE_MEMO) {
+	} else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO) {
 		conf_key = JOURNAL_SOURCES;
 		source_selection_key = SELECTED_JOURNALS;
 	} else {
@@ -350,32 +342,11 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
 		e_source_set_property (source, "acl-owner-name", account->id->name);
 		e_source_set_property (source, "acl-owner-email", account->id->address);
 
-		if (folder_type != MAPI_FOLDER_TYPE_APPOINTMENT)
+		if (folder_type != E_MAPI_FOLDER_TYPE_APPOINTMENT)
 			e_source_set_property (source, "alarm", "never");
 
 		if (is_new_source || !e_source_peek_color_spec (source)) {
-			static gint color_mover = 0;
-			static gint color_indexer = -1;
-			const guint32 colors[] = {
-				0x1464ae, /* dark blue */
-				0x14ae64, /* dark green */
-				0xae1464, /* dark red */
-				0
-			};
-			guint32 color;
-			gchar *color_str;
-
-			color_indexer++;
-			if (colors[color_indexer] == 0) {
-				color_mover += 1;
-				color_indexer = 0;
-			}
-
-			color = colors[color_indexer];
-			color = (color & ~(0xFF << (color_indexer * 8))) |
-				(((((color >> (color_indexer * 8)) & 0xFF) + (0x33 * color_mover)) % 0xFF) << (color_indexer * 8));
-
-			color_str = g_strdup_printf ("#%06x", color);
+			gchar *color_str = e_mapi_folder_pick_color_spec (1, folder_type != E_MAPI_FOLDER_TYPE_APPOINTMENT);
 			e_source_set_color_spec (source, color_str);
 			g_free (color_str);
 		}
@@ -403,7 +374,8 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
 			ESource *source = temp_list->data;
 
 			if (source && E_IS_SOURCE (source)) {
-				if (g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
+				if (!e_source_get_property (source, "foreign-username") &&
+				    g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
 					e_source_group_remove_source (group, source);
 			}
 		}
@@ -422,157 +394,6 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
 	g_object_unref (client);
 }
 
-void e_mapi_add_esource (CamelService *service, const gchar *folder_name, const gchar *fid, gint folder_type)
-{
-	CamelNetworkSettings *network_settings;
-	CamelOfflineSettings *offline_settings;
-	CamelMapiSettings *mapi_settings;
-	CamelSettings *settings;
-	ESourceList *source_list = NULL;
-	ESourceGroup *group = NULL;
-	const gchar *conf_key = NULL, *kerberos = NULL;
-	GConfClient* client;
-	GSList *sources;
-	ESource *source = NULL;
-	gchar *relative_uri = NULL;
-	gchar *base_uri = NULL;
-	const gchar *host;
-	const gchar *user;
-
-	g_return_if_fail (CAMEL_IS_SERVICE (service));
-
-	if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT)
-		conf_key = CALENDAR_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_TASK)
-		conf_key = TASK_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_MEMO)
-		conf_key = JOURNAL_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_JOURNAL)
-		conf_key = JOURNAL_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_CONTACT)
-		conf_key = ADDRESSBOOK_SOURCES;
-	else {
-		g_warning ("%s: %s: Unknown EMapiFolderType\n", G_STRLOC, G_STRFUNC);
-		return;
-	}
-
-	settings = camel_service_get_settings (service);
-
-	network_settings = CAMEL_NETWORK_SETTINGS (settings);
-	host = camel_network_settings_get_host (network_settings);
-	user = camel_network_settings_get_user (network_settings);
-
-	client = gconf_client_get_default ();
-	source_list = e_source_list_new_for_gconf (client, conf_key);
-	base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, user, host);
-	group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
-	sources = e_source_group_peek_sources (group);
-	for (; sources != NULL; sources = g_slist_next (sources)) {
-		ESource *source = E_SOURCE (sources->data);
-		gchar * folder_id = e_source_get_duped_property (source, "folder-id");
-		if (folder_id && fid) {
-			if (strcmp (fid, folder_id) != 0)
-				continue;
-			else {
-				g_warning ("%s: %s: Esource Already exist \n", G_STRLOC, G_STRFUNC);
-				return;
-			}
-		}
-	}
-
-	mapi_settings = CAMEL_MAPI_SETTINGS (settings);
-	offline_settings = CAMEL_OFFLINE_SETTINGS (settings);
-
-	relative_uri = g_strconcat (";", fid, NULL);
-	kerberos = camel_mapi_settings_get_kerberos (mapi_settings) ? "required" : NULL;
-	source = e_source_new (folder_name, relative_uri);
-	e_source_set_property (source, "auth", "1");
-	e_source_set_property (source, "auth-type", "plain/password");
-	e_source_set_property (source, "username", user);
-	e_source_set_property (source, "host", host);
-	e_source_set_property (source, "profile", camel_mapi_settings_get_profile (mapi_settings));
-	e_source_set_property (source, "domain", camel_mapi_settings_get_domain (mapi_settings));
-	e_source_set_property (source, "realm", camel_mapi_settings_get_realm (mapi_settings));
-	e_source_set_property (source, "folder-id", fid);
-	e_source_set_property (source, "offline_sync", camel_offline_settings_get_stay_synchronized (offline_settings) ? "1" : "0");
-	e_source_set_property (source, "public", "yes");
-	e_source_set_property (source, "delete", "yes");
-	SET_KRB_SSO(source, kerberos);
-
-	e_source_group_add_source (group, source, -1);
-
-	g_object_unref (source);
-	g_free (relative_uri);
-
-	if (!e_source_list_add_group (source_list, group, -1))
-		return;
-
-	if (!e_source_list_sync (source_list, NULL))
-		return;
-
-	g_object_unref (group);
-	g_object_unref (source_list);
-	g_object_unref (client);
-}
-
-void e_mapi_remove_esource (CamelService *service, const gchar * folder_name, const gchar *fid, gint folder_type)
-{
-	CamelNetworkSettings *network_settings;
-	CamelSettings *settings;
-	ESourceList *source_list = NULL;
-	ESourceGroup *group = NULL;
-	const gchar *conf_key = NULL;
-	GConfClient* client;
-	GSList *sources=NULL;
-	gchar *base_uri = NULL;
-	const gchar *host;
-	const gchar *user;
-
-	g_return_if_fail (CAMEL_IS_SERVICE (service));
-
-	if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT)
-		conf_key = CALENDAR_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_TASK)
-		conf_key = TASK_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_MEMO)
-		conf_key = JOURNAL_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_JOURNAL)
-		conf_key = JOURNAL_SOURCES;
-	else if (folder_type == MAPI_FOLDER_TYPE_CONTACT)
-		conf_key = ADDRESSBOOK_SOURCES;
-	else {
-		g_warning ("%s: %s: Unknown EMapiFolderType\n", G_STRLOC, G_STRFUNC);
-		return;
-	}
-
-	settings = camel_service_get_settings (service);
-
-	network_settings = CAMEL_NETWORK_SETTINGS (settings);
-	host = camel_network_settings_get_host (network_settings);
-	user = camel_network_settings_get_user (network_settings);
-
-	client = gconf_client_get_default ();
-	source_list = e_source_list_new_for_gconf (client, conf_key);
-	base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, user, host);
-	group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
-	sources = e_source_group_peek_sources (group);
-
-	for (; sources != NULL; sources = g_slist_next (sources)) {
-		ESource *source = E_SOURCE (sources->data);
-		gchar * folder_id = e_source_get_duped_property (source, "folder-id");
-		if (folder_id && fid)
-			if (strcmp(fid, folder_id) == 0) {
-				e_source_group_remove_source(group, source);
-				break;
-			}
-	}
-
-	g_free (base_uri);
-	g_object_unref (source_list);
-	g_object_unref (client);
-
-}
-
 static void
 remove_cal_esource (EAccount *existing_account_info, EMapiFolderType folder_type, CamelURL *url)
 {
@@ -584,13 +405,13 @@ remove_cal_esource (EAccount *existing_account_info, EMapiFolderType folder_type
 	GSList *node_tobe_deleted;
 	gchar *base_uri;
 
-	if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT) {
+	if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT) {
 		conf_key = CALENDAR_SOURCES;
 		source_selection_key = SELECTED_CALENDARS;
-	} else if (folder_type == MAPI_FOLDER_TYPE_TASK) {
+	} else if (folder_type == E_MAPI_FOLDER_TYPE_TASK) {
 		conf_key = TASK_SOURCES;
 		source_selection_key = SELECTED_TASKS;
-	} else if (folder_type == MAPI_FOLDER_TYPE_MEMO) {
+	} else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO) {
 		conf_key = JOURNAL_SOURCES;
 		source_selection_key = SELECTED_JOURNALS;
 	} else {
@@ -653,9 +474,9 @@ add_calendar_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid)
 		settings = g_object_new (CAMEL_TYPE_MAPI_SETTINGS, NULL);
 		camel_settings_load_from_url (settings, url);
 
-		add_cal_esource (account, folders, MAPI_FOLDER_TYPE_APPOINTMENT, url, settings, trash_fid);
-		add_cal_esource (account, folders, MAPI_FOLDER_TYPE_TASK, url, settings, trash_fid);
-		add_cal_esource (account, folders, MAPI_FOLDER_TYPE_MEMO, url, settings, trash_fid);
+		add_cal_esource (account, folders, E_MAPI_FOLDER_TYPE_APPOINTMENT, url, settings, trash_fid);
+		add_cal_esource (account, folders, E_MAPI_FOLDER_TYPE_TASK, url, settings, trash_fid);
+		add_cal_esource (account, folders, E_MAPI_FOLDER_TYPE_MEMO, url, settings, trash_fid);
 
 		g_object_unref (settings);
 		camel_url_free (url);
@@ -677,9 +498,9 @@ remove_calendar_sources_async (gpointer worker_data, gboolean cancelled, gpointe
 	url = camel_url_new (account->source->url, NULL);
 
 	if (url) {
-		remove_cal_esource (account, MAPI_FOLDER_TYPE_APPOINTMENT, url);
-		remove_cal_esource (account, MAPI_FOLDER_TYPE_TASK, url);
-		remove_cal_esource (account, MAPI_FOLDER_TYPE_MEMO, url);
+		remove_cal_esource (account, E_MAPI_FOLDER_TYPE_APPOINTMENT, url);
+		remove_cal_esource (account, E_MAPI_FOLDER_TYPE_TASK, url);
+		remove_cal_esource (account, E_MAPI_FOLDER_TYPE_MEMO, url);
 
 		camel_url_free (url);
 	}
@@ -763,7 +584,7 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
 		gchar *fid, *relative_uri;
 		gboolean is_new_source = FALSE;
 
-		if (folder->container_class != MAPI_FOLDER_TYPE_CONTACT || trash_fid == e_mapi_folder_get_parent_id (folder))
+		if (folder->container_class != E_MAPI_FOLDER_TYPE_CONTACT || trash_fid == e_mapi_folder_get_parent_id (folder))
 			continue;
 
 		fid = e_mapi_util_mapi_id_to_string (folder->folder_id);
@@ -869,7 +690,8 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
 			ESource *source = temp_list->data;
 
 			if (source && E_IS_SOURCE (source)) {
-				if (g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
+				if (!e_source_get_property (source, "foreign-username") &&
+				    g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
 					e_source_group_remove_source (group, source);
 			}
 		}
diff --git a/src/account-setup-eplugin/e-mapi-account-listener.h b/src/account-setup-eplugin/e-mapi-account-listener.h
index ff65549..795b19b 100644
--- a/src/account-setup-eplugin/e-mapi-account-listener.h
+++ b/src/account-setup-eplugin/e-mapi-account-listener.h
@@ -47,8 +47,6 @@ struct _EMapiAccountListenerClass {
 	GObjectClass parent_class;
 };
 
-void			e_mapi_add_esource			(CamelService *service, const gchar *folder_name, const gchar *fid, gint folder_type);
-void			e_mapi_remove_esource			(CamelService *service, const gchar *folder_name, const gchar *fid, gint folder_type);
 GType			e_mapi_account_listener_get_type	(void);
 EMapiAccountListener *	e_mapi_account_listener_new		(void);
 
diff --git a/src/account-setup-eplugin/e-mapi-account-settings.c b/src/account-setup-eplugin/e-mapi-account-settings.c
index ae55590..aab4d08 100644
--- a/src/account-setup-eplugin/e-mapi-account-settings.c
+++ b/src/account-setup-eplugin/e-mapi-account-settings.c
@@ -48,12 +48,11 @@
 #include <mail/em-folder-tree.h>
 
 #include "e-mapi-account-listener.h"
+#include "e-mapi-subscribe-foreign-folder.h"
 
 #define FOLDERSIZE_MENU_ITEM 0
 
-gboolean  e_plugin_ui_init (GtkUIManager *ui_manager,
-			    EShellView *shell_view);
-
+gboolean  e_plugin_ui_init (GtkUIManager *ui_manager, EShellView *shell_view);
 GtkWidget *org_gnome_e_mapi_settings (EPlugin *epl, EConfigHookItemFactoryData *data);
 
 enum {
@@ -218,9 +217,10 @@ folder_size_clicked (GtkButton *button,
 	mapi_settings_run_folder_size_dialog (profile, NULL);
 }
 
-static void
-action_folder_size_cb (GtkAction *action,
-		       EShellView *shell_view)
+static gchar *
+get_profile_name_from_folder_tree (EShellView *shell_view,
+				   gchar **pfolder_uri,
+				   CamelStore **pstore)
 {
 	EShellSidebar *shell_sidebar;
 	EMFolderTree *folder_tree;
@@ -260,11 +260,31 @@ action_folder_size_cb (GtkAction *action,
 				service = CAMEL_SERVICE (store);
 				settings = camel_service_get_settings (service);
 				g_object_get (settings, "profile", &profile, NULL);
+
+				if (pstore && profile)
+					*pstore = g_object_ref (store);
 			}
 		}
 	}
 
 	g_object_unref (folder_tree);
+
+	if (pfolder_uri)
+		*pfolder_uri = folder_uri;
+	else
+		g_free (folder_uri);
+
+	return profile;
+}
+
+static void
+action_folder_size_cb (GtkAction *action,
+		       EShellView *shell_view)
+{
+	gchar *folder_uri = NULL;
+	gchar *profile = NULL;
+
+	profile = get_profile_name_from_folder_tree (shell_view, &folder_uri, NULL);
 	g_return_if_fail (folder_uri != NULL);
 
 	if (g_str_has_prefix (folder_uri, "mapi://"))
@@ -275,47 +295,29 @@ action_folder_size_cb (GtkAction *action,
 }
 
 static void
-folder_size_actions_update_cb (EShellView *shell_view, GtkActionEntry *entries)
+action_subscribe_foreign_folder_cb (GtkAction *action,
+				    EShellView *shell_view)
 {
-	EShellWindow *shell_window;
-	GtkActionGroup *action_group;
-	GtkUIManager *ui_manager;
-	GtkAction *folder_size_action;
-
-	EShellSidebar *shell_sidebar;
-	EMFolderTree *folder_tree;
-	gchar *folder_uri = NULL;
-	CamelURL *url = NULL;
-	gboolean show_menu_entry = FALSE;
+	gchar *profile;
+	GtkWindow *parent;
+	EShellBackend *backend;
+	CamelSession *session = NULL;
+	CamelStore *store = NULL;
 
-	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
-	g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
-	folder_uri = em_folder_tree_get_selected_uri (folder_tree);
-	g_object_unref (folder_tree);
-	if (!(folder_uri && *folder_uri)) {
-		g_free (folder_uri);
+	profile = get_profile_name_from_folder_tree (shell_view, NULL, &store);
+	if (!profile)
 		return;
-	}
 
-	shell_window = e_shell_view_get_shell_window (shell_view);
+	g_free (profile);
 
-	ui_manager = e_shell_window_get_ui_manager (shell_window);
-	action_group = e_lookup_action_group (ui_manager, "mail");
+	parent = GTK_WINDOW (e_shell_view_get_shell_window (shell_view));
+	backend = e_shell_view_get_shell_backend (shell_view);
+	g_object_get (G_OBJECT (backend), "session", &session, NULL);
 
-	folder_size_action = gtk_action_group_get_action (action_group,
-							  "mail-mapi-folder-size");
+	e_mapi_subscribe_foreign_folder (parent, session, store);
 
-	/* Show / Hide action entry */
-	if (g_str_has_prefix (folder_uri, "mapi://")) {
-		show_menu_entry = TRUE;
-		url = camel_url_new (folder_uri, NULL);
-		if (url && url->path && strlen (url->path) > 1)
-			show_menu_entry = FALSE;
-		camel_url_free (url);
-	}
-
-	gtk_action_set_visible (folder_size_action, show_menu_entry);
-	g_free (folder_uri);
+	g_object_unref (session);
+	g_object_unref (store);
 }
 
 /* used only in Account Editor */
@@ -377,16 +379,96 @@ org_gnome_e_mapi_settings (EPlugin *epl, EConfigHookItemFactoryData *data)
 	return GTK_WIDGET (vsettings);
 }
 
-static GtkActionEntry folder_size_entries[] = {
+static GtkActionEntry folder_context_entries[] = {
 
 	{ "mail-mapi-folder-size",
 	  NULL,
-	  N_("Folder size"),
+	  N_("Folder size..."),
 	  NULL,
 	  NULL,  /* XXX Add a tooltip! */
-	  G_CALLBACK (action_folder_size_cb) }
+	  G_CALLBACK (action_folder_size_cb) },
+
+	{ "mail-mapi-subscribe-foreign-folder",
+	  NULL,
+	  N_("Subscribe to other user's folder..."),
+	  NULL,
+	  NULL,  /* XXX Add a tooltip! */
+	  G_CALLBACK (action_subscribe_foreign_folder_cb) }
 };
 
+static void
+mapi_plugin_update_actions_cb (EShellView *shell_view,
+			       GtkActionEntry *entries)
+{
+	EShellWindow *shell_window;
+	GtkActionGroup *action_group;
+	GtkUIManager *ui_manager;
+	EShellSidebar *shell_sidebar;
+	EMFolderTree *folder_tree;
+	gchar *folder_uri = NULL;
+	CamelURL *url = NULL;
+	gboolean show_menu_entry = FALSE;
+	gint ii;
+	GSList *actions = NULL, *iter;
+	gboolean online = FALSE;
+
+	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+	g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
+	folder_uri = em_folder_tree_get_selected_uri (folder_tree);
+	g_object_unref (folder_tree);
+	if (!(folder_uri && *folder_uri)) {
+		g_free (folder_uri);
+		return;
+	}
+
+	shell_window = e_shell_view_get_shell_window (shell_view);
+
+	ui_manager = e_shell_window_get_ui_manager (shell_window);
+	action_group = e_lookup_action_group (ui_manager, "mail");
+
+	for (ii = 0; ii < G_N_ELEMENTS (folder_context_entries); ii++) {
+		GtkAction *action;
+
+		action = gtk_action_group_get_action (action_group, folder_context_entries[ii].name);
+		if (action)
+			actions = g_slist_prepend (actions, action);
+	}
+
+	/* Show / Hide action entry */
+	if (g_str_has_prefix (folder_uri, "mapi://")) {
+		show_menu_entry = TRUE;
+		url = camel_url_new (folder_uri, NULL);
+		if (url && url->path && strlen (url->path) > 1)
+			show_menu_entry = FALSE;
+		camel_url_free (url);
+	}
+
+	g_free (folder_uri);
+
+	if (show_menu_entry) {
+		EShellBackend *backend;
+		CamelSession *session = NULL;
+
+		backend = e_shell_view_get_shell_backend (shell_view);
+		g_object_get (G_OBJECT (backend), "session", &session, NULL);
+
+		online = session && camel_session_get_online (session);
+
+		if (session)
+			g_object_unref (session);
+	}
+
+	for (iter = actions; iter; iter = iter->next) {
+		GtkAction *action = iter->data;
+
+		gtk_action_set_visible (action, show_menu_entry);
+		if (show_menu_entry)
+			gtk_action_set_sensitive (action, online);
+	}
+
+	g_slist_free (actions);
+}
+
 gboolean
 e_plugin_ui_init (GtkUIManager *ui_manager,
                   EShellView *shell_view)
@@ -399,11 +481,11 @@ e_plugin_ui_init (GtkUIManager *ui_manager,
 
 	/* Add actions to the "mail" action group. */
 	e_action_group_add_actions_localized (action_group, GETTEXT_PACKAGE,
-		folder_size_entries, G_N_ELEMENTS (folder_size_entries), shell_view);
+		folder_context_entries, G_N_ELEMENTS (folder_context_entries), shell_view);
 
 	/* Decide whether we want this option to be visible or not */
 	g_signal_connect (shell_view, "update-actions",
-			  G_CALLBACK (folder_size_actions_update_cb),
+			  G_CALLBACK (mapi_plugin_update_actions_cb),
 			  shell_view);
 
 	g_object_unref (action_group);
diff --git a/src/account-setup-eplugin/e-mapi-account-setup.c b/src/account-setup-eplugin/e-mapi-account-setup.c
index 10cd1f4..03d18ef 100644
--- a/src/account-setup-eplugin/e-mapi-account-setup.c
+++ b/src/account-setup-eplugin/e-mapi-account-setup.c
@@ -579,7 +579,7 @@ traverse_tree (GtkTreeModel *model, GtkTreeIter iter, EMapiFolderType folder_typ
 		}
 
 		gtk_tree_model_get (model, &iter, FOLDER_COL, &folder, -1);
-		if (folder && (e_mapi_folder_get_type (folder) == folder_type || (folder_type == MAPI_FOLDER_TYPE_MEMO && e_mapi_folder_get_type (folder) == MAPI_FOLDER_TYPE_JOURNAL))) {
+		if (folder && (e_mapi_folder_get_type (folder) == folder_type || (folder_type == E_MAPI_FOLDER_TYPE_MEMO && e_mapi_folder_get_type (folder) == E_MAPI_FOLDER_TYPE_JOURNAL))) {
 			sub_used = TRUE;
 		}
 
@@ -689,6 +689,20 @@ e_mapi_cursor_change (GtkTreeView *treeview, ESource *source)
 	}
 }
 
+static EMapiFolderCategory
+e_mapi_source_to_folder_category (ESource *source)
+{
+	g_return_val_if_fail (source != NULL, E_MAPI_FOLDER_CATEGORY_UNKNOWN);
+
+	if (e_source_get_property (source, "foreign-username"))
+		return E_MAPI_FOLDER_CATEGORY_FOREIGN;
+
+	if (g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0)
+		return E_MAPI_FOLDER_CATEGORY_PUBLIC;
+
+	return E_MAPI_FOLDER_CATEGORY_PERSONAL;
+}
+
 static GtkWidget *
 e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
 {
@@ -715,6 +729,15 @@ e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
 
 	e_plugin_util_add_check (parent, _("Lis_ten for server notifications"), source, "server-notification", "true", NULL);
 
+	switch (e_mapi_source_to_folder_category (source)) {
+	case E_MAPI_FOLDER_CATEGORY_FOREIGN:
+	case E_MAPI_FOLDER_CATEGORY_PUBLIC:
+		/* no extra options for subscribed folders */
+		return NULL;
+	default:
+		break;
+	}
+
 	folders = NULL;
 	group = e_source_peek_group (source);
 	profile = g_strdup (e_source_get_property (source, "profile"));
@@ -736,7 +759,7 @@ e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
 
 	table = g_object_new (GTK_TYPE_TABLE, NULL);
 
-	if (folder_type == MAPI_FOLDER_TYPE_CONTACT) {
+	if (folder_type == E_MAPI_FOLDER_TYPE_CONTACT) {
 		gtk_container_add (GTK_CONTAINER (parent), table);
 	} else {
 		g_object_get (parent, "n-rows", &row, NULL);
@@ -781,7 +804,7 @@ e_mapi_create_addressbook (EPlugin *epl, EConfigHookItemFactoryData *data)
 {
 	EABConfigTargetSource *t = (EABConfigTargetSource *) data->target;
 
-	return e_mapi_create (data->parent, t->source, MAPI_FOLDER_TYPE_CONTACT);
+	return e_mapi_create (data->parent, t->source, E_MAPI_FOLDER_TYPE_CONTACT);
 }
 
 GtkWidget *
@@ -792,13 +815,13 @@ e_mapi_create_calendar (EPlugin *epl, EConfigHookItemFactoryData *data)
 
 	switch (t->source_type) {
 	case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-		folder_type = MAPI_FOLDER_TYPE_APPOINTMENT;
+		folder_type = E_MAPI_FOLDER_TYPE_APPOINTMENT;
 		break;
 	case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-		folder_type = MAPI_FOLDER_TYPE_TASK;
+		folder_type = E_MAPI_FOLDER_TYPE_TASK;
 		break;
 	case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-		folder_type = MAPI_FOLDER_TYPE_MEMO;
+		folder_type = E_MAPI_FOLDER_TYPE_MEMO;
 		break;
 	default:
 		g_return_val_if_reached (NULL);
@@ -817,22 +840,49 @@ e_mapi_book_check (EPlugin *epl, EConfigHookPageCheckData *data)
 	if (!uri_text)
 		return TRUE;
 
-	/* FIXME: Offline handling */
-
 	/* not a MAPI account */
 	if (g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH)) {
 		g_free (uri_text);
 		return TRUE;
 	}
 
+	g_free (uri_text);
+
 	/* does not have a parent-fid which is needed for folder creation on server */
-	if (!e_source_get_property (source, "parent-fid")) {
-		g_free (uri_text);
-		return FALSE;
-	}
+	return e_source_get_property (source, "parent-fid") ||
+		e_source_get_property (source, "foreign-username") ||
+		g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
+}
 
-	g_free (uri_text);
-	return TRUE;
+static gboolean
+emas_open_folder (ESource *source,
+		  EMapiConnection *conn,
+		  mapi_id_t fid,
+		  mapi_object_t *obj_folder,
+		  GCancellable *cancellable,
+		  GError **perror)
+{
+	gchar *foreign_username;
+	gboolean is_public_folder;
+	gboolean res;
+
+	g_return_val_if_fail (source != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+	is_public_folder = g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
+	foreign_username = e_source_get_duped_property (source, "foreign-username");
+
+	if (foreign_username)
+		res = e_mapi_connection_open_foreign_folder (conn, foreign_username, fid, obj_folder, cancellable, perror);
+	else if (is_public_folder)
+		res = e_mapi_connection_open_public_folder (conn, fid, obj_folder, cancellable, perror);
+	else
+		res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+
+	g_free (foreign_username);
+
+	return res;
 }
 
 void
@@ -845,19 +895,35 @@ e_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
 	ESourceGroup *grp;
 	EMapiConnection *conn;
 	mapi_id_t fid, pfid;
+	mapi_object_t obj_folder;
 	GError *mapi_error = NULL;
 
 	uri_text = e_source_get_uri (source);
 	if (uri_text && g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH))
 		return;
 
+	switch (e_mapi_source_to_folder_category (source)) {
+	case E_MAPI_FOLDER_CATEGORY_FOREIGN:
+	case E_MAPI_FOLDER_CATEGORY_PUBLIC:
+		/* no extra changes for subscribed folders */
+		return;
+	default:
+		break;
+	}
+
 	e_mapi_util_mapi_id_from_string (e_source_get_property (source, "parent-fid"), &pfid);
 
 	/* the profile should be already connected */
 	conn = e_mapi_connection_find (e_source_get_property (source, "profile"));
 	g_return_if_fail (conn != NULL);
 
-	fid = e_mapi_connection_create_folder (conn, olFolderContacts, pfid, 0, e_source_peek_name (source), NULL, &mapi_error);
+	fid = 0;
+	if (emas_open_folder (source, conn, pfid, &obj_folder, NULL, NULL)) {
+		if (!e_mapi_connection_create_folder (conn, &obj_folder, e_source_peek_name (source), IPF_CONTACT, &fid, NULL, &mapi_error))
+			fid = 0;
+		e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
+	}
+
 	g_object_unref (conn);
 
 	if (!fid) {
@@ -875,7 +941,6 @@ e_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
 	r_uri = g_strconcat (";", sfid, NULL);
 	e_source_set_relative_uri (source, r_uri);
 
-	//FIXME: Offline handling
 	grp = e_source_peek_group (source);
 	e_source_set_property (source, "auth", "plain/password");
 	e_source_set_property(source, "user", NULL);
@@ -896,7 +961,6 @@ e_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
 	e_source_set_property (source, "public", "no");
 	e_source_set_property (source, "folder-id", sfid);
 
-	// Update the folder list in the plugin and EMapiFolder
 	g_free (r_uri);
 	g_free (sfid);
 
@@ -914,8 +978,6 @@ e_mapi_cal_check (EPlugin *epl, EConfigHookPageCheckData *data)
 	if (!uri_text)
 		return TRUE;
 
-	/* FIXME: Offline handling */
-
 	/* not a MAPI account */
 	if (g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH)) {
 		g_free (uri_text);
@@ -924,13 +986,9 @@ e_mapi_cal_check (EPlugin *epl, EConfigHookPageCheckData *data)
 
 	g_free (uri_text);
 
-	/* FIXME: Offline handling */
-
-	/* does not have a parent-fid which is needed for folder creation on server */
-	if (!e_source_get_property (source, "parent-fid"))
-		return FALSE;
-
-	return TRUE;
+	return e_source_get_property (source, "parent-fid") ||
+		e_source_get_property (source, "foreign-username") ||
+		g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
 }
 
 void
@@ -942,7 +1000,8 @@ e_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
 	ESource *source = t->source;
 	gchar *tmp, *sfid;
 	mapi_id_t fid, pfid;
-	uint32_t type;
+	mapi_object_t obj_folder;
+	const gchar *type;
 	gchar *uri_text = e_source_get_uri (source);
 	GError *mapi_error = NULL;
 
@@ -950,30 +1009,43 @@ e_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
 		return;
 	g_free (uri_text);
 
+	switch (e_mapi_source_to_folder_category (source)) {
+	case E_MAPI_FOLDER_CATEGORY_FOREIGN:
+	case E_MAPI_FOLDER_CATEGORY_PUBLIC:
+		/* no extra changes for subscribed folders */
+		return;
+	default:
+		break;
+	}
+
 	switch (t->source_type) {
 		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
-			type = olFolderCalendar;
+			type = IPF_APPOINTMENT;
 			break;
 		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
-			type = olFolderTasks;
+			type = IPF_TASK;
 			break;
 		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
-			type = olFolderNotes;
+			type = IPF_STICKYNOTE;
 			break;
 		default:
 			g_warning ("%s: %s: Unknown EMapiFolderType\n", G_STRLOC, G_STRFUNC);
 			return;
 	}
 
-	/* FIXME: Offline handling */
-
 	e_mapi_util_mapi_id_from_string (e_source_get_property (source, "parent-fid"), &pfid);
 
 	/* the profile should be already connected */
 	conn = e_mapi_connection_find (e_source_get_property (source, "profile"));
 	g_return_if_fail (conn != NULL);
 
-	fid = e_mapi_connection_create_folder (conn, type, pfid, 0, e_source_peek_name (source), NULL, &mapi_error);
+	fid = 0;
+	if (emas_open_folder (source, conn, pfid, &obj_folder, NULL, NULL)) {
+		if (!e_mapi_connection_create_folder (conn, &obj_folder, e_source_peek_name (source), type, &fid, NULL, &mapi_error))
+			fid = 0;
+		e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
+	}
+
 	g_object_unref (conn);
 
 	if (!fid) {
@@ -1050,3 +1122,145 @@ e_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
 	// Update the folder list in the plugin and EMapiFolder
 	return;
 }
+
+struct RunWithFeedbackData
+{
+	GtkWindow *parent;
+	GtkWidget *dialog;
+	GCancellable *cancellable;
+	GObject *with_object;
+	EMapiSetupFunc thread_func;
+	EMapiSetupFunc idle_func;
+	gpointer user_data;
+	GDestroyNotify free_user_data;
+	GError *error;
+};
+
+static void
+free_run_with_feedback_data (gpointer ptr)
+{
+	struct RunWithFeedbackData *rfd = ptr;
+
+	if (!rfd)
+		return;
+
+	if (rfd->dialog)
+		gtk_widget_destroy (rfd->dialog);
+
+	g_object_unref (rfd->cancellable);
+	g_object_unref (rfd->with_object);
+
+	if (rfd->free_user_data)
+		rfd->free_user_data (rfd->user_data);
+
+	g_clear_error (&rfd->error);
+
+	g_free (rfd);
+}
+
+static gboolean
+run_with_feedback_idle (gpointer user_data)
+{
+	struct RunWithFeedbackData *rfd = user_data;
+	gboolean was_cancelled = FALSE;
+
+	g_return_val_if_fail (rfd != NULL, FALSE);
+
+	if (!g_cancellable_is_cancelled (rfd->cancellable)) {
+		if (rfd->idle_func && !rfd->error)
+			rfd->idle_func (rfd->with_object, rfd->user_data, rfd->cancellable, &rfd->error);
+
+		was_cancelled = g_cancellable_is_cancelled (rfd->cancellable);
+
+		if (rfd->dialog) {
+			gtk_widget_destroy (rfd->dialog);
+			rfd->dialog = NULL;
+		}
+	}
+
+	if (!was_cancelled) {
+		if (rfd->error)
+			e_notice (rfd->parent, GTK_MESSAGE_ERROR, "%s", rfd->error->message);
+	}
+
+	free_run_with_feedback_data (rfd);
+
+	return FALSE;
+}
+
+static gpointer
+run_with_feedback_thread (gpointer user_data)
+{
+	struct RunWithFeedbackData *rfd = user_data;
+
+	g_return_val_if_fail (rfd != NULL, NULL);
+	g_return_val_if_fail (rfd->thread_func != NULL, NULL);
+
+	if (!g_cancellable_is_cancelled (rfd->cancellable))
+		rfd->thread_func (rfd->with_object, rfd->user_data, rfd->cancellable, &rfd->error);
+
+	g_idle_add (run_with_feedback_idle, rfd);
+
+	return NULL;
+}
+
+static void
+run_with_feedback_response_cb (GtkWidget *dialog,
+			       gint resonse_id,
+			       struct RunWithFeedbackData *rfd)
+{
+	g_return_if_fail (rfd != NULL);
+
+	rfd->dialog = NULL;
+	g_cancellable_cancel (rfd->cancellable);
+
+	gtk_widget_destroy (dialog);
+}
+
+void
+e_mapi_run_in_thread_with_feedback (GtkWindow *parent,
+				    GObject *with_object,
+				    const gchar *description,
+				    EMapiSetupFunc thread_func,
+				    EMapiSetupFunc idle_func,
+				    gpointer user_data,
+				    GDestroyNotify free_user_data)
+{
+	GtkWidget *dialog, *label, *content;
+	struct RunWithFeedbackData *rfd;
+
+	g_return_if_fail (with_object != NULL);
+	g_return_if_fail (description != NULL);
+	g_return_if_fail (thread_func != NULL);
+
+	dialog = gtk_dialog_new_with_buttons ("",
+		parent,
+		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+		NULL);
+
+	label = gtk_label_new (description);
+	gtk_widget_show (label);
+
+	content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+	gtk_container_add (GTK_CONTAINER (content), label);
+	gtk_container_set_border_width (GTK_CONTAINER (content), 12);
+
+	rfd = g_new0 (struct RunWithFeedbackData, 1);
+	rfd->parent = parent;
+	rfd->dialog = dialog;
+	rfd->cancellable = g_cancellable_new ();
+	rfd->with_object = g_object_ref (with_object);
+	rfd->thread_func = thread_func;
+	rfd->idle_func = idle_func;
+	rfd->user_data = user_data;
+	rfd->free_user_data = free_user_data;
+	rfd->error = NULL;
+
+	g_signal_connect (dialog, "response", G_CALLBACK (run_with_feedback_response_cb), rfd);
+
+	gtk_widget_show (dialog);
+
+	g_return_if_fail (g_thread_create (run_with_feedback_thread, rfd, FALSE, NULL));
+}
diff --git a/src/account-setup-eplugin/e-mapi-account-setup.h b/src/account-setup-eplugin/e-mapi-account-setup.h
index e268dd6..7551db8 100644
--- a/src/account-setup-eplugin/e-mapi-account-setup.h
+++ b/src/account-setup-eplugin/e-mapi-account-setup.h
@@ -24,12 +24,26 @@
 #ifndef E_MAPI_ACCOUNT_SETUP_H
 #define E_MAPI_ACCOUNT_SETUP_H
 
+#include <gtk/gtk.h>
+
 #include "e-mapi-account-listener.h"
 
 #define MAPI_URI_PREFIX   "mapi://" 
 #define MAPI_PREFIX_LENGTH 7
 
-EMapiAccountListener *
-e_mapi_accounts_peek_config_listener (void);
+EMapiAccountListener *	e_mapi_accounts_peek_config_listener	(void);
+
+typedef void		(* EMapiSetupFunc)			(GObject *with_object,
+								 gpointer user_data,
+								 GCancellable *cancellable,
+								 GError **perror);
+
+void			e_mapi_run_in_thread_with_feedback	(GtkWindow *parent,
+								 GObject *with_object,
+								 const gchar *description,
+								 EMapiSetupFunc thread_func,
+								 EMapiSetupFunc idle_func,
+								 gpointer user_data,
+								 GDestroyNotify free_user_data);
 
 #endif /* E_MAPI_ACCOUNT_SETUP_H */
diff --git a/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c
new file mode 100644
index 0000000..e2e1dd5
--- /dev/null
+++ b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c
@@ -0,0 +1,647 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * 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/>
+ *
+ *
+ * Authors:
+ *    Milan Crha <mcrha redhat com>
+ *
+ * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include <libedataserverui/e-name-selector.h>
+
+#include "camel/camel-mapi-store.h"
+#include "camel/camel-mapi-store-summary.h"
+
+#include "e-mapi-account-setup.h"
+#include "e-mapi-subscribe-foreign-folder.h"
+#include "e-mapi-debug.h"
+#include "e-mapi-utils.h"
+
+#ifndef PidTagMailboxOwnerName
+#define PidTagMailboxOwnerName PR_USER_NAME_UNICODE
+#endif
+
+#define STR_USER_NAME_SELECTOR_ENTRY	"e-mapi-name-selector-entry"
+#define STR_FOLDER_NAME_COMBO		"e-mapi-folder-name-combo"
+#define STR_MAPI_CAMEL_SESSION		"e-mapi-camel-session"
+#define STR_MAPI_CAMEL_STORE		"e-mapi-camel-store"
+
+static gboolean
+add_foreign_folder_to_camel (CamelMapiStore *mapi_store,
+			     const gchar *foreign_username,
+			     mapi_id_t folder_id,
+			     mapi_id_t parent_fid,
+			     const gchar *display_username,
+			     const gchar *display_foldername,
+			     GError **perror)
+{
+	gint ii, sz;
+	gboolean res = TRUE;
+	gchar *parent_path = NULL;
+	CamelStoreInfo *parent_si = NULL;
+
+	g_return_val_if_fail (mapi_store != NULL, FALSE);
+	g_return_val_if_fail (mapi_store->summary != NULL, FALSE);
+	g_return_val_if_fail (foreign_username != NULL, FALSE);
+	g_return_val_if_fail (folder_id != 0, FALSE);
+	g_return_val_if_fail (folder_id != parent_fid, FALSE);
+	g_return_val_if_fail (display_username != NULL, FALSE);
+	g_return_val_if_fail (display_foldername != NULL, FALSE);
+
+	sz = camel_store_summary_count (mapi_store->summary);
+	for (ii = 0; res && ii < sz; ii++) {
+		CamelStoreInfo *si;
+		CamelMapiStoreInfo *msi;
+
+		si = camel_store_summary_index (mapi_store->summary, ii);
+		if (!si)
+			continue;
+
+		msi = (CamelMapiStoreInfo *) si;
+
+		/* folder_id is unique even between users, thus can just check for it */
+		if (msi->folder_id == folder_id) {
+			res = FALSE;
+			g_propagate_error (perror,
+				g_error_new (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+				_("Cannot add folder, folder already exists as '%s'"), camel_store_info_path (mapi_store->summary, si)));
+		} else if (parent_fid != 0 && msi->folder_id == parent_fid) {
+			if (g_strcmp0 (foreign_username, msi->foreign_username) == 0) {
+				g_free (parent_path);
+				parent_path = g_strdup (camel_store_info_path (mapi_store->summary, si));
+				parent_si = si;
+				camel_store_summary_info_ref (mapi_store->summary, parent_si);
+			} else {
+				g_debug ("%s: parent folder '%s' with other user '%s' than expected '%s', skipping chain",
+					G_STRFUNC, camel_store_info_path (mapi_store->summary, si), msi->foreign_username, foreign_username);
+			}
+		}
+
+		camel_store_summary_info_free (mapi_store->summary, si);
+	}
+
+	if (res) {
+		gchar *path;
+
+		if (!parent_path) {
+			gchar *mailbox;
+
+			/* Translators: The '%s' is replaced with user name, to whom the foreign mailbox belongs.
+			   Example result: "Mailbox - John Smith"
+			*/
+			mailbox = g_strdup_printf (C_("ForeignFolder", "Mailbox - %s"), display_username);
+			parent_path = g_strdup_printf ("%s/%s", DISPLAY_NAME_FOREIGN_FOLDERS, mailbox);
+
+			g_free (mailbox);
+		}
+
+		path = g_strconcat (parent_path, "/", display_foldername, NULL);
+
+		/* make sure the path is unique */
+		camel_mapi_store_ensure_unique_path (mapi_store, &path);
+
+		if (camel_mapi_store_summary_add_from_full (mapi_store->summary, path, folder_id, parent_fid,
+			CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_SUBSCRIBED,
+			CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL,
+			foreign_username)) {
+			if (parent_si) {
+				CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) parent_si;
+
+				msi->camel_folder_flags = msi->camel_folder_flags & (~CAMEL_FOLDER_NOCHILDREN);
+			}
+
+			camel_store_summary_touch (mapi_store->summary);
+			camel_store_summary_save (mapi_store->summary);
+
+			camel_mapi_store_announce_subscribed_folder (mapi_store, path);
+		} else {
+			res = FALSE;
+			g_propagate_error (perror,
+				g_error_new (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+				_("Cannot add folder, failed to add to store's summary")));
+		}
+
+		g_free (path);
+	}
+
+	if (parent_si)
+		camel_store_summary_info_free (mapi_store->summary, parent_si);
+	g_free (parent_path);
+
+	return res;
+}
+
+static void
+name_entry_changed_cb (GObject *dialog)
+{
+	GtkEntry *entry;
+	const gchar *text;
+
+	g_return_if_fail (dialog != NULL);
+
+	entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+	g_return_if_fail (entry != NULL);
+
+	text = gtk_entry_get_text (entry);
+
+	gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, text && *text && *text != ' ' && *text != ',');
+}
+
+struct EMapiCheckForeignFolderData
+{
+	GtkWidget *dialog;
+	gchar *username;
+	gchar *user_displayname;
+	gchar *orig_foldername;
+	gchar *use_foldername;
+	gchar *folder_displayname;
+	gchar *folder_container_class;
+	mapi_id_t folder_id;
+	mapi_id_t parent_folder_id;
+};
+
+static void
+e_mapi_check_foreign_folder_data_free (gpointer ptr)
+{
+	struct EMapiCheckForeignFolderData *cffd = ptr;
+
+	if (!cffd)
+		return;
+
+	g_free (cffd->username);
+	g_free (cffd->user_displayname);
+	g_free (cffd->orig_foldername);
+	g_free (cffd->use_foldername);
+	g_free (cffd->folder_displayname);
+	g_free (cffd->folder_container_class);
+
+	/* folder_id tells whether successfully finished,
+	   then the dialog can be destroyed */
+	if (cffd->folder_id && cffd->dialog)
+		gtk_widget_destroy (cffd->dialog);
+
+	g_free (cffd);
+}
+
+static gboolean
+check_foreign_username_resolved_cb (EMapiConnection *conn,
+				    TALLOC_CTX *mem_ctx,
+				    /* const */ struct mapi_SPropValue_array *properties,
+				    gpointer user_data,
+				    GCancellable *cancellable,
+				    GError **perror)
+{
+	struct EMapiCheckForeignFolderData *cffd = user_data;
+
+	g_return_val_if_fail (properties != NULL, FALSE);
+	g_return_val_if_fail (cffd != NULL, FALSE);
+	g_return_val_if_fail (cffd->user_displayname == NULL, FALSE);
+
+	cffd->user_displayname = g_strdup (e_mapi_util_find_array_propval (properties, PidTagDisplayName));
+
+	return TRUE;
+}
+
+static gboolean
+foreign_folder_add_props_cb (EMapiConnection *conn,
+			     TALLOC_CTX *mem_ctx,
+			     struct SPropTagArray *props,
+			     gpointer data,
+			     GCancellable *cancellable,
+			     GError **perror)
+{
+	g_return_val_if_fail (mem_ctx != NULL, FALSE);
+	g_return_val_if_fail (props != NULL, FALSE);
+
+	SPropTagArray_add (mem_ctx, props, PidTagDisplayName);
+	SPropTagArray_add (mem_ctx, props, PidTagContainerClass);
+	SPropTagArray_add (mem_ctx, props, PidTagParentFolderId);
+
+	return TRUE;
+}
+
+static gboolean
+foreign_folder_get_props_cb (EMapiConnection *conn,
+			     TALLOC_CTX *mem_ctx,
+			     /* const */ struct mapi_SPropValue_array *properties,
+			     gpointer user_data,
+			     GCancellable *cancellable,
+			     GError **perror)
+{
+	struct EMapiCheckForeignFolderData *cffd = user_data;
+	const mapi_id_t *pid;
+
+	g_return_val_if_fail (properties != NULL, FALSE);
+	g_return_val_if_fail (cffd != NULL, FALSE);
+	g_return_val_if_fail (cffd->folder_displayname == NULL, FALSE);
+	g_return_val_if_fail (cffd->folder_container_class == NULL, FALSE);
+
+	pid = e_mapi_util_find_array_propval (properties, PidTagParentFolderId);
+
+	cffd->folder_displayname = g_strdup (e_mapi_util_find_array_propval (properties, PidTagDisplayName));
+	cffd->folder_container_class = g_strdup (e_mapi_util_find_array_propval (properties, PidTagContainerClass));
+	cffd->parent_folder_id = pid ? *pid : 0;
+
+	return TRUE;
+}
+
+static void
+check_foreign_folder_thread (GObject *with_object,
+			     gpointer user_data,
+			     GCancellable *cancellable,
+			     GError **perror)
+{
+	struct EMapiCheckForeignFolderData *cffd = user_data;
+	GError *local_error = NULL;
+	EMapiConnection *conn;
+	mapi_object_t obj_folder;
+	mapi_id_t fid = 0;
+
+	g_return_if_fail (with_object != NULL);
+	g_return_if_fail (CAMEL_IS_MAPI_STORE (with_object));
+	g_return_if_fail (user_data != NULL);
+	g_return_if_fail (cffd->username != NULL);
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		return;
+
+	conn = camel_mapi_store_get_connection (CAMEL_MAPI_STORE (with_object));
+	if (!conn || !e_mapi_connection_connected (conn)) {
+		make_mapi_error (perror, "EMapiConnection", MAPI_E_NOT_INITIALIZED);
+		return;
+	}
+
+	if (!e_mapi_connection_resolve_username (conn, cffd->username,
+		NULL, NULL,
+		check_foreign_username_resolved_cb, cffd,
+		cancellable, perror)) {
+		make_mapi_error (perror, "e_mapi_connection_resolve_username", MAPI_E_CALL_FAILED);
+		return;
+	}
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		return;
+	}
+
+	if (!e_mapi_connection_test_foreign_folder (conn, cffd->username,
+		cffd->use_foldername ? cffd->use_foldername : cffd->orig_foldername,
+		&fid, cancellable, &local_error)) {
+		if (g_error_matches (local_error, E_MAPI_ERROR, MAPI_E_NOT_FOUND)) {
+			g_clear_error (&local_error);
+			local_error = g_error_new (E_MAPI_ERROR, MAPI_E_NOT_FOUND,
+				_("Folder '%s' not found. Either it does not exist or you do not have permission to access it."),
+				cffd->orig_foldername);
+		}
+
+		g_propagate_error (perror, local_error);
+		return;
+	}
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		return;
+	}
+
+	if (!e_mapi_connection_open_foreign_folder (conn, cffd->username, fid, &obj_folder, cancellable, perror)) {
+		make_mapi_error (perror, "e_mapi_connection_open_foreign_folder", MAPI_E_CALL_FAILED);
+		return;
+	}
+
+	if (!e_mapi_connection_get_folder_properties (conn, &obj_folder,
+		foreign_folder_add_props_cb, NULL,
+		foreign_folder_get_props_cb, cffd,
+		cancellable, perror)) {
+		make_mapi_error (perror, "e_mapi_connection_get_folder_properties", MAPI_E_CALL_FAILED);
+
+		e_mapi_connection_close_folder (conn, &obj_folder, cancellable, perror);
+		return;
+	}
+
+	e_mapi_connection_close_folder (conn, &obj_folder, cancellable, perror);
+
+	if (!cffd->folder_container_class) {
+		g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_CALL_FAILED, _("Cannot add folder, cannot determine folder's type")));
+		return;
+	}
+
+	cffd->folder_id = fid;
+}
+
+static void
+check_foreign_folder_idle (GObject *with_object,
+			   gpointer user_data,
+			   GCancellable *cancellable,
+			   GError **perror)
+{
+	struct EMapiCheckForeignFolderData *cffd = user_data;
+	gchar *fid, *folder_name;
+	const gchar *base_username, *base_foldername;
+	CamelSettings *settings;
+	CamelMapiSettings *mapi_settings;
+	CamelMapiStore *mapi_store;
+	CamelNetworkSettings *network_settings;
+	EMapiFolderType folder_type;
+
+	g_return_if_fail (with_object != NULL);
+	g_return_if_fail (CAMEL_IS_MAPI_STORE (with_object));
+	g_return_if_fail (user_data != NULL);
+	g_return_if_fail (cffd->username != NULL);
+	g_return_if_fail (cffd->folder_container_class != NULL);
+
+	if (!cffd->folder_id)
+		return;
+
+	fid = e_mapi_util_mapi_id_to_string (cffd->folder_id);
+	g_return_if_fail (fid != NULL);
+
+	base_username = cffd->user_displayname ? cffd->user_displayname : cffd->username;
+	base_foldername = cffd->folder_displayname ? cffd->folder_displayname : cffd->orig_foldername;
+
+	/* Translators: This is used to name foreign folder.
+	   The first '%s' is replaced with user name to whom the folder belongs,
+	   the second '%s' is replaced with folder name.
+	   Example result: "John Smith - Calendar"
+	*/
+	folder_name = g_strdup_printf (C_("ForeignFolder", "%s - %s"), base_username, base_foldername);
+
+	mapi_store = CAMEL_MAPI_STORE (with_object);
+	settings = camel_service_get_settings (CAMEL_SERVICE (mapi_store));
+	mapi_settings = CAMEL_MAPI_SETTINGS (settings);
+	network_settings = CAMEL_NETWORK_SETTINGS (settings);
+
+	folder_type = e_mapi_folder_type_from_string (cffd->folder_container_class);
+	if ((folder_type == E_MAPI_FOLDER_TYPE_MAIL &&
+	     !add_foreign_folder_to_camel (mapi_store,
+		cffd->username,
+		cffd->folder_id,
+		cffd->parent_folder_id,
+		base_username,
+		base_foldername,
+		perror)) ||
+	    (folder_type != E_MAPI_FOLDER_TYPE_MAIL && !e_mapi_folder_add_as_esource (folder_type,
+		camel_mapi_settings_get_profile (mapi_settings),
+		camel_mapi_settings_get_domain (mapi_settings),
+		camel_mapi_settings_get_realm (mapi_settings),
+		camel_network_settings_get_host (network_settings),
+		camel_network_settings_get_user (network_settings),
+		camel_mapi_settings_get_kerberos (mapi_settings),
+		camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (mapi_settings)),
+		E_MAPI_FOLDER_CATEGORY_FOREIGN,
+		cffd->username,
+		folder_name,
+		fid,
+		perror))) {
+		/* to not destroy the dialog on error */
+		cffd->folder_id = 0;
+	}
+
+	g_free (folder_name);
+	g_free (fid);
+}
+
+static void
+subscribe_foreign_response_cb (GObject *dialog,
+			       gint response_id)
+{
+	struct EMapiCheckForeignFolderData *cffd;
+	ENameSelectorEntry *entry;
+	GtkComboBoxText *combo_text;
+	EDestinationStore *dest_store;
+	CamelStore *cstore;
+	gchar *description;
+	const gchar *username;
+	gchar *orig_foldername, *use_foldername = NULL;
+
+	if (response_id != GTK_RESPONSE_OK) {
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		return;
+	}
+
+	g_return_if_fail (dialog != NULL);
+
+	entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+	combo_text = g_object_get_data (dialog, STR_FOLDER_NAME_COMBO);
+	cstore = g_object_get_data (dialog, STR_MAPI_CAMEL_STORE);
+
+	g_return_if_fail (entry != NULL);
+	g_return_if_fail (cstore != NULL);
+
+	username = NULL;
+	dest_store = e_name_selector_entry_peek_destination_store (entry);
+	if (dest_store && e_destination_store_get_destination_count (dest_store) > 0) {
+		EDestination *dest;
+		GList *dests = e_destination_store_list_destinations (dest_store);
+
+		g_return_if_fail (dests != NULL);
+
+		/* pick the first, there is no option to limit to only one destination */
+		dest = dests->data;
+		if (dest) {
+			username = e_destination_get_email (dest);
+			if (!username || !*username)
+				username = e_destination_get_name (dest);
+		}
+
+		g_list_free (dests);
+	}
+
+	if (!username || !*username)
+		username = gtk_entry_get_text (GTK_ENTRY (entry));
+
+	orig_foldername = gtk_combo_box_text_get_active_text (combo_text);
+	if (!orig_foldername)
+		orig_foldername = g_strdup ("");
+
+	/* convert well-known names to their non-localized form */
+	if (g_strcmp0 (orig_foldername, _("Inbox")) == 0) {
+		use_foldername = g_strdup ("Inbox");
+	} else if (g_strcmp0 (orig_foldername, _("Contacts")) == 0) {
+		use_foldername = g_strdup ("Contacts");
+	} else if (g_strcmp0 (orig_foldername, _("Calendar")) == 0) {
+		use_foldername = g_strdup ("Calendar");
+	} else if (g_strcmp0 (orig_foldername, _("Memos")) == 0) {
+		use_foldername = g_strdup ("Notes");
+	} else if (g_strcmp0 (orig_foldername, _("Tasks")) == 0) {
+		use_foldername = g_strdup ("Tasks");
+	}
+
+	cffd = g_new0 (struct EMapiCheckForeignFolderData, 1);
+	cffd->dialog = GTK_WIDGET (dialog);
+	cffd->username = g_strdup (username ? username : "");
+	cffd->orig_foldername = orig_foldername;
+	cffd->use_foldername = use_foldername;
+	cffd->folder_id = 0;
+	cffd->parent_folder_id = 0;
+
+	description = g_strdup_printf (_("Testing availability of folder '%s' of user '%s', please wait..."), cffd->orig_foldername, cffd->username);
+
+	e_mapi_run_in_thread_with_feedback (
+		GTK_WINDOW (dialog),
+		G_OBJECT (cstore),
+		description,
+		check_foreign_folder_thread,
+		check_foreign_folder_idle,
+		cffd,
+		e_mapi_check_foreign_folder_data_free);
+
+	g_free (description);
+}
+
+/* Opens dialog to subscribe to folders of other
+   users in the given store */
+void
+e_mapi_subscribe_foreign_folder	(GtkWindow *parent,
+				 CamelSession *session,
+				 CamelStore *store)
+{
+	PangoAttrList *attrs;
+	ENameSelector *name_selector;
+	ENameSelectorModel *name_selector_model;
+	ENameSelectorDialog *name_selector_dialog;
+	GObject *dialog;
+	GtkWidget *content;
+	GtkWidget *label, *widget, *entry;
+	GtkGrid *grid;
+	GtkComboBoxText *combo_text;
+	gint row;
+
+	g_return_if_fail (session != NULL);
+	g_return_if_fail (store != NULL);
+	g_return_if_fail (CAMEL_IS_MAPI_STORE (store));
+
+	dialog = G_OBJECT (gtk_dialog_new_with_buttons (
+		_("Subscribe to other MAPI user's folder..."),
+		parent,
+		GTK_DIALOG_DESTROY_WITH_PARENT,
+		GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+		GTK_STOCK_OK, GTK_RESPONSE_OK,
+		NULL));
+
+	g_signal_connect (dialog, "response", G_CALLBACK (subscribe_foreign_response_cb), NULL);
+
+	content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+	grid = GTK_GRID (gtk_grid_new ());
+	gtk_grid_set_row_homogeneous (grid, FALSE);
+	gtk_grid_set_row_spacing (grid, 6);
+	gtk_grid_set_column_homogeneous (grid, FALSE);
+	gtk_grid_set_column_spacing (grid, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
+	gtk_container_add (GTK_CONTAINER (content), GTK_WIDGET (grid));
+
+	row = 0;
+
+	label = gtk_label_new (_("Account:"));
+	g_object_set (G_OBJECT (label),
+		"hexpand", FALSE,
+		"vexpand", FALSE,
+		"xalign", 0.0,
+		"halign", GTK_ALIGN_START,
+		NULL);
+
+	attrs = pango_attr_list_new ();
+	pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+	widget = gtk_label_new (camel_service_get_display_name (CAMEL_SERVICE (store)));
+	g_object_set (G_OBJECT (widget),
+		"hexpand", TRUE,
+		"vexpand", FALSE,
+		"use-underline", FALSE,
+		"attributes", attrs,
+		"xalign", 0.0,
+		"halign", GTK_ALIGN_START,
+		NULL);
+	pango_attr_list_unref (attrs);
+
+	gtk_grid_attach (grid, label, 0, row, 1, 1);
+	gtk_grid_attach (grid, widget, 1, row, 3, 1);
+
+	row++;
+
+	name_selector = e_name_selector_new ();
+	name_selector_model = e_name_selector_peek_model (name_selector);
+	e_name_selector_model_add_section (name_selector_model, "User", _("User"), NULL);
+	name_selector_dialog = e_name_selector_peek_dialog (name_selector);
+	g_signal_connect (name_selector_dialog, "response", G_CALLBACK (gtk_widget_hide), name_selector);
+	e_name_selector_load_books (name_selector);
+
+	g_object_set_data_full (dialog, "e-mapi-name-selector", name_selector, g_object_unref);
+
+	label = gtk_label_new_with_mnemonic (_("_User:"));
+	g_object_set (G_OBJECT (label),
+		"hexpand", FALSE,
+		"vexpand", FALSE,
+		"xalign", 0.0,
+		NULL);
+
+	entry = GTK_WIDGET (e_name_selector_peek_section_entry (name_selector, "User"));
+	g_object_set (G_OBJECT (entry),
+		"hexpand", TRUE,
+		"vexpand", FALSE,
+		NULL);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+	gtk_grid_attach (grid, label, 0, row, 1, 1);
+	gtk_grid_attach (grid, entry, 1, row, 1, 1);
+
+	row++;
+
+	label = gtk_label_new_with_mnemonic (_("_Folder name:"));
+	g_object_set (G_OBJECT (label),
+		"hexpand", FALSE,
+		"vexpand", FALSE,
+		"xalign", 0.0,
+		NULL);
+
+	widget = GTK_WIDGET (g_object_new (gtk_combo_box_text_get_type (),
+		"has-entry", TRUE,
+		"entry-text-column", 0,
+		"hexpand", TRUE,
+		"vexpand", FALSE,
+		NULL));
+
+	combo_text = GTK_COMBO_BOX_TEXT (widget);
+	gtk_combo_box_text_append_text (combo_text, _("Inbox"));
+	gtk_combo_box_text_append_text (combo_text, _("Contacts"));
+	gtk_combo_box_text_append_text (combo_text, _("Calendar"));
+	gtk_combo_box_text_append_text (combo_text, _("Memos"));
+	gtk_combo_box_text_append_text (combo_text, _("Tasks"));
+	gtk_combo_box_set_active (GTK_COMBO_BOX (combo_text), 0);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+	gtk_grid_attach (grid, label, 0, row, 1, 1);
+	gtk_grid_attach (grid, widget, 1, row, 2, 1);
+
+	/* remember widgets for later use */
+	g_object_set_data (dialog, STR_USER_NAME_SELECTOR_ENTRY, entry);
+	g_object_set_data (dialog, STR_FOLDER_NAME_COMBO, widget);
+
+	g_object_set_data_full (dialog, STR_MAPI_CAMEL_SESSION, g_object_ref (session), g_object_unref);
+	g_object_set_data_full (dialog, STR_MAPI_CAMEL_STORE, g_object_ref (store), g_object_unref);
+
+	g_signal_connect_swapped (entry, "changed", G_CALLBACK (name_entry_changed_cb), dialog);
+
+	name_entry_changed_cb (dialog);
+
+	gtk_widget_show_all (content);
+	gtk_widget_show (GTK_WIDGET (dialog));
+}
diff --git a/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.h b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.h
new file mode 100644
index 0000000..debf5b5
--- /dev/null
+++ b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * 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/>
+ *
+ *
+ * Authors:
+ *    Milan Crha <mcrha redhat com>
+ *
+ * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_MAPI_SUBSCRIBE_FOREIGN_FOLDER_H
+#define E_MAPI_SUBSCRIBE_FOREIGN_FOLDER_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+
+void	e_mapi_subscribe_foreign_folder	(GtkWindow *parent,
+					 CamelSession *session,
+					 CamelStore *store);
+
+#endif /* E_MAPI_SUBSCRIBE_FOREIGN_FOLDER_H */
diff --git a/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml b/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
index 30207c4..849aee0 100644
--- a/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
+++ b/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
@@ -82,6 +82,7 @@
 		    <popup name="mail-folder-popup">
 		      <placeholder name="mail-folder-popup-actions">
 			<menuitem action="mail-mapi-folder-size"/>
+			<menuitem action="mail-mapi-subscribe-foreign-folder"/>
 		      </placeholder>
 		    </popup>
 		  </ui-manager>
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index 0b77f9f..32ef991 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -54,8 +54,33 @@ struct _EBookBackendMAPIContactsPrivate
 {
 	mapi_id_t fid;
 	gboolean is_public_folder;
+	gchar *foreign_username; /* NULL, if not a foreign folder */
 };
 
+static gboolean
+ebbm_contacts_open_folder (EBookBackendMAPIContacts *ebmac,
+			   EMapiConnection *conn,
+			   mapi_object_t *obj_folder,
+			   GCancellable *cancellable,
+			   GError **perror)
+{
+	gboolean res;
+
+	g_return_val_if_fail (ebmac != NULL, FALSE);
+	g_return_val_if_fail (ebmac->priv != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+	if (ebmac->priv->foreign_username)
+		res = e_mapi_connection_open_foreign_folder (conn, ebmac->priv->foreign_username, ebmac->priv->fid, obj_folder, cancellable, perror);
+	else if (ebmac->priv->is_public_folder)
+		res = e_mapi_connection_open_public_folder (conn, ebmac->priv->fid, obj_folder, cancellable, perror);
+	else
+		res = e_mapi_connection_open_personal_folder (conn, ebmac->priv->fid, obj_folder, cancellable, perror);
+
+	return res;
+}
+
 typedef struct {
 	EContact *contact;
 	EBookBackendSqliteDB *db;
@@ -305,9 +330,14 @@ ebbm_contacts_open (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean
 
 	priv->fid = 0;
 	priv->is_public_folder = g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
-
+	priv->foreign_username = e_source_get_duped_property (source, "foreign-username");
 	e_mapi_util_mapi_id_from_string (e_source_get_property (source, "folder-id"), &priv->fid);
 
+	if (priv->foreign_username && !*priv->foreign_username) {
+		g_free (priv->foreign_username);
+		priv->foreign_username = NULL;
+	}
+
 	/* Chain up to parent's op_load_source() method. */
 	if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open)
 		E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open (ebma, cancellable, only_if_exists, &err);
@@ -320,7 +350,6 @@ static void
 ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_online)
 {
 	ESource *source;
-	EBookBackendMAPIContactsPrivate *priv = ((EBookBackendMAPIContacts *) ebma)->priv;
 
 	e_book_backend_notify_readonly (E_BOOK_BACKEND (ebma), !is_online);
 
@@ -341,10 +370,7 @@ ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_onl
 			return;
 		}
 
-		if (priv->is_public_folder)
-			status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, NULL, NULL);
-		else
-			status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, NULL, NULL);
+		status = ebbm_contacts_open_folder (E_BOOK_BACKEND_MAPI_CONTACTS (ebma), conn, &obj_folder, NULL, NULL);
 
 		if (status) {
 			e_mapi_connection_enable_notifications (conn, &obj_folder,
@@ -381,7 +407,7 @@ ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError
 		return;
 	}
 
-	if (!priv->is_public_folder) {
+	if (!priv->is_public_folder && !priv->foreign_username) {
 		EMapiConnection *conn;
 
 		e_book_backend_mapi_lock_connection (ebma);
@@ -390,7 +416,10 @@ ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError
 		if (!conn) {
 			g_propagate_error (error, EDB_ERROR (OFFLINE_UNAVAILABLE));
 		} else {
-			e_mapi_connection_remove_folder (conn, priv->fid, 0, cancellable, &mapi_error);
+			mapi_object_t *obj_store = NULL;
+
+			if (e_mapi_connection_peek_store (conn, priv->foreign_username ? FALSE : priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error))
+				e_mapi_connection_remove_folder (conn, obj_store, priv->fid, cancellable, &mapi_error);
 
 			if (mapi_error) {
 				mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to remove public folder"));
@@ -451,10 +480,7 @@ ebbm_contacts_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
 	e_book_backend_mapi_get_db (ebma, &mcd.db);
 	mcd.contact = contact;
 
-	if (priv->is_public_folder)
-		status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+	status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 	if (status) {
 		e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
@@ -495,6 +521,7 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
 	GError *mapi_error = NULL;
 	GSList *to_remove;
 	const GSList *l;
+	mapi_object_t obj_folder;
 
 	e_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
 	e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma), E_DATA_BOOK_STATUS_INVALID_ARG);
@@ -531,7 +558,10 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
 		}
 	}
 
-	e_mapi_connection_remove_items (conn, olFolderContacts, priv->fid, priv->is_public_folder ? MAPI_OPTIONS_USE_PFSTORE : 0, to_remove, cancellable, &mapi_error);
+	if (ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error)) {
+		e_mapi_connection_remove_items (conn, &obj_folder, to_remove, cancellable, &mapi_error);
+		e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+	}
 
 	e_book_backend_mapi_unlock_connection (ebma);
 
@@ -599,10 +629,7 @@ ebbm_contacts_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
 		mapi_object_t obj_folder;
 		gboolean status;
 
-		if (priv->is_public_folder)
-			status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-		else
-			status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+		status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 		if (status) {
 			status = e_mapi_connection_modify_object (conn, &obj_folder, mid,
@@ -672,10 +699,7 @@ ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, co
 		return;
 	}
 
-	if (priv->is_public_folder)
-		status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+	status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 	if (status) {
 		status = e_mapi_util_mapi_id_from_string (id, &mid);
@@ -758,10 +782,7 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
 	tcd.ebma = ebma;
 	tcd.cards = vCards;
 
-	if (priv->is_public_folder)
-		status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+	status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 	if (status) {
 		status = e_mapi_connection_list_objects (conn, &obj_folder,
@@ -811,7 +832,6 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
 				  GError **error)
 {
 	EBookBackendMAPIContacts *ebmac;
-	EBookBackendMAPIContactsPrivate *priv;
 	EMapiConnection *conn;
 	gboolean status;
 	mapi_object_t obj_folder;
@@ -824,8 +844,6 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
 	e_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
 	e_return_data_book_error_if_fail (ebmac->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
 
-	priv = ebmac->priv;
-
 	e_book_backend_mapi_lock_connection (ebma);
 
 	conn = e_book_backend_mapi_get_connection (ebma);
@@ -835,10 +853,7 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
 		return;
 	}
 
-	if (priv->is_public_folder)
-		status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+	status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 	if (status) {
 		struct FolderBasicPropertiesData fbp = { 0 };
@@ -869,7 +884,6 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
 			       GError **error)
 {
 	EBookBackendMAPIContacts *ebmac;
-	EBookBackendMAPIContactsPrivate *priv;
 	EMapiConnection *conn;
 	gboolean status;
 	mapi_object_t obj_folder;
@@ -884,8 +898,6 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
 	e_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
 	e_return_data_book_error_if_fail (ebmac->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
 
-	priv = ebmac->priv;
-
 	e_book_backend_mapi_lock_connection (ebma);
 
 	conn = e_book_backend_mapi_get_connection (ebma);
@@ -895,10 +907,7 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
 		return;
 	}
 
-	if (priv->is_public_folder)
-		status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+	status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 	if (status) {
 		status = e_mapi_connection_list_objects (conn, &obj_folder, build_rs_cb, build_rs_cb_data,
@@ -955,10 +964,7 @@ ebbm_contacts_transfer_contacts (EBookBackendMAPI *ebma,
 	tcd.book_view = book_view;
 	tcd.notify_contact_data = notify_contact_data;
 
-	if (priv->is_public_folder)
-		status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+	status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
 
 	if (status) {
 		GSList *mids = NULL;
@@ -999,15 +1005,34 @@ static void
 e_book_backend_mapi_contacts_init (EBookBackendMAPIContacts *backend)
 {
 	backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, E_TYPE_BOOK_BACKEND_MAPI_CONTACTS, EBookBackendMAPIContactsPrivate);
+
+	backend->priv->foreign_username = NULL;
+}
+
+static void
+ebbm_contacts_finalize (GObject *object)
+{
+	EBookBackendMAPIContactsPrivate *priv;
+
+	priv = E_BOOK_BACKEND_MAPI_CONTACTS (object)->priv;
+
+	g_free (priv->foreign_username);
+	priv->foreign_username = NULL;
+
+	G_OBJECT_CLASS (e_book_backend_mapi_contacts_parent_class)->finalize (object);
 }
 
 static void
 e_book_backend_mapi_contacts_class_init (EBookBackendMAPIContactsClass *klass)
 {
 	EBookBackendMAPIClass *parent_class;
+	GObjectClass *object_class;
 
 	g_type_class_add_private (klass, sizeof (EBookBackendMAPIContactsPrivate));
 
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = ebbm_contacts_finalize;
+
 	parent_class = E_BOOK_BACKEND_MAPI_CLASS (klass);
 
 	/* Set the virtual methods. */
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index b8356fa..1947d63 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -68,9 +68,9 @@ struct _ECalBackendMAPIPrivate {
 	EMapiOperationQueue *op_queue;
 
 	mapi_id_t		fid;
-	uint32_t		olFolder;
 	gchar			*profile;
 	gboolean is_public_folder;
+	gchar *foreign_username;
 	EMapiConnection *conn;
 
 	/* These fields are entirely for access rights */
@@ -102,6 +102,30 @@ struct _ECalBackendMAPIPrivate {
 	GCancellable *cancellable;
 };
 
+static gboolean
+ecbm_open_folder (ECalBackendMAPI *ecbm,
+		  EMapiConnection *conn,
+		  mapi_object_t *obj_folder,
+		  GCancellable *cancellable,
+		  GError **perror)
+{
+	gboolean res;
+
+	g_return_val_if_fail (ecbm != NULL, FALSE);
+	g_return_val_if_fail (ecbm->priv != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+	if (ecbm->priv->foreign_username)
+		res = e_mapi_connection_open_foreign_folder (conn, ecbm->priv->foreign_username, ecbm->priv->fid, obj_folder, cancellable, perror);
+	else if (ecbm->priv->is_public_folder)
+		res = e_mapi_connection_open_public_folder (conn, ecbm->priv->fid, obj_folder, cancellable, perror);
+	else
+		res = e_mapi_connection_open_personal_folder (conn, ecbm->priv->fid, obj_folder, cancellable, perror);
+
+	return res;
+}
+
 #define CACHE_REFRESH_INTERVAL 600000
 
 static GStaticMutex auth_mutex = G_STATIC_MUTEX_INIT;
@@ -295,10 +319,12 @@ ecbm_remove (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, GEr
 		g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
 		return;
 	}
-	if (!priv->is_public_folder) {
+	if (!priv->is_public_folder && !priv->foreign_username) {
 		GError *mapi_error = NULL;
+		mapi_object_t *obj_store = NULL;
 
-		if (!e_mapi_connection_remove_folder (priv->conn, priv->fid, 0, cancellable, &mapi_error)) {
+		if (!e_mapi_connection_peek_store (priv->conn, priv->foreign_username ? FALSE : priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error) ||
+		    !e_mapi_connection_remove_folder (priv->conn, obj_store, priv->fid, cancellable, &mapi_error)) {
 			mapi_error_to_edc_error (perror, mapi_error, OtherError, _("Failed to remove public folder"));
 			if (mapi_error)
 				g_error_free (mapi_error);
@@ -712,12 +738,7 @@ update_local_cache (ECalBackendMAPI *cbmapi, GCancellable *cancellable)
 
 	conn = g_object_ref (priv->conn);
 
-	if (priv->is_public_folder) {
-		success = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	} else {
-		success = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-	}
-
+	success = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
 	if (!success) {
 		notify_error (cbmapi, mapi_error, _("Failed to open folder: %s"));
 		goto cleanup;
@@ -1155,11 +1176,7 @@ ecbm_connect_user (ECalBackend *backend, GCancellable *cancellable, const gchar
 			mapi_object_t obj_folder;
 			gboolean status;
 
-			if (priv->is_public_folder)
-				status = e_mapi_connection_open_public_folder (priv->conn, priv->fid, &obj_folder, NULL, NULL);
-			else
-				status = e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, NULL, NULL);
-
+			status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, NULL, NULL);
 			if (status) {
 				e_mapi_connection_enable_notifications (priv->conn, &obj_folder,
 					fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved | fnevObjectCopied,
@@ -1199,7 +1216,6 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
 	ESource *esource;
 	const gchar *fid = NULL;
 	const gchar *cache_dir, *krb_sso = NULL;
-	uint32_t olFolder = 0;
 
 	if (e_cal_backend_is_opened (E_CAL_BACKEND (backend))) {
 		e_cal_backend_notify_opened (backend, NULL);
@@ -1221,19 +1237,6 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
 
 	cbmapi->priv->read_only = FALSE;
 
-	switch (e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi))) {
-	default:
-	case ICAL_VEVENT_COMPONENT:
-		olFolder = olFolderCalendar;
-		break;
-	case ICAL_VTODO_COMPONENT:
-		olFolder = olFolderTasks;
-		break;
-	case ICAL_VJOURNAL_COMPONENT:
-		olFolder = olFolderNotes;
-		break;
-	}
-
 	if (priv->store) {
 		g_object_unref (priv->store);
 		priv->store = NULL;
@@ -1281,8 +1284,13 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
 	priv->owner_email = g_strdup (e_source_get_property (esource, "acl-owner-email"));
 
 	e_mapi_util_mapi_id_from_string (fid, &priv->fid);
-	priv->olFolder = olFolder;
 	priv->is_public_folder = g_strcmp0 (e_source_get_property (esource, "public"), "yes") == 0;
+	priv->foreign_username = e_source_get_duped_property (esource, "foreign-username");
+
+	if (priv->foreign_username && !*priv->foreign_username) {
+		g_free (priv->foreign_username);
+		priv->foreign_username = NULL;
+	}
 
 	krb_sso = e_source_get_property (esource, "kerberos");
 	g_mutex_unlock (priv->mutex);
@@ -1434,7 +1442,7 @@ get_server_data (ECalBackendMAPI *cbmapi,
 	icalcomp = e_cal_component_get_icalcomponent (comp);
 	get_comp_mid (icalcomp, &mid);
 
-	if (!e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, cancellable, NULL))
+	if (!ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, NULL))
 		return;
 
 	if (!e_mapi_connection_transfer_object (priv->conn, &obj_folder, mid, ecbm_capture_req_props, cbdata, cancellable, &error)) {
@@ -1561,12 +1569,7 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
 		cbdata.globalid = NULL;
 		cbdata.cleanglobalid = NULL;
 
-		if (priv->is_public_folder) {
-			status = e_mapi_connection_open_public_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-		} else {
-			status = e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-		}
-
+		status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &mapi_error);
 		if (status) {
 			e_mapi_connection_create_object (priv->conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
 							 e_mapi_cal_utils_comp_to_object, &cbdata,
@@ -1767,12 +1770,7 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
 			cbdata.meeting_type = has_attendees ? MEETING_OBJECT_RCVD : NOT_A_MEETING;
 		}
 
-		if (priv->is_public_folder) {
-			status = e_mapi_connection_open_public_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-		} else {
-			status = e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
-		}
-
+		status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &mapi_error);
 		if (status) {
 			status = e_mapi_connection_modify_object (priv->conn, &obj_folder, mid, 
 								  e_mapi_cal_utils_comp_to_object, &cbdata,
@@ -1861,29 +1859,31 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
 		ecbm_modify_object (backend, cal, cancellable, new_calobj, CALOBJ_MOD_ALL, old_ecalcomp, new_ecalcomp, &err);
 		g_free (new_calobj);
 	} else {
+		mapi_object_t obj_folder;
 		GSList *list=NULL, *l, *comp_list = e_cal_backend_store_get_components_by_uid (priv->store, uid);
 		GError *ri_error = NULL;
+		mapi_id_t *pmid = g_new (mapi_id_t, 1);
 
-		/*if (e_cal_component_has_attendees (E_CAL_COMPONENT (comp_list->data))) {
-		} else {*/
-			mapi_id_t *pmid = g_new (mapi_id_t, 1);
-			*pmid = mid;
-			list = g_slist_prepend (list, pmid);
-		/* } */
-
-		if (e_mapi_connection_remove_items (priv->conn, priv->olFolder, priv->fid, 0, list, cancellable, &ri_error)) {
-			for (l = comp_list; l; l = l->next) {
-				ECalComponent *comp = E_CAL_COMPONENT (l->data);
-				ECalComponentId *id = e_cal_component_get_id (comp);
-
-				e_cal_backend_store_remove_component (priv->store, id->uid, id->rid);
-				if (!id->rid || !g_str_equal (id->rid, rid))
-					e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbmapi), id, comp, NULL);
-				e_cal_component_free_id (id);
+		*pmid = mid;
+		list = g_slist_prepend (list, pmid);
 
-				g_object_unref (comp);
+		if (ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &ri_error)) {
+			if (e_mapi_connection_remove_items (priv->conn, &obj_folder, list, cancellable, &ri_error)) {
+				for (l = comp_list; l; l = l->next) {
+					ECalComponent *comp = E_CAL_COMPONENT (l->data);
+					ECalComponentId *id = e_cal_component_get_id (comp);
+
+					e_cal_backend_store_remove_component (priv->store, id->uid, id->rid);
+					if (!id->rid || !g_str_equal (id->rid, rid))
+						e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbmapi), id, comp, NULL);
+					e_cal_component_free_id (id);
+
+					g_object_unref (comp);
+				}
 			}
 
+			e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, &ri_error);
+
 			*old_ecalcomp = e_cal_component_new_from_icalcomponent (icalparser_parse_string (calobj));
 			*new_ecalcomp = NULL;
 			err = NULL; /* Success */
@@ -3338,6 +3338,11 @@ ecbm_finalize (GObject *object)
 		priv->sendoptions_sync_timeout = 0;
 	}
 
+	if (priv->foreign_username) {
+		g_free (priv->foreign_username);
+		priv->foreign_username = NULL;
+	}
+
 	if (priv->conn) {
 		g_object_unref (priv->conn);
 		priv->conn = NULL;
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 543db40..0eaa248 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -54,11 +54,34 @@
 extern gint camel_application_is_exiting;
 
 struct _CamelMapiFolderPrivate {
-
 	GStaticMutex search_lock;	/* for locking the search object */
 
+	gchar *foreign_username;
 };
 
+static gboolean
+cmf_open_folder (CamelMapiFolder *mapi_folder,
+		 EMapiConnection *conn,
+		 mapi_object_t *obj_folder,
+		 GCancellable *cancellable,
+		 GError **perror)
+{
+	gboolean res;
+
+	g_return_val_if_fail (mapi_folder != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+	if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+		res = e_mapi_connection_open_foreign_folder (conn, mapi_folder->priv->foreign_username, mapi_folder->folder_id, obj_folder, cancellable, perror);
+	else if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+		res = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, perror);
+	else
+		res = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, perror);
+
+	return res;
+}
+
 /*for syncing flags back to server*/
 typedef struct {
 	guint32 changed;
@@ -691,11 +714,6 @@ camel_mapi_folder_fetch_summary (CamelFolder *folder, GCancellable *cancellable,
 
 	camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
-	if ((CAMEL_MAPI_FOLDER (folder)->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
-		status = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, mapi_error);
-	else
-		status = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, mapi_error);
-
 	si = camel_mapi_store_summary_get_folder_id (mapi_store->summary, mapi_folder->folder_id);
 	msi = (CamelMapiStoreInfo *) si;
 
@@ -709,6 +727,8 @@ camel_mapi_folder_fetch_summary (CamelFolder *folder, GCancellable *cancellable,
 		return FALSE;
 	}
 
+	status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, mapi_error);
+
 	if (status) {
 		status = e_mapi_connection_get_folder_properties (conn, &obj_folder, NULL, NULL, e_mapi_utils_get_folder_basic_properties_cb, &fbp, cancellable, mapi_error);
 		if (status) {
@@ -1114,7 +1134,7 @@ mapi_folder_append_message_sync (CamelFolder *folder,
 
 	/* Convert MIME to Item */
 	conn = camel_mapi_store_get_connection (mapi_store);
-	if (e_mapi_connection_open_personal_folder (conn, fid, &obj_folder, cancellable, &mapi_error)) {
+	if (cmf_open_folder (CAMEL_MAPI_FOLDER (folder), conn, &obj_folder, cancellable, &mapi_error)) {
 		struct CamelMapiCreateData cmc;
 
 		cmc.message = message;
@@ -1161,6 +1181,7 @@ mapi_folder_expunge_sync (CamelFolder *folder,
 	gboolean delete = FALSE, status = FALSE;
 	GSList *deleted_items, *deleted_head;
 	GSList *deleted_items_uid, *deleted_items_uid_head;
+	EMapiConnection *conn;
 
 	deleted_items = deleted_head = NULL;
 	deleted_items_uid = deleted_items_uid_head = NULL;
@@ -1169,8 +1190,10 @@ mapi_folder_expunge_sync (CamelFolder *folder,
 
 	mapi_folder = CAMEL_MAPI_FOLDER (folder);
 	mapi_store = CAMEL_MAPI_STORE (parent_store);
+	conn = camel_mapi_store_get_connection (mapi_store);
 
 	if ((mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) {
+		mapi_object_t obj_folder;
 		GError *mapi_error = NULL;
 		GPtrArray *folders;
 		gint ii;
@@ -1195,7 +1218,11 @@ mapi_folder_expunge_sync (CamelFolder *folder,
 		g_ptr_array_free (folders, TRUE);
 
 		camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
-		status = e_mapi_connection_empty_folder (camel_mapi_store_get_connection (mapi_store), mapi_folder->folder_id, 0, cancellable, &mapi_error);
+		status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
+		if (status) {
+			status = e_mapi_connection_empty_folder (conn, &obj_folder, cancellable, &mapi_error);
+			e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+		}
 		camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 		if (status) {
@@ -1248,9 +1275,15 @@ mapi_folder_expunge_sync (CamelFolder *folder,
 	deleted_items_uid_head = deleted_items_uid;
 
 	if (deleted_items) {
+		mapi_object_t obj_folder;
+
 		camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
-		status = e_mapi_connection_remove_items (camel_mapi_store_get_connection (mapi_store), 0, mapi_folder->folder_id, 0, deleted_items, cancellable, NULL);
+		status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, NULL);
+		if (status) {
+			status = e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, NULL);
+			e_mapi_connection_close_folder (conn, &obj_folder, cancellable, NULL);
+		}
 
 		camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
@@ -1406,11 +1439,7 @@ mapi_folder_get_message_sync (CamelFolder *folder,
 
 	conn = camel_mapi_store_get_connection (mapi_store);
 
-	if (mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC)
-		success = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, &mapi_error);
-	else
-		success = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, &mapi_error);
-
+	success = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
 	if (success) {
 		success = e_mapi_connection_transfer_object (conn, &obj_folder, id_message, transfer_mail_object_cb, &msg, cancellable, &mapi_error);
 
@@ -1463,15 +1492,16 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
 	CamelFolderChangeInfo *changes = NULL;
 	CamelServiceConnectionStatus status;
 	CamelService *service;
+	EMapiConnection *conn;
 	GPtrArray *known_uids;
 	GSList *read_items = NULL, *unread_items = NULL, *to_free = NULL, *junk_items = NULL, *deleted_items = NULL, *l;
 	flags_diff_t diff, unset_flags;
 	const gchar *folder_id;
 	const gchar *full_name;
-	mapi_id_t fid, deleted_items_fid;
+	mapi_id_t fid;
 	gint i;
-	guint32 options =0;
-	gboolean is_junk_folder;
+	gboolean is_junk_folder, has_obj_folder = FALSE;
+	mapi_object_t obj_folder;
 
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
@@ -1487,9 +1517,6 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
 		return TRUE;
 	}
 
-	if (((CamelMapiFolder *)folder)->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC)
-		options |= MAPI_OPTIONS_USE_PFSTORE;
-
 	folder_id =  camel_mapi_store_folder_id_lookup (mapi_store, full_name);
 	e_mapi_util_mapi_id_from_string (folder_id, &fid);
 
@@ -1572,28 +1599,36 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
 	   Evo doesnt not take care of it, as I find that scenario to be impractical.
 	*/
 
-	if (read_items) {
+	conn = camel_mapi_store_get_connection (mapi_store);
+	has_obj_folder = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, NULL);
+
+	if (read_items && has_obj_folder) {
 		camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
-		e_mapi_connection_set_flags (camel_mapi_store_get_connection (mapi_store), 0, fid, options, read_items, 0, cancellable, NULL);
+		e_mapi_connection_set_flags (conn, &obj_folder, read_items, 0, cancellable, NULL);
 		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 	}
 
-	if (unread_items) {
+	if (unread_items && has_obj_folder) {
 		camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
-		e_mapi_connection_set_flags (camel_mapi_store_get_connection (mapi_store), 0, fid, options, unread_items, CLEAR_READ_FLAG, cancellable, NULL);
+		e_mapi_connection_set_flags (conn, &obj_folder, unread_items, CLEAR_READ_FLAG, cancellable, NULL);
 		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 	}
 
 	/* Remove messages from server*/
-	if (deleted_items) {
+	if (deleted_items && has_obj_folder) {
 		camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 		if ((mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) {
-			e_mapi_connection_remove_items (camel_mapi_store_get_connection (mapi_store), 0, fid, options, deleted_items, cancellable, NULL);
+			e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, NULL);
 		} else {
 			GError *err = NULL;
+			mapi_id_t deleted_items_fid;
+			mapi_object_t deleted_obj_folder;
 
 			e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderDeletedItems), &deleted_items_fid);
-			e_mapi_connection_move_items (camel_mapi_store_get_connection (mapi_store), fid, options, deleted_items_fid, 0, deleted_items, cancellable, &err);
+			if (e_mapi_connection_open_personal_folder (conn, deleted_items_fid, &deleted_obj_folder, cancellable, &err)) {
+				e_mapi_connection_copymove_items (conn, &obj_folder, &deleted_obj_folder, FALSE, deleted_items, cancellable, &err);
+				e_mapi_connection_close_folder (conn, &deleted_obj_folder, cancellable, &err);
+			}
 
 			if (err) {
 				g_warning ("%s: Failed to move deleted items: %s", G_STRFUNC, err->message);
@@ -1604,14 +1639,20 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
 		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 	}
 
-	if (junk_items) {
+	if (junk_items && has_obj_folder) {
 		mapi_id_t junk_fid = 0;
+		mapi_object_t junk_obj_folder;
 		GError *err = NULL;
 
-		camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
-		e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderJunk), &junk_fid);
-		e_mapi_connection_move_items (camel_mapi_store_get_connection (mapi_store), fid, options, junk_fid, 0, junk_items, cancellable, &err);
-		camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+		if (has_obj_folder) {
+			camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+			e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderJunk), &junk_fid);
+			if (e_mapi_connection_open_personal_folder (conn, junk_fid, &junk_obj_folder, cancellable, &err)) {
+				e_mapi_connection_copymove_items (conn, &obj_folder, &junk_obj_folder, FALSE, junk_items, cancellable, &err);
+				e_mapi_connection_close_folder (conn, &junk_obj_folder, cancellable, &err);
+			}
+			camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+		}
 
 		/* in junk_items are only emails which are not deleted */
 		deleted_items = g_slist_concat (deleted_items, g_slist_copy (junk_items));
@@ -1622,6 +1663,9 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
 		}
 	}
 
+	if (has_obj_folder)
+		e_mapi_connection_close_folder (conn, &obj_folder, cancellable, NULL);
+
 	/*Remove messages from local cache*/
 	for (l = deleted_items; l; l = l->next) {
 		gchar *deleted_msg_uid = e_mapi_util_mapi_id_to_string (*((mapi_id_t *) l->data));
@@ -1667,8 +1711,6 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
                                        GCancellable *cancellable,
                                        GError **error)
 {
-	guint32 src_fid_options, dest_fid_options;
-
 	CamelOfflineStore *offline;
 	CamelMapiStore *mapi_store;
 	CamelFolderChangeInfo *changes = NULL;
@@ -1678,6 +1720,10 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
 	gint i = 0;
 	GSList *src_msg_ids = NULL;
 	gboolean success = TRUE;
+	GError *err = NULL;
+	mapi_object_t src_obj_folder, des_obj_folder;
+	gboolean copymoved = FALSE;
+	EMapiConnection *conn;
 
 	if (CAMEL_IS_MAPI_FOLDER (source)) {
 		/* make sure changed flags are written into the server */
@@ -1709,10 +1755,7 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
 		return FALSE;
 
 	src_mapi_folder = CAMEL_MAPI_FOLDER (source);
-	src_fid_options = (src_mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ? MAPI_OPTIONS_USE_PFSTORE : 0;
-
 	des_mapi_folder = CAMEL_MAPI_FOLDER (destination);
-	dest_fid_options = (des_mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ? MAPI_OPTIONS_USE_PFSTORE : 0;
 
 	for (i=0; i < uids->len; i++) {
 		mapi_id_t *mid = g_new0 (mapi_id_t, 1); /* FIXME : */
@@ -1722,40 +1765,38 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
 		src_msg_ids = g_slist_prepend (src_msg_ids, mid);
 	}
 
-	if (delete_originals) {
-		GError *err = NULL;
+	conn = camel_mapi_store_get_connection (mapi_store);
 
-		if (!e_mapi_connection_move_items (camel_mapi_store_get_connection (mapi_store), src_mapi_folder->folder_id, src_fid_options, des_mapi_folder->folder_id, dest_fid_options, src_msg_ids, cancellable, &err)) {
-			if (!e_mapi_utils_propagate_cancelled_error (err, error))
-				g_set_error (
-					error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
-					"%s", err ? err->message : _("Unknown error"));
-			g_clear_error (&err);
-			success = FALSE;
-		} else {
-			changes = camel_folder_change_info_new ();
+	if (cmf_open_folder (src_mapi_folder, conn, &src_obj_folder, cancellable, &err)) {
+		if (cmf_open_folder (des_mapi_folder, conn, &des_obj_folder, cancellable, &err)) {
+			copymoved = e_mapi_connection_copymove_items (conn, &src_obj_folder, &des_obj_folder, !delete_originals, src_msg_ids, cancellable, &err);
+			e_mapi_connection_close_folder (conn, &des_obj_folder, cancellable, &err);
+		}
 
-			for (i=0; i < uids->len; i++) {
-				camel_folder_summary_remove_uid (source->summary, uids->pdata[i]);
-				camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
-			}
-			camel_folder_changed (source, changes);
-			camel_folder_change_info_free (changes);
+		e_mapi_connection_close_folder (conn, &src_obj_folder, cancellable, &err);
+	}
 
-		}
+	if (!copymoved) {
+		if (!e_mapi_utils_propagate_cancelled_error (err, error))
+			g_set_error (
+				error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+				"%s", err ? err->message : _("Unknown error"));
+		g_clear_error (&err);
+		success = FALSE;
 	} else {
-		GError *err = NULL;
+		changes = camel_folder_change_info_new ();
 
-		if (!e_mapi_connection_copy_items (camel_mapi_store_get_connection (mapi_store), src_mapi_folder->folder_id, src_fid_options, des_mapi_folder->folder_id, dest_fid_options, src_msg_ids, cancellable, &err)) {
-			if (!e_mapi_utils_propagate_cancelled_error (err, error))
-				g_set_error (
-					error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
-					"%s", err ? err->message : _("Unknown error"));
-			g_clear_error (&err);
-			success = FALSE;
+		for (i=0; i < uids->len; i++) {
+			camel_folder_summary_remove_uid (source->summary, uids->pdata[i]);
+			camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
 		}
+		camel_folder_changed (source, changes);
+		camel_folder_change_info_free (changes);
+
 	}
 
+	g_clear_error (&err);
+
 	g_slist_foreach (src_msg_ids, (GFunc) g_free, NULL);
 	g_slist_free (src_msg_ids);
 
@@ -1906,6 +1947,11 @@ camel_mapi_folder_new (CamelStore *store, const gchar *folder_name, const gchar
 		mapi_folder->mapi_folder_flags = msi->mapi_folder_flags;
 		mapi_folder->camel_folder_flags = msi->camel_folder_flags;
 		mapi_folder->folder_id = msi->folder_id;
+		if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0) {
+			mapi_folder->priv->foreign_username = g_strdup (msi->foreign_username);
+		} else {
+			mapi_folder->priv->foreign_username = NULL;
+		}
 
 		if ((si->flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH)
 			folder->folder_flags |= CAMEL_FOLDER_IS_TRASH;
@@ -1920,5 +1966,11 @@ camel_mapi_folder_new (CamelStore *store, const gchar *folder_name, const gchar
 		((CamelMapiStore *) store)->summary,
 		folder_name, folder->summary);
 
+	/* sanity checking */
+	if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+		g_return_val_if_fail (mapi_folder->priv->foreign_username != NULL, folder);
+	if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+		g_return_val_if_fail (mapi_folder->priv->foreign_username == NULL, folder);
+
 	return folder;
 }
diff --git a/src/camel/camel-mapi-store-summary.c b/src/camel/camel-mapi-store-summary.c
index 5a1bbfd..a21f2af 100644
--- a/src/camel/camel-mapi-store-summary.c
+++ b/src/camel/camel-mapi-store-summary.c
@@ -137,15 +137,15 @@ store_info_load (CamelStoreSummary *s, FILE *in)
 		    || camel_file_util_decode_string (in, &parent_id_str) == -1
 		    || camel_file_util_decode_uint32 (in, &msi->camel_folder_flags) == -1
 		    || camel_file_util_decode_uint32 (in, &msi->mapi_folder_flags) == -1
-		    || camel_file_util_decode_string (in, &msi->foreign_user_name) == -1
+		    || camel_file_util_decode_string (in, &msi->foreign_username) == -1
 		    || !e_mapi_util_mapi_id_from_string (folder_id_str, &msi->folder_id)
 		    || !e_mapi_util_mapi_id_from_string (parent_id_str, &msi->parent_id)) {
 			camel_store_summary_info_free (s, si);
 			si = NULL;
 		} else {
-			if (msi->foreign_user_name && !*msi->foreign_user_name) {
-				g_free (msi->foreign_user_name);
-				msi->foreign_user_name = NULL;
+			if (msi->foreign_username && !*msi->foreign_username) {
+				g_free (msi->foreign_username);
+				msi->foreign_username = NULL;
 			}
 		}
 
@@ -174,7 +174,7 @@ store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *si)
 	    || camel_file_util_encode_string (out, parent_id_str) == -1
 	    || camel_file_util_encode_uint32 (out, msi->camel_folder_flags) == -1
 	    || camel_file_util_encode_uint32 (out, msi->mapi_folder_flags) == -1
-	    || camel_file_util_encode_string (out, msi->foreign_user_name ? msi->foreign_user_name : "") == -1)
+	    || camel_file_util_encode_string (out, msi->foreign_username ? msi->foreign_username : "") == -1)
 		res = -1;
 	else
 		res = 0;
@@ -190,7 +190,7 @@ store_info_free (CamelStoreSummary *s, CamelStoreInfo *si)
 {
 	CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
 
-	g_free (msi->foreign_user_name);
+	g_free (msi->foreign_username);
 
 	CAMEL_STORE_SUMMARY_CLASS (camel_mapi_store_summary_parent_class)->store_info_free (s, si);
 }
@@ -200,8 +200,8 @@ store_info_string (CamelStoreSummary *s, const CamelStoreInfo *si, gint type)
 {
 	CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
 
-	if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USER_NAME)
-		return msi->foreign_user_name;
+	if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USERNAME)
+		return msi->foreign_username;
 
 	return CAMEL_STORE_SUMMARY_CLASS (camel_mapi_store_summary_parent_class)->store_info_string (s, si, type);
 }
@@ -211,9 +211,9 @@ store_info_set_string (CamelStoreSummary *s, CamelStoreInfo *si, gint type, cons
 {
 	CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
 
-	if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USER_NAME) {
-		g_free (msi->foreign_user_name);
-		msi->foreign_user_name = g_strdup (str);
+	if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USERNAME) {
+		g_free (msi->foreign_username);
+		msi->foreign_username = g_strdup (str);
 
 		camel_store_summary_touch (s);
 	} else
@@ -233,7 +233,7 @@ camel_mapi_store_summary_add_from_full (CamelStoreSummary *s,
 					mapi_id_t parent_id,
 					guint32 camel_folder_flags,
 					guint32 mapi_folder_flags,
-					const gchar *foreign_user_name)
+					const gchar *foreign_username)
 {
 	CamelStoreInfo *si;
 
@@ -247,11 +247,13 @@ camel_mapi_store_summary_add_from_full (CamelStoreSummary *s,
 	if (si) {
 		CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
 
+		si->flags = camel_folder_flags;
+
 		msi->folder_id = folder_id;
 		msi->parent_id = parent_id;
 		msi->camel_folder_flags = camel_folder_flags;
 		msi->mapi_folder_flags = mapi_folder_flags;
-		msi->foreign_user_name = g_strdup ((foreign_user_name && *foreign_user_name) ? foreign_user_name : "");
+		msi->foreign_username = g_strdup ((foreign_username && *foreign_username) ? foreign_username : NULL);
 
 		msi->latest_last_modify = 0;
 		msi->last_obj_total = -1;
diff --git a/src/camel/camel-mapi-store-summary.h b/src/camel/camel-mapi-store-summary.h
index 3ae1390..8097d78 100644
--- a/src/camel/camel-mapi-store-summary.h
+++ b/src/camel/camel-mapi-store-summary.h
@@ -61,7 +61,7 @@ enum CamelMapiStoreFolderFlags {
 };
 
 enum {
-	CAMEL_MAPI_STORE_INFO_FOREIGN_USER_NAME = CAMEL_STORE_INFO_LAST,
+	CAMEL_MAPI_STORE_INFO_FOREIGN_USERNAME = CAMEL_STORE_INFO_LAST,
 	CAMEL_MAPI_STORE_INFO_LAST
 };
 
@@ -71,7 +71,7 @@ struct _CamelMapiStoreInfo {
 	mapi_id_t parent_id;
 	guint32 camel_folder_flags; /* CamelFolderInfo::flags */
 	guint32 mapi_folder_flags; /* bit-or of CamelMapiStoreFolderFlags */
-	gchar *foreign_user_name; /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
+	gchar *foreign_username; /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
 
 	/* these are not saved */
 	time_t latest_last_modify;
@@ -95,7 +95,7 @@ CamelStoreInfo *	camel_mapi_store_summary_add_from_full	(CamelStoreSummary *s,
 								 mapi_id_t parent_id,
 								 guint32 camel_folder_flags, /* CamelFolderInfo::flags */
 								 guint32 mapi_folder_flags, /* bit-or of CamelMapiStoreFolderFlags */
-								 const gchar *foreign_user_name); /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
+								 const gchar *foreign_username); /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
 CamelStoreInfo *	camel_mapi_store_summary_get_folder_id	(CamelStoreSummary *s,
 								 mapi_id_t folder_id);
 
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 97216d0..87ff10a 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -44,8 +44,9 @@
 #include "camel-mapi-settings.h"
 #include "camel-mapi-store-summary.h"
 #include "camel-mapi-folder-summary.h"
-#include "account-setup-eplugin/e-mapi-account-listener.h"
+
 #include <e-mapi-utils.h>
+#include <e-mapi-folder.h>
 
 #define d(x)
 
@@ -107,6 +108,78 @@ static CamelFolderInfo *
 						 GError **error);
 
 static gboolean
+cms_open_folder (CamelMapiStore *mapi_store,
+		 EMapiConnection *conn,
+		 mapi_id_t fid,
+		 mapi_object_t *obj_folder,
+		 GCancellable *cancellable,
+		 GError **perror)
+{
+	CamelStoreInfo *si;
+	CamelMapiStoreInfo *msi;
+	gboolean res;
+
+	g_return_val_if_fail (mapi_store != NULL, FALSE);
+	g_return_val_if_fail (mapi_store->summary != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (fid != 0, FALSE);
+	g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+	si = camel_mapi_store_summary_get_folder_id (mapi_store->summary, fid);
+	if (!si) {
+		g_propagate_error (perror, g_error_new_literal (CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot find folder in a local cache")));
+		return FALSE;
+	}
+
+	msi = (CamelMapiStoreInfo *) si;
+
+	if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+		res = e_mapi_connection_open_foreign_folder (conn, msi->foreign_username, fid, obj_folder, cancellable, perror);
+	else if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+		res = e_mapi_connection_open_public_folder (conn, fid, obj_folder, cancellable, perror);
+	else
+		res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+
+	return res;
+}
+
+static gboolean
+cms_peek_folder_store (CamelMapiStore *mapi_store,
+		       EMapiConnection *conn,
+		       mapi_id_t fid,
+		       mapi_object_t **obj_store,
+		       GCancellable *cancellable,
+		       GError **perror)
+{
+	CamelStoreInfo *si;
+	CamelMapiStoreInfo *msi;
+	gboolean res;
+
+	g_return_val_if_fail (mapi_store != NULL, FALSE);
+	g_return_val_if_fail (mapi_store->summary != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, FALSE);
+	g_return_val_if_fail (fid != 0, FALSE);
+	g_return_val_if_fail (obj_store != NULL, FALSE);
+
+	si = camel_mapi_store_summary_get_folder_id (mapi_store->summary, fid);
+	if (!si) {
+		g_propagate_error (perror, g_error_new_literal (CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot find folder in a local cache")));
+		return FALSE;
+	}
+
+	msi = (CamelMapiStoreInfo *) si;
+
+	if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+		res = e_mapi_connection_peek_store (conn, FALSE, msi->foreign_username, obj_store, cancellable, perror);
+	else if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+		res = e_mapi_connection_peek_store (conn, TRUE, NULL, obj_store, cancellable, perror);
+	else
+		res = e_mapi_connection_peek_store (conn, FALSE, NULL, obj_store, cancellable, perror);
+
+	return res;
+}
+
+static gboolean
 check_for_connection (CamelService *service, GError **error)
 {
 	CamelMapiStore *store = CAMEL_MAPI_STORE (service);
@@ -269,16 +342,16 @@ mapi_convert_to_folder_info (CamelMapiStore *store,
 		fi->flags |= CAMEL_FOLDER_SYSTEM;
 	} else {
 		switch (e_mapi_folder_get_type (folder)) {
-		case MAPI_FOLDER_TYPE_CONTACT:
+		case E_MAPI_FOLDER_TYPE_CONTACT:
 			fi->flags |= CAMEL_FOLDER_TYPE_CONTACTS;
 			break;
-		case MAPI_FOLDER_TYPE_APPOINTMENT:
+		case E_MAPI_FOLDER_TYPE_APPOINTMENT:
 			fi->flags |= CAMEL_FOLDER_TYPE_EVENTS;
 			break;
-		case MAPI_FOLDER_TYPE_MEMO:
+		case E_MAPI_FOLDER_TYPE_MEMO:
 			fi->flags |= CAMEL_FOLDER_TYPE_MEMOS;
 			break;
-		case MAPI_FOLDER_TYPE_TASK:
+		case E_MAPI_FOLDER_TYPE_TASK:
 			fi->flags |= CAMEL_FOLDER_TYPE_TASKS;
 			break;
 		default:
@@ -286,7 +359,7 @@ mapi_convert_to_folder_info (CamelMapiStore *store,
 		}
 	}
 
-	if (folder->category == MAPI_PERSONAL_FOLDER)
+	if (folder->category == E_MAPI_FOLDER_CATEGORY_PERSONAL)
 		fi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; /*Set this default for mailbox.*/
 
 	if (folder->child_count <=0)
@@ -416,9 +489,11 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
 			continue;
 
 		/* those whose left in old_cache_folders are removed at the end,
-		   which is not good for public folders, thus preserve them from
-		   an automatic removal */
-		if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) == 0 || (msi->info.flags & CAMEL_FOLDER_SUBSCRIBED) == 0)
+		   which is not good for public and foreign folders, thus preserve
+		   them from an automatic removal */
+		if (((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) == 0 &&
+		    (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) == 0) ||
+		    (msi->info.flags & CAMEL_FOLDER_SUBSCRIBED) == 0)
 			g_hash_table_insert (old_cache_folders, g_strdup (camel_store_info_path (store->summary, msi)), GINT_TO_POINTER (1));
 
 		camel_store_summary_info_free (store->summary, (CamelStoreInfo *) msi);
@@ -490,7 +565,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
 		if (folder->default_type == olPublicFoldersAllPublicFolders)
 			continue;
 
-		if (folder->container_class == MAPI_FOLDER_TYPE_MAIL) {
+		if (folder->container_class == E_MAPI_FOLDER_TYPE_MAIL) {
 			info = mapi_convert_to_folder_info (store, folder, NULL);
 			msi = (CamelMapiStoreInfo *) camel_store_summary_path (store->summary, info->full_name);
 
@@ -500,7 +575,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
 						e_mapi_folder_get_fid (folder),
 						e_mapi_folder_get_parent_id (folder),
 						info->flags,
-						folder->category == MAPI_PERSONAL_FOLDER ? CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL:
+						folder->category == E_MAPI_FOLDER_CATEGORY_PERSONAL ? CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL:
 						CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC,
 						NULL);
 				if (msi == NULL)
@@ -521,7 +596,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
 
 			camel_store_summary_info_free (store->summary, (CamelStoreInfo *) msi);
 			camel_folder_info_free (info);
-		} else if (folder->category == MAPI_FAVOURITE_FOLDER) {
+		} else if (folder->category == E_MAPI_FOLDER_CATEGORY_PUBLIC) {
 			info = mapi_convert_to_folder_info (store, folder, NULL);
 			msi = (CamelMapiStoreInfo *) camel_store_summary_path (store->summary, info->full_name);
 
@@ -603,7 +678,7 @@ match_path (const gchar *path, const gchar *name)
 }
 
 static void
-fix_folder_names (CamelFolderInfo *fi)
+unescape_folder_names (CamelFolderInfo *fi)
 {
 	while (fi) {
 		if (fi->display_name && strchr (fi->display_name, '\\')) {
@@ -615,7 +690,7 @@ fix_folder_names (CamelFolderInfo *fi)
 		}
 
 		if (fi->child)
-			fix_folder_names (fi->child);
+			unescape_folder_names (fi->child);
 
 		fi = fi->next;
 	}
@@ -631,6 +706,7 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
 	gchar *path;
 	gint i, count;
 	gboolean subscribed, subscription_list = FALSE;
+	gboolean has_public_folders = FALSE, has_foreign_folders = FALSE;
 
 	subscription_list = (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST);
 	subscribed = (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED);
@@ -665,7 +741,8 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
 		if (!subscription_list &&
 		    !(msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL) &&
 		    (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0 &&
-		    (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0) {
+		    ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ||
+		     (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)) {
 			camel_store_summary_info_free (mapi_store->summary, si);
 			continue;
 		}
@@ -676,8 +753,11 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
 			gchar *parent_name = NULL;
 			const gchar *folder_name = NULL;
 
+			has_public_folders = has_public_folders || (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0;
+			has_foreign_folders = has_foreign_folders || (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0;
+
 			if (subscribed && g_str_has_prefix (store_info_path, DISPLAY_NAME_ALL_PUBLIC_FOLDERS)) {
-				parent_name = DISPLAY_NAME_FAVOURITES;
+				parent_name = DISPLAY_NAME_FAVORITES;
 
 				folder_name = strrchr (store_info_path, '/');
 				if (folder_name != NULL)
@@ -694,19 +774,28 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
 		camel_store_summary_info_free (mapi_store->summary, si);
 	}
 
-	if (!(subscription_list) && top[0] == '\0') {
-		fi = mapi_build_folder_info (mapi_store, NULL, DISPLAY_NAME_FAVOURITES);
-		fi->flags |= CAMEL_FOLDER_NOSELECT;
-		fi->flags |= CAMEL_FOLDER_SYSTEM;
+	if (!subscription_list && !*top) {
+		if (has_public_folders) {
+			fi = mapi_build_folder_info (mapi_store, NULL, DISPLAY_NAME_FAVORITES);
+			fi->flags |= CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_SYSTEM;
 
-		g_ptr_array_add (folders, fi);
+			g_ptr_array_add (folders, fi);
+		}
+
+		if (has_foreign_folders) {
+			fi = mapi_build_folder_info (mapi_store, NULL, DISPLAY_NAME_FOREIGN_FOLDERS);
+			fi->flags |= CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_SYSTEM;
+
+			g_ptr_array_add (folders, fi);
+		}
 	}
 
 	g_free (path);
+	/* this adds also fake folders, if missing */
 	fi = camel_folder_info_build (folders, top, '/', TRUE);
 	g_ptr_array_free (folders, TRUE);
 
-	fix_folder_names (fi);
+	unescape_folder_names (fi);
 
 	return fi;
 }
@@ -838,12 +927,20 @@ stop_pending_updates (CamelMapiStore *mapi_store)
 static void
 mapi_store_dispose (GObject *object)
 {
+	CamelMapiStore *mapi_store;
 	CamelMapiStorePrivate *priv;
 
-	priv = CAMEL_MAPI_STORE (object)->priv;
+	mapi_store = CAMEL_MAPI_STORE (object);
+	priv = mapi_store->priv;
 
 	stop_pending_updates (CAMEL_MAPI_STORE (object));
 
+	if (mapi_store->summary) {
+		camel_store_summary_save (mapi_store->summary);
+		g_object_unref (mapi_store->summary);
+		mapi_store->summary = NULL;
+	}
+
 	if (priv->conn != NULL) {
 		g_signal_handlers_disconnect_by_func (priv->conn, camel_mapi_store_server_notification_cb, object);
 
@@ -1057,6 +1154,8 @@ mapi_store_create_folder_sync (CamelStore *store,
 	CamelFolderInfo *root = NULL;
 	gchar *parent_id;
 	mapi_id_t parent_fid, new_folder_id;
+	mapi_object_t obj_folder;
+	EMapiConnection *conn;
 	GError *mapi_error = NULL;
 
 	if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
@@ -1074,11 +1173,6 @@ mapi_store_create_folder_sync (CamelStore *store,
 		return NULL;
 	}
 
-	if (parent_name && (strlen(parent_name) > 0) )
-		parent_id = g_strdup (g_hash_table_lookup (priv->name_hash, parent_name));
-	else
-		parent_id = g_strdup ("");
-
 	if (!mapi_connect_sync (CAMEL_SERVICE(store), cancellable, NULL)) {
 		g_set_error (
 			error, CAMEL_SERVICE_ERROR,
@@ -1089,19 +1183,54 @@ mapi_store_create_folder_sync (CamelStore *store,
 
 	camel_service_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
+	if (parent_name && *parent_name)
+		parent_id = g_strdup (g_hash_table_lookup (priv->name_hash, parent_name));
+	else
+		parent_id = NULL;
+
+	if (!parent_id) {
+		camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		g_set_error (
+			error, CAMEL_SERVICE_ERROR,
+			CAMEL_SERVICE_ERROR_UNAVAILABLE,
+			_("Cannot find folder '%s'"), parent_name ? parent_name : "");
+		return NULL;
+	}
 	e_mapi_util_mapi_id_from_string (parent_id, &parent_fid);
-	new_folder_id = e_mapi_connection_create_folder (priv->conn, olFolderInbox, parent_fid, 0, folder_name, cancellable, &mapi_error);
+	new_folder_id = 0;
+
+	conn = priv->conn;
+	if (!cms_open_folder (mapi_store, conn, parent_fid, &obj_folder, cancellable, error)) {
+		camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+		return NULL;
+	}
+
+	if (!e_mapi_connection_create_folder (conn, &obj_folder, folder_name, IPF_NOTE, &new_folder_id, cancellable, &mapi_error))
+		new_folder_id = 0;
+	e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+
 	if (new_folder_id != 0) {
 		gchar *folder_id_str;
+		CamelMapiStoreInfo *parent_msi;
+		gboolean is_public, is_foreign;
+
+		parent_msi = (CamelMapiStoreInfo *) camel_mapi_store_summary_get_folder_id (mapi_store->summary, parent_fid);
+		is_public = parent_msi && (parent_msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0;
+		is_foreign = parent_msi && (parent_msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0;
 
 		root = mapi_build_folder_info (mapi_store, parent_name, folder_name);
 		camel_mapi_store_summary_add_from_full (mapi_store->summary,
 			root->full_name,
 			new_folder_id,
 			parent_fid,
-			root->flags,
-			CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL,
-			NULL);
+			root->flags | ((is_public || is_foreign) ? CAMEL_FOLDER_SUBSCRIBED | CAMEL_STORE_INFO_FOLDER_SUBSCRIBED : 0),
+			(is_public ? CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC :
+			is_foreign ? CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN :
+			CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL) | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL,
+			is_foreign ? parent_msi->foreign_username : NULL);
+
+		if (parent_msi)
+			camel_store_summary_info_free (mapi_store->summary, (CamelStoreInfo *) parent_msi);
 
 		camel_store_summary_save (mapi_store->summary);
 
@@ -1138,7 +1267,8 @@ mapi_store_delete_folder_sync (CamelStore *store,
 {
 	CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (store);
 	CamelMapiStorePrivate  *priv = mapi_store->priv;
-
+	CamelMapiStoreInfo *msi;
+	mapi_object_t *obj_store = NULL;
 	const gchar *folder_id;
 	mapi_id_t folder_fid;
 	gboolean status = FALSE;
@@ -1160,13 +1290,22 @@ mapi_store_delete_folder_sync (CamelStore *store,
 
 	folder_id = g_hash_table_lookup (priv->name_hash, folder_name);
 	e_mapi_util_mapi_id_from_string (folder_id, &folder_fid);
-	status = e_mapi_connection_remove_folder (priv->conn, folder_fid, 0, cancellable, &local_error);
+
+	msi = (CamelMapiStoreInfo *) camel_mapi_store_summary_get_folder_id (mapi_store->summary, folder_fid);
+	if (!msi ||
+	    (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ||
+	    (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0) {
+		/* do nore remove foreign or public folders, just unsubscribe from them,
+		   even when there are folder delete permissons on the folder
+		*/
+		status = TRUE;
+	} else if (cms_peek_folder_store (mapi_store, priv->conn, folder_fid, &obj_store, cancellable, &local_error))
+		status = e_mapi_connection_remove_folder (priv->conn, obj_store, folder_fid, cancellable, &local_error);
+	else
+		status = FALSE;
 
 	if (status) {
-		/* Fixme ??  */
-/*		if (mapi_store->current_folder) */
-/*			g_object_unref (mapi_store->current_folder); */
-		success = mapi_forget_folder(mapi_store,folder_name,error);
+		success = mapi_forget_folder (mapi_store,folder_name,error);
 
 		/* remove from name_cache at the end, because the folder_id is from there */
 		/*g_hash_table_remove (priv->parent_hash, folder_id);*/
@@ -1462,7 +1601,7 @@ mapi_store_subscribe_folder_sync (CamelSubscribable *subscribable,
 	if (g_str_has_prefix (folder_name, DISPLAY_NAME_ALL_PUBLIC_FOLDERS) ) {
 		const gchar *f_name = NULL;
 
-		parent_name = DISPLAY_NAME_FAVOURITES;
+		parent_name = DISPLAY_NAME_FAVORITES;
 
 		f_name = strrchr (folder_name,'/');
 		if (!f_name) {
@@ -1500,11 +1639,34 @@ mapi_store_subscribe_folder_sync (CamelSubscribable *subscribable,
 		camel_subscribable_folder_subscribed (subscribable, fi);
 		camel_folder_info_free (fi);
 	} else {
-		CamelService *service;
+		CamelSettings *settings;
+		CamelMapiSettings *mapi_settings;
+		CamelNetworkSettings *network_settings;
+
 		guint folder_type = mapi_folders_hash_table_type_lookup (mapi_store, folder_name);
 
-		service = CAMEL_SERVICE (mapi_store);
-		e_mapi_add_esource (service, use_folder_name, fid, folder_type);
+		settings = camel_service_get_settings (CAMEL_SERVICE (mapi_store));
+		mapi_settings = CAMEL_MAPI_SETTINGS (settings);
+		network_settings = CAMEL_NETWORK_SETTINGS (settings);
+		
+		if (!e_mapi_folder_add_as_esource (folder_type,
+			camel_mapi_settings_get_profile (mapi_settings),
+			camel_mapi_settings_get_domain (mapi_settings),
+			camel_mapi_settings_get_realm (mapi_settings),
+			camel_network_settings_get_host (network_settings),
+			camel_network_settings_get_user (network_settings),
+			camel_mapi_settings_get_kerberos (mapi_settings),
+			camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (mapi_settings)),
+			E_MAPI_FOLDER_CATEGORY_PUBLIC,
+			NULL,
+			use_folder_name,
+			fid,
+			error)) {
+			camel_store_summary_info_free (mapi_store->summary, si);
+
+			return FALSE;
+		}
+
 	}
 	camel_store_summary_info_free (mapi_store->summary, si);
 
@@ -1517,7 +1679,6 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
                                     GCancellable *cancellable,
                                     GError **error)
 {
-	CamelService *service;
 	CamelFolderInfo *fi;
 	CamelStoreInfo *si;
 	gchar *parent_name = NULL;
@@ -1526,7 +1687,6 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
 
 	CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (subscribable);
 
-	service = CAMEL_SERVICE (mapi_store);
 	fid = camel_mapi_store_folder_id_lookup(mapi_store, folder_name);
 	si = camel_store_summary_path (mapi_store->summary, folder_name);
 	if (si) {
@@ -1541,7 +1701,7 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
 	}
 
 	if (g_str_has_prefix (folder_name, DISPLAY_NAME_ALL_PUBLIC_FOLDERS) ) {
-		parent_name = DISPLAY_NAME_FAVOURITES;
+		parent_name = DISPLAY_NAME_FAVORITES;
 
 		f_name = strrchr(folder_name,'/');
 		if (f_name != NULL)
@@ -1554,8 +1714,22 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
 		camel_subscribable_folder_unsubscribed (subscribable, fi);
 		camel_folder_info_free (fi);
 	} else {
+		CamelSettings *settings;
+		CamelNetworkSettings *network_settings;
 		guint folder_type = mapi_folders_hash_table_type_lookup (mapi_store, use_folder_name);
-		e_mapi_remove_esource (service, folder_name, fid, folder_type);
+
+		settings = camel_service_get_settings (CAMEL_SERVICE (mapi_store));
+		network_settings = CAMEL_NETWORK_SETTINGS (settings);
+
+		if (!e_mapi_folder_remove_as_esource (folder_type,
+			camel_network_settings_get_host (network_settings),
+			camel_network_settings_get_user (network_settings),
+			fid,
+			error)) {
+			camel_store_summary_info_free (mapi_store->summary, si);
+
+			return FALSE;
+		}
 	}
 
 	camel_store_summary_info_free (mapi_store->summary, si);
@@ -2397,3 +2571,119 @@ camel_mapi_store_get_connection (CamelMapiStore *mapi_store)
 	return mapi_store->priv->conn;
 }
 
+/* ppath contains proposed path, this only makes sure that it's a unique path */
+void
+camel_mapi_store_ensure_unique_path (CamelMapiStore *mapi_store,
+				     gchar **ppath)
+{
+	gboolean done;
+	guint counter = 0;
+	gchar *base_path = NULL;
+
+	g_return_if_fail (mapi_store != NULL);
+	g_return_if_fail (mapi_store->summary != NULL);
+	g_return_if_fail (ppath != NULL);
+	g_return_if_fail (*ppath != NULL);
+
+	done = FALSE;
+	while (!done) {
+		CamelStoreInfo *si;
+
+		done = TRUE;
+
+		si = camel_store_summary_path (mapi_store->summary, *ppath);
+		if (si) {
+			camel_store_summary_info_free (mapi_store->summary, si);
+
+			done = FALSE;
+			counter++;
+			if (!counter) {
+				g_debug ("%s: Counter overflow", G_STRFUNC);
+				break;
+			}
+
+			if (!base_path)
+				base_path = *ppath;
+			else
+				g_free (*ppath);
+
+			*ppath = g_strdup_printf ("%s_%u", base_path, counter);
+		}
+	}
+
+	g_free (base_path);
+}
+
+void
+camel_mapi_store_announce_subscribed_folder (CamelMapiStore *mapi_store,
+					     const gchar *path)
+{
+	CamelStoreInfo *si;
+	CamelFolderInfo *fi;
+	CamelMapiStoreInfo *msi;
+	gchar **parts, *folder_id_str, *parent_id_str;
+	GString *partial_path;
+	gint ii;
+
+	g_return_if_fail (mapi_store != NULL);
+	g_return_if_fail (mapi_store->summary != NULL);
+	g_return_if_fail (path != NULL);
+
+	si = camel_store_summary_path (mapi_store->summary, path);
+	g_return_if_fail (si != NULL);
+
+	camel_store_summary_info_free (mapi_store->summary, si);
+
+	parts = g_strsplit (path, "/", -1);
+	g_return_if_fail (parts != NULL);
+
+	partial_path = g_string_new ("");
+
+	/* first announce about virtual parents */
+	for (ii = 0; parts[ii]; ii++) {
+		if (ii > 0)
+			g_string_append (partial_path, "/");
+		g_string_append (partial_path, parts[ii]);
+
+		si = camel_store_summary_path (mapi_store->summary, partial_path->str);
+		if (si) {
+			/* it's a known path, no need to announce it */
+			camel_store_summary_info_free (mapi_store->summary, si);
+		} else {
+			/* it's an unknown path, not a real path, thus announce it too,
+			   to ensure the folder path for this new path will exist
+			*/
+			fi = mapi_build_folder_info (mapi_store, NULL, partial_path->str);
+			fi->flags |= CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_SYSTEM;
+
+			camel_store_folder_created (CAMEL_STORE (mapi_store), fi);
+			camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (mapi_store), fi);
+
+			camel_folder_info_free (fi);
+		}
+	}
+
+	g_string_free (partial_path, TRUE);
+	g_strfreev (parts);
+
+	/* finally announce about the path itself */
+	si = camel_store_summary_path (mapi_store->summary, path);
+	g_return_if_fail (si != NULL);
+
+	msi = (CamelMapiStoreInfo *) si;
+	folder_id_str = e_mapi_util_mapi_id_to_string (msi->folder_id);
+	parent_id_str = e_mapi_util_mapi_id_to_string (msi->parent_id);
+
+	fi = mapi_build_folder_info (mapi_store, NULL, camel_store_info_path (mapi_store->summary, si));
+	fi->flags = msi->camel_folder_flags;
+
+	mapi_update_folder_hash_tables (mapi_store, fi->full_name, folder_id_str, parent_id_str);
+
+	camel_store_folder_created (CAMEL_STORE (mapi_store), fi);
+	camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (mapi_store), fi);
+
+	camel_folder_info_free (fi);
+	camel_store_summary_info_free (mapi_store->summary, si);
+	g_free (folder_id_str);
+	g_free (parent_id_str);
+}
diff --git a/src/camel/camel-mapi-store.h b/src/camel/camel-mapi-store.h
index 809ec48..41844be 100644
--- a/src/camel/camel-mapi-store.h
+++ b/src/camel/camel-mapi-store.h
@@ -50,8 +50,9 @@
 	(G_TYPE_INSTANCE_GET_CLASS \
 	((obj), CAMEL_TYPE_MAPI_STORE, CamelMapiStoreClass))
 
-#define DISPLAY_NAME_FAVOURITES _("Favorites")
-#define DISPLAY_NAME_ALL_PUBLIC_FOLDERS _("All Public Folders")
+#define DISPLAY_NAME_FAVORITES		_("Favorites")
+#define DISPLAY_NAME_FOREIGN_FOLDERS	_("Foreign folders")
+#define DISPLAY_NAME_ALL_PUBLIC_FOLDERS	_("All Public Folders")
 
 G_BEGIN_DECLS
 
@@ -80,6 +81,9 @@ const gchar *	mapi_folders_hash_table_name_lookup (CamelMapiStore *store, const
 
 EMapiConnection *	camel_mapi_store_get_connection (CamelMapiStore *mapi_store);
 
+void		camel_mapi_store_ensure_unique_path (CamelMapiStore *mapi_store, gchar **ppath);
+void		camel_mapi_store_announce_subscribed_folder (CamelMapiStore *mapi_store, const gchar *path);
+
 G_END_DECLS
 
 #endif /* CAMEL_OPENCHANGE_STORE_H */
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index 690ea2c..7df766b 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -540,7 +540,7 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
 	struct SRow		aRow;
 	enum MAPISTATUS		ms;
 	uint32_t		i;
-	mapi_object_t           obj_store;
+	mapi_object_t           obj_folder;
 	const GSList *l;
 
 	const uint32_t			*publish_start;
@@ -562,12 +562,15 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
 
 	*freebusy = NULL;
 
-	if (!e_mapi_connection_get_public_folder (conn, &obj_store, cancellable, mapi_error)) {
+	mapi_object_init (&obj_folder);
+
+	if (!e_mapi_connection_get_public_folder (conn, &obj_folder, cancellable, mapi_error)) {
+		mapi_object_release (&obj_folder);
 		return FALSE;
 	}
 
 	for ( l = users; l != NULL; l = g_slist_next (l)) {
-		ms = GetUserFreeBusyData (&obj_store, (const gchar *)l->data, &aRow);
+		ms = GetUserFreeBusyData (&obj_folder, (const gchar *)l->data, &aRow);
 
 		if (ms != MAPI_E_SUCCESS) {
 			gchar *context = g_strconcat ("GetUserFreeBusyData for ", l->data, NULL);
@@ -576,6 +579,8 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
 
 			g_free (context);
 
+			mapi_object_release (&obj_folder);
+
 			return FALSE;
 		}
 
@@ -643,6 +648,8 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
 		talloc_free (aRow.lpProps);
 	}
 
+	mapi_object_release (&obj_folder);
+
 	return TRUE;
 }
 
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index f35cf9a..1433506 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -128,6 +128,8 @@ make_mapi_error (GError **perror, const gchar *context, enum MAPISTATUS mapi_sta
 	err (MAPI_E_INVALID_ACCESS_TIME,		_("Invalid access time"));
 	err (MAPI_E_ACCOUNT_DISABLED,			_("Account is disabled"));
 	err (MAPI_E_END_OF_SESSION,			_("End of session"));
+	err (MAPI_E_NOT_INITIALIZED,			_("MAPI is not initialized or connected"));
+	err (MAPI_E_NO_ACCESS,				_("Permission denied"));
 
 	#undef err
 
@@ -173,6 +175,8 @@ struct _EMapiConnectionPrivate {
 	gboolean has_public_store;	/* whether is 'public_store' filled */
 	mapi_object_t public_store;
 
+	GHashTable *foreign_stores;	/* username (gchar *) => msg_store (mapi_object_t *); opened foreign stores */
+
 	GSList *folders;		/* list of ExchangeMapiFolder pointers */
 	GStaticRecMutex folders_lock;	/* lock for 'folders' variable */
 
@@ -242,6 +246,17 @@ stop_all_notifications (EMapiConnectionPrivate *priv)
 	priv->notification_thread = NULL;
 }
 
+static void
+release_foreign_stores_cb (gpointer pusername, gpointer pmsg_store, gpointer user_data)
+{
+	mapi_object_t *msg_store = pmsg_store;
+
+	g_return_if_fail (msg_store != NULL);
+
+	mapi_object_release (msg_store);
+	talloc_free (msg_store);
+}
+
 /* should have session_lock locked already, when calling this function */
 static void
 disconnect (EMapiConnectionPrivate *priv)
@@ -259,6 +274,10 @@ disconnect (EMapiConnectionPrivate *priv)
 
 	if (priv->has_public_store)
 		mapi_object_release (&priv->public_store);
+
+	g_hash_table_foreach (priv->foreign_stores, release_foreign_stores_cb, NULL);
+	g_hash_table_remove_all (priv->foreign_stores); 
+
 	Logoff (&priv->msg_store);
 	/* it's released by the Logoff() call
 	mapi_object_release (&priv->msg_store); */
@@ -272,7 +291,8 @@ disconnect (EMapiConnectionPrivate *priv)
 
 /* should have session_lock locked already, when calling this function */
 static gboolean
-ensure_public_store (EMapiConnectionPrivate *priv, GError **perror)
+ensure_public_store (EMapiConnectionPrivate *priv,
+		     GError **perror)
 {
 	e_return_val_mapi_error_if_fail (priv != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
@@ -295,6 +315,51 @@ ensure_public_store (EMapiConnectionPrivate *priv, GError **perror)
 	return priv->has_public_store;
 }
 
+/* should have session_lock locked already, when calling this function */
+static gboolean
+ensure_foreign_store (EMapiConnectionPrivate *priv,
+		      const gchar *username,
+		      mapi_object_t **pmsg_store,
+		      GError **perror)
+{
+	enum MAPISTATUS ms;
+	mapi_object_t *msg_store;
+
+	e_return_val_mapi_error_if_fail (priv != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (pmsg_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	*pmsg_store = NULL;
+
+	if (!priv->session)
+		return FALSE;
+
+	msg_store = g_hash_table_lookup (priv->foreign_stores, username);
+	if (msg_store) {
+		*pmsg_store = msg_store;
+		return TRUE;
+	}
+
+	msg_store = talloc_zero (priv->session, mapi_object_t);
+	mapi_object_init (msg_store);
+
+	ms = OpenUserMailbox (priv->session, username, msg_store);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenUserMailbox", ms);
+
+		mapi_object_release (msg_store);
+		talloc_free (msg_store);
+
+		return FALSE;
+	}
+
+	g_hash_table_insert (priv->foreign_stores, g_strdup (username), msg_store);
+
+	*pmsg_store = msg_store;
+
+	return TRUE;
+}
+
 static void
 e_mapi_connection_dispose (GObject *object)
 {
@@ -329,6 +394,10 @@ e_mapi_connection_finalize (GObject *object)
 			g_hash_table_destroy (priv->named_ids);
 		priv->named_ids = NULL;
 
+		if (priv->foreign_stores)
+			g_hash_table_destroy (priv->foreign_stores);
+		priv->foreign_stores = NULL;
+
 		UNLOCK ();
 		g_static_rec_mutex_free (&priv->session_lock);
 		g_static_rec_mutex_free (&priv->folders_lock);
@@ -382,6 +451,7 @@ e_mapi_connection_init (EMapiConnection *conn)
 	conn->priv->has_public_store = FALSE;
 	conn->priv->folders = NULL;
 
+	conn->priv->foreign_stores = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 	conn->priv->named_ids = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
 
 	conn->priv->known_notifications = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, NULL);
@@ -653,8 +723,99 @@ may_skip_property (uint32_t proptag)
 }
 
 gboolean
+e_mapi_connection_test_foreign_folder (EMapiConnection *conn,
+				       const gchar *username,
+				       const gchar *folder_name,
+				       mapi_id_t *fid, /* out */
+				       GCancellable *cancellable,
+				       GError **perror)
+{
+	enum MAPISTATUS ms;
+	mapi_id_t foreign_fid = 0;
+	mapi_object_t obj_store, obj_folder;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (folder_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	LOCK ();
+
+	mapi_object_init (&obj_store);
+	mapi_object_init (&obj_folder);
+
+	ms = OpenUserMailbox (priv->session, username, &obj_store);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenUserMailbox", ms);
+		goto cleanup;
+	}
+
+	if (folder_name[0] == '0' && folder_name[1] == 'x' && e_mapi_util_mapi_id_from_string (folder_name + 2, &foreign_fid)) {
+		ms = OpenFolder (&obj_store, foreign_fid, &obj_folder);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "OpenFolder", ms);
+			goto cleanup;
+		}
+	} else {
+		uint32_t def_folder_id = 0;
+
+		/* intentionally not localized strings */
+		if (g_ascii_strcasecmp (folder_name, "Inbox") == 0) {
+			def_folder_id = olFolderInbox;
+		} else if (g_ascii_strcasecmp (folder_name, "DeletedItems") == 0) {
+			def_folder_id = olFolderDeletedItems;
+		} else if (g_ascii_strcasecmp (folder_name, "Outbox") == 0) {
+			def_folder_id = olFolderOutbox;
+		} else if (g_ascii_strcasecmp (folder_name, "SentMail") == 0) {
+			def_folder_id = olFolderSentMail;
+		} else if (g_ascii_strcasecmp (folder_name, "Calendar") == 0) {
+			def_folder_id = olFolderCalendar;
+		} else if (g_ascii_strcasecmp (folder_name, "Contacts") == 0) {
+			def_folder_id = olFolderContacts;
+		} else if (g_ascii_strcasecmp (folder_name, "Notes") == 0) {
+			def_folder_id = olFolderNotes;
+		} else if (g_ascii_strcasecmp (folder_name, "Tasks") == 0) {
+			def_folder_id = olFolderTasks;
+		} else if (g_ascii_strcasecmp (folder_name, "Drafts") == 0) {
+			def_folder_id = olFolderDrafts;
+		} else if (g_ascii_strcasecmp (folder_name, "Junk") == 0) {
+			def_folder_id = olFolderJunk;
+		} else if (!e_mapi_util_mapi_id_from_string (folder_name, &foreign_fid)) {
+			ms = MAPI_E_CALL_FAILED;
+			g_propagate_error (perror, g_error_new (E_MAPI_ERROR, ms, _("Folder name '%s' is not a known default folder name, nor folder ID."), folder_name));
+			goto cleanup;
+		}
+
+		if (def_folder_id != 0) {
+			ms = GetDefaultFolder (&obj_store, &foreign_fid, def_folder_id);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "GetDefaultFolder", ms);
+				goto cleanup;
+			}
+		}
+
+		ms = OpenFolder (&obj_store, foreign_fid, &obj_folder);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "OpenFolder", ms);
+			goto cleanup;
+		}
+	}
+
+	*fid = mapi_object_get_id (&obj_folder);
+
+ cleanup:
+	mapi_object_release (&obj_folder);
+	mapi_object_release (&obj_store);
+
+	UNLOCK ();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
 e_mapi_connection_get_public_folder (EMapiConnection *conn,
-				     mapi_object_t *obj_store,
+				     mapi_object_t *obj_folder,
 				     GCancellable *cancellable,
 				     GError **perror)
 {
@@ -665,15 +826,13 @@ e_mapi_connection_get_public_folder (EMapiConnection *conn,
 
 	LOCK ();
 
-	mapi_object_init (&priv->public_store);
-
-	ms = OpenPublicFolder (priv->session, &priv->public_store);
+	mapi_object_init (obj_folder);
 
+	ms = OpenPublicFolder (priv->session, obj_folder);
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "OpenPublicFolder", ms);
 	}
 
-	*obj_store = priv->public_store;
 	UNLOCK ();
 
 	return ms == MAPI_E_SUCCESS;
@@ -712,6 +871,59 @@ open_folder (EMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 f
 }
 
 gboolean
+e_mapi_connection_peek_store (EMapiConnection *conn,
+			      gboolean public_store,
+			      const gchar *foreign_username,
+			      mapi_object_t **obj_store, /* out */
+			      GCancellable *cancellable,
+			      GError **perror)
+{
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	if (public_store)
+		e_return_val_mapi_error_if_fail (foreign_username == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	if (foreign_username)
+		e_return_val_mapi_error_if_fail (!public_store, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	LOCK ();
+
+	if (public_store) {
+		if (!ensure_public_store (priv, perror)) {
+			UNLOCK ();
+			return FALSE;
+		}
+
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			UNLOCK ();
+			return FALSE;
+		}
+
+		*obj_store = &priv->public_store;
+
+		UNLOCK ();
+
+		return TRUE;
+	}
+
+	if (foreign_username) {
+		if (!ensure_foreign_store (priv, foreign_username, obj_store, perror)) {
+			UNLOCK ();
+			return FALSE;
+		}
+
+		UNLOCK ();
+		return TRUE;
+	}
+
+	*obj_store = &priv->msg_store;
+
+	UNLOCK ();
+
+	return TRUE;
+}
+
+gboolean
 e_mapi_connection_open_default_folder (EMapiConnection *conn,
 				       uint32_t olFolderIdentifier,
 				       mapi_object_t *obj_folder,
@@ -809,6 +1021,51 @@ e_mapi_connection_open_public_folder (EMapiConnection *conn,
 }
 
 gboolean
+e_mapi_connection_open_foreign_folder (EMapiConnection *conn,
+				       const gchar *username,
+				       mapi_id_t fid,
+				       mapi_object_t *obj_folder, /* out */
+				       GCancellable *cancellable,
+				       GError **perror)
+{
+	enum MAPISTATUS ms;
+	mapi_object_t *msg_store = NULL;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	LOCK ();
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		UNLOCK ();
+		return FALSE;
+	}
+
+	if (!ensure_foreign_store (conn->priv, username, &msg_store, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		if (perror && !*perror)
+			g_propagate_error (perror, g_error_new (E_MAPI_ERROR, ms, _("Failed to open store for user '%s'"), username));
+	} else {
+		ms = MAPI_E_SUCCESS;
+	}
+
+	mapi_object_init (obj_folder);
+
+	if (ms == MAPI_E_SUCCESS) {
+		ms = OpenFolder (msg_store, fid, obj_folder);
+		if (ms == MAPI_E_NOT_FOUND)
+			g_propagate_error (perror, g_error_new (E_MAPI_ERROR, ms, _("Folder of user '%s' not found"), username));
+		else if (ms != MAPI_E_SUCCESS)
+			make_mapi_error (perror, "OpenFolder", ms);
+	}
+
+	UNLOCK ();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
 e_mapi_connection_close_folder (EMapiConnection *conn,
 				mapi_object_t *obj_folder,
 				GCancellable *cancellable,
@@ -826,13 +1083,87 @@ e_mapi_connection_close_folder (EMapiConnection *conn,
 	return TRUE;
 }
 
+static void
+maybe_add_named_id_tag (uint32_t proptag,
+			EResolveNamedIDsData **named_ids_list,
+			guint *named_ids_len)
+{
+	g_return_if_fail (named_ids_list != NULL);
+	g_return_if_fail (named_ids_len != NULL);
+
+	if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
+		if (!*named_ids_list) {
+			*named_ids_list = g_new0 (EResolveNamedIDsData, 1);
+			*named_ids_len = 0;
+		} else {
+			*named_ids_list = g_renew (EResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
+		}
+
+		(*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
+		(*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
+		(*named_ids_len) += 1;
+	}
+}
+
+/* free returned pointer with g_hash_table_destroy */
+static GHashTable *
+prepare_maybe_replace_hash (const EResolveNamedIDsData *named_ids_list,
+			    guint named_ids_len,
+			    gboolean to_server_ids)
+{
+	GHashTable *res;
+	gint ii;
+
+	if (!named_ids_list || !named_ids_len)
+		return NULL;
+
+	res = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+	for (ii = 0; ii < named_ids_len; ii++) {
+		uint32_t search_tag = named_ids_list[ii].pidlid_propid;
+		uint32_t replace_with = named_ids_list[ii].propid;
+
+		if (!to_server_ids) {
+			uint32_t ui32;
+
+			ui32 = search_tag;
+			search_tag = replace_with;
+			replace_with = ui32;
+		}
+
+		g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
+
+		search_tag = (search_tag & ~0xFFFF) | PT_ERROR;
+		replace_with = (replace_with & ~0xFFFF) | PT_ERROR;
+
+		g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
+	}
+
+	return res;
+}
+
+static void
+maybe_replace_named_id_tag (uint32_t *pproptag,
+			    GHashTable *replace_hash)
+{
+	gpointer key, value;
+
+	g_return_if_fail (pproptag != NULL);
+
+	if (!replace_hash)
+		return;
+
+	if (g_hash_table_lookup_extended (replace_hash, GUINT_TO_POINTER (*pproptag), &key, &value))
+		*pproptag = GPOINTER_TO_UINT (value);
+}
+
 /* deals with named IDs transparently, if not using NULL bpr_cb, thus it's OK to check with PidLid and PidName constants only */
 gboolean
 e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 					 mapi_object_t *obj_folder,
 					 BuildReadPropsCB brp_cb,
 					 gpointer brp_cb_user_data,
-					 GetFolderPropertiesCB cb,
+					 GetPropertiesCB cb,
 					 gpointer cb_user_data,
 					 GCancellable *cancellable,
 					 GError **perror)
@@ -869,6 +1200,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 		uint32_t prop_count = 0, k, ll;
 		EResolveNamedIDsData *named_ids_list = NULL;
 		guint named_ids_len = 0;
+		GHashTable *replace_hash = NULL;
 
 		lpProps = talloc_zero (mem_ctx, struct SPropValue);
 
@@ -881,12 +1213,8 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 					name = "";
 
 				g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
-			} else if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
-				if (!named_ids_list)
-					named_ids_list = g_new0 (EResolveNamedIDsData, spropTagArray->cValues - k + 1);
-				named_ids_list[named_ids_len].pidlid_propid = proptag;
-				named_ids_list[named_ids_len].propid = MAPI_E_RESERVED;
-				named_ids_len++;
+			} else {
+				maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
 			}
 		}
 
@@ -901,16 +1229,17 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 				goto cleanup;
 			}
 
-			for (k = 0, ll = 0; k < named_ids_len; k++) {
-				if (named_ids_list[k].propid != MAPI_E_RESERVED) {
-					while (ll < spropTagArray->cValues) {
-						if (spropTagArray->aulPropTag[k] == named_ids_list[k].pidlid_propid) {
-							spropTagArray->aulPropTag[k] = named_ids_list[k].propid;
-							break;
-						}
-						ll++;
-					}
+			replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
+			if (replace_hash) {
+				for (k = 0; k < spropTagArray->cValues; k++) {
+					uint32_t proptag = spropTagArray->aulPropTag[k];
+
+					maybe_replace_named_id_tag (&proptag, replace_hash);
+
+					spropTagArray->aulPropTag[k] = proptag;
 				}
+				g_hash_table_destroy (replace_hash);
+				replace_hash = NULL;
 			}
 		}
 
@@ -926,6 +1255,9 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 			goto cleanup;
 		}
 
+		if (named_ids_list)
+			replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, FALSE);
+
 		/* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
 		properties->cValues = prop_count;
 		properties->lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, prop_count + 1);
@@ -934,22 +1266,18 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
 				ll--;
 				properties->cValues--;
 			} else {
-				if (named_ids_list) {
-					guint m;
-
-					for (m = 0; m < named_ids_len; m++) {
-						if (lpProps[k].ulPropTag == named_ids_list[named_ids_len - m - 1].propid ||
-						    (((lpProps[k].ulPropTag & 0xFFFF) == PT_ERROR) &&
-							(lpProps[k].ulPropTag & ~0xFFFF) == (named_ids_list[named_ids_len - m - 1].propid & ~0xFFFF))) {
-							lpProps[k].ulPropTag = (lpProps[k].ulPropTag & 0xFFFF) | (named_ids_list[named_ids_len - m - 1].pidlid_propid & ~0xFFFF);
-							break;
-						}
-					}
-				}
+				uint32_t proptag = lpProps[k].ulPropTag;
+
+				maybe_replace_named_id_tag (&proptag, replace_hash);
+				lpProps[k].ulPropTag = proptag;
 
 				cast_mapi_SPropValue (mem_ctx, &properties->lpProps[ll], &lpProps[k]);
 			}
 		}
+
+		g_free (named_ids_list);
+		if (replace_hash)
+			g_hash_table_destroy (replace_hash);
 	} else {
 		ms = GetPropsAll (obj_folder, MAPI_UNICODE, properties);
 		if (ms != MAPI_E_SUCCESS) {
@@ -1083,28 +1411,6 @@ list_objects_internal_cb (EMapiConnection *conn,
 }
 
 static void
-maybe_add_named_id_tag (uint32_t proptag,
-			EResolveNamedIDsData **named_ids_list,
-			guint *named_ids_len)
-{
-	g_return_if_fail (named_ids_list != NULL);
-	g_return_if_fail (named_ids_len != NULL);
-
-	if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
-		if (!*named_ids_list) {
-			*named_ids_list = g_new0 (EResolveNamedIDsData, 1);
-			*named_ids_len = 0;
-		} else {
-			*named_ids_list = g_renew (EResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
-		}
-
-		(*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
-		(*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
-		(*named_ids_len) += 1;
-	}
-}
-
-static void
 gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
 				    EResolveNamedIDsData **named_ids_list,
 				    guint *named_ids_len)
@@ -1155,49 +1461,6 @@ gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
 	}
 }
 
-/* free returned pointer with g_hash_table_destroy */
-static GHashTable *
-prepare_maybe_replace_hash (const EResolveNamedIDsData *named_ids_list,
-			    guint named_ids_len)
-{
-	GHashTable *res;
-	gint ii;
-
-	if (!named_ids_list || !named_ids_len)
-		return NULL;
-
-	res = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-	for (ii = 0; ii < named_ids_len; ii++) {
-		uint32_t search_tag = named_ids_list[ii].pidlid_propid;
-		uint32_t replace_with = named_ids_list[ii].propid;
-
-		g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
-
-		search_tag = (search_tag & ~0xFFFF) | PT_ERROR;
-		replace_with = (replace_with & ~0xFFFF) | PT_ERROR;
-
-		g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
-	}
-
-	return res;
-}
-
-static void
-maybe_replace_named_id_tag (uint32_t *pproptag,
-			    GHashTable *replace_hash)
-{
-	gpointer key, value;
-
-	g_return_if_fail (pproptag != NULL);
-
-	if (!replace_hash)
-		return;
-
-	if (g_hash_table_lookup_extended (replace_hash, GUINT_TO_POINTER (*pproptag), &key, &value))
-		*pproptag = GPOINTER_TO_UINT (value);
-}
-
 static void
 replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
 				     GHashTable *replace_hash)
@@ -1279,7 +1542,7 @@ change_mapi_SRestriction_named_ids (EMapiConnection *conn,
 	res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
 
 	if (res) {
-		GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+		GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
 
 		if (replace_hash) {
 			replace_mapi_SRestriction_named_ids (restrictions, replace_hash);
@@ -2534,7 +2797,7 @@ convert_mapi_props_to_props (EMapiConnection *conn,
 		res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
 
 		if (res)
-			replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+			replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
 
 		if (replace_hash && *props) {
 			for (ii = 0; ii < *propslen; ii++) {
@@ -2871,7 +3134,7 @@ add_object_recipients (EMapiConnection *conn,
 			goto cleanup;
 		}
 
-		replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+		replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
 
 		for (ii = 0; ii < tags->cValues && replace_hash; ii++) {
 			uint32_t proptag = tags->aulPropTag[ii];
@@ -3699,7 +3962,7 @@ e_mapi_connection_list_gal_objects (EMapiConnection *conn,
 				res = e_mapi_connection_resolve_named_props (conn, 0, named_ids_list, named_ids_len, cancellable, perror);
 
 				if (res) {
-					GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+					GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
 
 					use_restriction = talloc_zero (mem_ctx, struct Restriction_r);
 					convert_mapi_SRestriction_to_Restriction_r (restrictions, use_restriction, mem_ctx, replace_hash);
@@ -3903,7 +4166,7 @@ e_mapi_connection_transfer_gal_objects (EMapiConnection *conn,
 			goto cleanup;
 		}
 
-		replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+		replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
 
 		if (replace_hash) {
 			for (ii = 0; ii < propTagArray->cValues; ii++) {
@@ -3964,36 +4227,29 @@ e_mapi_connection_transfer_gal_object (EMapiConnection *conn,
 	return res;
 }
 
-mapi_id_t
+gboolean
 e_mapi_connection_create_folder (EMapiConnection *conn,
-				 uint32_t olFolder,
-				 mapi_id_t pfid,
-				 guint32 fid_options,
+				 mapi_object_t *obj_parent_folder, /* in */
 				 const gchar *name,
+				 const gchar *new_folder_type, /* usually IPF_NOTE and similar */
+				 mapi_id_t *new_fid, /* out */
 				 GCancellable *cancellable,
 				 GError **perror)
 {
 	enum MAPISTATUS ms;
 	mapi_object_t obj_folder;
-	mapi_object_t obj_top;
 	struct SPropValue vals[1];
-	const gchar *type;
 	mapi_id_t fid = 0;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_parent_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (new_folder_type != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (new_fid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
-	mapi_object_init(&obj_top);
-	mapi_object_init(&obj_folder);
-
-	/* We now open the top/parent folder */
-	ms = open_folder (conn, olFolder, &pfid, fid_options, &obj_top, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
+	mapi_object_init (&obj_folder);
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
@@ -4001,34 +4257,14 @@ e_mapi_connection_create_folder (EMapiConnection *conn,
 	}
 
 	/* Attempt to create the folder */
-	ms = CreateFolder (&obj_top, FOLDER_GENERIC, name, "Created using Evolution/LibMAPI", OPEN_IF_EXISTS | MAPI_UNICODE, &obj_folder);
+	ms = CreateFolder (obj_parent_folder, FOLDER_GENERIC, name, "Created using Evolution/LibMAPI", OPEN_IF_EXISTS | MAPI_UNICODE, &obj_folder);
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "CreateFolder", ms);
 		goto cleanup;
 	}
 
-	switch (olFolder) {
-		case olFolderInbox:
-			type = IPF_NOTE;
-			break;
-		case olFolderCalendar:
-			type = IPF_APPOINTMENT;
-			break;
-		case olFolderContacts:
-			type = IPF_CONTACT;
-			break;
-		case olFolderTasks:
-			type = IPF_TASK;
-			break;
-		case olFolderNotes:
-			type = IPF_STICKYNOTE;
-			break;
-		default:
-			type = IPF_NOTE;
-	}
-
-	vals[0].value.lpszA = type;
-	vals[0].ulPropTag = PR_CONTAINER_CLASS;
+	vals[0].value.lpszW = new_folder_type;
+	vals[0].ulPropTag = PidTagContainerClass;
 
 	ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, vals, 1);
 	if (ms != MAPI_E_SUCCESS) {
@@ -4037,131 +4273,184 @@ e_mapi_connection_create_folder (EMapiConnection *conn,
 	}
 
 	fid = mapi_object_get_id (&obj_folder);
-	e_mapi_debug_print("Folder %s created with id %016" G_GINT64_MODIFIER "X ", name, fid);
+	if (fid == 0) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "mapi_object_get_id", ms);
+	} else {
+		*new_fid = fid;
+	}
 
-	g_static_rec_mutex_lock (&priv->folders_lock);
+ cleanup:
+	mapi_object_release (&obj_folder);
 
-	/* we should also update folder list locally */
-	if (fid != 0 && priv->folders != NULL) {
-		EMapiFolder *folder = NULL;
-		folder = e_mapi_folder_new (name, type, MAPI_PERSONAL_FOLDER, fid, pfid, 0, 0, 0);
-		if (folder)
-			priv->folders = g_slist_append (priv->folders, folder);
+	UNLOCK ();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
+e_mapi_connection_empty_folder (EMapiConnection *conn,
+				mapi_object_t *obj_folder,
+				GCancellable *cancellable,
+				GError **perror)
+{
+	enum MAPISTATUS ms;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	LOCK ();
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
 	}
 
-	g_static_rec_mutex_unlock (&priv->folders_lock);
+	/* Empty the contents of the folder */
+	ms = EmptyFolder (obj_folder);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "EmptyFolder", ms);
+		goto cleanup;
+	}
+
+ cleanup:
+	UNLOCK ();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
+static gboolean
+add_parent_fid_prop_cb (EMapiConnection *conn,
+			TALLOC_CTX *mem_ctx,
+			struct SPropTagArray *props,
+			gpointer data,
+			GCancellable *cancellable,
+			GError **perror)
+{
+	g_return_val_if_fail (mem_ctx != NULL, FALSE);
+	g_return_val_if_fail (props != NULL, FALSE);
+
+	SPropTagArray_add (mem_ctx, props, PidTagParentFolderId);
+
+	return TRUE;
+}
+
+static gboolean
+read_parent_fid_prop_cb (EMapiConnection *conn,
+			 TALLOC_CTX *mem_ctx,
+			 /* const */ struct mapi_SPropValue_array *properties,
+			 gpointer user_data,
+			 GCancellable *cancellable,
+			 GError **perror)
+{
+	mapi_id_t *pmid = user_data;
+	const mapi_id_t *cmid;
 
- cleanup:
-	mapi_object_release(&obj_folder);
-	mapi_object_release(&obj_top);
+	g_return_val_if_fail (properties != NULL, FALSE);
+	g_return_val_if_fail (pmid != NULL, FALSE);
 
-	UNLOCK ();
+	cmid = e_mapi_util_find_array_propval (properties, PidTagParentFolderId);
+	g_return_val_if_fail (cmid != NULL, FALSE);
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	*pmid = *cmid;
 
-	/* Shouldn't we return (EMapiFolder *) instead of a plain fid ? */
-	return fid;
+	return TRUE;
 }
 
-gboolean
-e_mapi_connection_empty_folder (EMapiConnection *conn,
-				mapi_id_t fid,
-				guint32 fid_options,
-				GCancellable *cancellable,
-				GError **perror)
+static gboolean
+emc_open_folders (EMapiConnection *conn,
+		  mapi_object_t *obj_store, /* in */
+		  mapi_id_t child_fid,
+		  mapi_object_t *obj_child_folder, /* out */
+		  mapi_object_t *obj_parent_folder, /* out */
+		  GCancellable *cancellable,
+		  GError **perror)
 {
 	enum MAPISTATUS ms;
-	mapi_object_t obj_folder;
-	gboolean result = FALSE;
+	mapi_id_t parent_fid = 0;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+	e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_child_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_parent_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
-	mapi_object_init (&obj_folder);
 
-	/* Attempt to open the folder to be emptied */
-	ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
+	ms = OpenFolder (obj_store, child_fid, obj_child_folder);
 	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenFolder-1", ms);
 		goto cleanup;
 	}
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
+		mapi_object_release (obj_child_folder);
 		goto cleanup;
 	}
 
-	/* Empty the contents of the folder */
-	ms = EmptyFolder (&obj_folder);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "EmptyFolder", ms);
+	if (!e_mapi_connection_get_folder_properties (conn, obj_child_folder, add_parent_fid_prop_cb, NULL, read_parent_fid_prop_cb, &parent_fid, cancellable, perror) ||
+	    parent_fid == 0) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "GetFolderProperties", ms);
+		mapi_object_release (obj_child_folder);
 		goto cleanup;
 	}
 
-	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		mapi_object_release (obj_child_folder);
+		goto cleanup;
+	}
 
-	result = TRUE;
+	ms = OpenFolder (obj_store, parent_fid, obj_parent_folder);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenFolder-2", ms);
+		mapi_object_release (obj_child_folder);
+		goto cleanup;
+	}
 
  cleanup:
-	mapi_object_release(&obj_folder);
 	UNLOCK ();
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
 gboolean
 e_mapi_connection_remove_folder (EMapiConnection *conn,
-				 mapi_id_t fid,
-				 guint32 fid_options,
+				 mapi_object_t *obj_store, /* in, store, to which folder belongs */
+				 mapi_id_t fid_to_remove,
 				 GCancellable *cancellable,
 				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	mapi_object_t obj_top;
+	mapi_object_t obj_parent;
 	mapi_object_t obj_folder;
 	EMapiFolder *folder;
-	gboolean result = FALSE;
 	GSList *l;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
 	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	g_return_val_if_fail (fid != 0, FALSE);
+	e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (fid_to_remove != 0, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
 	folder = NULL;
 	for (l = e_mapi_connection_peek_folders_list (conn); l; l = l->next) {
 		folder = l->data;
-		if (folder && folder->folder_id == fid)
+		if (folder && folder->folder_id == fid_to_remove)
 			break;
 		else
 			folder = NULL;
 	}
 
-	e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
 	LOCK ();
-	mapi_object_init(&obj_top);
-	mapi_object_init(&obj_folder);
-
-	/* FIXME: If the folder has sub-folders, open each of them in turn, empty them and delete them.
-	 * Note that this has to be done recursively, for the sub-folders as well.
-	 */
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
 
-	/* Attempt to open the folder to be removed */
-	ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
+	if (!emc_open_folders (conn, obj_store, fid_to_remove, &obj_folder, &obj_parent, cancellable, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "emc_open_folders", ms);
+		
 	}
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -4176,45 +4465,32 @@ e_mapi_connection_remove_folder (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
-
-	/* Attempt to open the top/parent folder */
-	ms = open_folder (conn, 0, &folder->parent_folder_id, fid_options, &obj_top, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
-
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
 		goto cleanup;
 	}
 
 	/* Call DeleteFolder on the folder to be removed */
-	ms = DeleteFolder (&obj_top, fid, DEL_FOLDERS, NULL);
+	ms = DeleteFolder (&obj_parent, fid_to_remove, DEL_FOLDERS, NULL);
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "DeleteFolder", ms);
 		goto cleanup;
 	}
 
-	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was deleted ", fid);
-
-	result = TRUE;
-
  cleanup:
-	mapi_object_release(&obj_folder);
-	mapi_object_release(&obj_top);
-
-	g_static_rec_mutex_lock (&priv->folders_lock);
-	priv->folders = g_slist_remove (priv->folders, folder);
-	g_static_rec_mutex_unlock (&priv->folders_lock);
+	mapi_object_release (&obj_folder);
+	mapi_object_release (&obj_parent);
 
-	e_mapi_folder_free (folder);
+	if (folder) {
+		g_static_rec_mutex_lock (&priv->folders_lock);
+		priv->folders = g_slist_remove (priv->folders, folder);
+		e_mapi_folder_free (folder);
+		g_static_rec_mutex_unlock (&priv->folders_lock);
+	}
 
 	UNLOCK ();
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
 gboolean
@@ -4755,9 +5031,7 @@ e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
 
 gboolean
 e_mapi_connection_set_flags (EMapiConnection *conn,
-			     uint32_t olFolder,
-			     mapi_id_t fid,
-			     guint32 fid_options,
+			     mapi_object_t *obj_folder,
 			     GSList *mids,
 			     uint32_t flag,
 			     GCancellable *cancellable,
@@ -4765,7 +5039,6 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
 {
 	enum MAPISTATUS ms;
 	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_folder;
 	uint32_t i;
 	mapi_id_t *id_messages;
 	GSList *tmp = mids;
@@ -4773,29 +5046,23 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
 	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
 	LOCK ();
 	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
 
-	id_messages = talloc_array(mem_ctx, mapi_id_t, g_slist_length (mids));
-	for (i=0; tmp; tmp=tmp->next, i++)
+	id_messages = talloc_array (mem_ctx, mapi_id_t, g_slist_length (mids));
+	for (i = 0; tmp; tmp = tmp->next, i++)
 		id_messages[i] = *((mapi_id_t *)tmp->data);
 
-	/* Attempt to open the folder */
-	ms = open_folder (conn, olFolder, &fid, fid_options, &obj_folder, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
-
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
 		goto cleanup;
 	}
 
-	ms = SetReadFlags (&obj_folder, flag, i, id_messages);
+	ms = SetReadFlags (obj_folder, flag, i, id_messages);
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "SetReadFlags", ms);
 		goto cleanup;
@@ -4804,8 +5071,7 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
 	result = TRUE;
 
  cleanup:
-	mapi_object_release(&obj_folder);
-	talloc_free(mem_ctx);
+	talloc_free (mem_ctx);
 
 	UNLOCK ();
 
@@ -4814,41 +5080,22 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
 	return result;
 }
 
-static gboolean
-mapi_move_items (EMapiConnection *conn,
-		 mapi_id_t src_fid,
-		 guint32 src_fid_options,
-		 mapi_id_t dest_fid,
-		 guint32 dest_fid_options,
-		 GSList *mid_list,
-		 gboolean do_copy,
-		 GCancellable *cancellable,
-		 GError **perror)
+gboolean
+e_mapi_connection_copymove_items (EMapiConnection *conn,
+				  mapi_object_t *src_obj_folder,
+				  mapi_object_t *des_obj_folder,
+				  gboolean do_copy,
+				  GSList *mid_list,
+				  GCancellable *cancellable,
+				  GError **perror)
 {
 	enum MAPISTATUS	ms;
-	mapi_object_t obj_folder_src;
-	mapi_object_t obj_folder_dst;
 	GSList *l;
 
-	e_return_val_mapi_error_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	mapi_object_init(&obj_folder_src);
-	mapi_object_init(&obj_folder_dst);
-
-	ms = open_folder (conn, 0, &src_fid, src_fid_options, &obj_folder_src, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
 
-	ms = open_folder (conn, 0, &dest_fid, dest_fid_options, &obj_folder_dst, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
+	LOCK ();
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
@@ -4866,7 +5113,7 @@ mapi_move_items (EMapiConnection *conn,
 
 		mid_list = l;
 
-		ms = MoveCopyMessages (&obj_folder_src, &obj_folder_dst, &msg_id_array, do_copy);
+		ms = MoveCopyMessages (src_obj_folder, des_obj_folder, &msg_id_array, do_copy);
 		mapi_id_array_release (&msg_id_array);
 
 		if (ms != MAPI_E_SUCCESS) {
@@ -4881,76 +5128,20 @@ mapi_move_items (EMapiConnection *conn,
 	}
 
  cleanup:
-	mapi_object_release(&obj_folder_dst);
-	mapi_object_release(&obj_folder_src);
-
-	return ms;
-}
-
-gboolean
-e_mapi_connection_copy_items (EMapiConnection *conn,
-			      mapi_id_t src_fid,
-			      guint32 src_fid_options,
-			      mapi_id_t dest_fid,
-			      guint32 dest_fid_options,
-			      GSList *mids,
-			      GCancellable *cancellable,
-			      GError **perror)
-{
-	enum MAPISTATUS ms;
-
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
-	LOCK ();
-	ms = mapi_move_items (conn, src_fid, src_fid_options, dest_fid, dest_fid_options, mids, TRUE, cancellable, perror);
-	UNLOCK ();
-
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-gboolean
-e_mapi_connection_move_items (EMapiConnection *conn,
-			      mapi_id_t src_fid,
-			      guint32 src_fid_options,
-			      mapi_id_t dest_fid,
-			      guint32 dest_fid_options,
-			      GSList *mids,
-			      GCancellable *cancellable,
-			      GError **perror)
-{
-	enum MAPISTATUS ms;
-
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
-	LOCK ();
-	ms = mapi_move_items (conn, src_fid, src_fid_options, dest_fid, dest_fid_options, mids, FALSE, cancellable, perror);
 	UNLOCK ();
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
 	return ms == MAPI_E_SUCCESS;
 }
 
 gboolean
 e_mapi_connection_remove_items (EMapiConnection *conn,
-				uint32_t olFolder,
-				mapi_id_t fid,
-				guint32 fid_options,
+				mapi_object_t *obj_folder,
 				const GSList *mids,
 				GCancellable *cancellable,
 				GError **perror)
 {
 	enum MAPISTATUS ms;
 	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_folder;
 	uint32_t i;
 	mapi_id_t *id_messages;
 	const GSList *tmp = mids;
@@ -4958,33 +5149,27 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
 	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
 	LOCK ();
 
 	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
 
-	id_messages = talloc_array(mem_ctx, mapi_id_t, g_slist_length ((GSList *) mids));
+	id_messages = talloc_array (mem_ctx, mapi_id_t, g_slist_length ((GSList *) mids));
 	for (i = 0; tmp; tmp = tmp->next, i++) {
 		mapi_id_t *data = tmp->data;
 		id_messages[i] = *data;
 	}
 
-	/* Attempt to open the folder */
-	ms = open_folder (conn, olFolder, &fid, fid_options, &obj_folder, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
-
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
 		goto cleanup;
 	}
 
 	/* Delete the messages from the folder */
-	ms = DeleteMessage (&obj_folder, id_messages, i);
+	ms = DeleteMessage (obj_folder, id_messages, i);
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "DeleteMessage", ms);
 		goto cleanup;
@@ -4993,7 +5178,6 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
 	result = TRUE;
 
  cleanup:
-	mapi_object_release(&obj_folder);
 	talloc_free(mem_ctx);
 
 	UNLOCK ();
@@ -5397,7 +5581,7 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
 
 	/* FIXME: May have to get the child folders count? Do we need/use it? */
 	folder = e_mapi_folder_new (mailbox_name, IPF_NOTE,
-					   MAPI_PERSONAL_FOLDER, mailbox_id, 0, 0, 0 ,0);
+					   E_MAPI_FOLDER_CATEGORY_PERSONAL, mailbox_id, 0, 0, 0 ,0);
 	folder->is_default = true;
 	folder->default_type = olFolderTopInformationStore; /*Is this correct ?*/
 	folder->size = mailbox_size ? *mailbox_size : 0;
@@ -5405,7 +5589,7 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
 	*mapi_folders = g_slist_prepend (*mapi_folders, folder);
 
 	/* FIXME: check status of get_child_folders */
-	result = get_child_folders (conn, mem_ctx, MAPI_PERSONAL_FOLDER, &priv->msg_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
+	result = get_child_folders (conn, mem_ctx, E_MAPI_FOLDER_CATEGORY_PERSONAL, &priv->msg_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
 
 	*mapi_folders = g_slist_reverse (*mapi_folders);
 
@@ -5471,7 +5655,7 @@ e_mapi_connection_get_pf_folders_list (EMapiConnection *conn,
 	folder->is_default = true;
 	folder->default_type = olPublicFoldersAllPublicFolders;
 	*mapi_folders = g_slist_prepend (*mapi_folders, folder);
-	result = get_child_folders (conn, mem_ctx, MAPI_FAVOURITE_FOLDER, &priv->public_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
+	result = get_child_folders (conn, mem_ctx, E_MAPI_FOLDER_CATEGORY_PUBLIC, &priv->public_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
 	*mapi_folders = g_slist_reverse (*mapi_folders);
 
  cleanup:
@@ -5523,7 +5707,7 @@ e_mapi_connection_ex_to_smtp (EMapiConnection *conn,
 	gchar			*smtp_addr = NULL;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, NULL);
 
 	e_return_val_mapi_error_if_fail (ex_address != NULL, MAPI_E_INVALID_PARAMETER, NULL);
 
@@ -5562,6 +5746,169 @@ e_mapi_connection_ex_to_smtp (EMapiConnection *conn,
 	return smtp_addr;
 }
 
+gboolean
+e_mapi_connection_resolve_username (EMapiConnection *conn,
+				    const gchar *to_resolve,
+				    BuildReadPropsCB brp_cb,
+				    gpointer brp_cb_user_data,
+				    GetPropertiesCB cb,
+				    gpointer cb_user_data,
+				    GCancellable *cancellable,
+				    GError **perror)
+{
+	enum MAPISTATUS ms;
+	TALLOC_CTX *mem_ctx;
+	struct SPropTagArray *tag_array;
+	struct SRowSet *rows = NULL;
+	struct PropertyTagArray_r *flaglist = NULL;
+	const gchar *str_array[2];
+	EResolveNamedIDsData *named_ids_list = NULL;
+	guint named_ids_len = 0, ii, jj, qq;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (to_resolve != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	str_array[0] = to_resolve;
+	str_array[1] = NULL;
+
+	LOCK ();
+
+	mem_ctx = talloc_new (priv->session);
+
+	tag_array = set_SPropTagArray (mem_ctx, 3,
+		PidTagEntryId,
+		PidTagDisplayName,
+		PidTagSmtpAddress);
+
+	ms = MAPI_E_SUCCESS;
+	if (brp_cb != NULL && !brp_cb (conn, mem_ctx, tag_array, brp_cb_user_data, cancellable, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "build_read_props_callback", ms);
+	}
+
+	if (ms == MAPI_E_SUCCESS) {
+		for (ii = 0; ii < tag_array->cValues; ii++) {
+			uint32_t proptag = tag_array->aulPropTag[ii];
+
+			if (may_skip_property (proptag)) {
+				const gchar *name = get_proptag_name (proptag);
+				if (!name)
+					name = "";
+
+				g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
+			} else {
+				maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+			}
+		}
+
+		if (named_ids_list) {
+			GHashTable *replace_hash;
+
+			if (!e_mapi_connection_resolve_named_props (conn, 0, named_ids_list, named_ids_len, cancellable, perror)) {
+				goto cleanup;
+			}
+
+			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+				goto cleanup;
+			}
+
+			replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
+			if (replace_hash) {
+				for (ii = 0; ii < tag_array->cValues; ii++) {
+					uint32_t proptag = tag_array->aulPropTag[ii];
+
+					maybe_replace_named_id_tag (&proptag, replace_hash);
+
+					tag_array->aulPropTag[ii] = proptag;
+				}
+
+				g_hash_table_destroy (replace_hash);
+				replace_hash = NULL;
+			}
+		}
+
+		ms = ResolveNames (priv->session, str_array, tag_array, &rows, &flaglist, MAPI_UNICODE);
+		if (ms != MAPI_E_SUCCESS && ms != MAPI_E_USER_CANCEL) {
+			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+				ms = MAPI_E_USER_CANCEL;
+			} else {
+				ms = ResolveNames (priv->session, str_array, tag_array, &rows, &flaglist, 0);
+			}
+		}
+
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "ResolveNames", ms);
+			goto cleanup;
+		}
+	}
+
+	if (ms == MAPI_E_SUCCESS && rows) {
+		GHashTable *replace_hash = NULL;
+
+		if (named_ids_list)
+			replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, FALSE);
+
+		for (qq = 0; qq < rows->cRows; qq++) {
+			struct mapi_SPropValue_array *properties;
+			struct SRow *row;
+
+			row = &rows->aRow[qq];
+			properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
+			if (!properties) {
+				UNLOCK();
+				e_return_val_mapi_error_if_fail (properties != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+			}
+
+			/* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
+			properties->cValues = row->cValues;
+			properties->lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, properties->cValues + 1);
+			for (ii = 0, jj = 0; ii < row->cValues; ii++, jj++) {
+				if (may_skip_property (row->lpProps[ii].ulPropTag)) {
+					jj--;
+					properties->cValues--;
+				} else {
+					uint32_t proptag = row->lpProps[ii].ulPropTag;
+
+					maybe_replace_named_id_tag (&proptag, replace_hash);
+					row->lpProps[ii].ulPropTag = proptag;
+
+					cast_mapi_SPropValue (mem_ctx, &properties->lpProps[jj], &row->lpProps[ii]);
+				}
+			}
+
+			if (!cb (conn, mem_ctx, properties, cb_user_data, cancellable, perror)) {
+				ms = MAPI_E_CALL_FAILED;
+				make_mapi_error (perror, "callback", ms);
+				talloc_free (properties);
+				break;
+			}
+
+			talloc_free (properties);
+		}
+
+		if (replace_hash)
+			g_hash_table_destroy (replace_hash);
+	} else if (ms == MAPI_E_SUCCESS) {
+		if (flaglist && flaglist->aulPropTag[0] == MAPI_AMBIGUOUS) {
+			ms = MAPI_E_AMBIGUOUS_RECIP;
+			g_set_error (perror, E_MAPI_ERROR, ms, _("User name '%s' is ambiguous"), to_resolve);
+		} else {
+			ms = MAPI_E_NOT_FOUND;
+			g_set_error (perror, E_MAPI_ERROR, ms, _("User name '%s' not found"), to_resolve);
+		}
+	}
+
+ cleanup:
+	g_free (named_ids_list);
+	talloc_free (mem_ctx);
+
+	UNLOCK ();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
 static gint
 emit_server_notification_signal (uint16_t event_type, gpointer event_data, gpointer user_data)
 {
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 348c0a3..dfd3d00 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -158,7 +158,7 @@ typedef gboolean (*WriteObjectCB)		(EMapiConnection *conn,
 						 gpointer user_data,
 						 GCancellable *cancellable,
 						 GError **perror);
-typedef gboolean (*GetFolderPropertiesCB)	(EMapiConnection *conn,
+typedef gboolean (*GetPropertiesCB)		(EMapiConnection *conn,
 						 TALLOC_CTX *mem_ctx,
 						 /* const */ struct mapi_SPropValue_array *properties,
 						 gpointer user_data,
@@ -196,6 +196,20 @@ gboolean		e_mapi_connection_reconnect		(EMapiConnection *conn,
 gboolean		e_mapi_connection_close			(EMapiConnection *conn);
 gboolean		e_mapi_connection_connected		(EMapiConnection *conn);
 
+gboolean		e_mapi_connection_test_foreign_folder	(EMapiConnection *conn,
+								 const gchar *username,
+								 const gchar *folder_name,
+								 mapi_id_t *fid, /* out */
+								 GCancellable *cancellable,
+								 GError **perror);
+
+gboolean		e_mapi_connection_peek_store		(EMapiConnection *conn,
+								 gboolean public_store,
+								 const gchar *foreign_username,
+								 mapi_object_t **obj_store, /* out */
+								 GCancellable *cancellable,
+								 GError **perror);
+
 gboolean		e_mapi_connection_open_default_folder	(EMapiConnection *conn,
 								 uint32_t olFolderIdentifier,
 								 mapi_object_t *obj_folder, /* out */
@@ -214,6 +228,13 @@ gboolean		e_mapi_connection_open_public_folder	(EMapiConnection *conn,
 								 GCancellable *cancellable,
 								 GError **perror);
 
+gboolean		e_mapi_connection_open_foreign_folder	(EMapiConnection *conn,
+								 const gchar *username,
+								 mapi_id_t fid,
+								 mapi_object_t *obj_folder, /* out */
+								 GCancellable *cancellable,
+								 GError **perror);
+
 gboolean		e_mapi_connection_close_folder		(EMapiConnection *conn,
 								 mapi_object_t *obj_folder,
 								 GCancellable *cancellable,
@@ -223,7 +244,7 @@ gboolean		e_mapi_connection_get_folder_properties	(EMapiConnection *conn,
 								 mapi_object_t *obj_folder,
 								 BuildReadPropsCB brp_cb,
 								 gpointer brp_cb_user_data,
-								 GetFolderPropertiesCB cb,
+								 GetPropertiesCB cb,
 								 gpointer cb_user_data,
 								 GCancellable *cancellable,
 								 GError **perror);
@@ -306,25 +327,26 @@ gboolean		e_mapi_connection_transfer_gal_object	(EMapiConnection *conn,
 								 GError **perror);
 
 gboolean		e_mapi_connection_get_public_folder	(EMapiConnection *conn,
-								 mapi_object_t *obj_object,
+								 mapi_object_t *obj_folder, /* out */
 								 GCancellable *cancellable,
 								 GError **perror);
 
-mapi_id_t		e_mapi_connection_create_folder		(EMapiConnection *conn,
-								 uint32_t olFolder,
-								 mapi_id_t pfid,
-								 guint32 fid_options,
+gboolean		e_mapi_connection_create_folder		(EMapiConnection *conn,
+								 mapi_object_t *obj_parent_folder, /* in */
 								 const gchar *name,
+								 const gchar *new_folder_type, /* usually IPF_NOTE and similar */
+								 mapi_id_t *new_fid, /* out */
 								 GCancellable *cancellable,
 								 GError **perror);
+
 gboolean		e_mapi_connection_remove_folder		(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 guint32 fid_options,
+								 mapi_object_t *obj_store, /* in, store, to which folder belongs */
+								 mapi_id_t fid_to_remove,
 								 GCancellable *cancellable,
 								 GError **perror);
+
 gboolean		e_mapi_connection_empty_folder		(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 guint32 fid_options,
+								 mapi_object_t *obj_folder,
 								 GCancellable *cancellable,
 								 GError **perror);
 gboolean		e_mapi_connection_rename_folder		(EMapiConnection *conn,
@@ -348,33 +370,20 @@ mapi_id_t		e_mapi_connection_get_default_folder_id	(EMapiConnection *conn,
 								 GError **perror);
 
 gboolean		e_mapi_connection_set_flags		(EMapiConnection *conn,
-								 uint32_t olFolder,
-								 mapi_id_t fid,
-								 guint32 fid_options,
+								 mapi_object_t *obj_folder,
 								 GSList *mid_list,
 								 uint32_t flag,
 								 GCancellable *cancellable,
 								 GError **perror);
 gboolean		e_mapi_connection_remove_items		(EMapiConnection *conn,
-								 uint32_t olFolder,
-								 mapi_id_t fid,
-								 guint32 fid_options,
+								 mapi_object_t *obj_folder,
 								 const GSList *mids, /* data is (mapi_id_t *) */
 								 GCancellable *cancellable,
 								 GError **perror);
-gboolean		e_mapi_connection_copy_items		(EMapiConnection *conn,
-								 mapi_id_t src_fid,
-								 guint32 src_fid_options,
-								 mapi_id_t dest_fid,
-								 guint32 dest_fid_options,
-								 GSList *mids,
-								 GCancellable *cancellable,
-								 GError **perror);
-gboolean		e_mapi_connection_move_items		(EMapiConnection *conn,
-								 mapi_id_t src_fid,
-								 guint32 src_fid_options,
-								 mapi_id_t dest_fid,
-								 guint32 dest_fid_options,
+gboolean		e_mapi_connection_copymove_items	(EMapiConnection *conn,
+								 mapi_object_t *src_obj_folder,
+								 mapi_object_t *des_obj_folder,
+								 gboolean do_copy,
 								 GSList *mids,
 								 GCancellable *cancellable,
 								 GError **perror);
@@ -414,6 +423,15 @@ gchar *			e_mapi_connection_ex_to_smtp		(EMapiConnection *conn,
 								 GCancellable *cancellable,
 								 GError **perror);
 
+gboolean		e_mapi_connection_resolve_username	(EMapiConnection *conn,
+								 const gchar *to_resolve,
+								 BuildReadPropsCB brp_cb,
+								 gpointer brp_cb_user_data,
+								 GetPropertiesCB cb,
+								 gpointer cb_user_data,
+								 GCancellable *cancellable,
+								 GError **perror);
+
 /* Push notifications APIs */
 
 gboolean		e_mapi_connection_enable_notifications	(EMapiConnection *conn,
diff --git a/src/libexchangemapi/e-mapi-folder.c b/src/libexchangemapi/e-mapi-folder.c
index 369db67..d99e3dd 100644
--- a/src/libexchangemapi/e-mapi-folder.c
+++ b/src/libexchangemapi/e-mapi-folder.c
@@ -25,44 +25,75 @@
 #include <config.h>
 #endif
 
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-group.h>
+#include <libedataserver/e-source-list.h>
+
 #include "e-mapi-connection.h"
 #include "e-mapi-folder.h"
 
 #define d(x)
 
-static EMapiFolderType
-container_class_to_type (const gchar *type)
+static struct _folder_type_map {
+	const gchar *container_class;
+	EMapiFolderType folder_type;
+} folder_type_map[] = {
+	{ IPF_APPOINTMENT,	E_MAPI_FOLDER_TYPE_APPOINTMENT },
+	{ IPF_CONTACT,		E_MAPI_FOLDER_TYPE_CONTACT },
+	{ IPF_STICKYNOTE,	E_MAPI_FOLDER_TYPE_MEMO },
+	{ IPF_TASK,		E_MAPI_FOLDER_TYPE_TASK },
+	{ IPF_NOTE,		E_MAPI_FOLDER_TYPE_MAIL },
+	{ "IPF.Note.HomePage",	E_MAPI_FOLDER_TYPE_NOTE_HOMEPAGE },
+	{ IPF_JOURNAL,		E_MAPI_FOLDER_TYPE_JOURNAL}
+};
+
+EMapiFolderType
+e_mapi_folder_type_from_string (const gchar *container_class)
+{
+	gint ii;
+
+	if (!container_class)
+		return E_MAPI_FOLDER_TYPE_UNKNOWN;
+
+	for (ii = 0; ii < G_N_ELEMENTS (folder_type_map); ii++) {
+		if (g_str_equal (folder_type_map[ii].container_class, container_class))
+			return folder_type_map[ii].folder_type;
+	}
+
+	return E_MAPI_FOLDER_TYPE_UNKNOWN;
+}
+
+const gchar *
+e_mapi_folder_type_to_string (EMapiFolderType folder_type)
 {
-	EMapiFolderType folder_type = MAPI_FOLDER_TYPE_UNKNOWN;;
+	gint ii;
 
-	if (!strcmp (type, IPF_APPOINTMENT))
-		folder_type = MAPI_FOLDER_TYPE_APPOINTMENT;
-	else if (!strcmp (type, IPF_CONTACT))
-		folder_type = MAPI_FOLDER_TYPE_CONTACT;
-	else if (!strcmp (type, IPF_STICKYNOTE))
-		folder_type = MAPI_FOLDER_TYPE_MEMO;
-	else if (!strcmp (type, IPF_TASK))
-		folder_type = MAPI_FOLDER_TYPE_TASK;
-	else if (!strcmp (type, IPF_NOTE))
-		folder_type = MAPI_FOLDER_TYPE_MAIL;
-	/* Fixme : no definition for this is available in mapidef.h */
-	else if (!strcmp (type, "IPF.Note.HomePage"))
-		folder_type = MAPI_FOLDER_TYPE_NOTE_HOMEPAGE;
-	else if (!strcmp (type, IPF_JOURNAL))
-		folder_type = MAPI_FOLDER_TYPE_JOURNAL;
+	for (ii = 0; ii < G_N_ELEMENTS (folder_type_map); ii++) {
+		if (folder_type_map[ii].folder_type == folder_type)
+			return folder_type_map[ii].container_class;
+	}
 
-	return folder_type;
+	return NULL;
 }
 
 EMapiFolder *
-e_mapi_folder_new (const gchar *folder_name, const gchar *container_class, EMapiFolderCategory category, mapi_id_t folder_id, mapi_id_t parent_folder_id, uint32_t child_count, uint32_t unread_count, uint32_t total)
+e_mapi_folder_new (const gchar *folder_name,
+		   const gchar *container_class,
+		   EMapiFolderCategory category,
+		   mapi_id_t folder_id,
+		   mapi_id_t parent_folder_id,
+		   uint32_t child_count,
+		   uint32_t unread_count,
+		   uint32_t total)
 {
 	EMapiFolder *folder;
 
 	folder = g_new0 (EMapiFolder, 1);
 	folder->is_default = FALSE;
 	folder->folder_name = g_strdup (folder_name);
-	folder->container_class = container_class_to_type (container_class);
+	folder->container_class = e_mapi_folder_type_from_string (container_class);
 	folder->folder_id = folder_id;
 	folder->parent_folder_id = parent_folder_id;
 	folder->child_count = child_count;
@@ -105,12 +136,6 @@ e_mapi_folder_free (EMapiFolder *folder)
 	}
 }
 
-EMapiFolderType
-e_mapi_container_class (gchar *type)
-{
-	return container_class_to_type (type);
-}
-
 const gchar *
 e_mapi_folder_get_name (EMapiFolder *folder)
 {
@@ -172,3 +197,256 @@ e_mapi_folder_free_list (GSList *folder_list)
 	g_slist_foreach (folder_list, (GFunc) e_mapi_folder_free, NULL);
 	g_slist_free (folder_list);
 }
+
+gchar *
+e_mapi_folder_pick_color_spec (gint move_by,
+			       gboolean around_middle)
+{
+	static gint color_mover = 0;
+	static gint color_indexer = -1;
+	const guint32 colors[] = {
+		0x1464ae, /* dark blue */
+		0x14ae64, /* dark green */
+		0xae1464, /* dark red */
+		0
+	};
+	guint32 color;
+
+	if (move_by <= 0)
+		move_by = 1;
+
+	while (move_by > 0) {
+		move_by--;
+
+		color_indexer++;
+		if (colors[color_indexer] == 0) {
+			color_mover += 1;
+			color_indexer = 0;
+		}
+	}
+
+	color = colors[color_indexer];
+	color = (color & ~(0xFF << (color_indexer * 8))) |
+		(((((color >> (color_indexer * 8)) & 0xFF) + (0x33 * color_mover)) % 0xFF) << (color_indexer * 8));
+
+	if (around_middle) {
+		gint rr, gg, bb, diff;
+
+		rr = (0xFF0000 & color) >> 16;
+		gg = (0x00FF00 & color) >>  8;
+		bb = (0x0000FF & color);
+
+		diff = 0x80 - rr;
+		if (diff < 0x80 - gg)
+			diff = 0x80 - gg;
+		if (diff < 0x80 - bb)
+			diff = 0x80 - bb;
+
+		rr = rr + diff < 0 ? 0 : rr + diff > 0xCC ? 0xCC : rr + diff;
+		gg = gg + diff < 0 ? 0 : gg + diff > 0xCC ? 0xCC : gg + diff;
+		bb = bb + diff < 0 ? 0 : bb + diff > 0xCC ? 0xCC : bb + diff;
+
+		color = (rr << 16) + (gg << 8) + bb;
+	}
+
+	return g_strdup_printf ("#%06x", color);
+}
+
+#define MAPI_URI_PREFIX   "mapi://" 
+
+gboolean
+e_mapi_folder_add_as_esource (EMapiFolderType folder_type,
+			      const gchar *login_profile,
+			      const gchar *login_domain,
+			      const gchar *login_realm,
+			      const gchar *login_host,
+			      const gchar *login_user,
+			      gboolean login_kerberos,
+			      gboolean offline_sync,
+			      EMapiFolderCategory folder_category,
+			      const gchar *foreign_username, /* NULL for public folder */
+			      const gchar *folder_name,
+			      const gchar *fid,
+			      GError **perror)
+{
+	ESourceList *source_list = NULL;
+	ESourceGroup *group = NULL;
+	const gchar *conf_key = NULL;
+	GConfClient* client;
+	GSList *sources;
+	ESource *source = NULL;
+	gchar *relative_uri = NULL;
+	gchar *base_uri = NULL;
+
+	g_return_val_if_fail (login_profile != NULL, FALSE);
+	g_return_val_if_fail (login_host != NULL, FALSE);
+	g_return_val_if_fail (login_user != NULL, FALSE);
+	g_return_val_if_fail (folder_name != NULL, FALSE);
+	g_return_val_if_fail (fid != NULL, FALSE);
+	g_return_val_if_fail (folder_category == E_MAPI_FOLDER_CATEGORY_PUBLIC || folder_category == E_MAPI_FOLDER_CATEGORY_FOREIGN, FALSE);
+	if (folder_category == E_MAPI_FOLDER_CATEGORY_FOREIGN)
+		g_return_val_if_fail (foreign_username != NULL, FALSE);
+
+	if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT)
+		conf_key = CALENDAR_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_TASK)
+		conf_key = TASK_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO)
+		conf_key = JOURNAL_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_JOURNAL)
+		conf_key = JOURNAL_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_CONTACT)
+		conf_key = ADDRESSBOOK_SOURCES;
+	else {
+		g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER, _("Cannot add folder, unsupported folder type")));
+		return FALSE;
+	}
+
+	client = gconf_client_get_default ();
+	source_list = e_source_list_new_for_gconf (client, conf_key);
+	base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, login_user, login_host);
+	group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
+	if (!group) {
+		g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER, _("Cannot add folder, group of sources not found")));
+		g_object_unref (source_list);
+		g_object_unref (client);
+		g_free (base_uri);
+
+		return FALSE;
+	}
+
+	sources = e_source_group_peek_sources (group);
+	for (; sources != NULL; sources = g_slist_next (sources)) {
+		ESource *source = E_SOURCE (sources->data);
+		gchar *folder_id = e_source_get_duped_property (source, "folder-id");
+		if (folder_id) {
+			if (g_str_equal (fid, folder_id)) {
+				g_object_unref (source_list);
+				g_object_unref (client);
+				g_free (folder_id);
+				g_free (base_uri);
+				
+				g_propagate_error (perror,
+					g_error_new (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+						_("Cannot add folder, folder already exists as '%s'"), e_source_peek_name (source)));
+				return FALSE;
+			}
+
+			g_free (folder_id);
+		}
+	}
+
+	relative_uri = g_strconcat (";", fid, NULL);
+	source = e_source_new (folder_name, relative_uri);
+	e_source_set_property (source, "username", login_user);
+	e_source_set_property (source, "host", login_host);
+	e_source_set_property (source, "profile", login_profile);
+	e_source_set_property (source, "domain", login_domain);
+	e_source_set_property (source, "realm", login_realm);
+	e_source_set_property (source, "folder-id", fid);
+	e_source_set_property (source, "offline_sync", offline_sync ? "1" : "0");
+	e_source_set_property (source, "delete", "yes");
+	if (folder_category == E_MAPI_FOLDER_CATEGORY_PUBLIC)
+		e_source_set_property (source, "public", "yes");
+	else
+		e_source_set_property (source, "foreign-username", foreign_username);
+	if (login_kerberos) {
+		e_source_set_property (source, "kerberos", "required");
+	} else {
+		e_source_set_property (source, "auth", "1");
+		e_source_set_property (source, "auth-type", "plain/password");
+	}
+
+	/* set also color for calendar-like sources */
+	if (folder_type != E_MAPI_FOLDER_TYPE_CONTACT) {
+		GSList *sources = e_source_group_peek_sources (group);
+		gchar *color_str;
+
+		color_str = e_mapi_folder_pick_color_spec (1 + g_slist_length (sources), folder_type != E_MAPI_FOLDER_TYPE_APPOINTMENT);
+		e_source_set_color_spec (source, color_str);
+		g_free (color_str);
+	}
+
+	e_source_group_add_source (group, source, -1);
+
+	g_object_unref (source);
+	g_object_unref (client);
+	g_free (relative_uri);
+	g_free (base_uri);
+
+	if (!e_source_list_sync (source_list, perror)) {
+		g_object_unref (source_list);
+		return FALSE;
+	}
+
+	g_object_unref (source_list);
+	return TRUE;
+}
+
+gboolean
+e_mapi_folder_remove_as_esource (EMapiFolderType folder_type,
+				 const gchar *login_host,
+				 const gchar *login_user,
+				 const gchar *fid,
+				 GError **perror)
+{
+	ESourceList *source_list = NULL;
+	ESourceGroup *group = NULL;
+	const gchar *conf_key = NULL;
+	GConfClient* client;
+	GSList *sources = NULL;
+	gchar *base_uri = NULL;
+
+	g_return_val_if_fail (login_host != NULL, FALSE);
+	g_return_val_if_fail (login_user != NULL, FALSE);
+	g_return_val_if_fail (fid != NULL, FALSE);
+
+	if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT)
+		conf_key = CALENDAR_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_TASK)
+		conf_key = TASK_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO)
+		conf_key = JOURNAL_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_JOURNAL)
+		conf_key = JOURNAL_SOURCES;
+	else if (folder_type == E_MAPI_FOLDER_TYPE_CONTACT)
+		conf_key = ADDRESSBOOK_SOURCES;
+	else {
+		g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER, _("Cannot remove folder, unsupported folder type")));
+		return FALSE;
+	}
+
+	client = gconf_client_get_default ();
+	source_list = e_source_list_new_for_gconf (client, conf_key);
+	base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, login_user, login_host);
+	group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
+	if (!group) {
+		g_free (base_uri);
+		g_object_unref (source_list);
+		g_object_unref (client);
+
+		return TRUE;
+	}
+
+	sources = e_source_group_peek_sources (group);
+	for (; sources != NULL; sources = g_slist_next (sources)) {
+		ESource *source = E_SOURCE (sources->data);
+		gchar *folder_id = e_source_get_duped_property (source, "folder-id");
+		if (folder_id) {
+			if (g_str_equal (fid, folder_id)) {
+				g_free (folder_id);
+
+				e_source_group_remove_source (group, source);
+				break;
+			}
+
+			g_free (folder_id);
+		}
+	}
+
+	g_free (base_uri);
+	g_object_unref (source_list);
+	g_object_unref (client);
+
+	return TRUE;
+}
diff --git a/src/libexchangemapi/e-mapi-folder.h b/src/libexchangemapi/e-mapi-folder.h
index a0fa528..3212fb6 100644
--- a/src/libexchangemapi/e-mapi-folder.h
+++ b/src/libexchangemapi/e-mapi-folder.h
@@ -28,21 +28,30 @@
 
 #include <libmapi/libmapi.h>
 
+#define CALENDAR_SOURCES	"/apps/evolution/calendar/sources"
+#define TASK_SOURCES		"/apps/evolution/tasks/sources"
+#define JOURNAL_SOURCES		"/apps/evolution/memos/sources"
+#define SELECTED_CALENDARS	"/apps/evolution/calendar/display/selected_calendars"
+#define SELECTED_TASKS		"/apps/evolution/calendar/tasks/selected_tasks"
+#define SELECTED_JOURNALS	"/apps/evolution/calendar/memos/selected_memos"
+#define ADDRESSBOOK_SOURCES     "/apps/evolution/addressbook/sources"
+
 typedef enum  {
-	MAPI_FOLDER_TYPE_MAIL=1,
-	MAPI_FOLDER_TYPE_APPOINTMENT,
-	MAPI_FOLDER_TYPE_CONTACT,
-	MAPI_FOLDER_TYPE_MEMO,
-	MAPI_FOLDER_TYPE_JOURNAL,
-	MAPI_FOLDER_TYPE_TASK,
-	MAPI_FOLDER_TYPE_NOTE_HOMEPAGE,
-	MAPI_FOLDER_TYPE_UNKNOWN
+	E_MAPI_FOLDER_TYPE_UNKNOWN = 0,
+	E_MAPI_FOLDER_TYPE_MAIL,
+	E_MAPI_FOLDER_TYPE_APPOINTMENT,
+	E_MAPI_FOLDER_TYPE_CONTACT,
+	E_MAPI_FOLDER_TYPE_MEMO,
+	E_MAPI_FOLDER_TYPE_JOURNAL,
+	E_MAPI_FOLDER_TYPE_TASK,
+	E_MAPI_FOLDER_TYPE_NOTE_HOMEPAGE
 } EMapiFolderType;
 
 typedef enum {
-	MAPI_PERSONAL_FOLDER,
-	MAPI_FAVOURITE_FOLDER,
-	MAPI_FOREIGN_FOLDER
+	E_MAPI_FOLDER_CATEGORY_UNKNOWN = 0,
+	E_MAPI_FOLDER_CATEGORY_PERSONAL,
+	E_MAPI_FOLDER_CATEGORY_PUBLIC,
+	E_MAPI_FOLDER_CATEGORY_FOREIGN
 } EMapiFolderCategory;
 
 typedef struct _EMapiFolder {
@@ -72,6 +81,9 @@ typedef struct _EMapiFolder {
 	gpointer reserved3;
 } EMapiFolder;
 
+EMapiFolderType		e_mapi_folder_type_from_string	(const gchar *container_class);
+const gchar *		e_mapi_folder_type_to_string	(EMapiFolderType folder_type);
+
 EMapiFolder *		e_mapi_folder_new		(const gchar *folder_name,
 							 const gchar *container_class,
 							 EMapiFolderCategory catgory,
@@ -82,7 +94,6 @@ EMapiFolder *		e_mapi_folder_new		(const gchar *folder_name,
 							 uint32_t total);
 EMapiFolder *		e_mapi_folder_copy		(EMapiFolder *src);
 void			e_mapi_folder_free		(EMapiFolder *folder);
-EMapiFolderType		e_mapi_container_class		(gchar *type);
 
 const gchar *		e_mapi_folder_get_name		(EMapiFolder *folder);
 mapi_id_t		e_mapi_folder_get_fid		(EMapiFolder *folder);
@@ -95,4 +106,26 @@ gboolean		e_mapi_folder_is_root		(EMapiFolder *folder);
 GSList *		e_mapi_folder_copy_list		(GSList *folder_list);
 void			e_mapi_folder_free_list		(GSList *folder_list);
 
+gchar *			e_mapi_folder_pick_color_spec	(gint move_by,
+							 gboolean around_middle);
+
+gboolean		e_mapi_folder_add_as_esource	(EMapiFolderType folder_type,
+							 const gchar *login_profile,
+							 const gchar *login_domain,
+							 const gchar *login_realm,
+							 const gchar *login_host,
+							 const gchar *login_user,
+							 gboolean login_kerberos,
+							 gboolean offline_sync,
+							 EMapiFolderCategory folder_category,
+							 const gchar *foreign_username, /* NULL for public folder */
+							 const gchar *folder_name,
+							 const gchar *fid,
+							 GError **perror);
+
+gboolean		e_mapi_folder_remove_as_esource	(EMapiFolderType folder_type,
+							 const gchar *login_host,
+							 const gchar *login_user,
+							 const gchar *fid,
+							 GError **perror);
 #endif



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