[evolution-mapi] Drop unused code and parameters



commit 6702fb2b57f2b193f9634a57c42c4de0239bc63a
Author: Milan Crha <mcrha redhat com>
Date:   Wed Dec 14 10:10:35 2011 +0100

    Drop unused code and parameters

 src/addressbook/e-book-backend-mapi-contacts.c |   12 +-
 src/calendar/e-cal-backend-mapi.c              |   22 +-
 src/camel/camel-mapi-folder.c                  |    1 -
 src/libexchangemapi/e-mapi-cal-utils.c         | 1764 +------
 src/libexchangemapi/e-mapi-cal-utils.h         |   55 +-
 src/libexchangemapi/e-mapi-connection.c        | 6999 +++++++++---------------
 src/libexchangemapi/e-mapi-connection.h        |  154 +-
 src/libexchangemapi/e-mapi-fast-transfer.c     |  146 -
 src/libexchangemapi/e-mapi-mail-utils.c        | 3453 ++++---------
 src/libexchangemapi/e-mapi-mail-utils.h        |   80 -
 src/libexchangemapi/e-mapi-utils.c             |  207 -
 src/libexchangemapi/e-mapi-utils.h             |   14 -
 12 files changed, 3655 insertions(+), 9252 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index a757a32..5ecb253 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -58,7 +58,6 @@ struct _EBookBackendMAPIContactsPrivate
 
 static gboolean
 build_restriction_from_sexp_query (EMapiConnection *conn,
-				   mapi_id_t fid,
 				   TALLOC_CTX *mem_ctx,
 				   struct mapi_SRestriction **restrictions,
 				   gpointer user_data,
@@ -431,7 +430,6 @@ transfer_contact_cb (EMapiConnection *conn,
 
 static gboolean
 gather_contact_mids_cb (EMapiConnection *conn,
-			mapi_id_t fid,
 			TALLOC_CTX *mem_ctx,
 			const ListObjectsData *object_data,
 			guint32 obj_index,
@@ -511,7 +509,6 @@ transfer_contacts_cb (EMapiConnection *conn,
 
 static gboolean
 gather_known_uids_cb (EMapiConnection *conn,
-		      mapi_id_t fid,
 		      TALLOC_CTX *mem_ctx,
 		      const ListObjectsData *object_data,
 		      guint32 obj_index,
@@ -832,17 +829,16 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
 
 	to_remove = NULL;
 	for (l = id_list; l; l = l->next) {
-		mapi_id_t mid;
 		const gchar *uid = l->data;
-		struct id_list *idl = g_new0 (struct id_list, 1);
+		mapi_id_t *pmid = g_new0 (mapi_id_t, 1);
 
-		if (e_mapi_util_mapi_id_from_string (uid, &mid)) {
-			idl->id = mid;
-			to_remove = g_slist_prepend (to_remove, idl);
+		if (e_mapi_util_mapi_id_from_string (uid, pmid)) {
+			to_remove = g_slist_prepend (to_remove, pmid);
 
 			*removed_ids = g_slist_prepend (*removed_ids, g_strdup (uid));
 		} else {
 			g_debug ("%s: Failed to decode MID from '%s'", G_STRFUNC, uid);
+			g_free (pmid);
 		}
 	}
 
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index 36ec3a3..b8356fa 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -512,7 +512,6 @@ struct ListCalendarObjectsData
 
 static gboolean
 list_calendar_objects_cb (EMapiConnection *conn,
-			  mapi_id_t fid,
 			  TALLOC_CTX *mem_ctx,
 			  const ListObjectsData *object_data,
 			  guint32 obj_index,
@@ -1349,7 +1348,6 @@ ecbm_capture_req_props (EMapiConnection *conn,
 
 static gboolean
 ecbm_list_for_one_mid_cb (EMapiConnection *conn,
-		          mapi_id_t fid,
 			  TALLOC_CTX *mem_ctx,
 			  const ListObjectsData *object_data,
 			  guint32 obj_index,
@@ -1370,7 +1368,6 @@ ecbm_list_for_one_mid_cb (EMapiConnection *conn,
 
 static gboolean
 ecbm_build_global_id_restriction (EMapiConnection *conn,
-				  mapi_id_t fid,
 				  TALLOC_CTX *mem_ctx,
 				  struct mapi_SRestriction **restrictions,
 				  gpointer user_data,
@@ -1382,21 +1379,16 @@ ecbm_build_global_id_restriction (EMapiConnection *conn,
 	struct SPropValue sprop;
 	struct mapi_SRestriction *restriction;
 	gchar *propval;
-	uint32_t proptag;
 
 	g_return_val_if_fail (restrictions != NULL, FALSE);
 	g_return_val_if_fail (comp != NULL, FALSE);
 
-	proptag = e_mapi_connection_resolve_named_prop (conn, fid, PidLidCleanGlobalObjectId, cancellable, perror);
-	if (proptag == MAPI_E_RESERVED)
-		proptag = PidLidCleanGlobalObjectId;
-
 	restriction = talloc_zero (mem_ctx, struct mapi_SRestriction);
 	g_return_val_if_fail (restriction != NULL, FALSE);
 
 	restriction->rt = RES_PROPERTY;
 	restriction->res.resProperty.relop = RELOP_EQ;
-	restriction->res.resProperty.ulPropTag = proptag;
+	restriction->res.resProperty.ulPropTag = PidLidGlobalObjectId;
 
 	propval = e_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-GLOBALID");
 	if (propval && *propval) {
@@ -1414,11 +1406,11 @@ ecbm_build_global_id_restriction (EMapiConnection *conn,
 		e_cal_component_get_dtstamp (comp, &ical_creation_time);
 
 		e_mapi_util_time_t_to_filetime (icaltime_as_timet (ical_creation_time), &creation_time);
-		e_mapi_cal_util_generate_globalobjectid (TRUE, uid, NULL, ical_creation_time.year ? &creation_time : NULL, &sb);
+		e_mapi_cal_util_generate_globalobjectid (FALSE, uid, NULL, ical_creation_time.year ? &creation_time : NULL, &sb);
 	}
 	g_free (propval);
 
-	set_SPropValue_proptag (&sprop, proptag, &sb);
+	set_SPropValue_proptag (&sprop, PidLidGlobalObjectId, &sb);
 	cast_mapi_SPropValue (mem_ctx, &(restriction->res.resProperty.lpProp), &sprop);
 
 	*restrictions = restriction;
@@ -1874,9 +1866,9 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
 
 		/*if (e_cal_component_has_attendees (E_CAL_COMPONENT (comp_list->data))) {
 		} else {*/
-			struct id_list *data = g_new (struct id_list, 1);
-			data->id = mid;
-			list = g_slist_prepend (list, (gpointer) data);
+			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)) {
@@ -1898,7 +1890,7 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
 		} else
 			mapi_error_to_edc_error (&err, ri_error, OtherError, "Cannot remove items from a server");
 
-		g_slist_free (list);
+		g_slist_free_full (list, g_free);
 		g_slist_free (comp_list);
 	}
 	g_free (calobj);
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 003367a..31dccf4 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -240,7 +240,6 @@ struct GatherChangedObjectsData
 
 static gboolean
 gather_changed_objects_to_slist (EMapiConnection *conn,
-				 mapi_id_t fid,
 				 TALLOC_CTX *mem_ctx,
 				 const ListObjectsData *object_data,
 				 guint32 obj_index,
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index ddaba75..690ea2c 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -45,9 +45,9 @@
 
 #define d(x) 
 
-static gboolean appt_build_name_id (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, GCancellable *cancellable, GError **perror);
-static gboolean task_build_name_id (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, GCancellable *cancellable, GError **perror);
-static gboolean note_build_name_id (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, GCancellable *cancellable, GError **perror);
+#define DEFAULT_APPT_REMINDER_MINS 15
+#define DEFAULT_TASK_REMINDER_MINS 1080
+
 
 static icalparameter_role
 get_role_from_type (OlMailRecipientType type)
@@ -151,1893 +151,190 @@ get_prop_from_taskstatus (icalproperty_status status)
 static icalproperty_class
 get_class_from_prop (uint32_t prop)
 {
-	/* FIXME: is this mapping correct ? */
-	switch (prop) {
-		case olPersonal		:
-		case olPrivate		: return ICAL_CLASS_PRIVATE;
-		case olConfidential	: return ICAL_CLASS_CONFIDENTIAL;
-		case olNormal		:
-		default			: return ICAL_CLASS_PUBLIC;
-	}
-}
-
-static uint32_t
-get_prop_from_class (icalproperty_class class)
-{
-	/* FIXME: is this mapping correct ? */
-	switch (class) {
-		case ICAL_CLASS_PRIVATE		: return olPrivate;
-		case ICAL_CLASS_CONFIDENTIAL	: return olConfidential;
-		default				: return olNormal;
-	}
-}
-
-static gint
-get_priority_from_prop (uint32_t prop)
-{
-	switch (prop) {
-		case PRIORITY_LOW	: return 7;
-		case PRIORITY_HIGH	: return 1;
-		case PRIORITY_NORMAL	:
-		default			: return 5;
-	}
-}
-
-static uint32_t
-get_prio_prop_from_priority (gint priority)
-{
-	if (priority > 0 && priority <= 4)
-		return PRIORITY_HIGH;
-	else if (priority > 5 && priority <= 9)
-		return PRIORITY_LOW;
-	else
-		return PRIORITY_NORMAL;
-}
-
-static uint32_t
-get_imp_prop_from_priority (gint priority)
-{
-	if (priority > 0 && priority <= 4)
-		return IMPORTANCE_HIGH;
-	else if (priority > 5 && priority <= 9)
-		return IMPORTANCE_LOW;
-	else
-		return IMPORTANCE_NORMAL;
-}
-
-void
-e_mapi_cal_util_fetch_attachments (ECalComponent *comp, GSList **attach_list, const gchar *local_store_uri)
-{
-	GSList *comp_attach_list = NULL, *new_attach_list = NULL;
-	GSList *l;
-	const gchar *uid;
-	gchar *safeuid;
-
-	e_cal_component_get_attachment_list (comp, &comp_attach_list);
-	e_cal_component_get_uid (comp, &uid);
-
-	safeuid = g_strdup (uid);
-	e_filename_make_safe (safeuid);
-	g_return_if_fail (safeuid != NULL);
-
-	for (l = comp_attach_list; l; l = l->next) {
-		gchar *sfname_uri = (gchar *) l->data;
-		gchar *sfname = NULL, *filename = NULL;
-		GMappedFile *mapped_file;
-		GError *error = NULL;
-
-		sfname = g_filename_from_uri (sfname_uri, NULL, NULL);
-		mapped_file = g_mapped_file_new (sfname, FALSE, &error);
-		filename = g_path_get_basename (sfname);
-
-		if (mapped_file) {
-			ExchangeMAPIAttachment *attach_item;
-			ExchangeMAPIStream *stream;
-			guint8 *attach = (guint8 *) g_mapped_file_get_contents (mapped_file);
-			guint filelength = g_mapped_file_get_length (mapped_file);
-			const gchar *split_name;
-			uint32_t flag;
-
-			if (g_str_has_prefix (filename, safeuid)) {
-				split_name = (filename + strlen (safeuid) + strlen ("-"));
-			} else {
-				split_name = filename;
-			}
-
-			new_attach_list = g_slist_append (new_attach_list, g_strdup (sfname_uri));
-
-			attach_item = g_new0 (ExchangeMAPIAttachment, 1);
-
-			attach_item->cValues = 4;
-			attach_item->lpProps = g_new0 (struct SPropValue, attach_item->cValues + 1);
-
-			flag = ATTACH_BY_VALUE;
-			set_SPropValue_proptag(&(attach_item->lpProps[0]), PR_ATTACH_METHOD, (gconstpointer ) (&flag));
-
-			/* MSDN Documentation: When the supplied offset is -1 (0xFFFFFFFF), the
-			 * attachment is not rendered using the PR_RENDERING_POSITION property.
-			 * All values other than -1 indicate the position within PR_BODY at which
-			 * the attachment is to be rendered.
-			 */
-			flag = 0xFFFFFFFF;
-			set_SPropValue_proptag(&(attach_item->lpProps[1]), PR_RENDERING_POSITION, (gconstpointer ) (&flag));
-
-			set_SPropValue_proptag(&(attach_item->lpProps[2]), PR_ATTACH_FILENAME_UNICODE, (gconstpointer ) g_strdup(split_name));
-			set_SPropValue_proptag(&(attach_item->lpProps[3]), PR_ATTACH_LONG_FILENAME_UNICODE, (gconstpointer ) g_strdup(split_name));
-
-			stream = g_new0 (ExchangeMAPIStream, 1);
-			stream->proptag = PR_ATTACH_DATA_BIN;
-			stream->value = g_byte_array_sized_new (filelength);
-			stream->value = g_byte_array_append (stream->value, attach, filelength);
-			attach_item->streams = g_slist_append (attach_item->streams, stream);
-
-			*attach_list = g_slist_append (*attach_list, attach_item);
-
-#if GLIB_CHECK_VERSION(2,21,3)
-			g_mapped_file_unref (mapped_file);
-#else
-			g_mapped_file_free (mapped_file);
-#endif
-		} else if (error) {
-			e_mapi_debug_print ("Could not map %s: %s \n", sfname_uri, error->message);
-			g_error_free (error);
-		}
-
-		g_free (filename);
-	}
-
-	e_cal_component_set_attachment_list (comp, new_attach_list);
-
-	g_slist_foreach (new_attach_list, (GFunc) g_free, NULL);
-	g_slist_free (new_attach_list);
-	g_free (safeuid);
-}
-
-#define RECIP_SENDABLE  0x1
-#define RECIP_ORGANIZER 0x2
-
-void
-e_mapi_cal_util_fetch_organizer (ECalComponent *comp, GSList **recip_list)
-{
-	icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
-	icalproperty *org_prop = NULL;
-	const gchar *org = NULL;
-
-	org_prop = icalcomponent_get_first_property (icalcomp, ICAL_ORGANIZER_PROPERTY);
-	org = icalproperty_get_organizer (org_prop);
-	if (org && *org) {
-		ExchangeMAPIRecipient *recipient;
-		uint32_t val = 0;
-		const gchar *str = NULL;
-		icalparameter *param;
-
-		recipient = g_new0 (ExchangeMAPIRecipient, 1);
-
-		if (!g_ascii_strncasecmp (org, "mailto:";, 7))
-			recipient->email_id = (org) + 7;
-		else
-			recipient->email_id = (org);
-
-		/* Required properties - set them always */
-		recipient->in.req_cValues = 5;
-		recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
-
-		val = 0;
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
-
-		val = RECIP_SENDABLE | RECIP_ORGANIZER;
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_RECIPIENT_FLAGS, (gconstpointer )&val);
-
-		val = olResponseNone;
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[2]), PR_RECIPIENT_TRACKSTATUS, (gconstpointer )&val);
-
-		val = olTo;
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[3]), PR_RECIPIENT_TYPE, (gconstpointer ) &val);
-
-		param = icalproperty_get_first_parameter (org_prop, ICAL_CN_PARAMETER);
-		str = icalparameter_get_cn (param);
-		if (!(str && *str))
-			str = "";
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[4]), PR_RECIPIENT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
-		/* External recipient properties - set them only when the recipient is unresolved */
-		recipient->in.ext_cValues = 5;
-		recipient->in.ext_lpProps = g_new0 (struct SPropValue, recipient->in.ext_cValues + 1);
-
-		val = DT_MAILUSER;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[0]), PR_DISPLAY_TYPE, (gconstpointer )&val);
-		val = MAPI_MAILUSER;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[1]), PR_OBJECT_TYPE, (gconstpointer )&val);
-		str = "SMTP";
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[2]), PR_ADDRTYPE_UNICODE, (gconstpointer )(str));
-		str = recipient->email_id;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[3]), PR_SMTP_ADDRESS_UNICODE, (gconstpointer )(str));
-
-		param = icalproperty_get_first_parameter (org_prop, ICAL_CN_PARAMETER);
-		str = icalparameter_get_cn (param);
-		if (!(str && *str))
-			str = "";
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[4]), PR_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
-		*recip_list = g_slist_append (*recip_list, recipient);
-	}
-}
-
-void
-e_mapi_cal_util_fetch_recipients (ECalComponent *comp, GSList **recip_list)
-{
-	icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
-	icalproperty *org_prop = NULL, *att_prop = NULL;
-	const gchar *org = NULL;
-
-	org_prop = icalcomponent_get_first_property (icalcomp, ICAL_ORGANIZER_PROPERTY);
-	org = icalproperty_get_organizer (org_prop);
-	if (!org)
-		org = "";
-
-	att_prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
-	while (att_prop) {
-		ExchangeMAPIRecipient *recipient;
-		uint32_t val = 0;
-		const gchar *str = NULL;
-		icalparameter *param;
-
-		str = icalproperty_get_attendee (att_prop);
-		if (!str || g_ascii_strcasecmp (str, org) == 0) {
-			att_prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
-			continue;
-		}
-
-		recipient = g_new0 (ExchangeMAPIRecipient, 1);
-
-		if (!g_ascii_strncasecmp (str, "mailto:";, 7))
-			recipient->email_id = (str) + 7;
-		else
-			recipient->email_id = (str);
-
-		/* Required properties - set them always */
-		recipient->in.req_cValues = 5;
-		recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
-
-		val = 0;
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
-
-		val = RECIP_SENDABLE | (!g_ascii_strcasecmp(str, org) ? RECIP_ORGANIZER : 0);
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_RECIPIENT_FLAGS, (gconstpointer )&val);
-
-		param = icalproperty_get_first_parameter (att_prop, ICAL_PARTSTAT_PARAMETER);
-		val = get_trackstatus_from_partstat (icalparameter_get_partstat(param));
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[2]), PR_RECIPIENT_TRACKSTATUS, (gconstpointer )&val);
-
-		param = icalproperty_get_first_parameter (att_prop, ICAL_ROLE_PARAMETER);
-		val = get_type_from_role (icalparameter_get_role(param));
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[3]), PR_RECIPIENT_TYPE, (gconstpointer ) &val);
-
-		param = icalproperty_get_first_parameter (att_prop, ICAL_CN_PARAMETER);
-		str = icalparameter_get_cn (param);
-		str = (str) ? str : recipient->email_id;
-		set_SPropValue_proptag (&(recipient->in.req_lpProps[4]), PR_RECIPIENT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
-		/* External recipient properties - set them only when the recipient is unresolved */
-		recipient->in.ext_cValues = 7;
-		recipient->in.ext_lpProps = g_new0 (struct SPropValue, recipient->in.ext_cValues + 1);
-
-		val = DT_MAILUSER;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[0]), PR_DISPLAY_TYPE, (gconstpointer )&val);
-		val = MAPI_MAILUSER;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[1]), PR_OBJECT_TYPE, (gconstpointer )&val);
-		str = "SMTP";
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[2]), PR_ADDRTYPE_UNICODE, (gconstpointer )(str));
-		str = recipient->email_id;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[3]), PR_SMTP_ADDRESS_UNICODE, (gconstpointer )(str));
-
-		param = icalproperty_get_first_parameter (att_prop, ICAL_CN_PARAMETER);
-		str = icalparameter_get_cn (param);
-		str = (str) ? str : recipient->email_id;
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[4]), PR_GIVEN_NAME_UNICODE, (gconstpointer )(str));
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[5]), PR_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-		set_SPropValue_proptag (&(recipient->in.ext_lpProps[6]), PR_7BIT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-
-		*recip_list = g_slist_append (*recip_list, recipient);
-
-		att_prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
-	}
-}
-
-static void
-set_attachments_to_cal_component (ECalComponent *comp, GSList *attach_list, const gchar *local_store_uri)
-{
-	GSList *comp_attach_list = NULL, *l;
-	const gchar *uid;
-	gchar *safeuid;
-
-	g_return_if_fail (comp != NULL);
-
-	e_cal_component_get_uid (comp, &uid);
-
-	safeuid = g_strdup (uid);
-	e_filename_make_safe (safeuid);
-	g_return_if_fail (safeuid != NULL);
-
-	for (l = attach_list; l; l = l->next) {
-		ExchangeMAPIAttachment *attach_item = (ExchangeMAPIAttachment *) (l->data);
-		ExchangeMAPIStream *stream;
-		gchar *attach_file_url, *filename;
-		const gchar *str, *attach;
-		GError *error = NULL;
-		guint len;
-		gint fd = -1;
-
-		stream = e_mapi_util_find_stream (attach_item->streams, PR_ATTACH_DATA_BIN);
-		if (!stream)
-			continue;
-
-		attach = (const gchar *)stream->value->data;
-		len = stream->value->len;
-
-		str = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach_item->lpProps, PR_ATTACH_LONG_FILENAME_UNICODE);
-		if (!(str && *str))
-			str = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach_item->lpProps, PR_ATTACH_FILENAME_UNICODE);
-		filename = g_strconcat (local_store_uri, G_DIR_SEPARATOR_S, safeuid, "-", str, NULL);
-		attach_file_url = g_filename_to_uri (filename, NULL, &error);
-	
-		if (!attach_file_url) {
-			g_message ("Could not get attach_file_url %s \n", error->message);
-			g_clear_error (&error);
-			g_free (filename);
-			return;
-		}
-
-		fd = g_open (filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
-		if (fd == -1) {
-			/* skip gracefully */
-			e_mapi_debug_print ("Could not open %s for writing \n", filename);
-		} else if (len && write (fd, attach, len) == -1) {
-			/* skip gracefully */
-			e_mapi_debug_print ("Attachment write failed \n");
-		}
-		if (fd != -1) {
-			close (fd);
-			comp_attach_list = g_slist_append (comp_attach_list, g_strdup (attach_file_url));
-		}
-
-		g_free (filename);
-		g_free (attach_file_url);
-	}
-
-	e_cal_component_set_attachment_list (comp, comp_attach_list);
-	g_free (safeuid);
-}
-
-static void
-ical_attendees_from_props (icalcomponent *ical_comp, GSList *recipients, gboolean rsvp)
-{
-	GSList *l;
-	for (l=recipients; l; l=l->next) {
-		ExchangeMAPIRecipient *recip = (ExchangeMAPIRecipient *)(l->data);
-		icalproperty *prop = NULL;
-		icalparameter *param;
-		gchar *val;
-		const uint32_t *ui32;
-		const gchar *str;
-		const uint32_t *flags;
-
-		if (recip->email_id)
-			val = g_strdup_printf ("MAILTO:%s", recip->email_id);
-		else
-			continue;
-
-		flags = (const uint32_t *) get_SPropValue_SRow_data (&recip->out_SRow, PR_RECIPIENT_FLAGS);
-
-		if (flags && (*flags & RECIP_ORGANIZER)) {
-			prop = icalproperty_new_organizer (val);
-
-			/* CN */
-			str = recip->display_name;
-			if (!str || !*str)
-				str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
-			if (!str)
-				str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_DISPLAY_NAME_UNICODE);
-			if (str) {
-				param = icalparameter_new_cn (str);
-				icalproperty_add_parameter (prop, param);
-			}
-		} else {
-			prop = icalproperty_new_attendee (val);
-
-			/* CN */
-			str = recip->display_name;
-			if (!str || !*str)
-				str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
-			if (!str)
-				str = (const gchar *) e_mapi_util_find_row_propval (&recip->out_SRow, PR_DISPLAY_NAME_UNICODE);
-			if (str) {
-				param = icalparameter_new_cn (str);
-				icalproperty_add_parameter (prop, param);
-			}
-			/* RSVP */
-			param = icalparameter_new_rsvp (rsvp ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE);
-			icalproperty_add_parameter (prop, param);
-			/* PARTSTAT */
-			ui32 = (const uint32_t *) get_SPropValue_SRow_data (&recip->out_SRow, PR_RECIPIENT_TRACKSTATUS);
-			param = icalparameter_new_partstat (get_partstat_from_trackstatus (ui32 ? *ui32 : olResponseNone));
-			icalproperty_add_parameter (prop, param);
-			/* ROLE */
-			ui32 = (const uint32_t *) get_SPropValue_SRow_data (&recip->out_SRow, PR_RECIPIENT_TYPE);
-			param = icalparameter_new_role (get_role_from_type (ui32 ? *ui32 : olTo));
-			icalproperty_add_parameter (prop, param);
-
-			/* CALENDAR USER TYPE */
-			param = NULL;
-			if (ui32 && *ui32 == 0x03)
-				param = icalparameter_new_cutype (ICAL_CUTYPE_RESOURCE);
-			if (!param)
-				param = icalparameter_new_cutype (ICAL_CUTYPE_INDIVIDUAL);
-			icalproperty_add_parameter (prop, param);
-		}
-
-		if (prop)
-			icalcomponent_add_property (ical_comp, prop);
-
-		g_free (val);
-	}
-}
-
-static const uint8_t GID_START_SEQ[] = {
-	0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0xe0, 0x00,
-	0x74, 0xc5, 0xb7, 0x10, 0x1a, 0x82, 0xe0, 0x08
-};
-
-/* exception_replace_time is a value of PidLidExceptionReplaceTime; this is not used for 'clean' object ids.
-   creation_time is a value of PR_CREATION_TIME
-*/
-void
-e_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb)
-{
-	GByteArray *ba;
-	guint32 val32;
-	guchar *buf = NULL;
-	gsize len;
-	d(guint32 i);
-
-	ba = g_byte_array_new ();
-
-	ba = g_byte_array_append (ba, GID_START_SEQ, (sizeof (GID_START_SEQ) / sizeof (GID_START_SEQ[0])));
-
-	val32 = 0;
-	if (!is_clean && exception_replace_time) {
-		struct icaltimetype icaltm = icaltime_from_timet_with_zone (exception_replace_time->tv_sec, 0, icaltimezone_get_utc_timezone ());
-
-		val32 |= (icaltm.year & 0xFF00) << 16;
-		val32 |= (icaltm.year & 0xFF) << 16;
-		val32 |= (icaltm.month & 0xFF) << 8;
-		val32 |= (icaltm.day & 0xFF);
-	}
-
-	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-
-	/* creation time */
-	val32 = creation_time ? creation_time->dwLowDateTime : 0;
-	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-	val32 = creation_time ? creation_time->dwHighDateTime : 0;
-	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-
-	/* RESERVED - should be all 0's  */
-	val32 = 0;
-	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-	val32 = 0;
-	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-
-	/* We put Evolution's UID in base64 here */
-	buf = g_base64_decode (uid, &len);
-	if (len % 2 != 0)
-		--len;
-	val32 = len;
-
-	/* Size in bytes of the following data */
-	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
-	/* Data */
-	ba = g_byte_array_append (ba, (const guint8 *)buf, val32);
-	g_free (buf);
-
-	sb->lpb = ba->data;
-	sb->cb = ba->len;
-
-	d(g_message ("New GlobalObjectId.. Length: %d bytes.. Hex-data follows:", ba->len));
-	d(for (i = 0; i < ba->len; i++)
-		g_print("0x%02X ", ba->data[i]));
-
-	g_byte_array_free (ba, FALSE);
-}
-
-/* returns complete globalid as base64 encoded string */
-static gchar *
-globalid_to_string (const guint8 *lpb, guint32 cb)
-{
-	const guint8 *ptr;
-	guint32 i, j;
-
-	g_return_val_if_fail (lpb != NULL, NULL);
-
-	/* MSDN docs: the globalID must have an even number of bytes */
-	if ((cb) % 2 != 0)
-		return NULL;
-
-	ptr = lpb;
-
-	/* starting seq - len = 16 bytes */
-	for (i = 0, j = 0; i < cb && j < sizeof (GID_START_SEQ); i++, ptr++, j++) {
-		if (*ptr != GID_START_SEQ[j])
-			return NULL;
-	}
-
-	/* take complete global id */
-	return g_base64_encode (lpb, cb);
-}
-
-ECalComponent *
-e_mapi_cal_util_mapi_props_to_comp (EMapiConnection *conn, mapi_id_t fid, icalcomponent_kind kind, const gchar *mid, struct mapi_SPropValue_array *properties,
-					   GSList *streams, GSList *recipients, GSList *attachments,
-					   const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply, GSList **detached_components)
-{
-	ECalComponent *comp = NULL;
-	struct timeval t;
-	ExchangeMAPIStream *body_stream;
-	const gchar *subject = NULL, *body = NULL;
-	const struct StringArrayW_r *categories_array;
-	const uint32_t *ui32;
-	const bool *b;
-	icalcomponent *ical_comp;
-	icalproperty *prop = NULL;
-	icalparameter *param = NULL;
-	const icaltimezone *utc_zone;
-
-	switch (kind) {
-		case ICAL_VEVENT_COMPONENT:
-		case ICAL_VTODO_COMPONENT:
-		case ICAL_VJOURNAL_COMPONENT:
-			comp = e_cal_component_new ();
-			ical_comp = icalcomponent_new (kind);
-			e_cal_component_set_icalcomponent (comp, ical_comp);
-			icalcomponent_set_uid (ical_comp, mid);
-			e_cal_component_set_uid (comp, mid);
-			break;
-		default:
-			return NULL;
-	}
-
-	utc_zone = icaltimezone_get_utc_timezone ();
-
-	subject = (const gchar *)e_mapi_util_find_array_propval(properties, PR_SUBJECT_UNICODE);
-	if (!subject)
-		subject = (const gchar *)e_mapi_util_find_array_propval(properties, PR_NORMALIZED_SUBJECT_UNICODE);
-	if (!subject)
-		subject = (const gchar *)e_mapi_util_find_array_propval(properties, PR_CONVERSATION_TOPIC_UNICODE);
-	if (!subject)
-		subject = "";
-
-	body = (const gchar *)e_mapi_util_find_array_propval(properties, PR_BODY_UNICODE);
-	if (!body) {
-		body_stream = e_mapi_util_find_stream (streams, PR_HTML);
-		body = body_stream ? (const gchar *) body_stream->value->data : "";
-	}
-
-	/* set dtstamp - in UTC */
-	if (get_mapi_SPropValue_array_date_timeval (&t, properties, PR_CREATION_TIME) == MAPI_E_SUCCESS)
-		icalcomponent_set_dtstamp (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 0, utc_zone));
-
-	/* created - in UTC */
-	prop = icalproperty_new_created (icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ()));
-	icalcomponent_add_property (ical_comp, prop);
-
-	/* last modified - in UTC */
-	if (get_mapi_SPropValue_array_date_timeval (&t, properties, PR_LAST_MODIFICATION_TIME) == MAPI_E_SUCCESS) {
-		prop = icalproperty_new_lastmodified (icaltime_from_timet_with_zone (t.tv_sec, 0, utc_zone));
-		icalcomponent_add_property (ical_comp, prop);
-	}
-
-	icalcomponent_set_summary (ical_comp, subject);
-	icalcomponent_set_description (ical_comp, body);
-
-	categories_array = e_mapi_util_find_array_namedid (properties, conn, fid, PidNameKeywords);
-	if (categories_array) {
-		GSList *categories = NULL;
-		gint ii;
-
-		for (ii = 0; ii < categories_array->cValues; ii++) {
-			const gchar *category = categories_array->lppszW[ii];
-
-			if (!category || !*category)
-				continue;
-
-			categories = g_slist_append (categories, (gpointer) category);
-		}
-
-		e_cal_component_set_categories_list (comp, categories);
-
-		g_slist_free (categories);
-	}
-
-	if (icalcomponent_isa (ical_comp) == ICAL_VEVENT_COMPONENT) {
-		const gchar *location = NULL;
-		const gchar *dtstart_tz_location = NULL, *dtend_tz_location = NULL;
-		gboolean all_day;
-		ExchangeMAPIStream *stream;
-
-		/* GlobalObjectId */
-		stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidGlobalObjectId);
-		if (stream && stream->value) {
-			gchar *value = globalid_to_string (stream->value->data, stream->value->len);
-			prop = icalproperty_new_x (value);
-			icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-GLOBALID");
-			icalcomponent_add_property (ical_comp, prop);
-			if (value && *value) {
-				e_cal_component_set_uid (comp, value);
-
-				if (!g_str_equal (value, mid)) {
-					prop = icalproperty_new_x (mid);
-					icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-MID");
-					icalcomponent_add_property (ical_comp, prop);
-				}
-			}
-
-			g_free (value);
-		}
-
-		ui32 = find_mapi_SPropValue_data(properties, PR_OWNER_APPT_ID);
-		if (ui32) {
-			gchar *value = e_mapi_util_mapi_id_to_string ((mapi_id_t) (*ui32));
-
-			prop = icalproperty_new_x (value);
-			icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-OWNER-APPT-ID");
-			icalcomponent_add_property (ical_comp, prop);
-			g_free (value);
-		}
-
-		/* AppointmentSequence */
-		ui32 = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidAppointmentSequence);
-		if (ui32) {
-			gchar *value = g_strdup_printf ("%d", *ui32);
-			prop = icalproperty_new_x (value);
-			icalproperty_set_x_name (prop, "X-EVOLUTION-MAPI-APPTSEQ");
-			icalcomponent_add_property (ical_comp, prop);
-			g_free (value);
-		}
-
-		location = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidLocation);
-		if (location && *location)
-			icalcomponent_set_location (ical_comp, location);
-
-		b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidAppointmentSubType);;
-		all_day = b && *b;
-
-		stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidAppointmentTimeZoneDefinitionStartDisplay);
-		if (stream && stream->value) {
-			gchar *buf = e_mapi_cal_util_bin_to_mapi_tz (stream->value->data, stream->value->len);
-			dtstart_tz_location = e_mapi_cal_tz_util_get_ical_equivalent (buf);
-			g_free (buf);
-		}
-
-		if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidAppointmentStartWhole) == MAPI_E_SUCCESS) {
-			icaltimezone *zone = dtstart_tz_location ? icaltimezone_get_builtin_timezone (dtstart_tz_location) : (icaltimezone *)default_zone;
-			prop = icalproperty_new_dtstart (icaltime_from_timet_with_zone (t.tv_sec, all_day, zone));
-			if (!all_day && zone && icaltimezone_get_tzid (zone)) {
-				icalproperty_add_parameter (prop, icalparameter_new_tzid (icaltimezone_get_tzid (zone)));
-			}
-
-			icalcomponent_add_property (ical_comp, prop);
-		}
-
-		stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidAppointmentTimeZoneDefinitionEndDisplay);
-		if (stream && stream->value) {
-			gchar *buf = e_mapi_cal_util_bin_to_mapi_tz (stream->value->data, stream->value->len);
-			dtend_tz_location = e_mapi_cal_tz_util_get_ical_equivalent (buf);
-			g_free (buf);
-		}
-
-		if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidAppointmentEndWhole) == MAPI_E_SUCCESS) {
-			icaltimezone *zone;
-
-			if (!dtend_tz_location)
-				dtend_tz_location = dtstart_tz_location;
-
-			zone = dtend_tz_location ? icaltimezone_get_builtin_timezone (dtend_tz_location) : (icaltimezone *) default_zone;
-			prop = icalproperty_new_dtend (icaltime_from_timet_with_zone (t.tv_sec, all_day, zone));
-			if (!all_day && zone && icaltimezone_get_tzid (zone)) {
-				icalproperty_add_parameter (prop, icalparameter_new_tzid (icaltimezone_get_tzid (zone)));
-			}
-
-			icalcomponent_add_property (ical_comp, prop);
-		}
-
-		ui32 = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidBusyStatus);
-		if (ui32) {
-			prop = icalproperty_new_transp (get_transp_from_prop (*ui32));
-			icalcomponent_add_property (ical_comp, prop);
-		}
-
-		if (recipients) {
-			b = (const bool *)find_mapi_SPropValue_data(properties, PR_RESPONSE_REQUESTED);
-			ical_attendees_from_props (ical_comp, recipients, (b && *b));
-			if (is_reply) {
-				if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
-					gchar *val, *to_free = NULL;
-					const gchar *name = e_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_NAME_UNICODE);
-					const gchar *email_type = e_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE);
-					const gchar *email = e_mapi_util_find_array_propval (properties, PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE);
-
-					if (!name)
-						name = "";
-					if (!email_type)
-						email_type = "";
-					if (!email)
-						email = "";
-
-					if (g_str_equal (email_type, "EX")) {
-						to_free = e_mapi_connection_ex_to_smtp (conn, email, NULL, NULL, NULL);
-						email = to_free;
-					}
-
-					val = g_strdup_printf ("MAILTO:%s", email);
-					prop = icalproperty_new_organizer (val);
-					g_free (val);
-
-					/* CN */
-					param = icalparameter_new_cn (name);
-					icalproperty_add_parameter (prop, param);
-
-					icalcomponent_add_property (ical_comp, prop);
-
-					g_free (to_free);
-				}
-
-				if (icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY) == NULL) {
-					const uint32_t *ui32;
-					gchar *val, *to_free = NULL;
-					const gchar *name = e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_NAME_UNICODE);
-					const gchar *email_type = e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_ADDRTYPE_UNICODE);
-					const gchar *email = e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE);
-
-					if (!name)
-						name = "";
-					if (!email_type)
-						email_type = "";
-					if (!email)
-						email = "";
-
-					if (g_str_equal (email_type, "EX")) {
-						to_free = e_mapi_connection_ex_to_smtp (conn, email, NULL, NULL, NULL);
-						email = to_free;
-					}
-
-					val = g_strdup_printf ("MAILTO:%s", email);
-					prop = icalproperty_new_attendee (val);
-					g_free (val);
-
-					/* CN */
-					param = icalparameter_new_cn (name);
-					icalproperty_add_parameter (prop, param);
-
-					ui32 = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidResponseStatus);
-					param = icalparameter_new_partstat (get_partstat_from_trackstatus (ui32 ? *ui32 : olResponseNone));
-					icalproperty_add_parameter (prop, param);
-
-					icalcomponent_add_property (ical_comp, prop);
-
-					g_free (to_free);
-				}
-			} else if (icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY) == NULL) {
-				gchar *val, *sender_free = NULL, *sent_free = NULL;
-				const gchar *sender_email_type = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENDER_ADDRTYPE_UNICODE);
-				const gchar *sender_email = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENDER_EMAIL_ADDRESS_UNICODE);
-				const gchar *sent_name = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_NAME_UNICODE);
-				const gchar *sent_email_type = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_ADDRTYPE_UNICODE);
-				const gchar *sent_email = (const gchar *) e_mapi_util_find_array_propval (properties, PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE);
-
-				if (!g_utf8_collate (sender_email_type, "EX")) {
-					sender_free = e_mapi_connection_ex_to_smtp (conn, sender_email, NULL, NULL, NULL);
-					sender_email = sender_free;
-				}
-				if (!g_utf8_collate (sent_email_type, "EX")) {
-					sent_free = e_mapi_connection_ex_to_smtp (conn, sent_email, NULL, NULL, NULL);
-					sent_email = sent_free;
-				}
-
-				val = g_strdup_printf ("MAILTO:%s", sent_email);
-				prop = icalproperty_new_organizer (val);
-				g_free (val);
-				/* CN */
-				param = icalparameter_new_cn (sent_name);
-				icalproperty_add_parameter (prop, param);
-				/* SENTBY */
-				if (g_utf8_collate (sent_email, sender_email)) {
-					val = g_strdup_printf ("MAILTO:%s", sender_email);
-					param = icalparameter_new_sentby (val);
-					icalproperty_add_parameter (prop, param);
-					g_free (val);
-				}
-
-				icalcomponent_add_property (ical_comp, prop);
-
-				g_free (sender_free);
-				g_free (sent_free);
-			}
-		}
-
-		b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidRecurring);
-		if (b && *b) {
-			stream = e_mapi_util_find_stream_namedid (streams, conn, fid, PidLidAppointmentRecur);
-			if (stream && stream->value) {
-				icaltimezone *recur_zone;
-				const gchar *recur_tz_location;
-
-				recur_tz_location = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidTimeZoneDescription);
-				if (recur_tz_location)
-					recur_tz_location = e_mapi_cal_tz_util_get_ical_equivalent (recur_tz_location);
-				recur_zone = recur_tz_location ? icaltimezone_get_builtin_timezone (recur_tz_location) : (icaltimezone *) default_zone;
-
-				e_mapi_cal_util_bin_to_rrule (stream->value->data, stream->value->len, comp, detached_components, recur_zone);
-			}
-		}
-
-		b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidReminderSet);
-		if (b && *b) {
-			struct timeval start, displaytime;
-
-			if ((e_mapi_util_find_array_datetime_namedid (&start, properties, conn, fid, PidLidReminderTime) == MAPI_E_SUCCESS)
-			 && (e_mapi_util_find_array_datetime_namedid (&displaytime, properties, conn, fid, PidLidReminderSignalTime) == MAPI_E_SUCCESS)) {
-				ECalComponentAlarm *e_alarm = e_cal_component_alarm_new ();
-				ECalComponentAlarmTrigger trigger;
-
-				trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
-				trigger.u.rel_duration = icaltime_subtract (icaltime_from_timet_with_zone (displaytime.tv_sec, 0, 0),
-									    icaltime_from_timet_with_zone (start.tv_sec, 0, 0));
-
-				e_cal_component_alarm_set_action (e_alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
-				e_cal_component_alarm_set_trigger (e_alarm, trigger);
-
-				e_cal_component_add_alarm (comp, e_alarm);
-			}
-		} else
-			e_cal_component_remove_all_alarms (comp);
-
-	} else if (icalcomponent_isa (ical_comp) == ICAL_VTODO_COMPONENT) {
-		const double *complete = NULL;
-		const uint64_t *status = NULL;
-
-		/* NOTE: Exchange tasks are DATE values, not DATE-TIME values, but maybe someday, we could expect Exchange to support it;) */
-		if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidTaskStartDate) == MAPI_E_SUCCESS)
-			icalcomponent_set_dtstart (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
-		if (e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidTaskDueDate) == MAPI_E_SUCCESS)
-			icalcomponent_set_due (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
-
-		status = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidTaskStatus);
-		if (status) {
-			icalcomponent_set_status (ical_comp, get_taskstatus_from_prop(*status));
-			if (*status == olTaskComplete
-			&& e_mapi_util_find_array_datetime_namedid (&t, properties, conn, fid, PidLidTaskDateCompleted) == MAPI_E_SUCCESS) {
-				prop = icalproperty_new_completed (icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
-				icalcomponent_add_property (ical_comp, prop);
-			}
-		}
-
-		complete = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidPercentComplete);
-		if (complete) {
-			prop = icalproperty_new_percentcomplete ((gint)(*complete * 100 + 1e-9));
-			icalcomponent_add_property (ical_comp, prop);
-		}
-
-		b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidTaskFRecurring);
-		if (b && *b) {
-			/* FIXME: Evolution does not support recurring tasks */
-			g_warning ("Encountered a recurring task.");
-		}
-
-		b = e_mapi_util_find_array_namedid (properties, conn, fid, PidLidReminderSet);
-		if (b && *b) {
-			struct timeval abs;
-
-			if (e_mapi_util_find_array_datetime_namedid (&abs, properties, conn, fid, PidLidReminderTime) == MAPI_E_SUCCESS) {
-				ECalComponentAlarm *e_alarm = e_cal_component_alarm_new ();
-				ECalComponentAlarmTrigger trigger;
-
-				trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE;
-				trigger.u.abs_time = icaltime_from_timet_with_zone (abs.tv_sec, 0, default_zone);
-
-				e_cal_component_alarm_set_action (e_alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
-				e_cal_component_alarm_set_trigger (e_alarm, trigger);
-
-				e_cal_component_add_alarm (comp, e_alarm);
-			}
-		} else
-			e_cal_component_remove_all_alarms (comp);
-
-	} else if (icalcomponent_isa (ical_comp) == ICAL_VJOURNAL_COMPONENT) {
-		if (get_mapi_SPropValue_array_date_timeval (&t, properties, PR_LAST_MODIFICATION_TIME) == MAPI_E_SUCCESS)
-			icalcomponent_set_dtstart (ical_comp, icaltime_from_timet_with_zone (t.tv_sec, 1, default_zone));
-	}
-
-	if (icalcomponent_isa (ical_comp) == ICAL_VEVENT_COMPONENT || icalcomponent_isa (ical_comp) == ICAL_VTODO_COMPONENT) {
-		/* priority */
-		ui32 = (const uint32_t *)find_mapi_SPropValue_data(properties, PR_PRIORITY);
-		if (ui32) {
-			prop = icalproperty_new_priority (get_priority_from_prop (*ui32));
-			icalcomponent_add_property (ical_comp, prop);
-		}
-	}
-
-	/* classification */
-	ui32 = (const uint32_t *)find_mapi_SPropValue_data(properties, PR_SENSITIVITY);
-	if (ui32) {
-		prop = icalproperty_new_class (get_class_from_prop (*ui32));
-		icalcomponent_add_property (ical_comp, prop);
-	}
-
-	set_attachments_to_cal_component (comp, attachments, local_store_uri);
-
-	e_cal_component_rescan (comp);
-
-	return comp;
-}
-
-struct fetch_camel_cal_data {
-	icalcomponent_kind kind;
-	icalproperty_method method;
-	gchar *result_data;
-};
-
-static gboolean
-fetch_camel_cal_comp_cb (FetchItemsCallbackData *item_data,
-			 gpointer data,
-			 GCancellable *cancellable,
-			 GError **perror)
-{
-	struct fetch_camel_cal_data *fccd = data;
-	ECalComponent *comp = NULL;
-	GSList *detached_recurrences = NULL, *d_i = NULL;
-	mapi_id_t mid = 0;
-	icalcomponent *icalcomp = NULL;
-	gchar *str = NULL, *smid = NULL, *filepath;
-
-	g_return_val_if_fail (item_data != NULL, FALSE);
-	g_return_val_if_fail (fccd != NULL, FALSE);
-
-	filepath = g_strdup (g_get_tmp_dir ());
-
-	if (!comp) {
-		/* read component from a mail, if not found in the calendar */
-		if (mid)
-			smid = e_mapi_util_mapi_id_to_string (mid);
-		else if (item_data->mid)
-			smid = e_mapi_util_mapi_id_to_string (item_data->mid);
-		else
-			smid = e_cal_component_gen_uid();
-		comp = e_mapi_cal_util_mapi_props_to_comp (item_data->conn, item_data->fid, fccd->kind, smid,
-							item_data->properties, item_data->streams, item_data->recipients,
-							item_data->attachments, filepath, NULL, fccd->method == ICAL_METHOD_REPLY,
-							&detached_recurrences);
-
-		g_free (smid);
-	}
-
-	g_free (filepath);
-
-	icalcomp = e_cal_util_new_top_level ();
-	icalcomponent_set_method (icalcomp, fccd->method);
-	if (comp)
-		icalcomponent_add_component (icalcomp,
-			icalcomponent_new_clone(e_cal_component_get_icalcomponent(comp)));
-	for (d_i = detached_recurrences; d_i; d_i = g_slist_next (d_i)) {
-		icalcomponent_add_component (icalcomp,
-				icalcomponent_new_clone (e_cal_component_get_icalcomponent (d_i->data)));
-		g_object_unref (d_i->data);
-	}
-	str = icalcomponent_as_ical_string_r (icalcomp);
-	icalcomponent_free (icalcomp);
-	if (comp)
-		g_object_unref (comp);
-	g_slist_free (detached_recurrences);
-
-	e_mapi_util_free_stream_list (&item_data->streams);
-	e_mapi_util_free_recipient_list (&item_data->recipients);
-	e_mapi_util_free_attachment_list (&item_data->attachments);
-
-	fccd->result_data = str;
-
-	return TRUE;
-}
-
-gchar *
-e_mapi_cal_util_camel_helper (EMapiConnection *conn, mapi_id_t orig_fid, mapi_id_t orig_mid, mapi_object_t *obj_message, const gchar *msg_class,
-				   GSList *streams, GSList *recipients, GSList *attachments)
-{
-	struct fetch_camel_cal_data fccd = { 0 };
-
-	fccd.kind = ICAL_NO_COMPONENT;
-	fccd.method = ICAL_METHOD_NONE;
-
-	g_return_val_if_fail (msg_class && *msg_class, NULL);
-	g_return_val_if_fail (conn != NULL, NULL);
-
-	if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST)) {
-		fccd.method = ICAL_METHOD_REQUEST;
-		fccd.kind = ICAL_VEVENT_COMPONENT;
-	} else if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED)) {
-		fccd.method = ICAL_METHOD_CANCEL;
-		fccd.kind = ICAL_VEVENT_COMPONENT;
-	} else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
-		fccd.method = ICAL_METHOD_REPLY;
-		fccd.kind = ICAL_VEVENT_COMPONENT;
-	} else
-		return NULL;
-
-	if (obj_message)
-		e_mapi_connection_fetch_object_props (conn, NULL, orig_fid, orig_mid, obj_message,
-					e_mapi_cal_utils_get_props_cb, GINT_TO_POINTER (fccd.kind),
-					fetch_camel_cal_comp_cb, &fccd,
-					MAPI_OPTIONS_FETCH_ALL, NULL, NULL);
-	else
-		e_mapi_connection_fetch_item (conn, orig_fid, orig_mid,
-					e_mapi_cal_utils_get_props_cb, GINT_TO_POINTER (fccd.kind),
-					fetch_camel_cal_comp_cb, &fccd,
-					MAPI_OPTIONS_FETCH_ALL, NULL, NULL);
-
-	return fccd.result_data;
-}
-
-/* call with props = NULL to fetch named ids into the connection cache */
-gboolean
-e_mapi_cal_utils_add_named_ids (EMapiConnection *conn,
-				mapi_id_t fid,
-				TALLOC_CTX *mem_ctx,
-				struct SPropTagArray *props,
-				gint pkind,
-				GCancellable *cancellable,
-				GError **perror)
-{
-	/* do not make this array static, the function modifies it on run */
-	ResolveNamedIDsData common_nids[] = {
-		{ PidLidReminderDelta, 0 },
-		{ PidLidReminderTime, 0 },
-		{ PidLidReminderSet, 0 },
-		{ PidLidPrivate, 0 },
-		{ PidLidSideEffects, 0 },
-		{ PidLidCommonStart, 0 },
-		{ PidLidCommonEnd, 0 },
-		{ PidLidTaskMode, 0 },
-		{ PidLidReminderSignalTime, 0 },
-		{ PidLidTimeZoneStruct, 0 },
-		{ PidLidTimeZoneDescription, 0 },
-		{ PidLidExceptionReplaceTime, 0 },
-		{ PidNameKeywords, 0 }
-	};
-	icalcomponent_kind kind = pkind;
-
-	if (!props) {
-		if (!e_mapi_connection_resolve_named_props (conn, fid, common_nids, G_N_ELEMENTS (common_nids), cancellable, perror))
-			return FALSE;
-	} else if (!e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, common_nids, G_N_ELEMENTS (common_nids), cancellable, perror))
-		return FALSE;
-
-	if (kind == ICAL_VEVENT_COMPONENT)
-		return appt_build_name_id (conn, fid, mem_ctx, props, cancellable, perror);
-	else if (kind == ICAL_VTODO_COMPONENT)
-		return task_build_name_id (conn, fid, mem_ctx, props, cancellable, perror);
-	else if (kind == ICAL_VJOURNAL_COMPONENT)
-		return note_build_name_id (conn, fid, mem_ctx, props, cancellable, perror);
-
-	return TRUE;
-}
-
-#define DEFAULT_APPT_REMINDER_MINS 15
-
-static gboolean
-appt_build_name_id (EMapiConnection *conn,
-		    mapi_id_t fid,
-		    TALLOC_CTX *mem_ctx,
-		    struct SPropTagArray *props,
-		    GCancellable *cancellable,
-		    GError **perror)
-{
-	/* do not make this array static, the function modifies it on run */
-	ResolveNamedIDsData nids[] = {
-		{ PidLidAppointmentSequence, 0 },
-		{ PidLidBusyStatus, 0 },
-		{ PidLidLocation, 0 },
-		{ PidLidAppointmentStartWhole, 0 },
-		{ PidLidAppointmentEndWhole, 0 },
-		{ PidLidAppointmentDuration, 0 },
-		{ PidLidAppointmentSubType, 0 },
-		{ PidLidAppointmentRecur, 0 },
-		{ PidLidAppointmentStateFlags, 0 },
-		{ PidLidResponseStatus, 0 },
-		{ PidLidRecurring, 0 },
-		{ PidLidIntendedBusyStatus, 0 },
-		{ PidLidExceptionReplaceTime, 0 },
-		{ PidLidFInvited, 0 },
-		{ PidLidRecurrenceType, 0 },
-		{ PidLidClipStart, 0 },
-		{ PidLidClipEnd, 0 },
-		{ PidLidAutoFillLocation, 0 },
-		{ PidLidAppointmentCounterProposal, 0 },
-		{ PidLidAppointmentNotAllowPropose, 0 },
-		{ PidLidAppointmentTimeZoneDefinitionStartDisplay, 0 },
-		{ PidLidAppointmentTimeZoneDefinitionEndDisplay, 0 },
-		{ PidLidWhere, 0 },
-		{ PidLidGlobalObjectId, 0 },
-		{ PidLidIsRecurring, 0 },
-		{ PidLidIsException, 0 },
-		{ PidLidCleanGlobalObjectId, 0 },
-		{ PidLidAppointmentMessageClass, 0 },
-		{ PidLidMeetingType, 0 },
-		{ PidLidTimeZone, 0 }
-	};
-
-	if (!props)
-		return e_mapi_connection_resolve_named_props (conn, fid, nids, G_N_ELEMENTS (nids), cancellable, perror);
-
-	return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-#define DEFAULT_TASK_REMINDER_MINS 1080
-
-static gboolean
-task_build_name_id (EMapiConnection *conn,
-		    mapi_id_t fid,
-		    TALLOC_CTX *mem_ctx,
-		    struct SPropTagArray *props,
-		    GCancellable *cancellable,
-		    GError **perror)
-{
-	/* do not make this array static, the function modifies it on run */
-	ResolveNamedIDsData nids[] = {
-		{ PidLidTaskStatus, 0 },
-		{ PidLidPercentComplete, 0 },
-		{ PidLidTeamTask, 0 },
-		{ PidLidTaskStartDate, 0 },
-		{ PidLidTaskDueDate, 0 },
-		{ PidLidTaskDateCompleted, 0 },
-		/*{ PidLidTaskRecurrence, 0 },*/
-		{ PidLidTaskComplete, 0 },
-		{ PidLidTaskOwner, 0 },
-		{ PidLidTaskAssigner, 0 },
-		{ PidLidTaskFRecurring, 0 },
-		{ PidLidTaskOwnership, 0 },
-		{ PidLidTaskAcceptanceState, 0 },
-		{ PidLidTaskRole, 0 }
-	};
-
-	if (!props)
-		return e_mapi_connection_resolve_named_props (conn, fid, nids, G_N_ELEMENTS (nids), cancellable, perror);
-
-	return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-static gboolean
-note_build_name_id (EMapiConnection *conn,
-		    mapi_id_t fid,
-		    TALLOC_CTX *mem_ctx,
-		    struct SPropTagArray *props,
-		    GCancellable *cancellable,
-		    GError **perror)
-{
-	/* do not make this array static, the function modifies it on run */
-	ResolveNamedIDsData nids[] = {
-		{ PidLidNoteColor, 0 },
-		{ PidLidNoteWidth, 0 },
-		{ PidLidNoteHeight, 0 }
-	};
-
-	if (!props)
-		return e_mapi_connection_resolve_named_props (conn, fid, nids, G_N_ELEMENTS (nids), cancellable, perror);
-
-	return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-/* retrieves timezone location from a timezone ID */
-static const gchar *
-get_tzid_location (const gchar *tzid, struct cal_cbdata *cbdata)
-{
-	icaltimezone *zone = NULL;
-
-	if (!tzid || !*tzid || g_str_equal (tzid, "UTC"))
-		return NULL;
-
-	/* ask backend first, if any */
-	if (cbdata && cbdata->get_timezone)
-		zone = cbdata->get_timezone (cbdata->get_tz_data, tzid);
-
-	if (!zone)
-		zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
-
-	/* the old TZID prefix used in previous versions of evolution-mapi */
-	#define OLD_TZID_PREFIX "/softwarestudio.org/Tzfile/"
-
-	if (!zone && g_str_has_prefix (tzid, OLD_TZID_PREFIX))
-		zone = icaltimezone_get_builtin_timezone (tzid + strlen (OLD_TZID_PREFIX));
-
-	#undef OLD_TZID_PREFIX
-
-	if (!zone)
-		return NULL;
-
-	return icaltimezone_get_location (zone);
-}
-
-#define MINUTES_IN_HOUR 60
-#define SECS_IN_MINUTE 60
-
-gboolean
-e_mapi_cal_utils_write_props_cb (EMapiConnection *conn,
-				 mapi_id_t fid,
-				 TALLOC_CTX *mem_ctx,
-				 struct SPropValue **values,
-				 uint32_t *n_values,
-				 gpointer data,
-				 GCancellable *cancellable,
-				 GError **perror)
-{
-	struct cal_cbdata *cbdata = (struct cal_cbdata *) data;
-	ECalComponent *comp;
-	icalcomponent *ical_comp;
-	icalcomponent_kind kind;
-	uint32_t flag32;
-	bool b;
-	icalproperty *prop;
-	struct icaltimetype dtstart, dtend, utc_dtstart, utc_dtend, all_day_dtstart = {0}, all_day_dtend = {0};
-	const icaltimezone *utc_zone;
-	const gchar *dtstart_tz_location, *dtend_tz_location, *text = NULL;
-	time_t tt;
-	gboolean is_all_day;
-	GSList *categories = NULL;
-
-	g_return_val_if_fail (conn != NULL, FALSE);
-	g_return_val_if_fail (mem_ctx != NULL, FALSE);
-	g_return_val_if_fail (values != NULL, FALSE);
-	g_return_val_if_fail (n_values != NULL, FALSE);
-	g_return_val_if_fail (cbdata != NULL, FALSE);
-
-	switch (cbdata->kind) {
-		case ICAL_VEVENT_COMPONENT:
-		case ICAL_VTODO_COMPONENT:
-		case ICAL_VJOURNAL_COMPONENT:
-			if (!e_mapi_cal_utils_add_named_ids (conn, fid, mem_ctx, NULL, cbdata->kind, cancellable, perror))
-				return FALSE;
-			break;
-		default:
-			return FALSE;
-	}
-
-	comp = cbdata->comp;
-	ical_comp = e_cal_component_get_icalcomponent (comp);
-	kind = icalcomponent_isa (ical_comp);
-	g_return_val_if_fail (kind == cbdata->kind, FALSE);
-
-	#define set_value(hex, val) G_STMT_START { \
-		if (!e_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, val)) \
-			return FALSE;	\
-		} G_STMT_END
-
-	#define set_named_value(named_id, val) G_STMT_START { \
-		if (!e_mapi_utils_add_spropvalue_namedid (conn, fid, mem_ctx, values, n_values, named_id, val, cancellable, perror)) \
-			return FALSE;	\
-		} G_STMT_END
-
-	#define set_datetime_value(hex, dtval) G_STMT_START {		\
-		struct FILETIME	filetime;				\
-									\
-		e_mapi_util_time_t_to_filetime (dtval, &filetime); \
-									\
-		if (!e_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, &filetime)) \
-			return FALSE;	\
-		} G_STMT_END
-
-	#define set_named_datetime_value(named_id, dtval) G_STMT_START { \
-		struct FILETIME	filetime;				\
-									\
-		e_mapi_util_time_t_to_filetime (dtval, &filetime); \
-									\
-		if (!e_mapi_utils_add_spropvalue_namedid (conn, fid, mem_ctx, values, n_values, named_id, &filetime, cancellable, perror)) \
-			return FALSE;	\
-		} G_STMT_END
-
-	utc_zone = icaltimezone_get_utc_timezone ();
-
-	dtstart = icalcomponent_get_dtstart (ical_comp);
-
-	/* For VEVENTs */
-	if (icalcomponent_get_first_property (ical_comp, ICAL_DTEND_PROPERTY) != 0)
-		dtend = icalcomponent_get_dtend (ical_comp);
-	/* For VTODOs */
-	else if (icalcomponent_get_first_property (ical_comp, ICAL_DUE_PROPERTY) != 0)
-		dtend = icalcomponent_get_due (ical_comp);
-	else
-		dtend = icalcomponent_get_dtstart (ical_comp);
-
-	dtstart_tz_location = get_tzid_location (icaltime_get_tzid (dtstart), cbdata);
-	dtend_tz_location = get_tzid_location (icaltime_get_tzid (dtend), cbdata);
-
-	is_all_day = kind == ICAL_VEVENT_COMPONENT && icaltime_is_date (dtstart) && icaltime_is_date (dtend);
-	if (is_all_day) {
-		const gchar *def_location;
-		icaltimezone *use_zone = NULL;
-
-		/* all-day events expect times not in UTC but in local time;
-		   if this differs from the server timezone, then the event
-		   is shown spread among (two) days */
-		def_location = get_tzid_location ("*default-zone*", cbdata);
-		if (def_location && *def_location)
-			use_zone = icaltimezone_get_builtin_timezone (def_location);
-
-		if (!use_zone)
-			use_zone = (icaltimezone *) utc_zone;
-
-		dtstart.is_date = 0;
-		dtstart.hour = 0;
-		dtstart.minute = 0;
-		dtstart.second = 0;
-		all_day_dtstart = icaltime_convert_to_zone (dtstart, use_zone);
-		dtstart.is_date = 1;
-		all_day_dtstart = icaltime_convert_to_zone (all_day_dtstart, (icaltimezone *) utc_zone);
-
-		dtend.is_date = 0;
-		dtend.hour = 0;
-		dtend.minute = 0;
-		dtend.second = 0;
-		all_day_dtend = icaltime_convert_to_zone (dtend, use_zone);
-		dtend.is_date = 1;
-		all_day_dtend = icaltime_convert_to_zone (all_day_dtend, (icaltimezone *) utc_zone);
-	}
-
-	utc_dtstart = icaltime_convert_to_zone (dtstart, (icaltimezone *)utc_zone);
-	utc_dtend = icaltime_convert_to_zone (dtend, (icaltimezone *)utc_zone);
-
-	text = icalcomponent_get_summary (ical_comp);
-	if (!(text && *text))
-		text = "";
-	set_value (PR_SUBJECT_UNICODE, text);
-	set_value (PR_NORMALIZED_SUBJECT_UNICODE, text);
-	if (cbdata->appt_seq == 0)
-		set_value (PR_CONVERSATION_TOPIC_UNICODE, text);
-	text = NULL;
-
-	/* we don't support HTML event/task/memo editor */
-	flag32 = olEditorText;
-	set_value (PR_MSG_EDITOR_FORMAT, &flag32);
-
-	/* it'd be better to convert, then set it in unicode */
-	text = icalcomponent_get_description (ical_comp);
-	if (!(text && *text) || !g_utf8_validate (text, -1, NULL))
-		text = "";
-	set_value (PR_BODY_UNICODE, text);
-	text = NULL;
-
-	e_cal_component_get_categories_list (comp, &categories);
-	if (categories) {
-		gint ii;
-		GSList *c;
-		struct StringArrayW_r *categories_array;
-
-		categories_array = talloc_zero (mem_ctx, struct StringArrayW_r);
-		categories_array->cValues = g_slist_length (categories);
-		categories_array->lppszW = (const char **) talloc_zero_array (mem_ctx, gchar *, categories_array->cValues);
-
-		for (c = categories, ii = 0; c; c = c->next, ii++) {
-			const gchar *category = c->data;
-
-			if (!category || !*category) {
-				ii--;
-				categories_array->cValues--;
-				continue;
-			}
-
-			categories_array->lppszW[ii] = talloc_strdup (mem_ctx, category);
-		}
-
-		set_named_value (PidNameKeywords, categories_array);
-
-		e_cal_component_free_categories_list (categories);
-	}
-
-	/* Priority and Importance */
-	prop = icalcomponent_get_first_property (ical_comp, ICAL_PRIORITY_PROPERTY);
-	flag32 = prop ? get_prio_prop_from_priority (icalproperty_get_priority (prop)) : PRIORITY_NORMAL;
-	set_value (PR_PRIORITY, &flag32);
-	flag32 = prop ? get_imp_prop_from_priority (icalproperty_get_priority (prop)) : IMPORTANCE_NORMAL;
-	set_value (PR_IMPORTANCE, &flag32);
-
-	if (cbdata->ownername && cbdata->owneridtype && cbdata->ownerid) {
-		set_value (PR_SENT_REPRESENTING_NAME_UNICODE, cbdata->ownername);
-		set_value (PR_SENT_REPRESENTING_ADDRTYPE_UNICODE, cbdata->owneridtype);
-		set_value (PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE, cbdata->ownerid);
-	}
-
-	if (cbdata->username && cbdata->useridtype && cbdata->userid) {
-		set_value (PR_SENDER_NAME_UNICODE, cbdata->username);
-		set_value (PR_SENDER_ADDRTYPE_UNICODE, cbdata->useridtype);
-		set_value (PR_SENDER_EMAIL_ADDRESS_UNICODE, cbdata->userid);
-	}
-
-	flag32 = cbdata->msgflags;
-	set_value (PR_MESSAGE_FLAGS, &flag32);
-
-	flag32 = 0x0;
-	b = e_cal_component_has_alarms (comp);
-	if (b) {
-		/* We know there would be only a single alarm of type:DISPLAY [static properties of the backend] */
-		GList *alarm_uids = e_cal_component_get_alarm_uids (comp);
-		ECalComponentAlarm *alarm = e_cal_component_get_alarm (comp, (const gchar *)(alarm_uids->data));
-		ECalComponentAlarmAction action;
-		e_cal_component_alarm_get_action (alarm, &action);
-		if (action == E_CAL_COMPONENT_ALARM_DISPLAY) {
-			ECalComponentAlarmTrigger trigger;
-			gint dur_int = 0;
-			e_cal_component_alarm_get_trigger (alarm, &trigger);
-			switch (trigger.type) {
-			case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START :
-				dur_int = (icaldurationtype_as_int (trigger.u.rel_duration)) / SECS_IN_MINUTE;
-			/* we cannot set an alarm to popup after the start of an appointment on Exchange */
-				flag32 = (dur_int < 0) ? -(dur_int) : 0;
-				break;
-			default :
-				break;
-			}
-		}
-		e_cal_component_alarm_free (alarm);
-		cal_obj_uid_list_free (alarm_uids);
-	}
-	if (!flag32)
-		switch (kind) {
-			case ICAL_VEVENT_COMPONENT:
-				flag32 = DEFAULT_APPT_REMINDER_MINS;
-				break;
-			case ICAL_VTODO_COMPONENT:
-				flag32 = DEFAULT_TASK_REMINDER_MINS;
-				break;
-			default:
-				break;
-		}
-	set_named_value (PidLidReminderSet, &b);
-	set_named_value (PidLidReminderDelta, &flag32);
-	tt = icaltime_as_timet (utc_dtstart);
-	set_named_datetime_value (PidLidReminderTime, tt);
-	tt = icaltime_as_timet (utc_dtstart) - (flag32 * SECS_IN_MINUTE);
-	/* ReminderNextTime: FIXME for recurrence */
-	set_named_datetime_value (PidLidReminderSignalTime, tt);
-
-	/* Sensitivity, Private */
-	flag32 = olNormal;	/* default */
-	b = 0;			/* default */
-	prop = icalcomponent_get_first_property (ical_comp, ICAL_CLASS_PROPERTY);
-	if (prop)
-		flag32 = get_prop_from_class (icalproperty_get_class (prop));
-	if (flag32 == olPrivate || flag32 == olConfidential)
-		b = 1;
-	set_value (PR_SENSITIVITY, &flag32);
-	set_named_value (PidLidPrivate, &b);
-
-	tt = icaltime_as_timet (is_all_day ? all_day_dtstart : utc_dtstart);
-	set_named_datetime_value (PidLidCommonStart, tt);
-	set_datetime_value (PR_START_DATE, tt);
-
-	tt = icaltime_as_timet (is_all_day ? all_day_dtend : utc_dtend);
-	set_named_datetime_value (PidLidCommonEnd, tt);
-	set_datetime_value (PR_END_DATE, tt);
-
-	b = 1;
-	set_value (PR_RESPONSE_REQUESTED, &b);
-
-	/* PR_OWNER_APPT_ID needs to be set in certain cases only */
-	/* PR_ICON_INDEX needs to be set appropriately */
-
-	b = 0;
-	set_value (PR_RTF_IN_SYNC, &b);
-
-	if (kind == ICAL_VEVENT_COMPONENT) {
-		const gchar *mapi_tzid;
-		struct SBinary_short start_tz, end_tz;
-
-		set_named_value (PidLidAppointmentMessageClass, IPM_APPOINTMENT);
-
-		/* Busy Status */
-		flag32 = olBusy;	/* default */
-		prop = icalcomponent_get_first_property (ical_comp, ICAL_TRANSP_PROPERTY);
-		if (prop)
-			flag32 = get_prop_from_transp (icalproperty_get_transp (prop));
-		if (cbdata->meeting_type == MEETING_CANCEL)
-			flag32 = olFree;
-		set_named_value (PidLidIntendedBusyStatus, &flag32);
-
-		if (cbdata->meeting_type == MEETING_REQUEST || cbdata->meeting_type == MEETING_REQUEST_RCVD) {
-			flag32 = olTentative;
-			set_named_value (PidLidBusyStatus, &flag32);
-		} else if (cbdata->meeting_type == MEETING_CANCEL) {
-			flag32 = olFree;
-			set_named_value (PidLidBusyStatus, &flag32);
-		} else
-			set_named_value (PidLidBusyStatus, &flag32);
-
-		/* Location */
-		text = icalcomponent_get_location (ical_comp);
-		if (!(text && *text))
-			text = "";
-		set_named_value (PidLidLocation, text);
-		set_named_value (PidLidWhere, text);
-		text = NULL;
-		/* Auto-Location is always FALSE - Evolution doesn't work that way */
-		b = 0;
-		set_named_value (PidLidAutoFillLocation, &b);
-
-		/* All-day event */
-		b = is_all_day ? 1 : 0;
-		set_named_value (PidLidAppointmentSubType, &b);
-
-		/* Start */
-		tt = icaltime_as_timet (is_all_day ? all_day_dtstart : utc_dtstart);
-		set_named_datetime_value (PidLidAppointmentStartWhole, tt);
-		/* FIXME: for recurrence */
-		set_named_datetime_value (PidLidClipStart, tt);
-
-		/* Start TZ */
-		mapi_tzid = e_mapi_cal_tz_util_get_mapi_equivalent ((dtstart_tz_location && *dtstart_tz_location) ? dtstart_tz_location : "UTC");
-		if (mapi_tzid && *mapi_tzid) {
-			e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &start_tz, mem_ctx);
-			set_named_value (PidLidAppointmentTimeZoneDefinitionStartDisplay, &start_tz);
-		}
-		set_named_value (PidLidTimeZoneDescription, mapi_tzid ? mapi_tzid : "");
-
-		/* End */
-		tt = icaltime_as_timet (is_all_day ? all_day_dtend : utc_dtend);
-		set_named_datetime_value (PidLidAppointmentEndWhole, tt);
-		/* FIXME: for recurrence */
-		set_named_datetime_value (PidLidClipEnd, tt);
-
-		/* End TZ */
-		mapi_tzid = e_mapi_cal_tz_util_get_mapi_equivalent ((dtend_tz_location && *dtend_tz_location) ? dtend_tz_location : "UTC");
-		if (mapi_tzid && *mapi_tzid) {
-			e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &end_tz, mem_ctx);
-			set_named_value (PidLidAppointmentTimeZoneDefinitionEndDisplay, &end_tz);
-		}
-
-		/* Recurrences also need to have this rather arbitrary index set
-		   to properly determine SDT/DST and appear in OWA (Bug #629057). */
-		if (e_cal_component_has_recurrences (comp)) {
-			uint64_t pltz;
-			icaltimezone *ictz;
-			const gchar *zone_location = dtstart_tz_location;
-
-			if (!zone_location)
-				zone_location = get_tzid_location ("*default-zone*", cbdata);
-
-			ictz = icaltimezone_get_builtin_timezone (zone_location);
-			pltz = e_mapi_cal_util_mapi_tz_pidlidtimezone (ictz);
-			set_named_value (PidLidTimeZone, &pltz);
-		}
-
-		/* Duration */
-		flag32 = icaldurationtype_as_int (icaltime_subtract (dtend, dtstart));
-		flag32 /= MINUTES_IN_HOUR;
-		set_named_value (PidLidAppointmentDuration, &flag32);
-
-		if (e_cal_component_has_recurrences (comp)) {
-			GSList *rrule_list = NULL;
-			struct icalrecurrencetype *rt = NULL;
-
-			e_cal_component_get_rrule_list (comp, &rrule_list);
-			rt = (struct icalrecurrencetype *)(rrule_list->data);
-
-			if (rt->freq == ICAL_DAILY_RECURRENCE)
-				flag32 = rectypeDaily;
-			else if (rt->freq == ICAL_WEEKLY_RECURRENCE)
-				flag32 = rectypeWeekly;
-			else if (rt->freq == ICAL_MONTHLY_RECURRENCE)
-				flag32 = rectypeMonthly;
-			else if (rt->freq == ICAL_YEARLY_RECURRENCE)
-				flag32 = rectypeYearly;
-			else
-				flag32 = rectypeNone;
-
-			e_cal_component_free_recur_list (rrule_list);
-		} else
-			flag32 = rectypeNone;
-		set_named_value (PidLidRecurrenceType, &flag32);
-
-		flag32 = cbdata->appt_id;
-		if (!flag32) {
-			gchar *propval;
-
-			propval = e_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp), "X-EVOLUTION-MAPI-OWNER-APPT-ID");
-			if (propval && *propval) {
-				mapi_id_t as_id = 0;
-
-				if (e_mapi_util_mapi_id_from_string (propval, &as_id))
-					flag32 = (uint32_t) as_id;
-			}
-
-			g_free (propval);
-		}
-		set_value (PR_OWNER_APPT_ID, &flag32);
-
-		flag32 = cbdata->appt_seq;
-		set_named_value (PidLidAppointmentSequence, &flag32);
-
-		if (cbdata->cleanglobalid) {
-			set_named_value (PidLidCleanGlobalObjectId, cbdata->cleanglobalid);
-		}
-
-		if (cbdata->globalid) {
-			set_named_value (PidLidGlobalObjectId, cbdata->globalid);
-		}
-
-		flag32 = cbdata->resp;
-		set_named_value (PidLidResponseStatus, &flag32);
-
-		switch (cbdata->meeting_type) {
-		case MEETING_OBJECT :
-			set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
-
-			flag32 = e_cal_component_has_recurrences (comp) ? RecurMeet : SingleMeet;
-			set_value (PR_ICON_INDEX, &flag32);
-
-			flag32 = 0x0171;
-			set_named_value (PidLidSideEffects, &flag32);
-
-			flag32 = asfMeeting;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
-
-			flag32 = mtgRequest;
-			set_named_value (PidLidMeetingType, &flag32);
-
-			b = 1;
-			set_named_value (PidLidFInvited, &b);
-
-			break;
-		case MEETING_OBJECT_RCVD :
-			set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
-
-			flag32 = e_cal_component_has_recurrences (comp) ? RecurMeet : SingleMeet;
-			set_value (PR_ICON_INDEX, (gconstpointer ) &flag32);
-
-			flag32 = 0x0171;
-			set_named_value (PidLidSideEffects, &flag32);
-
-			flag32 = asfMeeting | asfReceived;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
-
-			flag32 = mtgRequest;
-			set_named_value (PidLidMeetingType, &flag32);
-
-			b = 1;
-			set_named_value (PidLidFInvited, &b);
-
-			break;
-		case MEETING_REQUEST :
-			set_value (PR_MESSAGE_CLASS, IPM_SCHEDULE_MEETING_REQUEST);
-
-			flag32 = 0xFFFFFFFF;  /* no idea why this has to be -1, but that's what the docs say */
-			set_value (PR_ICON_INDEX, &flag32);
-
-			flag32 = 0x1C61;
-			set_named_value (PidLidSideEffects, &flag32);
-
-			flag32 = asfMeeting | asfReceived;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
-
-			flag32 = (cbdata->appt_seq == 0) ? mtgRequest : mtgFull;
-			set_named_value (PidLidMeetingType, &flag32);
-
-			b = 1;
-			set_named_value (PidLidFInvited, &b);
-
-			break;
-		case MEETING_REQUEST_RCVD :
-			set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
-
-			flag32 = e_cal_component_has_recurrences (comp) ? RecurMeet : SingleMeet;
-			set_value (PR_ICON_INDEX, &flag32);
-
-			flag32 = 0x0171;
-			set_named_value (PidLidSideEffects, &flag32);
-
-			flag32 = asfMeeting | asfReceived;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
-
-			flag32 = mtgRequest;
-			set_named_value (PidLidMeetingType, &flag32);
-
-			b = 1;
-			set_named_value (PidLidFInvited, &b);
-
-			break;
-		case MEETING_CANCEL :
-			set_value (PR_MESSAGE_CLASS, IPM_SCHEDULE_MEETING_CANCELED);
-
-			flag32 = 0xFFFFFFFF;  /* no idea why this has to be -1, but that's what the docs say */
-			set_value (PR_ICON_INDEX, &flag32);
-
-			flag32 = 0x1C61;
-			set_named_value (PidLidSideEffects, &flag32);
-
-			flag32 = asfMeeting | asfReceived | asfCanceled;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
-
-			flag32 = mtgEmpty;
-			set_named_value (PidLidMeetingType, &flag32);
+	/* FIXME: is this mapping correct ? */
+	switch (prop) {
+		case olPersonal		:
+		case olPrivate		: return ICAL_CLASS_PRIVATE;
+		case olConfidential	: return ICAL_CLASS_CONFIDENTIAL;
+		case olNormal		:
+		default			: return ICAL_CLASS_PUBLIC;
+	}
+}
 
-			b = 1;
-			set_named_value (PidLidFInvited, &b);
+static uint32_t
+get_prop_from_class (icalproperty_class class)
+{
+	/* FIXME: is this mapping correct ? */
+	switch (class) {
+		case ICAL_CLASS_PRIVATE		: return olPrivate;
+		case ICAL_CLASS_CONFIDENTIAL	: return olConfidential;
+		default				: return olNormal;
+	}
+}
 
-			break;
-		case MEETING_RESPONSE :
-			#define prefix_subject(prefix) {					\
-				const gchar *summary;						\
-												\
-				summary = icalcomponent_get_summary (ical_comp);		\
-				if (!(summary && *summary))					\
-					summary = "";						\
-												\
-				summary = talloc_asprintf (mem_ctx, "%s %s", prefix, summary);	\
-												\
-				set_value (PR_SUBJECT_UNICODE, summary);			\
-				set_value (PR_NORMALIZED_SUBJECT_UNICODE, summary);		\
-				if (cbdata->appt_seq == 0)					\
-					set_value (PR_CONVERSATION_TOPIC_UNICODE, summary);	\
-			}
-			if (cbdata->resp == olResponseAccepted) {
-				/* Translators: This is a meeting response prefix which will be shown in a message Subject */
-				prefix_subject (C_("MeetingResp", "Accepted:"));
-				text = IPM_SCHEDULE_MEETING_RESP_POS;
-			} else if (cbdata->resp == olResponseTentative) {
-				/* Translators: This is a meeting response prefix which will be shown in a message Subject */
-				prefix_subject (C_("MeetingResp", "Tentative:"));
-				text = IPM_SCHEDULE_MEETING_RESP_TENT;
-			} else if (cbdata->resp == olResponseDeclined) {
-				/* Translators: This is a meeting response prefix which will be shown in a message Subject */
-				prefix_subject (C_("MeetingResp", "Declined:"));
-				text = IPM_SCHEDULE_MEETING_RESP_NEG;
-			} else {
-				text = "";
-			}
-			#undef prefix_subject
-			set_value (PR_MESSAGE_CLASS, text);
-			text = NULL;
+static gint
+get_priority_from_prop (uint32_t prop)
+{
+	switch (prop) {
+		case PRIORITY_LOW	: return 7;
+		case PRIORITY_HIGH	: return 1;
+		case PRIORITY_NORMAL	:
+		default			: return 5;
+	}
+}
 
-			flag32 = 0xFFFFFFFF;  /* no idea why this has to be -1, but that's what the docs say */
-			set_value (PR_ICON_INDEX, &flag32);
+static uint32_t
+get_prio_prop_from_priority (gint priority)
+{
+	if (priority > 0 && priority <= 4)
+		return PRIORITY_HIGH;
+	else if (priority > 5 && priority <= 9)
+		return PRIORITY_LOW;
+	else
+		return PRIORITY_NORMAL;
+}
 
-			flag32 = 0x1C61;
-			set_named_value (PidLidSideEffects, &flag32);
+static uint32_t
+get_imp_prop_from_priority (gint priority)
+{
+	if (priority > 0 && priority <= 4)
+		return IMPORTANCE_HIGH;
+	else if (priority > 5 && priority <= 9)
+		return IMPORTANCE_LOW;
+	else
+		return IMPORTANCE_NORMAL;
+}
 
-			flag32 = asfNone;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
+#define RECIP_SENDABLE  0x1
+#define RECIP_ORGANIZER 0x2
 
-			flag32 = mtgEmpty;
-			set_named_value (PidLidMeetingType, &flag32);
+static const uint8_t GID_START_SEQ[] = {
+	0x04, 0x00, 0x00, 0x00, 0x82, 0x00, 0xe0, 0x00,
+	0x74, 0xc5, 0xb7, 0x10, 0x1a, 0x82, 0xe0, 0x08
+};
 
-			break;
-		case NOT_A_MEETING :
-		default :
-			set_value (PR_MESSAGE_CLASS, IPM_APPOINTMENT);
+/* exception_replace_time is a value of PidLidExceptionReplaceTime; this is not used for 'clean' object ids.
+   creation_time is a value of PR_CREATION_TIME
+*/
+void
+e_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb)
+{
+	GByteArray *ba;
+	guint32 val32;
+	guchar *buf = NULL;
+	gsize len;
+	d(guint32 i);
 
-			flag32 = e_cal_component_has_recurrences (comp) ? RecurAppt : SingleAppt;
-			set_value (PR_ICON_INDEX, &flag32);
+	ba = g_byte_array_new ();
 
-			flag32 = 0x0171;
-			set_named_value (PidLidSideEffects, &flag32);
+	ba = g_byte_array_append (ba, GID_START_SEQ, (sizeof (GID_START_SEQ) / sizeof (GID_START_SEQ[0])));
 
-			flag32 = 0;
-			set_named_value (PidLidAppointmentStateFlags, &flag32);
+	val32 = 0;
+	if (!is_clean && exception_replace_time) {
+		struct icaltimetype icaltm = icaltime_from_timet_with_zone (exception_replace_time->tv_sec, 0, icaltimezone_get_utc_timezone ());
 
-			b = 0;
-			set_named_value (PidLidFInvited, &b);
+		val32 |= (icaltm.year & 0xFF00) << 16;
+		val32 |= (icaltm.year & 0xFF) << 16;
+		val32 |= (icaltm.month & 0xFF) << 8;
+		val32 |= (icaltm.day & 0xFF);
+	}
 
-			break;
-		}
+	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
 
-		b = e_cal_component_has_recurrences (comp);
-		set_named_value (PidLidRecurring, &b);
-		set_named_value (PidLidIsRecurring, &b);
-		/* FIXME: Modified exceptions */
-		b = e_cal_component_has_exceptions (comp) && FALSE; b = 0;
-		set_named_value (PidLidIsException, &b);
+	/* creation time */
+	val32 = creation_time ? creation_time->dwLowDateTime : 0;
+	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+	val32 = creation_time ? creation_time->dwHighDateTime : 0;
+	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
 
-		/* Counter Proposal for appointments : not supported */
-		b = 1;
-		set_named_value (PidLidAppointmentNotAllowPropose, &b);
-		b = 0;
-		set_named_value (PidLidAppointmentCounterProposal, &b);
+	/* RESERVED - should be all 0's  */
+	val32 = 0;
+	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+	val32 = 0;
+	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
 
-	} else if (kind == ICAL_VTODO_COMPONENT) {
-		gdouble d;
+	/* We put Evolution's UID in base64 here */
+	buf = g_base64_decode (uid, &len);
+	if (len % 2 != 0)
+		--len;
+	val32 = len;
 
-		set_value (PR_MESSAGE_CLASS, IPM_TASK);
+	/* Size in bytes of the following data */
+	ba = g_byte_array_append (ba, (const guint8 *) &val32, sizeof (guint32));
+	/* Data */
+	ba = g_byte_array_append (ba, (const guint8 *)buf, val32);
+	g_free (buf);
 
-		/* Context menu flags */ /* FIXME: for assigned tasks */
-		flag32 = 0x0110;
-		set_named_value (PidLidSideEffects, &flag32);
+	sb->lpb = ba->data;
+	sb->cb = ba->len;
 
-		/* Status, Percent complete, IsComplete */
-		flag32 = olTaskNotStarted;	/* default */
-		b = 0;				/* default */
-		d = 0.0;
-		prop = icalcomponent_get_first_property (ical_comp, ICAL_PERCENTCOMPLETE_PROPERTY);
-		if (prop)
-			d = 0.01 * icalproperty_get_percentcomplete (prop);
+	d(g_message ("New GlobalObjectId.. Length: %d bytes.. Hex-data follows:", ba->len));
+	d(for (i = 0; i < ba->len; i++)
+		g_print("0x%02X ", ba->data[i]));
 
-		flag32 = get_prop_from_taskstatus (icalcomponent_get_status (ical_comp));
-		if (flag32 == olTaskComplete) {
-			b = 1;
-			d = 1.0;
-		}
+	g_byte_array_free (ba, FALSE);
+}
 
-		set_named_value (PidLidTaskStatus, &flag32);
-		set_named_value (PidLidPercentComplete, &d);
-		set_named_value (PidLidTaskComplete, &b);
+/* returns complete globalid as base64 encoded string */
+static gchar *
+globalid_to_string (const guint8 *lpb, guint32 cb)
+{
+	const guint8 *ptr;
+	guint32 i, j;
 
-		/* Date completed */
-		if (b) {
-			struct icaltimetype completed;
-			prop = icalcomponent_get_first_property (ical_comp, ICAL_COMPLETED_PROPERTY);
-			completed = icalproperty_get_completed (prop);
+	g_return_val_if_fail (lpb != NULL, NULL);
 
-			completed.hour = completed.minute = completed.second = 0; completed.is_date = completed.is_utc = 1;
-			tt = icaltime_as_timet (completed);
-			set_named_datetime_value (PidLidTaskDateCompleted, tt);
-		}
+	/* MSDN docs: the globalID must have an even number of bytes */
+	if ((cb) % 2 != 0)
+		return NULL;
 
-		/* Start */
-		dtstart.hour = dtstart.minute = dtstart.second = 0; dtstart.is_date = dtstart.is_utc = 1;
-		tt = icaltime_as_timet (dtstart);
-		if (!icaltime_is_null_time (dtstart)) {
-			set_named_datetime_value (PidLidTaskStartDate, tt);
-		}
+	ptr = lpb;
 
-		/* Due */
-		dtend.hour = dtend.minute = dtend.second = 0; dtend.is_date = dtend.is_utc = 1;
-		tt = icaltime_as_timet (dtend);
-		if (!icaltime_is_null_time (dtend)) {
-			set_named_datetime_value (PidLidTaskDueDate, tt);
-		}
+	/* starting seq - len = 16 bytes */
+	for (i = 0, j = 0; i < cb && j < sizeof (GID_START_SEQ); i++, ptr++, j++) {
+		if (*ptr != GID_START_SEQ[j])
+			return NULL;
+	}
 
-		/* FIXME: Evolution does not support recurring tasks */
-		b = 0;
-		set_named_value (PidLidTaskFRecurring, &b);
+	/* take complete global id */
+	return g_base64_encode (lpb, cb);
+}
 
-	} else if (kind == ICAL_VJOURNAL_COMPONENT) {
-		uint32_t color = olYellow;
+/* retrieves timezone location from a timezone ID */
+static const gchar *
+get_tzid_location (const gchar *tzid, struct cal_cbdata *cbdata)
+{
+	icaltimezone *zone = NULL;
 
-		set_value (PR_MESSAGE_CLASS, IPM_STICKYNOTE);
+	if (!tzid || !*tzid || g_str_equal (tzid, "UTC"))
+		return NULL;
 
-		/* Context menu flags */
-		flag32 = 0x0110;
-		set_named_value (PidLidSideEffects, &flag32);
+	/* ask backend first, if any */
+	if (cbdata && cbdata->get_timezone)
+		zone = cbdata->get_timezone (cbdata->get_tz_data, tzid);
 
-		flag32 = 0x0300 + color;
-		set_value (PR_ICON_INDEX, &flag32);
+	if (!zone)
+		zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
 
-		flag32 = color;
-		set_named_value (PidLidNoteColor, &flag32);
+	/* the old TZID prefix used in previous versions of evolution-mapi */
+	#define OLD_TZID_PREFIX "/softwarestudio.org/Tzfile/"
 
-		/* some random value */
-		flag32 = 0x00FF;
-		set_named_value (PidLidNoteWidth, &flag32);
+	if (!zone && g_str_has_prefix (tzid, OLD_TZID_PREFIX))
+		zone = icaltimezone_get_builtin_timezone (tzid + strlen (OLD_TZID_PREFIX));
 
-		/* some random value */
-		flag32 = 0x00FF;
-		set_named_value (PidLidNoteHeight, &flag32);
-	}
+	#undef OLD_TZID_PREFIX
 
-	#undef set_value
-	#undef set_named_value
-	#undef set_datetime_value
-	#undef set_named_datetime_value
+	if (!zone)
+		return NULL;
 
-	return TRUE;
+	return icaltimezone_get_location (zone);
 }
 
+#define MINUTES_IN_HOUR 60
+#define SECS_IN_MINUTE 60
+
 static gboolean
 emcu_build_restriction (EMapiConnection *conn,
-			mapi_id_t fid,
 			TALLOC_CTX *mem_ctx,
 			struct mapi_SRestriction **restrictions,
 			gpointer user_data,
@@ -2070,7 +367,6 @@ emcu_build_restriction (EMapiConnection *conn,
 
 static gboolean
 emcu_check_id_exists_cb (EMapiConnection *conn,
-			 mapi_id_t fid,
 			 TALLOC_CTX *mem_ctx,
 			 const ListObjectsData *object_data,
 			 guint32 obj_index,
@@ -2350,60 +646,6 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
 	return TRUE;
 }
 
-/* beware, the 'data' pointer is an integer of the event kind */
-gboolean
-e_mapi_cal_utils_get_props_cb (EMapiConnection *conn,
-			       mapi_id_t fid,
-			       TALLOC_CTX *mem_ctx,
-			       struct SPropTagArray *props,
-			       gpointer data,
-			       GCancellable *cancellable,
-			       GError **perror)
-{
-	static const uint32_t cal_GetPropsList[] = {
-		PR_FID,
-		PR_MID,
-
-		PR_SUBJECT_UNICODE,
-		PR_NORMALIZED_SUBJECT_UNICODE,
-		PR_CONVERSATION_TOPIC_UNICODE,
-		PR_BODY,
-		PR_BODY_UNICODE,
-
-		PR_CREATION_TIME,
-		PR_LAST_MODIFICATION_TIME,
-		PR_PRIORITY,
-		PR_SENSITIVITY,
-		PR_START_DATE,
-		PR_END_DATE,
-		PR_RESPONSE_REQUESTED,
-		PR_OWNER_APPT_ID,
-		PR_PROCESSED,
-		PR_MSG_EDITOR_FORMAT,
-
-		PR_SENT_REPRESENTING_NAME_UNICODE,
-		PR_SENT_REPRESENTING_ADDRTYPE_UNICODE,
-		PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE,
-
-		PR_SENDER_NAME_UNICODE,
-		PR_SENDER_ADDRTYPE_UNICODE,
-		PR_SENDER_EMAIL_ADDRESS_UNICODE,
-
-		PR_RCVD_REPRESENTING_NAME_UNICODE,
-		PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE,
-		PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE
-	};
-
-	g_return_val_if_fail (conn != NULL, FALSE);
-	g_return_val_if_fail (mem_ctx != NULL, FALSE);
-	g_return_val_if_fail (props != NULL, FALSE);
-
-	if (!e_mapi_utils_add_props_to_props_array (mem_ctx, props, cal_GetPropsList, G_N_ELEMENTS (cal_GetPropsList)))
-		return FALSE;
-
-	return e_mapi_cal_utils_add_named_ids (conn, fid, mem_ctx, props, GPOINTER_TO_INT (data), cancellable, perror);
-}
-
 gchar *
 e_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp, const gchar *key)
 {
diff --git a/src/libexchangemapi/e-mapi-cal-utils.h b/src/libexchangemapi/e-mapi-cal-utils.h
index 38a5142..d4f056f 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.h
+++ b/src/libexchangemapi/e-mapi-cal-utils.h
@@ -74,50 +74,14 @@ struct cal_cbdata {
 	icaltimezone * (*get_timezone)(gpointer get_tz_data, const gchar *tzid);
 };
 
-void
-e_mapi_cal_util_fetch_organizer (ECalComponent *comp, GSList **recip_list);
-void
-e_mapi_cal_util_fetch_recipients (ECalComponent *comp, GSList **recip_list);
-void
-e_mapi_cal_util_fetch_attachments (ECalComponent *comp, GSList **attach_list, const gchar *local_store_uri);
-
-ECalComponent *
-e_mapi_cal_util_mapi_props_to_comp (EMapiConnection *conn, mapi_id_t fid, icalcomponent_kind kind, const gchar *mid, struct mapi_SPropValue_array *properties,
-					   GSList *streams, GSList *recipients, GSList *attachments,
-					   const gchar *local_store_uri, const icaltimezone *default_zone, gboolean is_reply, GSList **detached_components);
-
-void
-e_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, const struct timeval *exception_replace_time, const struct FILETIME *creation_time, struct Binary_r *sb);
-
-gchar *
-e_mapi_cal_util_camel_helper (EMapiConnection *conn, mapi_id_t fid, mapi_id_t mid, mapi_object_t *obj_message, const gchar *msg_class,
-				   GSList *streams, GSList *recipients, GSList *attachments);
-
-uint32_t
-e_mapi_cal_util_get_new_appt_id (EMapiConnection *conn, mapi_id_t fid);
-
-gboolean	e_mapi_cal_utils_add_named_ids			(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 TALLOC_CTX *mem_ctx,
-								 struct SPropTagArray *props,
-								 gint pkind,
-								 GCancellable *cancellable,
-								 GError **perror);
-gboolean	e_mapi_cal_utils_get_props_cb			(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 TALLOC_CTX *mem_ctx,
-								 struct SPropTagArray *props,
-								 gpointer data,
-								 GCancellable *cancellable,
-								 GError **perror);
-gboolean	e_mapi_cal_utils_write_props_cb			(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 TALLOC_CTX *mem_ctx,
-								 struct SPropValue **values,
-								 uint32_t *n_values,
-								 gpointer data,
-								 GCancellable *cancellable,
-								 GError **perror);
+void		e_mapi_cal_util_generate_globalobjectid		(gboolean is_clean,
+								 const gchar *uid,
+								 const struct timeval *exception_replace_time,
+								 const struct FILETIME *creation_time,
+								 struct Binary_r *sb);
+
+uint32_t	e_mapi_cal_util_get_new_appt_id			(EMapiConnection *conn,
+								 mapi_id_t fid);
 
 gboolean	e_mapi_cal_utils_get_free_busy_data		(EMapiConnection *conn,
 								 const GSList *users,
@@ -142,7 +106,8 @@ gboolean	e_mapi_cal_utils_comp_to_object			(EMapiConnection *conn,
 								 GCancellable *cancellable,
 								 GError **perror);
 
-gchar *	e_mapi_cal_utils_get_icomp_x_prop (icalcomponent *comp, const gchar *key);
+gchar *		e_mapi_cal_utils_get_icomp_x_prop		(icalcomponent *comp,
+								 const gchar *key);
 
 G_END_DECLS
 
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index ae94799..b1d2f54 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -616,4491 +616,2636 @@ e_mapi_connection_connected (EMapiConnection *conn)
 	return priv->session != NULL;
 }
 
-/* proptag should be already set for this stream */
-static void
-set_stream_value (ExchangeMAPIStream *stream, const uint32_t *cpid, const guint8 *buf_data, guint32 buf_len, gboolean converted)
+static gboolean
+may_skip_property (uint32_t proptag)
 {
-	g_return_if_fail (stream != NULL);
-
-	stream->value = NULL;
-
-	if (!converted && (stream->proptag == PR_HTML || (stream->proptag & 0xFFFF) == PT_UNICODE) && ((cpid && (*cpid == 1200 || *cpid == 1201)) || (buf_len > 5 && buf_data[3] == '\0'))) {
-		/* this is special, get the CPID and transform to utf8 when it's utf16 */
-		gsize written = 0;
-		gchar *in_utf8;
-
-		/* skip Unicode marker, if there */
-		if (buf_len >= 2 && buf_data[0] == 0xFF && buf_data[1] == 0xFE)
-			in_utf8 = g_convert ((const gchar *) buf_data + 2, buf_len - 2, "UTF-8", "UTF-16", NULL, &written, NULL);
-		else
-			in_utf8 = g_convert ((const gchar *) buf_data, buf_len, "UTF-8", "UTF-16", NULL, &written, NULL);
-
-		if (in_utf8 && written > 0) {
-			stream->value = g_byte_array_sized_new (written + 1);
-			g_byte_array_append (stream->value, (const guint8 *) in_utf8, written);
+	/* skip all "strange" properties */
+	gboolean skip = TRUE;
 
-			if (in_utf8[written] != '\0')
-				g_byte_array_append (stream->value, (const guint8 *) "", 1);
-		}
+	switch (proptag & 0xFFFF) {
+	case PT_BOOLEAN:
+	case PT_I2:
+	case PT_LONG:
+	case PT_DOUBLE:
+	case PT_I8:
+	case PT_STRING8:
+	case PT_UNICODE:
+	case PT_SYSTIME:
+	case PT_BINARY:
+	case PT_ERROR:
+	case PT_CLSID:
+	case PT_SVREID:
+	case PT_MV_STRING8:
+	case PT_MV_UNICODE:
+	case PT_MV_BINARY:
+	case PT_MV_LONG:
+		skip = FALSE;
+		break;
+	default:
+		break;
 	}
 
-	if (!stream->value) {
-		stream->value = g_byte_array_sized_new (buf_len);
-		g_byte_array_append (stream->value, buf_data, buf_len);
-	}
+	return skip;
 }
 
-/* returns whether found that property */
-static gboolean
-add_stream_from_properties (GSList **stream_list, struct mapi_SPropValue_array *properties, uint32_t proptag, const uint32_t *cpid)
+gboolean
+e_mapi_connection_fetch_gal (EMapiConnection *conn,
+			     BuildRestrictionsCB build_rs_cb,
+			     gpointer build_rs_cb_data,
+			     BuildReadPropsCB build_props,
+			     gpointer brp_data,
+			     FetchGALCallback cb,
+			     gpointer data,
+			     GCancellable *cancellable,
+			     GError **perror)
 {
-	if (e_mapi_util_find_stream (*stream_list, proptag)) {
-		return TRUE;
-	} else if (properties) {
-		gconstpointer data;
-
-		data = e_mapi_util_find_array_propval (properties, proptag);
-		if (data) {
-			const struct SBinary_short *bin;
-			const gchar *str;
-			ExchangeMAPIStream *stream;
-
-			switch (proptag & 0xFFFF) {
-			case PT_BINARY:
-				bin = data;
-				if (bin->cb) {
-					stream = g_new0 (ExchangeMAPIStream, 1);
+	struct SPropTagArray	*propsTagArray;
+	struct SRowSet		*aRowSet;
+	enum MAPISTATUS		ms;
+	uint32_t		i, count, n_rows = 0;
+	uint8_t			ulFlags;
+	TALLOC_CTX *mem_ctx;
 
-					stream->proptag = proptag;
-					set_stream_value (stream, cpid, bin->lpb, bin->cb, FALSE);
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (build_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-					*stream_list = g_slist_append (*stream_list, stream);
-				}
+	mem_ctx = talloc_new (priv->session);
 
-				return TRUE;
-			case PT_STRING8:
-			case PT_UNICODE:
-				str = data;
-				stream = g_new0 (ExchangeMAPIStream, 1);
+	LOCK ();
 
-				stream->proptag = proptag;
-				set_stream_value (stream, cpid, (const guint8 *) str, strlen (str) + 1, FALSE);
+	ms = GetGALTableCount (priv->session, &n_rows);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "GetGALTableCount", ms);
+		n_rows = 0;
+	}
 
-				*stream_list = g_slist_append (*stream_list, stream);
+	propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
+	if (!build_props (conn, 0, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
+		make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+		UNLOCK();
+		talloc_free (mem_ctx);
+		return FALSE;
+	}
 
-				return TRUE;
+	ms = MAPI_E_SUCCESS;
+	count = 0;
+	ulFlags = TABLE_START;
+	while (ms == MAPI_E_SUCCESS) {
+		aRowSet = NULL;
+		/* fetch per 100 items */
+		ms = GetGALTable (priv->session, propsTagArray, &aRowSet, 100, ulFlags);
+		if ((!aRowSet) || (!(aRowSet->aRow)) || ms != MAPI_E_SUCCESS) {
+			break;
+		}
+		if (aRowSet->cRows) {
+			global_unlock ();
+			for (i = 0; i < aRowSet->cRows; i++, count++) {
+				if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data, cancellable, perror)) {
+					ms = MAPI_E_RESERVED;
+					break;
+				}
 			}
+			global_lock ();
+		} else {
+			talloc_free (aRowSet);
+			break;
 		}
+
+		ulFlags = TABLE_CUR;
+		talloc_free (aRowSet);
 	}
 
-	return FALSE;
+	talloc_free (mem_ctx);
+
+	UNLOCK ();
+
+	if (ms != MAPI_E_SUCCESS && ms != MAPI_E_RESERVED)
+		make_mapi_error (perror, "GetGALTable", ms);
+
+	return ms == MAPI_E_SUCCESS;
 }
 
-static gboolean
-e_mapi_util_read_generic_stream (TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, const uint32_t *cpid, uint32_t proptag, GSList **stream_list, struct mapi_SPropValue_array *properties, GError **perror)
+gboolean
+e_mapi_connection_get_public_folder (EMapiConnection *conn,
+				     mapi_object_t *obj_store,
+				     GCancellable *cancellable,
+				     GError **perror)
 {
-	enum MAPISTATUS	ms;
-	mapi_object_t	obj_stream;
-	uint16_t	cn_read = 0, max_read;
-	uint32_t	off_data = 0;
-	uint8_t		*buf_data = NULL;
-	uint32_t	buf_size = 0;
-	gboolean	done = FALSE;
-
-	/* sanity */
-	e_return_val_mapi_error_if_fail (obj_message, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (((proptag & 0xFFFF) == PT_BINARY) || ((proptag & 0xFFFF) == PT_STRING8 || ((proptag & 0xFFFF) == PT_UNICODE)), MAPI_E_INVALID_PARAMETER, FALSE);
-
-	/* if compressed RTF stream, then return */
-	if (proptag == PR_RTF_COMPRESSED)
-		return FALSE;
+	enum MAPISTATUS ms;
 
-	if (add_stream_from_properties (stream_list, properties, proptag, cpid))
-		return TRUE;
+	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_mapi_debug_print("Attempt to read stream for proptag 0x%08X ", proptag);
+	LOCK ();
 
-	mapi_object_init(&obj_stream);
+	mapi_object_init (&priv->public_store);
 
-	/* get a stream on specified proptag */
-	ms = OpenStream(obj_message, proptag, STREAM_ACCESS_READ, &obj_stream);
-	if (ms != MAPI_E_SUCCESS) {
-	/* If OpenStream failed, should we attempt any other call(s) to fetch the blob? */
-		make_mapi_error (perror, "OpenStream", ms);
-		goto cleanup;
-	}
+	ms = OpenPublicFolder (priv->session, &priv->public_store);
 
-	/* NOTE: This may prove unreliable for streams larger than 4GB length */
-	ms = GetStreamSize(&obj_stream, &buf_size);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetStreamSize", ms);
-		goto cleanup;
+		make_mapi_error (perror, "OpenPublicFolder", ms);
 	}
 
-	buf_data = talloc_size (mem_ctx, buf_size);
-	if (!buf_data)
-		goto cleanup;
+	*obj_store = priv->public_store;
+	UNLOCK ();
 
-	/* determine max_read first, to read by chunks as long as possible */
-	max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
-	do {
-		ms = ReadStream (&obj_stream, (buf_data) + off_data, max_read, &cn_read);
-		if (ms == MAPI_E_SUCCESS) {
-			if (cn_read == 0) {
-				done = TRUE;
-			} else {
-				off_data += cn_read;
-				if (off_data >= buf_size)
-					done = TRUE;
-			}
-			break;
-		}
+	return ms == MAPI_E_SUCCESS;
+}
 
-		if (ms == 0x2c80)
-			max_read = max_read >> 1;
-		else
-			max_read = STREAM_MAX_READ_SIZE_DF;
+static enum MAPISTATUS
+open_folder (EMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 fid_options, mapi_object_t *obj_folder, GError **perror)
+{
+	enum MAPISTATUS ms;
 
-		if (max_read < STREAM_MAX_READ_SIZE_DF)
-			max_read = STREAM_MAX_READ_SIZE_DF;
-	} while (ms == 0x2c80); /* an error when max_read is too large? */
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+	e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
 
-	/* Read from the stream */
-	while (!done) {
-		ms = ReadStream (&obj_stream, (buf_data) + off_data, max_read, &cn_read);
+	if (*fid == 0) {
+		ms = GetDefaultFolder (&priv->msg_store, fid, olFolder);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "ReadStream", ms);
-			done = TRUE;
-		} else if (cn_read == 0) {
-			done = TRUE;
-		} else {
-			off_data += cn_read;
-			if (off_data >= buf_size)
-				done = TRUE;
+			make_mapi_error (perror, "GetDefaultFolder", ms);
+			return ms;
 		}
-	}
-
-	if (ms == MAPI_E_SUCCESS) {
-		ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
 
-		stream->proptag = proptag;
-		set_stream_value (stream, cpid, buf_data, off_data, FALSE);
-
-		e_mapi_debug_print("Attempt succeeded for proptag 0x%08X (after name conversion) ", stream->proptag);
-
-		*stream_list = g_slist_append (*stream_list, stream);
+		fid_options = 0;
 	}
 
-cleanup:
-	mapi_object_release(&obj_stream);
+	if ((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0) {
+		if (!ensure_public_store (priv, perror)) {
+			return MAPI_E_CALL_FAILED;
+		}
+	}
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	ms = OpenFolder (((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0 ? &priv->public_store : &priv->msg_store), *fid, obj_folder);
+	if (ms != MAPI_E_SUCCESS)
+		make_mapi_error (perror, "OpenFolder", ms);
 
-	return (ms == MAPI_E_SUCCESS);
+	return ms;
 }
 
-static void
-e_mapi_util_read_body_stream (TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList **stream_list, struct mapi_SPropValue_array *properties, gboolean by_best_body)
+gboolean
+e_mapi_connection_open_default_folder (EMapiConnection *conn,
+				       uint32_t olFolderIdentifier,
+				       mapi_object_t *obj_folder,
+				       GCancellable *cancellable,
+				       GError **perror)
 {
-	const uint32_t *cpid = e_mapi_util_find_array_propval (properties, PR_INTERNET_CPID);
-	gboolean can_html = FALSE, has_body = FALSE, has_body_unicode;
+	enum MAPISTATUS ms;
+	mapi_id_t fid = 0;
+	gboolean res;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	has_body_unicode = add_stream_from_properties (stream_list, properties, PR_BODY_UNICODE, cpid);
-	if (!has_body_unicode)
-		has_body = add_stream_from_properties (stream_list, properties, PR_BODY, cpid);
+	LOCK ();
 
-	if (by_best_body) {
-		uint8_t best_body = 0;
+	mapi_object_init (obj_folder);
 
-		can_html = GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML;
-	} else {
-		const uint32_t *ui32 = e_mapi_util_find_array_propval (properties, PR_MSG_EDITOR_FORMAT);
-		can_html = ui32 && *ui32 == olEditorHTML;
+	ms = GetDefaultFolder (&priv->msg_store, &fid, olFolderIdentifier);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "GetDefaultFolder", ms);
+		UNLOCK ();
+		return FALSE;
+	}
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		UNLOCK ();
+		return FALSE;
 	}
 
-	if (can_html)
-		e_mapi_util_read_generic_stream (mem_ctx, obj_message, cpid, PR_HTML, stream_list, properties, NULL);
+	res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
 
-	if (!has_body_unicode)
-		has_body_unicode = e_mapi_util_read_generic_stream (mem_ctx, obj_message, cpid, PR_BODY_UNICODE, stream_list, properties, NULL);
+	UNLOCK ();
 
-	if (!has_body && !has_body_unicode)
-		e_mapi_util_read_generic_stream (mem_ctx, obj_message, cpid, PR_BODY, stream_list, properties, NULL);
+	return res;
 }
 
-/* Returns TRUE if all streams were written succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_write_generic_streams (mapi_object_t *obj_message, GSList *stream_list, GError **perror)
+gboolean
+e_mapi_connection_open_personal_folder (EMapiConnection *conn,
+					mapi_id_t fid,
+					mapi_object_t *obj_folder,
+					GCancellable *cancellable,
+					GError **perror)
 {
-	GSList		*l;
-	enum MAPISTATUS	ms;
-	gboolean	status = TRUE;
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
-	for (l = stream_list; l; l = l->next) {
-		ExchangeMAPIStream	*stream = (ExchangeMAPIStream *) (l->data);
-		uint32_t		total_written;
-		gboolean		done = FALSE;
-		mapi_object_t		obj_stream;
+	enum MAPISTATUS ms;
 
-		mapi_object_init(&obj_stream);
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		/* OpenStream on required proptag */
-		ms = OpenStream (obj_message, stream->proptag, STREAM_ACCESS_READWRITE, &obj_stream);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "OpenStream", ms);
-			goto cleanup;
-		}
+	LOCK ();
 
-		/* Set the stream size */
-		ms = SetStreamSize (&obj_stream, stream->value->len);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SetStreamSize", ms);
-			goto cleanup;
-		}
+	mapi_object_init (obj_folder);
 
-		total_written = 0;
-		/* Write attachment */
-		while (!done) {
-			uint16_t	cn_written = 0;
-			DATA_BLOB	blob;
+	ms = OpenFolder (&priv->msg_store, fid, obj_folder);
+	if (ms != MAPI_E_SUCCESS)
+		make_mapi_error (perror, "OpenFolder", ms);
 
-			blob.length = (stream->value->len - total_written) < STREAM_MAX_WRITE_SIZE ?
-					(stream->value->len - total_written) : STREAM_MAX_WRITE_SIZE;
-			blob.data = (stream->value->data) + total_written;
+	UNLOCK ();
 
-			ms = WriteStream (&obj_stream, &blob, &cn_written);
+	return ms == MAPI_E_SUCCESS;
+}
 
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "WriteStream", ms);
-				done = TRUE;
-			} else if (cn_written == 0) {
-				done = TRUE;
-			} else {
-				total_written += cn_written;
-				if (total_written >= stream->value->len)
-					done = TRUE;
-			}
-		}
-
-		/* Commit the stream */
-		ms = CommitStream (&obj_stream);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "CommitStream", ms);
-			goto cleanup;
-		}
-
-	cleanup:
-		if (ms != MAPI_E_SUCCESS)
-			status = FALSE;
-		mapi_object_release(&obj_stream);
-	}
-
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return status;
-}
-
-static void
-set_recipient_properties (TALLOC_CTX *mem_ctx, struct SRow *aRow, ExchangeMAPIRecipient *recipient, gboolean is_external)
-{
-	uint32_t i;
-
-	if (is_external && recipient->in.ext_lpProps) {
-	/* FIXME: Setting PR_ENTRYID property seems to create problems for now. We should take
-	 * another look at this after the CreateOneoffEntryId API is provided by LibMAPI. */
-#if 0
-		struct Binary_r oneoff_eid;
-		struct SPropValue sprop;
-		const gchar *dn = NULL, *email = NULL;
-
-		dn = (const gchar *) e_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_DISPLAY_NAME_UNICODE);
-		dn = (dn) ? dn : "";
-		email = (const gchar *) e_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_SMTP_ADDRESS_UNICODE);
-		email = (email) ? email : "";
-		e_mapi_util_recip_entryid_generate_smtp (mem_ctx, &oneoff_eid, dn, email);
-		set_SPropValue_proptag (&sprop, PR_ENTRYID, (gconstpointer )(oneoff_eid));
-		SRow_addprop (aRow, sprop);
-#endif
-
-	/* Now, add the properties which are specified for unresolved recipients alone. */
-		for (i = 0; i < recipient->in.ext_cValues; ++i)
-			SRow_addprop (aRow, recipient->in.ext_lpProps[i]);
-	}
-
-	/* Now, add the properties which are specified for each recipient
-	 * irrespective of whether it was resolved or not. */
-	for (i = 0; i < recipient->in.req_cValues; ++i)
-		SRow_addprop (aRow, recipient->in.req_lpProps[i]);
-}
-
-static gboolean
-e_mapi_util_modify_recipients (EMapiConnection *conn, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message , GSList *recipients, gboolean remove_existing, GError **perror)
+gboolean
+e_mapi_connection_open_public_folder (EMapiConnection *conn,
+				      mapi_id_t fid,
+				      mapi_object_t *obj_folder,
+				      GCancellable *cancellable,
+				      GError **perror)
 {
-	enum MAPISTATUS	ms;
-	struct SPropTagArray	*SPropTagArray = NULL;
-	struct SRowSet		*SRowSet = NULL;
-	struct PropertyTagArray_r *FlagList = NULL;
-	GSList			*l;
-	const gchar		**users = NULL;
-	uint32_t		i, j, count = 0;
+	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_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
-	SPropTagArray = set_SPropTagArray(mem_ctx, 0xA,
-					  PR_ENTRYID,
-					  PR_DISPLAY_NAME_UNICODE,
-					  PR_OBJECT_TYPE,
-					  PR_DISPLAY_TYPE,
-					  PR_TRANSMITTABLE_DISPLAY_NAME_UNICODE,
-					  PR_EMAIL_ADDRESS_UNICODE,
-					  PR_ADDRTYPE_UNICODE,
-					  PR_SEND_RICH_INFO,
-					  PR_7BIT_DISPLAY_NAME_UNICODE,
-					  PR_SMTP_ADDRESS_UNICODE);
-
-	count = g_slist_length (recipients);
-	users = g_new0 (const gchar *, count + 1);
-
-	for (i = 0, l = recipients; (i < count && l != NULL); ++i, l = l->next) {
-		ExchangeMAPIRecipient *recipient = (ExchangeMAPIRecipient *)(l->data);
-		users[i] = recipient->email_id;
-	}
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	/* Attempt to resolve names from the server */
 	LOCK ();
-	ms = ResolveNames (priv->session, users, SPropTagArray, &SRowSet, &FlagList, MAPI_UNICODE);
-	UNLOCK ();
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "ResolveNames", ms);
-		goto cleanup;
-	}
-
-	g_assert (count == FlagList->cValues);
-
-	if (!SRowSet) /* This happens when there are ZERO RESOLVED recipients */
-		SRowSet = talloc_zero(mem_ctx, struct SRowSet);
-
-	for (i = 0, l = recipients, j = 0; (i < count && l != NULL); ++i, l = l->next) {
-		ExchangeMAPIRecipient *recipient = (ExchangeMAPIRecipient *)(l->data);
-		uint32_t last;
 
-		if (FlagList->aulPropTag[i] == MAPI_AMBIGUOUS) {
-			/* We should never get an ambiguous resolution as we use the email-id for resolving.
-			 * However, if we do still get an ambiguous entry, we can't handle it :-( */
-			e_mapi_debug_print ("%s: %s() - '%s' is ambiguous ", G_STRLOC, G_STRFUNC, recipient->email_id);
-			ms = MAPI_E_AMBIGUOUS_RECIP;
-			/* Translators: %s is replaced with an email address which was found ambiguous on a remote server */
-			g_set_error (perror, E_MAPI_ERROR, ms, _("Recipient '%s' is ambiguous"), recipient->email_id);
-			goto cleanup;
-		} else if (FlagList->aulPropTag[i] == MAPI_UNRESOLVED) {
-			/* If the recipient is unresolved, consider it is a SMTP one */
-			SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 1);
-			last = SRowSet->cRows;
-			SRowSet->aRow[last].cValues = 0;
-			SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
-			set_recipient_properties(mem_ctx, &SRowSet->aRow[last], recipient, TRUE);
-			SRowSet->cRows += 1;
-		} else if (FlagList->aulPropTag[i] == MAPI_RESOLVED) {
-			set_recipient_properties (mem_ctx, &SRowSet->aRow[j], recipient, FALSE);
-			j += 1;
-		}
+	if (!ensure_public_store (priv, perror)) {
+		UNLOCK ();
+		return FALSE;
 	}
 
-	if (remove_existing) {
-		ms = RemoveAllRecipients (obj_message);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "RemoveAllRecipients", ms);
-			goto cleanup;
-		}
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		UNLOCK ();
+		return FALSE;
 	}
 
-	/* Modify the recipient table */
-	ms = ModifyRecipients (obj_message, SRowSet);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "ModifyRecipients", ms);
-		goto cleanup;
-	}
+	mapi_object_init (obj_folder);
 
-cleanup:
-	g_free (users);
+	ms = OpenFolder (&priv->public_store, fid, obj_folder);
+	if (ms != MAPI_E_SUCCESS)
+		make_mapi_error (perror, "OpenFolder", ms);
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	UNLOCK ();
 
 	return ms == MAPI_E_SUCCESS;
 }
 
-static gboolean
-e_mapi_util_delete_attachments (TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GError **perror)
+gboolean
+e_mapi_connection_close_folder (EMapiConnection *conn,
+				mapi_object_t *obj_folder,
+				GCancellable *cancellable,
+				GError **perror)
 {
-	enum MAPISTATUS		ms;
-	mapi_object_t		obj_tb_attach;
-	struct SPropTagArray	*proptags;
-	struct SRowSet		rows_attach;
-	uint32_t		attach_count;
-	uint32_t		i_row_attach;
-	gboolean		status = TRUE;
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
-	proptags = set_SPropTagArray(mem_ctx, 0x4,
-				     PR_ATTACH_NUM,
-				     PR_INSTANCE_KEY,
-				     PR_RECORD_KEY,
-				     PR_RENDERING_POSITION);
-
-	mapi_object_init(&obj_tb_attach);
-
-	/* open attachment table */
-	ms = GetAttachmentTable (obj_message, &obj_tb_attach);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetAttachmentTable", ms);
-		goto cleanup;
-	}
-
-	ms = SetColumns (&obj_tb_attach, proptags);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetColumns", ms);
-		goto cleanup;
-	}
-
-	ms = QueryPosition (&obj_tb_attach, NULL, &attach_count);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "QueryPosition", ms);
-		goto cleanup;
-	}
-
-	if (!attach_count)
-		goto cleanup;
-
-	ms = QueryRows (&obj_tb_attach, attach_count, TBL_ADVANCE, &rows_attach);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "QueryRows", ms);
-		goto cleanup;
-	}
-
-	/* foreach attachment, delete by PR_ATTACH_NUM */
-	for (i_row_attach = 0; i_row_attach < rows_attach.cRows; i_row_attach++) {
-		const uint32_t	*num_attach;
-
-		num_attach = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_NUM);
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		ms = DeleteAttach (obj_message, *num_attach);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "DeleteAttach", ms);
-			status = FALSE;
-		}
-	}
+	LOCK ();
 
-cleanup:
-	if (ms != MAPI_E_SUCCESS)
-		status = FALSE;
-	mapi_object_release(&obj_tb_attach);
+	mapi_object_release (obj_folder);
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	UNLOCK ();
 
-	return status;
+	return TRUE;
 }
 
-/* Returns TRUE if all attachments were written succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_set_attachments (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList *attach_list, gboolean remove_existing, GError **perror)
+/* 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,
+					 gpointer cb_user_data,
+					 GCancellable *cancellable,
+					 GError **perror)
 {
-	GSList		*l;
-	enum MAPISTATUS	ms;
-	gboolean	status = FALSE;
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+	enum MAPISTATUS ms;
+	TALLOC_CTX *mem_ctx;
+	struct SPropTagArray *spropTagArray = NULL;
+	struct mapi_SPropValue_array *properties = NULL;
+	gboolean res = FALSE;
 
-	if (remove_existing)
-		e_mapi_util_delete_attachments (mem_ctx, obj_message, 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 (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	for (l = attach_list; l; l = l->next) {
-		ExchangeMAPIAttachment *attachment = (ExchangeMAPIAttachment *) (l->data);
-		mapi_object_t		obj_attach;
+	LOCK ();
+	mem_ctx = talloc_new (priv->session);
 
-		mapi_object_init(&obj_attach);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		goto cleanup;
 
-		/* CreateAttach */
-		ms = CreateAttach (obj_message, &obj_attach);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "CreateAttach", ms);
+	spropTagArray = set_SPropTagArray (mem_ctx, 3, PidTagFolderId, PidTagLastModificationTime, PidTagContentCount);
+	if (brp_cb) {
+		if (!brp_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, spropTagArray, brp_cb_user_data, cancellable, perror)) {
 			goto cleanup;
 		}
+	} else {
+		talloc_free (spropTagArray);
+		spropTagArray = NULL;
+	}
 
-		if (attachment->mail) {
-			struct SPropValue *props = NULL;
-			uint32_t propslen = 0, ui32;
-			MailItem *item = attachment->mail;
-			mapi_object_t obj_emb_msg;
-
-			ui32 = ATTACH_EMBEDDED_MSG;
-			e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_METHOD, &ui32);
-			ui32 = 0;
-			e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_RENDERING_POSITION, &ui32);
-			e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_MIME_TAG, "message/rfc822");
-			if (item->header.subject)
-				e_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_FILENAME_UNICODE, item->header.subject);
+	properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
+	if (spropTagArray && spropTagArray->cValues) {
+		struct SPropValue *lpProps;
+		uint32_t prop_count = 0, k, ll;
+		ResolveNamedIDsData *named_ids_list = NULL;
+		guint named_ids_len = 0;
 
-			/* set properties for the item */
-			ms = SetProps (&obj_attach, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "SetProps", ms);
-				goto cleanup;
-			}
+		lpProps = talloc_zero (mem_ctx, struct SPropValue);
 
-			props = NULL;
-			propslen = 0;
+		for (k = 0; k < spropTagArray->cValues; k++) {
+			uint32_t proptag = spropTagArray->aulPropTag[k];
 
-			mapi_object_init (&obj_emb_msg);
+			if (may_skip_property (proptag)) {
+				const gchar *name = get_proptag_name (proptag);
+				if (!name)
+					name = "";
 
-			ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "OpenEmbeddedMessage", ms);
-				goto cleanup;
+				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 (ResolveNamedIDsData, 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++;
 			}
+		}
 
-			if (!mapi_mail_utils_create_item_build_props (conn, fid, mem_ctx, &props, &propslen, item, NULL, perror)) {
-				make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+		if (named_ids_list) {
+			if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
+				g_free (named_ids_list);
 				goto cleanup;
 			}
 
-			/* set properties for the item */
-			ms = SetProps (&obj_emb_msg, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
-			if (ms != MAPI_E_SUCCESS) {
-				mapi_object_release (&obj_emb_msg);
-				make_mapi_error (perror, "SetProps", ms);
+			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+				g_free (named_ids_list);
 				goto cleanup;
 			}
 
-			if (item->generic_streams) {
-				if (!e_mapi_util_write_generic_streams (&obj_emb_msg, item->generic_streams, perror)) {
-					mapi_object_release (&obj_emb_msg);
-					goto cleanup;
-				}
-			}
-
-			/* Set attachments if any */
-			if (item->attachments) {
-				if (!e_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_emb_msg, item->attachments, FALSE, perror)) {
-					mapi_object_release (&obj_emb_msg);
-					goto cleanup;
-				}
-			}
-
-			/* Set recipients if any */
-			if (item->recipients) {
-				if (!e_mapi_util_modify_recipients (conn, mem_ctx, &obj_emb_msg, item->recipients, FALSE, perror)) {
-					mapi_object_release (&obj_emb_msg);
-					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++;
+					}
 				}
 			}
-
-			ms = SaveChangesMessage (&obj_attach, &obj_emb_msg, KeepOpenReadOnly);
-			if (ms != MAPI_E_SUCCESS) {
-				mapi_object_release (&obj_emb_msg);
-				make_mapi_error (perror, "SaveChangesMessage", ms);
-				goto cleanup;
-			}
-
-			mapi_object_release (&obj_emb_msg);
-		} else {
-			/* SetProps */
-			ms = SetProps (&obj_attach, MAPI_PROPS_SKIP_NAMEDID_CHECK, attachment->lpProps, attachment->cValues);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "SetProps", ms);
-				goto cleanup;
-			}
-
-			/* If there are any streams to be set, write them. */
-			if (!e_mapi_util_write_generic_streams (&obj_attach, attachment->streams, perror))
-				goto cleanup;
 		}
 
-		/* message->SaveChangesAttachment() */
-		ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
+		ms = GetProps (obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, spropTagArray, &lpProps, &prop_count);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SaveChangesAttachment", ms);
+			make_mapi_error (perror, "GetProps", ms);
+			g_free (named_ids_list);
 			goto cleanup;
 		}
 
-		status = TRUE;
-
-	cleanup:
-		mapi_object_release(&obj_attach);
-	}
-
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return status;
-}
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			g_free (named_ids_list);
+			goto cleanup;
+		}
 
-static GByteArray *
-obj_message_to_camel_mime (EMapiConnection *conn, mapi_id_t fid, mapi_object_t *obj_msg)
-{
-	GByteArray *res = NULL;
-	MailItem *item = NULL;
-	CamelMimeMessage *msg;
-
-	g_return_val_if_fail (conn != NULL, NULL);
-	g_return_val_if_fail (obj_msg != NULL, NULL);
+		/* 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);
+		for (k = 0, ll = 0; k < prop_count; k++, ll++) {
+			if (may_skip_property (lpProps[k].ulPropTag)) {
+				ll--;
+				properties->cValues--;
+			} else {
+				if (named_ids_list) {
+					guint m;
 
-	if (!e_mapi_connection_fetch_object_props (conn, NULL, fid, 0, obj_msg, mapi_mail_get_item_prop_list, NULL,
-					fetch_props_to_mail_item_cb, &item,
-					MAPI_OPTIONS_FETCH_ALL | MAPI_OPTIONS_GETBESTBODY, NULL, NULL)
-	    || item == NULL) {
-		if (item)
-			mail_item_free (item);
+					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;
+						}
+					}
+				}
 
-		return NULL;
+				cast_mapi_SPropValue (mem_ctx, &properties->lpProps[ll], &lpProps[k]);
+			}
+		}
+	} else {
+		ms = GetPropsAll (obj_folder, MAPI_UNICODE, properties);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "GetPropsAll", ms);
+			goto cleanup;
+		}
 	}
 
-	msg = mapi_mail_item_to_mime_message (conn, item);
-	mail_item_free (item);
-
-	if (msg) {
-		CamelStream *mem = camel_stream_mem_new ();
-
-		res = g_byte_array_new ();
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		goto cleanup;
 
-		mem = camel_stream_mem_new ();
-		camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), res);
-		camel_data_wrapper_write_to_stream_sync (
-			CAMEL_DATA_WRAPPER (msg), mem, NULL, NULL);
+	res = cb (conn, mem_ctx, properties, cb_user_data, cancellable, perror);
 
-		g_object_unref (mem);
-		g_object_unref (msg);
-	}
+ cleanup:
+	talloc_free (spropTagArray);
+	talloc_free (properties);
+	talloc_free (mem_ctx);
+	UNLOCK();
 
 	return res;
 }
 
-static gboolean
-may_skip_property (uint32_t proptag)
-{
-	/* skip all "strange" properties */
-	gboolean skip = TRUE;
-
-	switch (proptag & 0xFFFF) {
-	case PT_BOOLEAN:
-	case PT_I2:
-	case PT_LONG:
-	case PT_DOUBLE:
-	case PT_I8:
-	case PT_STRING8:
-	case PT_UNICODE:
-	case PT_SYSTIME:
-	case PT_BINARY:
-	case PT_ERROR:
-	case PT_CLSID:
-	case PT_SVREID:
-	case PT_MV_STRING8:
-	case PT_MV_UNICODE:
-	case PT_MV_BINARY:
-	case PT_MV_LONG:
-		skip = FALSE;
-		break;
-	default:
-		break;
-	}
-
-	return skip;
-}
+typedef gboolean (*ForeachTableRowCB)	(EMapiConnection *conn,
+					 TALLOC_CTX *mem_ctx,
+					 struct SRow *srow,
+					 guint32 row_index,
+					 guint32 rows_total,
+					 gpointer user_data,
+					 GCancellable *cancellable,
+					 GError **perror);
 
-/* Returns TRUE if all attachments were read succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_get_attachments (EMapiConnection *conn,
-			     mapi_id_t fid,
-			     TALLOC_CTX *mem_ctx,
-			     mapi_object_t *obj_message,
-			     GSList **attach_list,
-			     GError **perror)
+static enum MAPISTATUS
+foreach_tablerow (EMapiConnection *conn,
+		  TALLOC_CTX *mem_ctx,
+		  mapi_object_t *obj_table,
+		  ForeachTableRowCB cb,
+		  gpointer user_data,
+		  GCancellable *cancellable,
+		  GError **perror)
 {
-	enum MAPISTATUS		ms;
-	mapi_object_t		obj_tb_attach;
-	struct SPropTagArray	*proptags;
-	struct SRowSet		rows_attach;
-	uint32_t		attach_count;
-	uint32_t		i_row_attach;
-	gboolean		status = TRUE;
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
-	proptags = set_SPropTagArray(mem_ctx, 0x5,
-				     PR_ATTACH_NUM,
-				     PR_INSTANCE_KEY,
-				     PR_RECORD_KEY,
-				     PR_RENDERING_POSITION,
-				     PR_ATTACH_METHOD);
-
-	mapi_object_init(&obj_tb_attach);
-
-	/* open attachment table */
-	ms = GetAttachmentTable (obj_message, &obj_tb_attach);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetAttachmentTable", ms);
-		goto cleanup;
-	}
-
-	ms = SetColumns (&obj_tb_attach, proptags);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetColumns", ms);
-		goto cleanup;
-	}
-
-	ms = QueryPosition (&obj_tb_attach, NULL, &attach_count);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "QueryPosition", ms);
-		goto cleanup;
-	}
-
-	if (!attach_count)
-		goto cleanup;
-
-	ms = QueryRows (&obj_tb_attach, attach_count, TBL_ADVANCE, &rows_attach);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "QueryRows", ms);
-		goto cleanup;
-	}
-
-	/* foreach attachment, open by PR_ATTACH_NUM */
-	for (i_row_attach = 0; i_row_attach < rows_attach.cRows; i_row_attach++) {
-		ExchangeMAPIAttachment	*attachment;
-		struct mapi_SPropValue_array properties;
-		const uint32_t	*ui32;
-		mapi_object_t	obj_attach;
-		uint32_t	z, az;
-
-		mapi_object_init(&obj_attach);
+	enum MAPISTATUS ms;
+	struct SRowSet SRowSet;
+	uint32_t count, i, cursor_pos = 0;
 
-		ui32 = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_NUM);
+	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 (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_table != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		ms = OpenAttach (obj_message, *ui32, &obj_attach);
+	do {
+		/* Number of items in the container */
+		ms = QueryPosition (obj_table, &cursor_pos, &count);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "OpenAttach", ms);
-			goto loop_cleanup;
+			make_mapi_error (perror, "QueryPosition", ms);
+			break;
 		}
 
-		ms = GetPropsAll (&obj_attach, MAPI_UNICODE, &properties);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "GetPropsAll", ms);
-			goto loop_cleanup;
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			ms = MAPI_E_USER_CANCEL;
+			break;
 		}
 
-		az = 0;
-		attachment = g_new0 (ExchangeMAPIAttachment, 1);
-		attachment->cValues = properties.cValues;
-		attachment->lpProps = g_new0 (struct SPropValue, attachment->cValues + 1);
-		for (z=0; z < properties.cValues; z++) {
-			if (may_skip_property (properties.lpProps[z].ulPropTag)) {
-				attachment->cValues--;
-				continue;
-			}
-
-			cast_SPropValue (mem_ctx, &properties.lpProps[z],
-					 &(attachment->lpProps[az]));
-
-			if ((attachment->lpProps[az].ulPropTag & 0xFFFF) == PT_STRING8) {
-				struct SPropValue *lpProps;
-				struct SPropTagArray *tags;
-				uint32_t prop_count = 0;
-
-				/* prefer unicode strings, if available */
-				tags = set_SPropTagArray (mem_ctx, 0x1, (attachment->lpProps[az].ulPropTag & 0xFFFF0000) | PT_UNICODE);
-				if (MAPI_E_SUCCESS == GetProps (&obj_attach, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count) && prop_count == 1 && lpProps) {
-					if ((lpProps->ulPropTag & 0xFFFF) == PT_UNICODE)
-						attachment->lpProps[az] = *lpProps;
-				}
-				talloc_free (tags);
-			}
+		if (!count)
+			break;
 
-			az++;
+		/* Fill the table columns with data from the rows */
+		ms = QueryRows (obj_table, count, TBL_ADVANCE, &SRowSet);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "QueryRows", ms);
+			break;
 		}
 
-		/* just to get all the other streams */
-		for (z = 0; z < properties.cValues; z++) {
-			if ((properties.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY) {
-				e_mapi_util_read_generic_stream (mem_ctx, &obj_attach, e_mapi_util_find_array_propval (&properties, PR_INTERNET_CPID), properties.lpProps[z].ulPropTag, &(attachment->streams), &properties, NULL);
-			}
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			ms = MAPI_E_USER_CANCEL;
+			break;
 		}
 
-		ui32 = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_METHOD);
-		if (ui32 && *ui32 == ATTACH_BY_VALUE) {
-			e_mapi_util_read_generic_stream (mem_ctx, &obj_attach, e_mapi_util_find_array_propval (&properties, PR_INTERNET_CPID), PR_ATTACH_DATA_BIN, &(attachment->streams), &properties, NULL);
-		} else if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG) {
-			mapi_object_t obj_emb_msg;
-
-			mapi_object_init (&obj_emb_msg);
-
-			if (OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_READONLY) == MAPI_E_SUCCESS) {
-				/* very the same is in camel-mapi-folder.c, how I hate diplicating the code */
-				GByteArray *bytes;
-
-				bytes = obj_message_to_camel_mime (conn, fid, &obj_emb_msg);
-				if (bytes) {
-					ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
-
-					stream->value = bytes;
-					stream->proptag = PR_ATTACH_DATA_BIN;
+		for (i = 0; i < SRowSet.cRows && ms == MAPI_E_SUCCESS; i++) {
+			if (!cb (conn, mem_ctx, &SRowSet.aRow[i], cursor_pos + i + 1, count, user_data, cancellable, perror))
+				ms = MAPI_E_RESERVED;
+			else if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+				ms = MAPI_E_USER_CANCEL;
+		}
+	} while (cursor_pos < count && ms == MAPI_E_SUCCESS);
 
-					attachment->streams = g_slist_append (attachment->streams, stream);
-				}
-			}
+	return ms;
+}
 
-			mapi_object_release (&obj_emb_msg);
-		}
+struct ListObjectsInternalData
+{
+	ListObjectsCB cb;
+	gpointer user_data;
+};
 
-		*attach_list = g_slist_append (*attach_list, attachment);
+static gboolean
+list_objects_internal_cb (EMapiConnection *conn,
+			  TALLOC_CTX *mem_ctx,
+			  struct SRow *srow,
+			  guint32 row_index,
+			  guint32 rows_total,
+			  gpointer user_data,
+			  GCancellable *cancellable,
+			  GError **perror)
+{
+	struct ListObjectsInternalData *loi_data = user_data;
+	ListObjectsData lod;
+	const mapi_id_t	*pmid;
+	const gchar *msg_class;
+	const uint32_t *pmsg_flags;
+	const struct FILETIME *last_modified;
 
-	loop_cleanup:
-		if (ms != MAPI_E_SUCCESS)
-			status = FALSE;
-		mapi_object_release(&obj_attach);
-	}
+	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 (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (srow != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
- cleanup:
-	if (ms != MAPI_E_SUCCESS)
-		status = FALSE;
-	mapi_object_release(&obj_tb_attach);
+	pmid = get_SPropValue_SRow_data (srow, PidTagMid);
+	msg_class = get_SPropValue_SRow_data (srow, PidTagMessageClass);
+	pmsg_flags = get_SPropValue_SRow_data (srow, PidTagMessageFlags);
+	last_modified = get_SPropValue_SRow_data (srow, PidTagLastModificationTime);
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	lod.mid = pmid ? *pmid : 0;
+	lod.msg_class = msg_class;
+	lod.msg_flags = pmsg_flags ? *pmsg_flags : 0;
+	lod.last_modified = last_modified ? e_mapi_util_filetime_to_time_t (last_modified) : 0;
 
-	return status;
+	return loi_data->cb (conn, mem_ctx, &lod, row_index, rows_total, loi_data->user_data, cancellable, perror);
 }
 
-gboolean
-e_mapi_connection_fetch_gal (EMapiConnection *conn,
-			     BuildRestrictionsCB build_rs_cb,
-			     gpointer build_rs_cb_data,
-			     BuildReadPropsCB build_props,
-			     gpointer brp_data,
-			     FetchGALCallback cb,
-			     gpointer data,
-			     GCancellable *cancellable,
-			     GError **perror)
+static void
+maybe_add_named_id_tag (uint32_t proptag,
+			ResolveNamedIDsData **named_ids_list,
+			guint *named_ids_len)
 {
-	struct SPropTagArray	*propsTagArray;
-	struct SRowSet		*aRowSet;
-	enum MAPISTATUS		ms;
-	uint32_t		i, count, n_rows = 0;
-	uint8_t			ulFlags;
-	TALLOC_CTX *mem_ctx;
+	g_return_if_fail (named_ids_list != NULL);
+	g_return_if_fail (named_ids_len != NULL);
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (build_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
+		if (!*named_ids_list) {
+			*named_ids_list = g_new0 (ResolveNamedIDsData, 1);
+			*named_ids_len = 0;
+		} else {
+			*named_ids_list = g_renew (ResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
+		}
 
-	mem_ctx = talloc_new (priv->session);
+		(*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
+		(*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
+		(*named_ids_len) += 1;
+	}
+}
 
-	LOCK ();
+static void
+gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
+				    ResolveNamedIDsData **named_ids_list,
+				    guint *named_ids_len)
+{
+	guint i;
 
-	ms = GetGALTableCount (priv->session, &n_rows);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetGALTableCount", ms);
-		n_rows = 0;
-	}
+	g_return_if_fail (restriction != NULL);
+	g_return_if_fail (named_ids_list != NULL);
+	g_return_if_fail (named_ids_len != NULL);
 
-	propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
-	if (!build_props (conn, 0, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
-		make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
-		UNLOCK();
-		talloc_free (mem_ctx);
-		return FALSE;
+	switch (restriction->rt) {
+	case RES_AND:
+		for (i = 0; i < restriction->res.resAnd.cRes; i++) {
+			gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
+		}
+		break;
+	case RES_OR:
+		for (i = 0; i < restriction->res.resOr.cRes; i++) {
+			gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
+		}
+		break;
+	#ifdef HAVE_RES_NOT_SUPPORTED
+	case RES_NOT:
+		gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) restriction->res.resNot.res, named_ids_list, named_ids_len);
+		break;
+	#endif
+	case RES_CONTENT:
+		maybe_add_named_id_tag (restriction->res.resContent.ulPropTag, named_ids_list, named_ids_len);
+		maybe_add_named_id_tag (restriction->res.resContent.lpProp.ulPropTag, named_ids_list, named_ids_len);
+		break;
+	case RES_PROPERTY:
+		maybe_add_named_id_tag (restriction->res.resProperty.ulPropTag, named_ids_list, named_ids_len);
+		maybe_add_named_id_tag (restriction->res.resProperty.lpProp.ulPropTag, named_ids_list, named_ids_len);
+		break;
+	case RES_COMPAREPROPS:
+		maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag1, named_ids_list, named_ids_len);
+		maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag2, named_ids_list, named_ids_len);
+		break;
+	case RES_BITMASK:
+		maybe_add_named_id_tag (restriction->res.resBitmask.ulPropTag, named_ids_list, named_ids_len);
+		break;
+	case RES_SIZE:
+		maybe_add_named_id_tag (restriction->res.resSize.ulPropTag, named_ids_list, named_ids_len);
+		break;
+	case RES_EXIST:
+		maybe_add_named_id_tag (restriction->res.resExist.ulPropTag, named_ids_list, named_ids_len);
+		break;
 	}
+}
 
-	ms = MAPI_E_SUCCESS;
-	count = 0;
-	ulFlags = TABLE_START;
-	while (ms == MAPI_E_SUCCESS) {
-		aRowSet = NULL;
-		/* fetch per 100 items */
-		ms = GetGALTable (priv->session, propsTagArray, &aRowSet, 100, ulFlags);
-		if ((!aRowSet) || (!(aRowSet->aRow)) || ms != MAPI_E_SUCCESS) {
+static void
+maybe_replace_named_id_tag (uint32_t *pproptag,
+			    const ResolveNamedIDsData *named_ids_list,
+			    guint named_ids_len)
+{
+	gint i;
+
+	g_return_if_fail (pproptag != NULL);
+	g_return_if_fail (named_ids_list != NULL);
+
+	if ((((*pproptag) >> 16) & 0xFFFF) < 0x8000)
+		return;
+
+	for (i = 0; i < named_ids_len; i++) {
+		if ((*pproptag) == named_ids_list[i].pidlid_propid ||
+		    ((((*pproptag) & 0xFFFF) == PT_ERROR) &&
+			((*pproptag) & ~0xFFFF) == (named_ids_list[i].pidlid_propid & ~0xFFFF))) {
+			(*pproptag) = ((*pproptag) & 0xFFFF) | (named_ids_list[i].propid & ~0xFFFF);
 			break;
 		}
-		if (aRowSet->cRows) {
-			global_unlock ();
-			for (i = 0; i < aRowSet->cRows; i++, count++) {
-				if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data, cancellable, perror)) {
-					ms = MAPI_E_RESERVED;
-					break;
-				}
-			}
-			global_lock ();
-		} else {
-			talloc_free (aRowSet);
-			break;
+	}
+}
+
+static void
+replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
+				     const ResolveNamedIDsData *named_ids_list,
+				     guint named_ids_len)
+{
+	guint i;
+	uint32_t proptag;
+
+	g_return_if_fail (restriction != NULL);
+	g_return_if_fail (named_ids_list != NULL);
+
+	#define check_proptag(x) {								\
+			proptag = x;								\
+			maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);	\
+			x = proptag;								\
 		}
 
-		ulFlags = TABLE_CUR;
-		talloc_free (aRowSet);
+	switch (restriction->rt) {
+	case RES_AND:
+		for (i = 0; i < restriction->res.resAnd.cRes; i++) {
+			replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
+		}
+		break;
+	case RES_OR:
+		for (i = 0; i < restriction->res.resOr.cRes; i++) {
+			replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
+		}
+		break;
+	#ifdef HAVE_RES_NOT_SUPPORTED
+	case RES_NOT:
+		replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, named_ids_list, named_ids_len);
+		break;
+	#endif
+	case RES_CONTENT:
+		check_proptag (restriction->res.resContent.ulPropTag);
+		check_proptag (restriction->res.resContent.lpProp.ulPropTag);
+		break;
+	case RES_PROPERTY:
+		check_proptag (restriction->res.resProperty.ulPropTag);
+		check_proptag (restriction->res.resProperty.lpProp.ulPropTag);
+		break;
+	case RES_COMPAREPROPS:
+		check_proptag (restriction->res.resCompareProps.ulPropTag1);
+		check_proptag (restriction->res.resCompareProps.ulPropTag2);
+		break;
+	case RES_BITMASK:
+		check_proptag (restriction->res.resBitmask.ulPropTag);
+		break;
+	case RES_SIZE:
+		check_proptag (restriction->res.resSize.ulPropTag);
+		break;
+	case RES_EXIST:
+		check_proptag (restriction->res.resExist.ulPropTag);
+		break;
 	}
 
-	talloc_free (mem_ctx);
+	#undef check_proptag
+}
 
-	UNLOCK ();
+static gboolean
+change_mapi_SRestriction_named_ids (EMapiConnection *conn,
+				    mapi_object_t *obj_folder,
+				    struct mapi_SRestriction *restrictions,
+				    GCancellable *cancellable,
+				    GError **perror)
+{
+	ResolveNamedIDsData *named_ids_list = NULL;
+	guint named_ids_len = 0;
+	gboolean res = FALSE;
 
-	if (ms != MAPI_E_SUCCESS && ms != MAPI_E_RESERVED)
-		make_mapi_error (perror, "GetGALTable", 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 != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (restrictions != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	return ms == MAPI_E_SUCCESS;
+	gather_mapi_SRestriction_named_ids (restrictions, &named_ids_list, &named_ids_len);
+
+	if (!named_ids_list)
+		return TRUE;
+
+	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_mapi_SRestriction_named_ids (restrictions, named_ids_list, named_ids_len);
+
+	g_free (named_ids_list);
+
+	return res;
 }
 
+/* deals with named IDs transparently, thus it's OK to pass Restrictions with PidLid and PidName constants */
 gboolean
-e_mapi_connection_get_public_folder (EMapiConnection *conn,
-				     mapi_object_t *obj_store,
-				     GCancellable *cancellable,
-				     GError **perror)
+e_mapi_connection_list_objects (EMapiConnection *conn,
+				mapi_object_t *obj_folder,
+				BuildRestrictionsCB build_rs_cb,
+				gpointer build_rs_cb_data,
+				ListObjectsCB cb,
+				gpointer user_data,
+				GCancellable *cancellable,
+				GError **perror)
 {
 	enum MAPISTATUS ms;
+	TALLOC_CTX *mem_ctx;
+	mapi_object_t obj_table;
+	struct SPropTagArray *propTagArray;
+	struct ListObjectsInternalData loi_data;
 
 	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 (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
+	mem_ctx = talloc_new (priv->session);
+	mapi_object_init (&obj_table);
 
-	mapi_object_init (&priv->public_store);
-
-	ms = OpenPublicFolder (priv->session, &priv->public_store);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
+	/* Get a handle on the container */
+	ms = GetContentsTable (obj_folder, &obj_table, TableFlags_UseUnicode, NULL);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenPublicFolder", ms);
+		make_mapi_error (perror, "GetContentsTable", ms);
+		goto cleanup;
 	}
 
-	*obj_store = priv->public_store;
-	UNLOCK ();
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-/* Returns TRUE if all recipients were read succcesfully, else returns FALSE */
-static gboolean
-e_mapi_util_get_recipients (EMapiConnection *conn, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList **recip_list, GError **perror)
-{
-	enum MAPISTATUS		ms;
-	struct SPropTagArray	proptags;
-	struct SRowSet		rows_recip;
-	uint32_t		i_row_recip;
-	gboolean		status = TRUE;
-
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+	propTagArray = set_SPropTagArray (mem_ctx, 0x4,
+					  PidTagMid,
+					  PidTagMessageClass,
+					  PidTagMessageFlags,
+					  PidTagLastModificationTime);
 
-	/* fetch recipient table */
-	ms = GetRecipientTable (obj_message, &rows_recip, &proptags);
+	/* Set primary columns to be fetched */
+	ms = SetColumns (&obj_table, propTagArray);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetRecipientTable", ms);
+		make_mapi_error (perror, "SetColumns", ms);
 		goto cleanup;
 	}
 
-	for (i_row_recip = 0; i_row_recip < rows_recip.cRows; i_row_recip++) {
-		ExchangeMAPIRecipient *recipient = g_new0 (ExchangeMAPIRecipient, 1);
-		gchar *display_name = NULL, *email = NULL;
-		const struct Binary_r *entryid;
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-		recipient->mem_ctx = talloc_new (conn->priv->session);
+	if (build_rs_cb) {
+		struct mapi_SRestriction *restrictions = NULL;
 
-		entryid = e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_RECIPIENT_ENTRYID);
-		if (entryid && e_mapi_util_recip_entryid_decode (conn, entryid, &display_name, &email) && email) {
-			recipient->email_id = talloc_strdup (recipient->mem_ctx, email);
-			if (display_name)
-				recipient->display_name = talloc_strdup (recipient->mem_ctx, display_name);
-		} else {
-			recipient->email_id = talloc_steal (recipient->mem_ctx, (const gchar *) e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_SMTP_ADDRESS_UNICODE));
-			/* fallback */
-			if (!recipient->email_id) {
-				uint32_t fallback_props[] = {
-					PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
-					PR_RECIPIENT_DISPLAY_NAME_UNICODE
-				};
-				gint ii;
-				const gchar *addrtype = e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_ADDRTYPE_UNICODE);
-
-				if (addrtype && !g_ascii_strcasecmp (addrtype, "SMTP"))
-					recipient->email_id = talloc_steal (recipient->mem_ctx, (const gchar *) e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_EMAIL_ADDRESS_UNICODE));
-
-				for (ii = 0; !recipient->email_id && ii < G_N_ELEMENTS (fallback_props); ii++) {
-					recipient->email_id = talloc_steal (recipient->mem_ctx, (const gchar *) e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), fallback_props[ii]));
-				}
+		if (!build_rs_cb (conn, mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
+			ms = MAPI_E_CALL_FAILED;
+			make_mapi_error (perror, "build_restrictions", ms);
+			goto cleanup;
+		}
+
+		if (restrictions) {
+			change_mapi_SRestriction_named_ids (conn, obj_folder, restrictions, cancellable, perror);
+
+			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+				ms = MAPI_E_USER_CANCEL;
+				goto cleanup;
 			}
 
-			if (recipient->email_id) {
-				const gchar *addrtype = e_mapi_util_find_row_propval (&(rows_recip.aRow[i_row_recip]), PR_ADDRTYPE_UNICODE);
+			/* Applying any restriction that are set. */
+			ms = Restrict (&obj_table, restrictions, NULL);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "Restrict", ms);
+				goto cleanup;
+			}
 
-				if (addrtype && g_ascii_strcasecmp (addrtype, "EX") == 0)
-					recipient->email_id = talloc_strdup (recipient->mem_ctx, e_mapi_connection_ex_to_smtp (conn, recipient->email_id, NULL, NULL, NULL));
+			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+				ms = MAPI_E_USER_CANCEL;
+				goto cleanup;
 			}
 		}
+	}
 
-		recipient->out_SRow.ulAdrEntryPad = rows_recip.aRow[i_row_recip].ulAdrEntryPad;
-		recipient->out_SRow.cValues = rows_recip.aRow[i_row_recip].cValues;
-		recipient->out_SRow.lpProps = talloc_steal ((TALLOC_CTX *)recipient->mem_ctx, rows_recip.aRow[i_row_recip].lpProps);
+	loi_data.cb = cb;
+	loi_data.user_data = user_data;
 
-		*recip_list = g_slist_append (*recip_list, recipient);
+	ms = foreach_tablerow (conn, mem_ctx, &obj_table, list_objects_internal_cb, &loi_data, cancellable, perror);
 
-		g_free (display_name);
-		g_free (email);
-	}
-
-cleanup:
-	if (ms != MAPI_E_SUCCESS)
-		status = FALSE;
-
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ cleanup:
+	mapi_object_release (&obj_table);
+	talloc_free (mem_ctx);
+	UNLOCK ();
 
-	return status;
+	return ms == MAPI_E_SUCCESS;
 }
 
-static enum MAPISTATUS
-open_folder (EMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 fid_options, mapi_object_t *obj_folder, GError **perror)
+static gboolean
+has_embedded_message_with_html (EMapiObject *object)
 {
-	enum MAPISTATUS ms;
+	EMapiAttachment *attach;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
-	e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
+	if (!object)
+		return FALSE;
 
-	if (*fid == 0) {
-		ms = GetDefaultFolder (&priv->msg_store, fid, olFolder);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "GetDefaultFolder", ms);
-			return ms;
-		}
+	for (attach = object->attachments; attach; attach = attach->next) {
+		if (!attach->embedded_object)
+			continue;
 
-		fid_options = 0;
-	}
+		if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
+		    !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody))
+			return TRUE;
 
-	if ((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0) {
-		if (!ensure_public_store (priv, perror)) {
-			return MAPI_E_CALL_FAILED;
-		}
+		if (has_embedded_message_with_html (attach->embedded_object))
+			return TRUE;
 	}
 
-	ms = OpenFolder (((fid_options & MAPI_OPTIONS_USE_PFSTORE) != 0 ? &priv->public_store : &priv->msg_store), *fid, obj_folder);
-	if (ms != MAPI_E_SUCCESS)
-		make_mapi_error (perror, "OpenFolder", ms);
-
-	return ms;
+	return FALSE;
 }
 
-gboolean
-e_mapi_connection_open_default_folder (EMapiConnection *conn,
-				       uint32_t olFolderIdentifier,
-				       mapi_object_t *obj_folder,
-				       GCancellable *cancellable,
-				       GError **perror)
+static gboolean
+get_additional_properties_cb (EMapiConnection *conn,
+			      TALLOC_CTX *mem_ctx,
+			      /* const */ EMapiObject *object,
+			      guint32 obj_index,
+			      guint32 obj_total,
+			      gpointer user_data,
+			      GCancellable *cancellable,
+			      GError **perror)
 {
-	enum MAPISTATUS ms;
-	mapi_id_t fid = 0;
-	gboolean res;
-
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	uint32_t ii;
+	EMapiObject *dest_object = user_data;
 
-	LOCK ();
+	g_return_val_if_fail (object != NULL, FALSE);
+	g_return_val_if_fail (dest_object != NULL, FALSE);
 
-	mapi_object_init (obj_folder);
+	for (ii = 0; ii < object->properties.cValues; ii++) {
+		uint32_t proptag = object->properties.lpProps[ii].ulPropTag;
 
-	ms = GetDefaultFolder (&priv->msg_store, &fid, olFolderIdentifier);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetDefaultFolder", ms);
-		UNLOCK ();
-		return FALSE;
-	}
+		if ((proptag & 0xFFFF) == PT_ERROR
+		    || e_mapi_util_find_array_propval (&dest_object->properties, proptag))
+			continue;
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		UNLOCK ();
-		return FALSE;
-	}
+		dest_object->properties.cValues++;
+		dest_object->properties.lpProps = talloc_realloc (mem_ctx,
+				    dest_object->properties.lpProps,
+				    struct mapi_SPropValue,
+				    dest_object->properties.cValues + 1);
+		dest_object->properties.lpProps[dest_object->properties.cValues - 1] = object->properties.lpProps[ii];
 
-	res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+		#define steal_ptr(x) (x) = talloc_steal (dest_object, (x))
+		switch (proptag & 0xFFFF) {
+		case PT_BOOLEAN:
+		case PT_I2:
+		case PT_LONG:
+		case PT_DOUBLE:
+		case PT_I8:
+		case PT_SYSTIME:
+			break;
+		case PT_STRING8:
+			steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszA);
+			break;
+		case PT_UNICODE:
+			steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszW);
+			break;
+		default:
+			g_debug ("%s: Do not know how to steal property type 0x%x, skipping it", G_STRFUNC, proptag & 0xFFFF);
+			dest_object->properties.cValues--;
+			break;
+		}
+		#undef steal_ptr
 
-	UNLOCK ();
+		dest_object->properties.lpProps[dest_object->properties.cValues].ulPropTag = 0;
+	}
 
-	return res;
+	return TRUE;
 }
 
-gboolean
-e_mapi_connection_open_personal_folder (EMapiConnection *conn,
-					mapi_id_t fid,
-					mapi_object_t *obj_folder,
-					GCancellable *cancellable,
-					GError **perror)
+static void
+traverse_attachments_for_body (EMapiConnection *conn,
+			       TALLOC_CTX *mem_ctx,
+			       EMapiObject *object,
+			       mapi_object_t *obj_message,
+			       GCancellable *cancellable,
+			       GError **perror)
 {
-	enum MAPISTATUS ms;
-
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	LOCK ();
-
-	mapi_object_init (obj_folder);
+	EMapiAttachment *attach;
 
-	ms = OpenFolder (&priv->msg_store, fid, obj_folder);
-	if (ms != MAPI_E_SUCCESS)
-		make_mapi_error (perror, "OpenFolder", ms);
+	g_return_if_fail (conn != NULL);
+	g_return_if_fail (mem_ctx != NULL);
+	g_return_if_fail (obj_message != NULL);
 
-	UNLOCK ();
+	if (!has_embedded_message_with_html (object))
+		return;
 
-	return ms == MAPI_E_SUCCESS;
-}
+	for (attach = object->attachments; attach && !g_cancellable_is_cancelled (cancellable); attach = attach->next) {
+		if (attach->embedded_object) {
+			const uint32_t *pattach_num;
+			mapi_object_t obj_attach;
+			mapi_object_t obj_embedded;
+			gboolean have_embedded = FALSE;
 
-gboolean
-e_mapi_connection_open_public_folder (EMapiConnection *conn,
-				      mapi_id_t fid,
-				      mapi_object_t *obj_folder,
-				      GCancellable *cancellable,
-				      GError **perror)
-{
-	enum MAPISTATUS ms;
+			pattach_num = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachNumber);
+			if (!pattach_num)
+				continue;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+			mapi_object_init (&obj_attach);
+			mapi_object_init (&obj_embedded);
 
-	LOCK ();
+			if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
+			    !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody)) {
+				struct SPropTagArray *tags;
 
-	if (!ensure_public_store (priv, perror)) {
-		UNLOCK ();
-		return FALSE;
-	}
+				if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
+					continue;
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		UNLOCK ();
-		return FALSE;
-	}
+				if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
+					mapi_object_release (&obj_attach);
+					continue;
+				}
 
-	mapi_object_init (obj_folder);
+				have_embedded = TRUE;
 
-	ms = OpenFolder (&priv->public_store, fid, obj_folder);
-	if (ms != MAPI_E_SUCCESS)
-		make_mapi_error (perror, "OpenFolder", ms);
+				tags = set_SPropTagArray (mem_ctx, 1, PidTagBody);
 
-	UNLOCK ();
+				e_mapi_fast_transfer_properties (conn, mem_ctx, &obj_embedded, tags, get_additional_properties_cb, attach->embedded_object, cancellable, perror);
 
-	return ms == MAPI_E_SUCCESS;
-}
+				talloc_free (tags);
+			}
 
-gboolean
-e_mapi_connection_close_folder (EMapiConnection *conn,
-				mapi_object_t *obj_folder,
-				GCancellable *cancellable,
-				GError **perror)
-{
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+			if (has_embedded_message_with_html (attach->embedded_object)) {
+				if (!have_embedded) {
+					if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
+						continue;
 
-	LOCK ();
+					if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
+						mapi_object_release (&obj_attach);
+						continue;
+					}
 
-	mapi_object_release (obj_folder);
+					have_embedded = TRUE;
+				}
 
-	UNLOCK ();
+				traverse_attachments_for_body (conn, mem_ctx, attach->embedded_object, &obj_embedded, cancellable, perror);
+			}
 
-	return TRUE;
+			mapi_object_release (&obj_embedded);
+			mapi_object_release (&obj_attach);
+		}
+	}
 }
 
-/* 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,
-					 gpointer cb_user_data,
-					 GCancellable *cancellable,
-					 GError **perror)
+struct EnsureAdditionalPropertiesData
 {
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	struct SPropTagArray *spropTagArray = NULL;
-	struct mapi_SPropValue_array *properties = NULL;
-	gboolean res = FALSE;
+	TransferObjectCB cb;
+	gpointer cb_user_data;
+	mapi_object_t *obj_folder;
+	guint32 downloaded;
+};
 
-	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);
+static gboolean
+ensure_additional_properties_cb (EMapiConnection *conn,
+				 TALLOC_CTX *mem_ctx,
+				 /* const */ EMapiObject *object,
+				 guint32 obj_index,
+				 guint32 obj_total,
+				 gpointer user_data,
+				 GCancellable *cancellable,
+				 GError **perror)
+{
+	struct ap_data {
+		uint32_t orig_proptag, use_proptag;
+	} additional_properties[] = {
+		{ PidTagBody, MAPI_E_RESERVED },
+		{ PidNameContentClass, MAPI_E_RESERVED }
+	};
+	struct EnsureAdditionalPropertiesData *eap = user_data;
+	gboolean need_any = FALSE, need_attachments;
+	uint32_t ii;
 
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
+	g_return_val_if_fail (eap != NULL, FALSE);
+	g_return_val_if_fail (eap->cb != NULL, FALSE);
+	g_return_val_if_fail (object != NULL, FALSE);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-		goto cleanup;
+	for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
+		uint32_t prop = additional_properties[ii].orig_proptag;
 
-	spropTagArray = set_SPropTagArray (mem_ctx, 3, PidTagFolderId, PidTagLastModificationTime, PidTagContentCount);
-	if (brp_cb) {
-		if (!brp_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, spropTagArray, brp_cb_user_data, cancellable, perror)) {
-			goto cleanup;
+		if (!e_mapi_util_find_array_propval (&object->properties, prop)) {
+			if (((prop >> 16) & 0xFFFF) >= 0x8000) {
+				prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
+			}
+		} else {
+			prop = MAPI_E_RESERVED;
 		}
-	} else {
-		talloc_free (spropTagArray);
-		spropTagArray = NULL;
-	}
 
-	properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
-	if (spropTagArray && spropTagArray->cValues) {
-		struct SPropValue *lpProps;
-		uint32_t prop_count = 0, k, ll;
-		ResolveNamedIDsData *named_ids_list = NULL;
-		guint named_ids_len = 0;
+		additional_properties[ii].use_proptag = prop;
+		need_any = need_any || prop != MAPI_E_RESERVED;
+	}
 
-		lpProps = talloc_zero (mem_ctx, struct SPropValue);
+	need_attachments = has_embedded_message_with_html (object);
 
-		for (k = 0; k < spropTagArray->cValues; k++) {
-			uint32_t proptag = spropTagArray->aulPropTag[k];
+	/* Fast-transfer transfers only Html or Body, never both */
+	if (need_any || need_attachments) {
+		const mapi_id_t *mid;
 
-			if (may_skip_property (proptag)) {
-				const gchar *name = get_proptag_name (proptag);
-				if (!name)
-					name = "";
+		mid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
+		if (mid && *mid) {
+			mapi_object_t obj_message;
+			
+			mapi_object_init (&obj_message);
 
-				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 (ResolveNamedIDsData, 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++;
-			}
-		}
+			if (OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), *mid, &obj_message, 0) == MAPI_E_SUCCESS) {
+				struct SPropTagArray *tags = NULL;
 
-		if (named_ids_list) {
-			if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
-				g_free (named_ids_list);
-				goto cleanup;
-			}
+				for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
+					uint32_t prop = additional_properties[ii].use_proptag;
 
-			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-				g_free (named_ids_list);
-				goto cleanup;
-			}
+					if (prop == MAPI_E_RESERVED)
+						continue;
 
-			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++;
-					}
+					if (!tags)
+						tags = set_SPropTagArray (mem_ctx, 1, prop);
+					else
+						SPropTagArray_add (mem_ctx, tags, prop);
 				}
-			}
-		}
 
-		ms = GetProps (obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, spropTagArray, &lpProps, &prop_count);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "GetProps", ms);
-			g_free (named_ids_list);
-			goto cleanup;
-		}
+				if (tags) {
+					uint32_t jj = object->properties.cValues;
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			g_free (named_ids_list);
-			goto cleanup;
-		}
+					e_mapi_fast_transfer_properties	(conn, mem_ctx, &obj_message, tags, get_additional_properties_cb, object, cancellable, perror);
 
-		/* 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);
-		for (k = 0, ll = 0; k < prop_count; k++, ll++) {
-			if (may_skip_property (lpProps[k].ulPropTag)) {
-				ll--;
-				properties->cValues--;
-			} else {
-				if (named_ids_list) {
-					guint m;
+					while (jj < object->properties.cValues) {
+						for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
+							uint32_t proptag = object->properties.lpProps[jj].ulPropTag;
 
-					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;
+							if (additional_properties[ii].use_proptag == proptag ||
+							    (((proptag & 0xFFFF) == PT_STRING8 || (proptag & 0xFFFF) == PT_UNICODE) &&
+							        (proptag & ~0xFFFF) == (additional_properties[ii].use_proptag & ~0xFFFF))) {
+								/* string8 and unicode properties are interchangeable in the union, luckily */
+								object->properties.lpProps[jj].ulPropTag = additional_properties[ii].orig_proptag;
+								break;
+							}
 						}
+
+						jj++;
 					}
+
+					talloc_free (tags);
 				}
 
-				cast_mapi_SPropValue (mem_ctx, &properties->lpProps[ll], &lpProps[k]);
+				if (need_attachments)
+					traverse_attachments_for_body (conn, mem_ctx, object, &obj_message, cancellable, perror);
 			}
-		}
-	} else {
-		ms = GetPropsAll (obj_folder, MAPI_UNICODE, properties);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "GetPropsAll", ms);
-			goto cleanup;
+
+			mapi_object_release (&obj_message);
 		}
 	}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-		goto cleanup;
-
-	res = cb (conn, mapi_object_get_id (obj_folder), mem_ctx, properties, cb_user_data, cancellable, perror);
-
- cleanup:
-	talloc_free (spropTagArray);
-	talloc_free (properties);
-	talloc_free (mem_ctx);
-	UNLOCK();
+	eap->downloaded++;
 
-	return res;
+	return eap->cb (conn, mem_ctx, object, obj_index, obj_total, eap->cb_user_data, cancellable, perror);
 }
 
-typedef gboolean (*ForeachTableRowCB) (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SRow *srow, guint32 row_index, guint32 rows_total, gpointer user_data, GCancellable *cancellable, GError **perror);
-
 static enum MAPISTATUS
-foreach_tablerow (EMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, mapi_object_t *obj_table, ForeachTableRowCB cb, gpointer user_data, GCancellable *cancellable, GError **perror)
+fetch_object_property_as_stream (EMapiConnection *conn,
+				 TALLOC_CTX *mem_ctx,
+				 mapi_object_t *obj_message,
+				 uint32_t proptag,
+				 struct SBinary_short *bin,
+				 GCancellable *cancellable,
+				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	struct SRowSet SRowSet;
-	uint32_t count, i, cursor_pos = 0;
+	mapi_object_t obj_stream;
+	uint32_t buf_size, max_read;
+	uint16_t off_data, cn_read;
+	gboolean done = FALSE;
 
-	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 (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (obj_table != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (bin != NULL, MAPI_E_INVALID_PARAMETER);
 
-	do {
-		/* Number of items in the container */
-		ms = QueryPosition (obj_table, &cursor_pos, &count);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "QueryPosition", ms);
-			break;
-		}
+	mapi_object_init (&obj_stream);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			break;
-		}
+	ms = OpenStream (obj_message, proptag, STREAM_ACCESS_READ, &obj_stream);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenStream", ms);
+		goto cleanup;
+	}
 
-		if (!count)
-			break;
+	bin->cb = 0;
 
-		/* Fill the table columns with data from the rows */
-		ms = QueryRows (obj_table, count, TBL_ADVANCE, &SRowSet);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "QueryRows", ms);
-			break;
-		}
+	ms = GetStreamSize (&obj_stream, &buf_size);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "GetStreamSize", ms);
+		goto cleanup;
+	}
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			break;
-		}
+	bin->cb = buf_size;
+	bin->lpb = talloc_size (mem_ctx, bin->cb + 1);
+	if (!bin->lpb || !bin->cb)
+		goto cleanup;
 
-		for (i = 0; i < SRowSet.cRows && ms == MAPI_E_SUCCESS; i++) {
-			if (!cb (conn, fid, mem_ctx, &SRowSet.aRow[i], cursor_pos + i + 1, count, user_data, cancellable, perror))
-				ms = MAPI_E_RESERVED;
-			else if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-				ms = MAPI_E_USER_CANCEL;
+	/* determine max_read first, to read by chunks as long as possible */
+	off_data = 0;
+	max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
+	do {
+		ms = ReadStream (&obj_stream, (bin->lpb) + off_data, max_read, &cn_read);
+		if (ms == MAPI_E_SUCCESS) {
+			if (cn_read == 0) {
+				done = TRUE;
+			} else {
+				off_data += cn_read;
+				if (off_data >= buf_size)
+					done = TRUE;
+			}
+			break;
 		}
-	} while (cursor_pos < count && ms == MAPI_E_SUCCESS);
 
-	return ms;
-}
-
-struct ListObjectsInternalData
-{
-	ListObjectsCB cb;
-	gpointer user_data;
-};
-
-static gboolean
-list_objects_internal_cb (EMapiConnection *conn,
-			  mapi_id_t fid,
-			  TALLOC_CTX *mem_ctx,
-			  struct SRow *srow,
-			  guint32 row_index,
-			  guint32 rows_total,
-			  gpointer user_data,
-			  GCancellable *cancellable,
-			  GError **perror)
-{
-	struct ListObjectsInternalData *loi_data = user_data;
-	ListObjectsData lod;
-	const mapi_id_t	*pmid;
-	const gchar *msg_class;
-	const uint32_t *pmsg_flags;
-	const struct FILETIME *last_modified;
-
-	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 (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (srow != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	pmid = get_SPropValue_SRow_data (srow, PidTagMid);
-	msg_class = get_SPropValue_SRow_data (srow, PidTagMessageClass);
-	pmsg_flags = get_SPropValue_SRow_data (srow, PidTagMessageFlags);
-	last_modified = get_SPropValue_SRow_data (srow, PidTagLastModificationTime);
-
-	lod.mid = pmid ? *pmid : 0;
-	lod.msg_class = msg_class;
-	lod.msg_flags = pmsg_flags ? *pmsg_flags : 0;
-	lod.last_modified = last_modified ? e_mapi_util_filetime_to_time_t (last_modified) : 0;
-
-	return loi_data->cb (conn, fid, mem_ctx, &lod, row_index, rows_total, loi_data->user_data, cancellable, perror);
-}
-
-static void
-maybe_add_named_id_tag (uint32_t proptag,
-			ResolveNamedIDsData **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 (ResolveNamedIDsData, 1);
-			*named_ids_len = 0;
-		} else {
-			*named_ids_list = g_renew (ResolveNamedIDsData, *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,
-				    ResolveNamedIDsData **named_ids_list,
-				    guint *named_ids_len)
-{
-	guint i;
-
-	g_return_if_fail (restriction != NULL);
-	g_return_if_fail (named_ids_list != NULL);
-	g_return_if_fail (named_ids_len != NULL);
-
-	switch (restriction->rt) {
-	case RES_AND:
-		for (i = 0; i < restriction->res.resAnd.cRes; i++) {
-			gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
-		}
-		break;
-	case RES_OR:
-		for (i = 0; i < restriction->res.resOr.cRes; i++) {
-			gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
-		}
-		break;
-	#ifdef HAVE_RES_NOT_SUPPORTED
-	case RES_NOT:
-		gather_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) restriction->res.resNot.res, named_ids_list, named_ids_len);
-		break;
-	#endif
-	case RES_CONTENT:
-		maybe_add_named_id_tag (restriction->res.resContent.ulPropTag, named_ids_list, named_ids_len);
-		maybe_add_named_id_tag (restriction->res.resContent.lpProp.ulPropTag, named_ids_list, named_ids_len);
-		break;
-	case RES_PROPERTY:
-		maybe_add_named_id_tag (restriction->res.resProperty.ulPropTag, named_ids_list, named_ids_len);
-		maybe_add_named_id_tag (restriction->res.resProperty.lpProp.ulPropTag, named_ids_list, named_ids_len);
-		break;
-	case RES_COMPAREPROPS:
-		maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag1, named_ids_list, named_ids_len);
-		maybe_add_named_id_tag (restriction->res.resCompareProps.ulPropTag2, named_ids_list, named_ids_len);
-		break;
-	case RES_BITMASK:
-		maybe_add_named_id_tag (restriction->res.resBitmask.ulPropTag, named_ids_list, named_ids_len);
-		break;
-	case RES_SIZE:
-		maybe_add_named_id_tag (restriction->res.resSize.ulPropTag, named_ids_list, named_ids_len);
-		break;
-	case RES_EXIST:
-		maybe_add_named_id_tag (restriction->res.resExist.ulPropTag, named_ids_list, named_ids_len);
-		break;
-	}
-}
-
-static void
-maybe_replace_named_id_tag (uint32_t *pproptag,
-			    const ResolveNamedIDsData *named_ids_list,
-			    guint named_ids_len)
-{
-	gint i;
-
-	g_return_if_fail (pproptag != NULL);
-	g_return_if_fail (named_ids_list != NULL);
-
-	if ((((*pproptag) >> 16) & 0xFFFF) < 0x8000)
-		return;
-
-	for (i = 0; i < named_ids_len; i++) {
-		if ((*pproptag) == named_ids_list[i].pidlid_propid ||
-		    ((((*pproptag) & 0xFFFF) == PT_ERROR) &&
-			((*pproptag) & ~0xFFFF) == (named_ids_list[i].pidlid_propid & ~0xFFFF))) {
-			(*pproptag) = ((*pproptag) & 0xFFFF) | (named_ids_list[i].propid & ~0xFFFF);
-			break;
-		}
-	}
-}
-
-static void
-replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
-				     const ResolveNamedIDsData *named_ids_list,
-				     guint named_ids_len)
-{
-	guint i;
-	uint32_t proptag;
-
-	g_return_if_fail (restriction != NULL);
-	g_return_if_fail (named_ids_list != NULL);
-
-	#define check_proptag(x) {								\
-			proptag = x;								\
-			maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);	\
-			x = proptag;								\
-		}
-
-	switch (restriction->rt) {
-	case RES_AND:
-		for (i = 0; i < restriction->res.resAnd.cRes; i++) {
-			replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resAnd.res[i]), named_ids_list, named_ids_len);
-		}
-		break;
-	case RES_OR:
-		for (i = 0; i < restriction->res.resOr.cRes; i++) {
-			replace_mapi_SRestriction_named_ids ((struct mapi_SRestriction *) &(restriction->res.resOr.res[i]), named_ids_list, named_ids_len);
-		}
-		break;
-	#ifdef HAVE_RES_NOT_SUPPORTED
-	case RES_NOT:
-		replace_mapi_SRestriction_named_ids (restriction->res.resNot.res, named_ids_list, named_ids_len);
-		break;
-	#endif
-	case RES_CONTENT:
-		check_proptag (restriction->res.resContent.ulPropTag);
-		check_proptag (restriction->res.resContent.lpProp.ulPropTag);
-		break;
-	case RES_PROPERTY:
-		check_proptag (restriction->res.resProperty.ulPropTag);
-		check_proptag (restriction->res.resProperty.lpProp.ulPropTag);
-		break;
-	case RES_COMPAREPROPS:
-		check_proptag (restriction->res.resCompareProps.ulPropTag1);
-		check_proptag (restriction->res.resCompareProps.ulPropTag2);
-		break;
-	case RES_BITMASK:
-		check_proptag (restriction->res.resBitmask.ulPropTag);
-		break;
-	case RES_SIZE:
-		check_proptag (restriction->res.resSize.ulPropTag);
-		break;
-	case RES_EXIST:
-		check_proptag (restriction->res.resExist.ulPropTag);
-		break;
-	}
-
-	#undef check_proptag
-}
-
-static gboolean
-change_mapi_SRestriction_named_ids (EMapiConnection *conn,
-				    mapi_object_t *obj_folder,
-				    struct mapi_SRestriction *restrictions,
-				    GCancellable *cancellable,
-				    GError **perror)
-{
-	ResolveNamedIDsData *named_ids_list = NULL;
-	guint named_ids_len = 0;
-	gboolean res = FALSE;
-
-	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_return_val_mapi_error_if_fail (restrictions != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	gather_mapi_SRestriction_named_ids (restrictions, &named_ids_list, &named_ids_len);
-
-	if (!named_ids_list)
-		return TRUE;
-
-	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_mapi_SRestriction_named_ids (restrictions, named_ids_list, named_ids_len);
-
-	g_free (named_ids_list);
-
-	return res;
-}
-
-/* deals with named IDs transparently, thus it's OK to pass Restrictions with PidLid and PidName constants */
-gboolean
-e_mapi_connection_list_objects (EMapiConnection *conn,
-				mapi_object_t *obj_folder,
-				BuildRestrictionsCB build_rs_cb,
-				gpointer build_rs_cb_data,
-				ListObjectsCB cb,
-				gpointer user_data,
-				GCancellable *cancellable,
-				GError **perror)
-{
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_table;
-	struct SPropTagArray *propTagArray;
-	struct ListObjectsInternalData loi_data;
-
-	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 (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init (&obj_table);
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
-
-	/* Get a handle on the container */
-	ms = GetContentsTable (obj_folder, &obj_table, TableFlags_UseUnicode, NULL);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetContentsTable", ms);
-		goto cleanup;
-	}
-
-	propTagArray = set_SPropTagArray (mem_ctx, 0x4,
-					  PidTagMid,
-					  PidTagMessageClass,
-					  PidTagMessageFlags,
-					  PidTagLastModificationTime);
-
-	/* Set primary columns to be fetched */
-	ms = SetColumns (&obj_table, propTagArray);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetColumns", ms);
-		goto cleanup;
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
-
-	if (build_rs_cb) {
-		struct mapi_SRestriction *restrictions = NULL;
-
-		if (!build_rs_cb (conn, mapi_object_get_id (obj_folder), mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
-			ms = MAPI_E_CALL_FAILED;
-			make_mapi_error (perror, "build_restrictions", ms);
-			goto cleanup;
-		}
-
-		if (restrictions) {
-			change_mapi_SRestriction_named_ids (conn, obj_folder, restrictions, cancellable, perror);
-
-			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-				ms = MAPI_E_USER_CANCEL;
-				goto cleanup;
-			}
-
-			/* Applying any restriction that are set. */
-			ms = Restrict (&obj_table, restrictions, NULL);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "Restrict", ms);
-				goto cleanup;
-			}
-
-			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-				ms = MAPI_E_USER_CANCEL;
-				goto cleanup;
-			}
-		}
-	}
-
-	loi_data.cb = cb;
-	loi_data.user_data = user_data;
-
-	ms = foreach_tablerow (conn, mapi_object_get_id (obj_folder), mem_ctx, &obj_table, list_objects_internal_cb, &loi_data, cancellable, perror);
-
- cleanup:
-	mapi_object_release (&obj_table);
-	talloc_free (mem_ctx);
-	UNLOCK ();
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-static gboolean
-has_embedded_message_with_html (EMapiObject *object)
-{
-	EMapiAttachment *attach;
-
-	if (!object)
-		return FALSE;
-
-	for (attach = object->attachments; attach; attach = attach->next) {
-		if (!attach->embedded_object)
-			continue;
-
-		if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
-		    !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody))
-			return TRUE;
-
-		if (has_embedded_message_with_html (attach->embedded_object))
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-get_additional_properties_cb (EMapiConnection *conn,
-			      TALLOC_CTX *mem_ctx,
-			      /* const */ EMapiObject *object,
-			      guint32 obj_index,
-			      guint32 obj_total,
-			      gpointer user_data,
-			      GCancellable *cancellable,
-			      GError **perror)
-{
-	uint32_t ii;
-	EMapiObject *dest_object = user_data;
-
-	g_return_val_if_fail (object != NULL, FALSE);
-	g_return_val_if_fail (dest_object != NULL, FALSE);
-
-	for (ii = 0; ii < object->properties.cValues; ii++) {
-		uint32_t proptag = object->properties.lpProps[ii].ulPropTag;
-
-		if ((proptag & 0xFFFF) == PT_ERROR
-		    || e_mapi_util_find_array_propval (&dest_object->properties, proptag))
-			continue;
-
-		dest_object->properties.cValues++;
-		dest_object->properties.lpProps = talloc_realloc (mem_ctx,
-				    dest_object->properties.lpProps,
-				    struct mapi_SPropValue,
-				    dest_object->properties.cValues + 1);
-		dest_object->properties.lpProps[dest_object->properties.cValues - 1] = object->properties.lpProps[ii];
-
-		#define steal_ptr(x) (x) = talloc_steal (dest_object, (x))
-		switch (proptag & 0xFFFF) {
-		case PT_BOOLEAN:
-		case PT_I2:
-		case PT_LONG:
-		case PT_DOUBLE:
-		case PT_I8:
-		case PT_SYSTIME:
-			break;
-		case PT_STRING8:
-			steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszA);
-			break;
-		case PT_UNICODE:
-			steal_ptr (dest_object->properties.lpProps[dest_object->properties.cValues - 1].value.lpszW);
-			break;
-		default:
-			g_debug ("%s: Do not know how to steal property type 0x%x, skipping it", G_STRFUNC, proptag & 0xFFFF);
-			dest_object->properties.cValues--;
-			break;
-		}
-		#undef steal_ptr
-
-		dest_object->properties.lpProps[dest_object->properties.cValues].ulPropTag = 0;
-	}
-
-	return TRUE;
-}
-
-static void
-traverse_attachments_for_body (EMapiConnection *conn,
-			       TALLOC_CTX *mem_ctx,
-			       EMapiObject *object,
-			       mapi_object_t *obj_message,
-			       GCancellable *cancellable,
-			       GError **perror)
-{
-	EMapiAttachment *attach;
-
-	g_return_if_fail (conn != NULL);
-	g_return_if_fail (mem_ctx != NULL);
-	g_return_if_fail (obj_message != NULL);
-
-	if (!has_embedded_message_with_html (object))
-		return;
-
-	for (attach = object->attachments; attach && !g_cancellable_is_cancelled (cancellable); attach = attach->next) {
-		if (attach->embedded_object) {
-			const uint32_t *pattach_num;
-			mapi_object_t obj_attach;
-			mapi_object_t obj_embedded;
-			gboolean have_embedded = FALSE;
-
-			pattach_num = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachNumber);
-			if (!pattach_num)
-				continue;
-
-			mapi_object_init (&obj_attach);
-			mapi_object_init (&obj_embedded);
-
-			if (e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagHtml) &&
-			    !e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagBody)) {
-				struct SPropTagArray *tags;
-
-				if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
-					continue;
-
-				if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
-					mapi_object_release (&obj_attach);
-					continue;
-				}
-
-				have_embedded = TRUE;
-
-				tags = set_SPropTagArray (mem_ctx, 1, PidTagBody);
-
-				e_mapi_fast_transfer_properties (conn, mem_ctx, &obj_embedded, tags, get_additional_properties_cb, attach->embedded_object, cancellable, perror);
-
-				talloc_free (tags);
-			}
-
-			if (has_embedded_message_with_html (attach->embedded_object)) {
-				if (!have_embedded) {
-					if (OpenAttach (obj_message, *pattach_num, &obj_attach) != MAPI_E_SUCCESS)
-						continue;
-
-					if (OpenEmbeddedMessage (&obj_attach, &obj_embedded, MAPI_READONLY) != MAPI_E_SUCCESS) {
-						mapi_object_release (&obj_attach);
-						continue;
-					}
-
-					have_embedded = TRUE;
-				}
-
-				traverse_attachments_for_body (conn, mem_ctx, attach->embedded_object, &obj_embedded, cancellable, perror);
-			}
-
-			mapi_object_release (&obj_embedded);
-			mapi_object_release (&obj_attach);
-		}
-	}
-}
-
-struct EnsureAdditionalPropertiesData
-{
-	TransferObjectCB cb;
-	gpointer cb_user_data;
-	mapi_object_t *obj_folder;
-	guint32 downloaded;
-};
-
-static gboolean
-ensure_additional_properties_cb (EMapiConnection *conn,
-				 TALLOC_CTX *mem_ctx,
-				 /* const */ EMapiObject *object,
-				 guint32 obj_index,
-				 guint32 obj_total,
-				 gpointer user_data,
-				 GCancellable *cancellable,
-				 GError **perror)
-{
-	struct ap_data {
-		uint32_t orig_proptag, use_proptag;
-	} additional_properties[] = {
-		{ PidTagBody, MAPI_E_RESERVED },
-		{ PidNameContentClass, MAPI_E_RESERVED }
-	};
-	struct EnsureAdditionalPropertiesData *eap = user_data;
-	gboolean need_any = FALSE, need_attachments;
-	uint32_t ii;
-
-	g_return_val_if_fail (eap != NULL, FALSE);
-	g_return_val_if_fail (eap->cb != NULL, FALSE);
-	g_return_val_if_fail (object != NULL, FALSE);
-
-	for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
-		uint32_t prop = additional_properties[ii].orig_proptag;
-
-		if (!e_mapi_util_find_array_propval (&object->properties, prop)) {
-			if (((prop >> 16) & 0xFFFF) >= 0x8000) {
-				prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
-			}
-		} else {
-			prop = MAPI_E_RESERVED;
-		}
-
-		additional_properties[ii].use_proptag = prop;
-		need_any = need_any || prop != MAPI_E_RESERVED;
-	}
-
-	need_attachments = has_embedded_message_with_html (object);
-
-	/* Fast-transfer transfers only Html or Body, never both */
-	if (need_any || need_attachments) {
-		const mapi_id_t *mid;
-
-		mid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
-		if (mid && *mid) {
-			mapi_object_t obj_message;
-			
-			mapi_object_init (&obj_message);
-
-			if (OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), *mid, &obj_message, 0) == MAPI_E_SUCCESS) {
-				struct SPropTagArray *tags = NULL;
-
-				for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
-					uint32_t prop = additional_properties[ii].use_proptag;
-
-					if (prop == MAPI_E_RESERVED)
-						continue;
-
-					if (!tags)
-						tags = set_SPropTagArray (mem_ctx, 1, prop);
-					else
-						SPropTagArray_add (mem_ctx, tags, prop);
-				}
-
-				if (tags) {
-					uint32_t jj = object->properties.cValues;
-
-					e_mapi_fast_transfer_properties	(conn, mem_ctx, &obj_message, tags, get_additional_properties_cb, object, cancellable, perror);
-
-					while (jj < object->properties.cValues) {
-						for (ii = 0; ii < G_N_ELEMENTS (additional_properties); ii++) {
-							uint32_t proptag = object->properties.lpProps[jj].ulPropTag;
-
-							if (additional_properties[ii].use_proptag == proptag ||
-							    (((proptag & 0xFFFF) == PT_STRING8 || (proptag & 0xFFFF) == PT_UNICODE) &&
-							        (proptag & ~0xFFFF) == (additional_properties[ii].use_proptag & ~0xFFFF))) {
-								/* string8 and unicode properties are interchangeable in the union, luckily */
-								object->properties.lpProps[jj].ulPropTag = additional_properties[ii].orig_proptag;
-								break;
-							}
-						}
-
-						jj++;
-					}
-
-					talloc_free (tags);
-				}
-
-				if (need_attachments)
-					traverse_attachments_for_body (conn, mem_ctx, object, &obj_message, cancellable, perror);
-			}
-
-			mapi_object_release (&obj_message);
-		}
-	}
-
-	eap->downloaded++;
-
-	return eap->cb (conn, mem_ctx, object, obj_index, obj_total, eap->cb_user_data, cancellable, perror);
-}
-
-static enum MAPISTATUS
-fetch_object_property_as_stream (EMapiConnection *conn,
-				 TALLOC_CTX *mem_ctx,
-				 mapi_object_t *obj_message,
-				 uint32_t proptag,
-				 struct SBinary_short *bin,
-				 GCancellable *cancellable,
-				 GError **perror)
-{
-	enum MAPISTATUS ms;
-	mapi_object_t obj_stream;
-	uint32_t buf_size, max_read;
-	uint16_t off_data, cn_read;
-	gboolean done = FALSE;
-
-	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (bin != NULL, MAPI_E_INVALID_PARAMETER);
-
-	mapi_object_init (&obj_stream);
-
-	ms = OpenStream (obj_message, proptag, STREAM_ACCESS_READ, &obj_stream);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenStream", ms);
-		goto cleanup;
-	}
-
-	bin->cb = 0;
-
-	ms = GetStreamSize (&obj_stream, &buf_size);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetStreamSize", ms);
-		goto cleanup;
-	}
-
-	bin->cb = buf_size;
-	bin->lpb = talloc_size (mem_ctx, bin->cb + 1);
-	if (!bin->lpb || !bin->cb)
-		goto cleanup;
-
-	/* determine max_read first, to read by chunks as long as possible */
-	off_data = 0;
-	max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
-	do {
-		ms = ReadStream (&obj_stream, (bin->lpb) + off_data, max_read, &cn_read);
-		if (ms == MAPI_E_SUCCESS) {
-			if (cn_read == 0) {
-				done = TRUE;
-			} else {
-				off_data += cn_read;
-				if (off_data >= buf_size)
-					done = TRUE;
-			}
-			break;
-		}
-
-		if (ms == 0x2c80)
-			max_read = max_read >> 1;
-		else
-			max_read = STREAM_MAX_READ_SIZE_DF;
-
-		if (max_read < STREAM_MAX_READ_SIZE_DF)
-			max_read = STREAM_MAX_READ_SIZE_DF;
-	} while (ms == 0x2c80); /* an error when max_read is too large? */
-
-	while (!done) {
-		ms = ReadStream (&obj_stream, bin->lpb + off_data, max_read, &cn_read);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "ReadStream", ms);
-			done = TRUE;
-		} else if (cn_read == 0) {
-			done = TRUE;
-		} else {
-			off_data += cn_read;
-			if (off_data >= buf_size)
-				done = TRUE;
-		}
-	}
-
- cleanup:
-	mapi_object_release (&obj_stream);
-
-	return ms;
-}
-
-static enum MAPISTATUS
-e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
-					 TALLOC_CTX *mem_ctx,
-					 mapi_object_t *obj_message,
-					 struct EnsureAdditionalPropertiesData *eap,
-					 EMapiObject **out_object,
-					 GCancellable *cancellable,
-					 GError **perror);
-
-struct FetchObjectAttachmentData
-{
-	mapi_object_t *obj_message;
-	struct EnsureAdditionalPropertiesData *eap;
-	EMapiObject *object; /* to add attachments to */
-};
-
-static gboolean
-fetch_object_attachment_cb (EMapiConnection *conn,
-			    mapi_id_t fid,
-			    TALLOC_CTX *mem_ctx,
-			    struct SRow *srow,
-			    guint32 row_index,
-			    guint32 rows_total,
-			    gpointer user_data,
-			    GCancellable *cancellable,
-			    GError **perror)
-{
-	enum MAPISTATUS ms;
-	struct FetchObjectAttachmentData *foa = user_data;
-	EMapiAttachment *attachment = NULL;
-	mapi_object_t obj_attach;
-	const uint32_t *attach_num, *attach_method;
-
-	g_return_val_if_fail (conn != NULL, FALSE);
-	g_return_val_if_fail (mem_ctx != NULL, FALSE);
-	g_return_val_if_fail (srow != NULL, FALSE);
-	g_return_val_if_fail (user_data != NULL, FALSE);
-	g_return_val_if_fail (foa->obj_message != NULL, FALSE);
-	g_return_val_if_fail (foa->object != NULL, FALSE);
-
-	mapi_object_init (&obj_attach);
-
-	attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
-	if (!attach_num)
-		return FALSE;
-
-	ms = OpenAttach (foa->obj_message, *attach_num, &obj_attach);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenAttach", ms);
-		goto cleanup;
-	}
-
-	attachment = e_mapi_attachment_new (foa->object);
-
-	ms = GetPropsAll (&obj_attach, MAPI_UNICODE, &attachment->properties);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "Attachment::GetPropsAll", ms);
-		goto cleanup;
-	}
-
-	attach_method = e_mapi_util_find_row_propval (srow, PidTagAttachMethod);
-	if (attach_method && *attach_method == ATTACH_BY_VALUE) {
-		if (!e_mapi_util_find_array_propval (&attachment->properties, PidTagAttachDataBinary)) {
-			struct SBinary_short bin;
-
-			ms = fetch_object_property_as_stream (conn, mem_ctx, &obj_attach, PidTagAttachDataBinary, &bin, cancellable, perror);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "Attachment::fetch PidTagAttachDataBinary", ms);
-				goto cleanup;
-			}
-
-			attachment->properties.cValues++;
-			attachment->properties.lpProps = talloc_realloc (mem_ctx,
-									 attachment->properties.lpProps,
-									 struct mapi_SPropValue,
-									 attachment->properties.cValues + 1);
-			attachment->properties.lpProps[attachment->properties.cValues - 1].ulPropTag = PidTagAttachDataBinary;
-			attachment->properties.lpProps[attachment->properties.cValues - 1].value.bin = bin;
-			attachment->properties.lpProps[attachment->properties.cValues].ulPropTag = 0;
-		}
-	} else if (attach_method && *attach_method == ATTACH_EMBEDDED_MSG) {
-		mapi_object_t obj_emb_msg;
-
-		mapi_object_init (&obj_emb_msg);
-
-		if (OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_READONLY) == MAPI_E_SUCCESS) {
-			e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_emb_msg, foa->eap, &attachment->embedded_object, cancellable, perror);
-		}
-
-		mapi_object_release (&obj_emb_msg);
-	}
-
- cleanup:
-	mapi_object_release (&obj_attach);
-
-	if (ms == MAPI_E_SUCCESS) {
-		if (!foa->object->attachments) {
-			foa->object->attachments = attachment;
-		} else {
-			EMapiAttachment *attach = foa->object->attachments;
-			while (attach->next)
-				attach = attach->next;
-			attach->next = attachment;
-		}
-	} else {
-		e_mapi_attachment_free (attachment);
-	}
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-static enum MAPISTATUS
-e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
-					 TALLOC_CTX *mem_ctx,
-					 mapi_object_t *obj_message,
-					 struct EnsureAdditionalPropertiesData *eap,
-					 EMapiObject **out_object,
-					 GCancellable *cancellable,
-					 GError **perror)
-{
-	enum MAPISTATUS ms;
-	EMapiObject *object;
-	uint16_t ui16, uj16, np_count = 0, *np_propID = NULL;
-	uint32_t ui32;
-	struct MAPINAMEID *np_nameid = NULL;
-	const bool *has_attachments;
-	struct SPropTagArray recipient_proptags;
-	struct SRowSet recipient_rows;
-	mapi_object_t attach_table;
-
-	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (out_object != NULL, MAPI_E_INVALID_PARAMETER);
-
-	mapi_object_init (&attach_table);
-
-	object = e_mapi_object_new (mem_ctx);
-
-	ms = GetPropsAll (obj_message, MAPI_UNICODE, &object->properties);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetPropsAll", ms);
-		goto cleanup;
-	}
-
-	/* to transform named ids to their PidLid or PidName tags, like the fast-transfer does */
-	ms = QueryNamedProperties (obj_message, 0, NULL, &np_count, &np_propID, &np_nameid);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "QueryNamedProperties", ms);
-		goto cleanup;
-	}
-
-	if (np_count && np_propID && np_nameid) {
-		for (ui16 = 0; ui16 < np_count; ui16++) {
-			uint32_t proptag = np_propID[ui16];
-
-			for (uj16 = 0; uj16 < object->properties.cValues; uj16++) {
-				if (object->properties.lpProps[uj16].ulPropTag == proptag) {
-					uint32_t lid = MAPI_E_RESERVED;
-					char *guid;
-
-					guid = GUID_string (mem_ctx, &(np_nameid[ui16].lpguid));
-
-					if (np_nameid[ui16].ulKind == MNID_ID) {
-						if (e_mapi_nameid_lid_lookup_canonical (np_nameid[ui16].kind.lid, guid, &lid) != MAPI_E_SUCCESS)
-							lid = MAPI_E_RESERVED;
-					} else if (np_nameid[ui16].ulKind == MNID_STRING) {
-						if (e_mapi_nameid_string_lookup_canonical (np_nameid[ui16].kind.lpwstr.Name, guid, &lid) != MAPI_E_SUCCESS)
-							lid = MAPI_E_RESERVED;
-					}
-
-					talloc_free (guid);
-
-					if (lid != MAPI_E_RESERVED && (lid & 0xFFFF) == (proptag & 0xFFFF)) {
-						object->properties.lpProps[uj16].ulPropTag = lid;
-					}
-
-					break;
-				}
-			}
-		}
-	}
-
-	talloc_free (np_propID);
-	talloc_free (np_nameid);
-
-	/* ensure certain properties */
-	if (!e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
-		uint8_t best_body = 0;
-
-		if (GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML) {
-			struct SBinary_short bin;
-
-			ms = fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagHtml, &bin, cancellable, perror);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "Object::fetch PidTagHtml", ms);
-				goto cleanup;
-			}
-
-			object->properties.cValues++;
-			object->properties.lpProps = talloc_realloc (mem_ctx,
-								     object->properties.lpProps,
-								     struct mapi_SPropValue,
-								     object->properties.cValues + 1);
-			object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagHtml;
-			object->properties.lpProps[object->properties.cValues - 1].value.bin = bin;
-			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
-		}
-	}
-
-	if (!e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
-		struct SBinary_short bin;
-
-		if (fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagBody, &bin, cancellable, NULL) == MAPI_E_SUCCESS) {
-			object->properties.cValues++;
-			object->properties.lpProps = talloc_realloc (mem_ctx,
-								     object->properties.lpProps,
-								     struct mapi_SPropValue,
-								     object->properties.cValues + 1);
-			object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagBody;
-			if (bin.cb > 0 && bin.lpb[bin.cb - 1] == 0)
-				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = (const char *) talloc_steal (object, bin.lpb);
-			else
-				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strndup (object, (char *) bin.lpb, bin.cb);
-			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
-		}
-	}
-
-	if (!e_mapi_util_find_array_propval (&object->properties, PidNameContentClass)) {
-		uint32_t prop = PidNameContentClass;
-
-		prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
-		if (prop != MAPI_E_RESERVED) {
-			struct SPropTagArray *tags;
-			struct SPropValue *lpProps = NULL;
-			uint32_t prop_count = 0;
-
-			tags = set_SPropTagArray (mem_ctx, 1, prop);
-
-			if (GetProps (obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count) == MAPI_E_SUCCESS && lpProps) {
-				if (lpProps[0].ulPropTag == prop) {
-					object->properties.cValues++;
-					object->properties.lpProps = talloc_realloc (mem_ctx,
-										     object->properties.lpProps,
-										     struct mapi_SPropValue,
-										     object->properties.cValues + 1);
-					object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidNameContentClass;
-					object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strdup (object, lpProps[0].value.lpszW);
-					object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
-				}
-			}
-
-			talloc_free (tags);
-			talloc_free (lpProps);
-		}
-	}
-
-	/* fetch attachments */
-	has_attachments = e_mapi_util_find_array_propval (&object->properties, PidTagHasAttachments);
-	if (has_attachments && *has_attachments) {
-		struct SPropTagArray *attach_columns;
-		struct FetchObjectAttachmentData foa;
-
-		ms = GetAttachmentTable (obj_message, &attach_table);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "GetAttachmentTable", ms);
-			goto cleanup;
-		}
-
-		attach_columns = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
-		ms = SetColumns (&attach_table, attach_columns);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "AttachTable::SetColumns", ms);
-			talloc_free (attach_columns);
-			goto cleanup;
-		}
-		talloc_free (attach_columns);
-
-		foa.obj_message = obj_message;
-		foa.eap = eap;
-		foa.object = object;
-
-		ms = foreach_tablerow (conn, mapi_object_get_id (eap->obj_folder), mem_ctx, &attach_table, fetch_object_attachment_cb, &foa, cancellable, perror);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "AttachTable::foreach_tablerow", ms);
-			goto cleanup;
-		}
-	}
-
-	/* get recipients */
-	ms = GetRecipientTable (obj_message, &recipient_rows, &recipient_proptags);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetRecipientTable", ms);
-		goto cleanup;
-	}
-
-	if (recipient_rows.cRows > 0) {
-		uint32_t uj32, uk32;
-		EMapiRecipient *first_recipient = NULL;
-
-		for (ui32 = 0; ui32 < recipient_rows.cRows; ui32++) {
-			struct SRow *row = &recipient_rows.aRow[ui32];
-			EMapiRecipient *recipient;
-
-			recipient = e_mapi_recipient_new (object);
-			recipient->properties.cValues = row->cValues;
-			recipient->properties.lpProps = talloc_zero_array (recipient, struct mapi_SPropValue, recipient->properties.cValues + 1);
-
-			for (uj32 = 0, uk32 = 0; uj32 < row->cValues; uj32++, uk32++) {
-				if (may_skip_property (row->lpProps[uj32].ulPropTag) ||
-				    !e_mapi_utils_copy_to_mapi_SPropValue (recipient, &recipient->properties.lpProps[uk32], &row->lpProps[uj32])) {
-					uk32--;
-					recipient->properties.cValues--;
-					recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
-				}
-			}
-
-			recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
-		}
-
-		object->recipients = first_recipient;
-	}
-
- cleanup:
-	mapi_object_release (&attach_table);
-
-	if (ms == MAPI_E_SUCCESS) {
-		*out_object = object;
-	} else {
-		*out_object = NULL;
-		e_mapi_object_free (object);
-	}
-
-	return ms;
-}
-
-static enum MAPISTATUS
-e_mapi_connection_fetch_objects_internal (EMapiConnection *conn,
-					  TALLOC_CTX *mem_ctx,
-					  mapi_id_array_t *ids,
-					  struct EnsureAdditionalPropertiesData *eap,
-					  GCancellable *cancellable,
-					  GError **perror)
-{
-	enum MAPISTATUS ms;
-	guint32 idx;
-	mapi_container_list_t *element;
-
-	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (ids != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (eap->obj_folder != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (eap->downloaded < ids->count, MAPI_E_INVALID_PARAMETER);
-
-	for (idx = 0, element = ids->lpContainerList; idx < ids->count && idx < eap->downloaded && element; idx++) {
-		element = element->next;
-	}
-
-	g_return_val_if_fail (idx < ids->count, MAPI_E_INVALID_PARAMETER);
-
-	ms = MAPI_E_SUCCESS;
-	while (element && ms == MAPI_E_SUCCESS) {
-		mapi_object_t obj_message;
-		EMapiObject *object = NULL;
-		GError *local_error = NULL;
-
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			break;
-		}
-
-		mapi_object_init (&obj_message);
-
-		ms = OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), element->id, &obj_message, 0 /* read-only */);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "OpenMessage", ms);
-			mapi_object_release (&obj_message);
-			break;
-		}
-
-		/* silently skip broken objects */
-		ms = e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_message, eap, &object, cancellable, &local_error);
-		if (ms == MAPI_E_SUCCESS) {
-			if (!eap->cb (conn, mem_ctx, object, eap->downloaded, ids->count, eap->cb_user_data, cancellable, perror)) {
-				ms = MAPI_E_USER_CANCEL;
-				make_mapi_error (perror, "Object processing", ms);
-			}
-		} else {
-			e_mapi_debug_print ("%s: Skipping object %016" G_GINT64_MODIFIER "X because its fetch failed: %s",
-				G_STRFUNC, element->id, local_error ? local_error->message : mapi_get_errstr (ms));
-			ms = MAPI_E_SUCCESS;
-		}
-
-		e_mapi_object_free (object);
-		mapi_object_release (&obj_message);
-
-		eap->downloaded++;
-
-		element = element->next;
-	}
-
-	return ms;
-}
-
-/* deals with named IDs transparently, thus it's OK to check with PidLid and PidName constants only */
-gboolean
-e_mapi_connection_transfer_objects (EMapiConnection *conn,
-				    mapi_object_t *obj_folder,
-				    const GSList *mids,
-				    TransferObjectCB cb,
-				    gpointer cb_user_data,
-				    GCancellable *cancellable,
-				    GError **perror)
-{
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	mapi_id_array_t ids;
-	const GSList *iter;
-	struct EnsureAdditionalPropertiesData eap;
-
-	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 (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
-
-	ms = mapi_id_array_init (priv->mapi_ctx, &ids);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "mapi_id_array_init", ms);
-		goto cleanup;
-	}
-
-	for (iter = mids; iter; iter = iter->next) {
-		mapi_id_t *pmid = iter->data;
-
-		if (pmid)
-			mapi_id_array_add_id (&ids, *pmid);
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		mapi_id_array_release (&ids);
-		goto cleanup;
-	}
-
-	eap.cb = cb;
-	eap.cb_user_data = cb_user_data;
-	eap.obj_folder = obj_folder;
-	eap.downloaded = 0;
-
-	ms = e_mapi_fast_transfer_objects (conn, mem_ctx, obj_folder, &ids, ensure_additional_properties_cb, &eap, cancellable, perror);
-	if (ms == MAPI_E_CALL_FAILED) {
-		/* err, fallback to slow transfer, probably FXGetBuffer failed;
-		   see http://tracker.openchange.org/issues/378
-		*/
-
-		g_clear_error (perror);
-
-		e_mapi_debug_print ("%s: Failed to fast-transfer, fallback to slow fetch from %d of %d objects\n", G_STRFUNC, eap.downloaded, ids.count);
-
-		ms = e_mapi_connection_fetch_objects_internal (conn, mem_ctx, &ids, &eap, cancellable, perror);
-	}
-
-	mapi_id_array_release (&ids);
-
- cleanup:
-	talloc_free (mem_ctx);
-	UNLOCK ();
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-gboolean
-e_mapi_connection_transfer_object (EMapiConnection *conn,
-				   mapi_object_t *obj_folder,
-				   mapi_id_t message_id,
-				   TransferObjectCB cb,
-				   gpointer cb_user_data,
-				   GCancellable *cancellable,
-				   GError **perror)
-{
-	GSList *mids;
-	gboolean res;
-
-	mids = g_slist_append (NULL, &message_id);
-	res = e_mapi_connection_transfer_objects (conn, obj_folder, mids, cb, cb_user_data, cancellable, perror);
-	g_slist_free (mids);
-
-	return res;
-}
-
-struct GetSummaryData {
-	guint32 obj_index;
-	guint32 obj_total;
-	struct SPropValue *lpProps;
-	uint32_t prop_count;
-	TransferObjectCB cb;
-	gpointer cb_user_data;
-};
-
-static gboolean
-internal_get_summary_cb (EMapiConnection *conn,
-			 TALLOC_CTX *mem_ctx,
-			 /* const */ EMapiObject *object,
-			 guint32 obj_index,
-			 guint32 obj_total,
-			 gpointer user_data,
-			 GCancellable *cancellable,
-			 GError **perror)
-{
-	struct GetSummaryData *gsd = user_data;
-
-	g_return_val_if_fail (gsd != NULL, FALSE);
-	g_return_val_if_fail (gsd->cb != NULL, FALSE);
-	g_return_val_if_fail (object != NULL, FALSE);
-
-	/* also include properties received from GetProps,
-	   as those like PR_MID are not included by default */
-	if (gsd->lpProps && gsd->prop_count > 0) {
-		uint32_t ii;
-
-		for (ii = 0; ii < gsd->prop_count; ii++) {
-			/* skip errors and already included properties */
-			if ((gsd->lpProps[ii].ulPropTag & 0xFFFF) == PT_ERROR
-			    || e_mapi_util_find_array_propval (&object->properties, gsd->lpProps[ii].ulPropTag))
-				continue;
-
-			object->properties.cValues++;
-			object->properties.lpProps = talloc_realloc (mem_ctx,
-					    object->properties.lpProps,
-					    struct mapi_SPropValue,
-					    object->properties.cValues + 1);
-			cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &gsd->lpProps[ii]);
-			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
-		}
-	}
-
-	return gsd->cb (conn, mem_ctx, object, gsd->obj_index, gsd->obj_total, gsd->cb_user_data, cancellable, perror);
-}
-
-/* transfers items summary, which is either PR_TRANSPORT_MESSAGE_HEADERS_UNICODE or
-   the object without attachment */
-gboolean
-e_mapi_connection_transfer_summary (EMapiConnection *conn,
-				    mapi_object_t *obj_folder,
-				    const GSList *mids,
-				    TransferObjectCB cb,
-				    gpointer cb_user_data,
-				    GCancellable *cancellable,
-				    GError **perror)
-{
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	const GSList *iter;
-	guint32 index, total;
-
-	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 (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
-
-	ms = MAPI_E_SUCCESS;
-	total = g_slist_length ((GSList *) mids);
-	for (iter = mids, index = 0; iter && ms == MAPI_E_SUCCESS; iter = iter->next, index++) {
-		mapi_id_t *pmid = iter->data;
-
-		if (pmid) {
-			mapi_object_t obj_message;
-			struct SPropTagArray *tags;
-			struct SPropValue *lpProps = NULL;
-			uint32_t prop_count = 0, ii;
-
-			mapi_object_init (&obj_message);
-
-			ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), *pmid, &obj_message, 0);
-			if (ms != MAPI_E_SUCCESS && ms != MAPI_E_NOT_FOUND) {
-				make_mapi_error (perror, "OpenMessage", ms);
-				goto cleanup;
-			}
-
-			tags = set_SPropTagArray (mem_ctx, 6,
-				PR_FID,
-				PR_MID,
-				PR_MESSAGE_FLAGS,
-				PR_LAST_MODIFICATION_TIME,
-				PR_MESSAGE_CLASS,
-				PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
-
-			ms = GetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count);
-			if (ms == MAPI_E_SUCCESS) {
-				ms = MAPI_E_NOT_FOUND;
-				if (lpProps && prop_count > 0) {
-					const gchar *headers = e_mapi_util_find_SPropVal_array_propval (lpProps, PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
-
-					if (headers && *headers) {
-						EMapiObject *object;
-
-						ms = MAPI_E_SUCCESS;
-
-						object = e_mapi_object_new (mem_ctx);
-						for (ii = 0; ii < prop_count; ii++) {
-							object->properties.cValues++;
-							object->properties.lpProps = talloc_realloc (mem_ctx,
-									    object->properties.lpProps,
-									    struct mapi_SPropValue,
-									    object->properties.cValues + 1);
-							cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &lpProps[ii]);
-							object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
-						}
-
-						if (!cb (conn, mem_ctx, object, index, total, cb_user_data, cancellable, perror)) {
-							ms = MAPI_E_USER_CANCEL;
-							e_mapi_object_free (object);
-							mapi_object_release (&obj_message);
-							goto cleanup;
-						}
-
-						e_mapi_object_free (object);
-					}
-				}
-			}
-
-			if (ms == MAPI_E_NOT_FOUND) {
-				struct GetSummaryData gsd;
-
-				gsd.obj_index = index;
-				gsd.obj_total = total;
-				gsd.lpProps = lpProps;
-				gsd.prop_count = prop_count;
-				gsd.cb = cb;
-				gsd.cb_user_data = cb_user_data;
-
-				ms = e_mapi_fast_transfer_object (conn, mem_ctx, &obj_message, E_MAPI_FAST_TRANSFER_FLAG_RECIPIENTS, internal_get_summary_cb, &gsd, cancellable, perror);
-				if (ms != MAPI_E_SUCCESS) {
-					make_mapi_error (perror, "transfer_object", ms);
-					mapi_object_release (&obj_message);
-					goto cleanup;
-				}
-			}
-
-			mapi_object_release (&obj_message);
-			talloc_free (tags);
-		}
-
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
-	}
-
- cleanup:
-	talloc_free (mem_ctx);
-	UNLOCK ();
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-typedef struct {
-	uint32_t proptag;
-	uint32_t cb;
-	const uint8_t *lpb; /* taken from the original mapi prop, no need to copy the memory */
-} EMapiStreamedProp;
-
-static gboolean
-convert_mapi_props_to_props (EMapiConnection *conn,
-			     mapi_object_t *obj_folder,
-			     const struct mapi_SPropValue_array *mapi_props,
-			     struct SPropValue **props,
-			     uint32_t *propslen,
-			     EMapiStreamedProp **streams, /* can be NULL for no streaming */
-			     guint *streamslen, /* can be NULL only if streams is NULL; is ignored if streams is NULL */
-			     TALLOC_CTX *mem_ctx,
-			     GCancellable *cancellable,
-			     GError **perror)
-{
-	uint16_t ii;
-	ResolveNamedIDsData *named_ids_list = NULL;
-	guint named_ids_len = 0;
-	gboolean res = TRUE;
-
-	e_return_val_mapi_error_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (mapi_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (propslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	if (streams) {
-		e_return_val_mapi_error_if_fail (streamslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	}
-
-	for (ii = 0; ii < mapi_props->cValues; ii++) {
-		gboolean processed = FALSE;
-		uint32_t proptag = mapi_props->lpProps[ii].ulPropTag;
-		gconstpointer propdata = get_mapi_SPropValue_data (&mapi_props->lpProps[ii]);
-
-		maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
-
-		if (streams && propdata) {
-			/* copy anything longer than 1KB as streams; this doesn't count total packet size needed,
-			   but because this is usually useful only for PidTagBody, PidTagHtml, which are there
-			   only once, then no big deal
-			*/
-
-			uint32_t sz;
-			const gchar *str;
-			const struct SBinary_short *bin;
-
-			#define addstream() {										\
-					if (!*streams) {								\
-						*streams = g_new0 (EMapiStreamedProp, 1);				\
-						*streamslen = 0;							\
-					} else {									\
-						*streams = g_renew (EMapiStreamedProp, *streams, *streamslen + 1);	\
-					}										\
-															\
-					(*streams)[*streamslen].proptag = proptag;					\
-					(*streams)[*streamslen].cb = 0;							\
-					(*streams)[*streamslen].lpb = NULL;						\
-					(*streamslen) += 1;								\
-				}
-
-			switch (proptag & 0xFFFF) {
-			case PT_BINARY:
-				bin = propdata;
-				if (bin->cb > MAX_PROPERTY_WRITE_SIZE) {
-					addstream ();
-					(*streams)[(*streamslen) - 1].cb = bin->cb;
-					(*streams)[(*streamslen) - 1].lpb = bin->lpb;
-					processed = TRUE;
-				}
-				break;
-			case PT_STRING8:
-				str = propdata;
-				sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
-				if (sz > MAX_PROPERTY_WRITE_SIZE) {
-					addstream ();
-					(*streams)[(*streamslen) - 1].cb = sz;
-					(*streams)[(*streamslen) - 1].lpb = (uint8_t *) str;
-					processed = TRUE;
-				}
-				break;
-			case PT_UNICODE:
-				str = propdata;
-				sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
-				if (sz > MAX_PROPERTY_WRITE_SIZE) {
-					gchar *in_unicode;
-					gsize written = 0;
-
-					addstream ();
-
-					in_unicode = g_convert (str, strlen (str), "UTF-16", "UTF-8", NULL, &written, NULL);
-					if (in_unicode && written > 0) {
-						uint8_t *bytes = talloc_zero_size (mem_ctx, written + 2);
-
-						/* skip Unicode marker, if there */
-						if (written >= 2 && (const guchar) in_unicode[0] == 0xFF && (const guchar) in_unicode[1] == 0xFE) {
-							memcpy (bytes, in_unicode + 2, written - 2);
-							written -= 2;
-						} else
-							memcpy (bytes, in_unicode, written);
-
-						/* null-terminated unicode string */
-						(*streams)[(*streamslen) - 1].lpb = bytes;
-						(*streams)[(*streamslen) - 1].cb = written + 2;
-					}
-					g_free (in_unicode);
-					processed = TRUE;
-				}
-				break;
-			}
-
-			#undef addstream
-		}
-
-		if (!processed)
-			e_mapi_utils_add_spropvalue (mem_ctx, props, propslen, proptag, propdata);
-	}
-
-	if (named_ids_list) {
-		res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
-
-		if (res && *props) {
-			for (ii = 0; ii < *propslen; ii++) {
-				uint32_t proptag = (*props)[ii].ulPropTag;
-
-				maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
-
-				(*props)[ii].ulPropTag = proptag;
-			}
-		}
-
-		if (res && streams) {
-			for (ii = 0; ii < *streamslen; ii++) {
-				maybe_replace_named_id_tag (&((*streams)[ii].proptag), named_ids_list, named_ids_len);
-			}
-		}
-	}
-
-	g_free (named_ids_list);
-
-	return res;
-}
-
-static gboolean
-write_streamed_prop (EMapiConnection *conn,
-		     mapi_object_t *obj_object,
-		     const EMapiStreamedProp *stream,
-		     GCancellable *cancellable,
-		     GError **perror)
-{
-	enum MAPISTATUS	ms;
-	uint32_t total_written;
-	gboolean done = FALSE;
-	mapi_object_t obj_stream;
-
-	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_object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (stream != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	LOCK ();
-
-	mapi_object_init (&obj_stream);
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
-
-	/* OpenStream on required proptag */
-	ms = OpenStream (obj_object, stream->proptag, STREAM_ACCESS_READWRITE, &obj_stream);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenStream", ms);
-		goto cleanup;
-	}
+		if (ms == 0x2c80)
+			max_read = max_read >> 1;
+		else
+			max_read = STREAM_MAX_READ_SIZE_DF;
 
-	/* Set the stream size */
-	ms = SetStreamSize (&obj_stream, stream->cb);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetStreamSize", ms);
-		goto cleanup;
-	}
+		if (max_read < STREAM_MAX_READ_SIZE_DF)
+			max_read = STREAM_MAX_READ_SIZE_DF;
+	} while (ms == 0x2c80); /* an error when max_read is too large? */
 
-	total_written = 0;
-	/* Write stream */
 	while (!done) {
-		uint16_t cn_written = 0;
-		DATA_BLOB blob;
-
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
-
-		blob.length = (stream->cb - total_written) < STREAM_MAX_WRITE_SIZE ?
-			      (stream->cb - total_written) : STREAM_MAX_WRITE_SIZE;
-		blob.data = (uint8_t *) (stream->lpb + total_written);
-
-		ms = WriteStream (&obj_stream, &blob, &cn_written);
+		ms = ReadStream (&obj_stream, bin->lpb + off_data, max_read, &cn_read);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "WriteStream", ms);
+			make_mapi_error (perror, "ReadStream", ms);
 			done = TRUE;
-		} else if (cn_written == 0) {
+		} else if (cn_read == 0) {
 			done = TRUE;
 		} else {
-			total_written += cn_written;
-			if (total_written >= stream->cb)
+			off_data += cn_read;
+			if (off_data >= buf_size)
 				done = TRUE;
 		}
 	}
 
-	if (ms == MAPI_E_SUCCESS) {
-		/* Commit the stream */
-		ms = CommitStream (&obj_stream);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "CommitStream", ms);
-			goto cleanup;
-		}
-	}
-
  cleanup:
 	mapi_object_release (&obj_stream);
 
-	UNLOCK ();
-
-	return ms == MAPI_E_SUCCESS;
+	return ms;
 }
 
+static enum MAPISTATUS
+e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
+					 TALLOC_CTX *mem_ctx,
+					 mapi_object_t *obj_message,
+					 struct EnsureAdditionalPropertiesData *eap,
+					 EMapiObject **out_object,
+					 GCancellable *cancellable,
+					 GError **perror);
+
+struct FetchObjectAttachmentData
+{
+	mapi_object_t *obj_message;
+	struct EnsureAdditionalPropertiesData *eap;
+	EMapiObject *object; /* to add attachments to */
+};
+
 static gboolean
-update_props_on_object (EMapiConnection *conn,
-			mapi_object_t *obj_folder,
-			mapi_object_t *obj_object,
-			const struct mapi_SPropValue_array *properties,
-			TALLOC_CTX *mem_ctx,
-			GCancellable *cancellable,
-			GError **perror)
+fetch_object_attachment_cb (EMapiConnection *conn,
+			    TALLOC_CTX *mem_ctx,
+			    struct SRow *srow,
+			    guint32 row_index,
+			    guint32 rows_total,
+			    gpointer user_data,
+			    GCancellable *cancellable,
+			    GError **perror)
 {
-	enum MAPISTATUS	ms;
-	struct SPropValue *props = NULL;
-	uint32_t propslen = 0;
-	EMapiStreamedProp *streams = NULL;
-	guint streamslen = 0;
+	enum MAPISTATUS ms;
+	struct FetchObjectAttachmentData *foa = user_data;
+	EMapiAttachment *attachment = NULL;
+	mapi_object_t obj_attach;
+	const uint32_t *attach_num, *attach_method;
 
-	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 (conn != NULL, FALSE);
+	g_return_val_if_fail (mem_ctx != NULL, FALSE);
+	g_return_val_if_fail (srow != NULL, FALSE);
+	g_return_val_if_fail (user_data != NULL, FALSE);
+	g_return_val_if_fail (foa->obj_message != NULL, FALSE);
+	g_return_val_if_fail (foa->object != NULL, FALSE);
 
-	LOCK ();
+	mapi_object_init (&obj_attach);
 
-	if (!convert_mapi_props_to_props (conn, obj_folder, properties, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
-		ms = MAPI_E_CALL_FAILED;
-		make_mapi_error (perror, "convert_mapi_props_to_props", ms);
-		goto cleanup;
-	}
+	attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
+	if (!attach_num)
+		return FALSE;
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
+	ms = OpenAttach (foa->obj_message, *attach_num, &obj_attach);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenAttach", ms);
 		goto cleanup;
 	}
 
-	if (props) {
-		/* set properties for the item */
-		ms = SetProps (obj_object, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
-
-		talloc_free (props);
-
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SetProps", ms);
-			goto cleanup;
-		}
-	}
+	attachment = e_mapi_attachment_new (foa->object);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
+	ms = GetPropsAll (&obj_attach, MAPI_UNICODE, &attachment->properties);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "Attachment::GetPropsAll", ms);
 		goto cleanup;
 	}
 
-	if (streams) {
-		guint ii;
+	attach_method = e_mapi_util_find_row_propval (srow, PidTagAttachMethod);
+	if (attach_method && *attach_method == ATTACH_BY_VALUE) {
+		if (!e_mapi_util_find_array_propval (&attachment->properties, PidTagAttachDataBinary)) {
+			struct SBinary_short bin;
 
-		for (ii = 0; ii < streamslen; ii++) {
-			if (!write_streamed_prop (conn, obj_object, &streams[ii], cancellable, perror)) {
-				ms = MAPI_E_CALL_FAILED;
-				make_mapi_error (perror, "write_streamed_prop", ms);
-				break;
+			ms = fetch_object_property_as_stream (conn, mem_ctx, &obj_attach, PidTagAttachDataBinary, &bin, cancellable, perror);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "Attachment::fetch PidTagAttachDataBinary", ms);
+				goto cleanup;
 			}
 
-			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-				ms = MAPI_E_USER_CANCEL;
-				break;
-			}
+			attachment->properties.cValues++;
+			attachment->properties.lpProps = talloc_realloc (mem_ctx,
+									 attachment->properties.lpProps,
+									 struct mapi_SPropValue,
+									 attachment->properties.cValues + 1);
+			attachment->properties.lpProps[attachment->properties.cValues - 1].ulPropTag = PidTagAttachDataBinary;
+			attachment->properties.lpProps[attachment->properties.cValues - 1].value.bin = bin;
+			attachment->properties.lpProps[attachment->properties.cValues].ulPropTag = 0;
 		}
+	} else if (attach_method && *attach_method == ATTACH_EMBEDDED_MSG) {
+		mapi_object_t obj_emb_msg;
 
-		g_free (streams);
-	}
- cleanup:
-	UNLOCK ();
-
-	return ms == MAPI_E_SUCCESS;
-}
-
-static gboolean
-update_recipient_properties (EMapiConnection *conn,
-			     mapi_object_t *obj_folder,
-			     struct SRow *aRow,
-			     EMapiRecipient *recipient,
-			     gboolean is_resolved,
-			     TALLOC_CTX *mem_ctx,
-			     GCancellable *cancellable,
-			     GError **perror)
-{
-	struct SPropValue *props = NULL;
-	uint32_t propslen = 0, ii;
-
-	g_return_val_if_fail (recipient != NULL, FALSE);
+		mapi_object_init (&obj_emb_msg);
 
-	if (!convert_mapi_props_to_props (conn, obj_folder, &recipient->properties, &props, &propslen, NULL, NULL, mem_ctx, cancellable, perror))
-		return FALSE;
+		if (OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_READONLY) == MAPI_E_SUCCESS) {
+			e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_emb_msg, foa->eap, &attachment->embedded_object, cancellable, perror);
+		}
 
-	for (ii = 0; ii < propslen; ii++) {
-		/* do not overwrite all properties, if recipient was resolved properly */
-		if (!is_resolved
-		    || props[ii].ulPropTag == PidTagRecipientType
-		    || props[ii].ulPropTag == PidTagSendInternetEncoding
-		    || props[ii].ulPropTag == PidTagRecipientFlags
-		    || props[ii].ulPropTag == PidTagRecipientTrackStatus)
-			SRow_addprop (aRow, props[ii]);
+		mapi_object_release (&obj_emb_msg);
 	}
 
-	return TRUE;
-}
-
-static gboolean
-delete_object_recipients (EMapiConnection *conn,
-			  mapi_object_t *obj_folder,
-			  mapi_object_t *obj_object,
-			  TALLOC_CTX *mem_ctx,
-			  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);
-
-	LOCK ();
-
-	ms = RemoveAllRecipients (obj_object);
-	if (ms != MAPI_E_SUCCESS)
-		make_mapi_error (perror, "RemoveAllRecipients", ms);
+ cleanup:
+	mapi_object_release (&obj_attach);
 
-	UNLOCK ();
+	if (ms == MAPI_E_SUCCESS) {
+		if (!foa->object->attachments) {
+			foa->object->attachments = attachment;
+		} else {
+			EMapiAttachment *attach = foa->object->attachments;
+			while (attach->next)
+				attach = attach->next;
+			attach->next = attachment;
+		}
+	} else {
+		e_mapi_attachment_free (attachment);
+	}
 
 	return ms == MAPI_E_SUCCESS;
 }
 
-static gboolean
-add_object_recipients (EMapiConnection *conn,
-		       mapi_object_t *obj_folder,
-		       mapi_object_t *obj_message,
-		       EMapiRecipient *recipients,
-		       TALLOC_CTX *mem_ctx,
-		       GCancellable *cancellable,
-		       GError **perror)
+static enum MAPISTATUS
+e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
+					 TALLOC_CTX *mem_ctx,
+					 mapi_object_t *obj_message,
+					 struct EnsureAdditionalPropertiesData *eap,
+					 EMapiObject **out_object,
+					 GCancellable *cancellable,
+					 GError **perror)
 {
-	const uint32_t required_tags[] = {PidTagEntryId,
-					  PidTagDisplayName,
-					  PidTagObjectType,
-					  PidTagDisplayType,
-					  PidTagTransmittableDisplayName,
-					  PidTagEmailAddress,
-					  PidTagAddressType,
-					  PidTagSendRichInfo,
-					  PidTag7BitDisplayName};
-	enum MAPISTATUS	ms;
-	struct SPropTagArray *tags;
-	struct SRowSet *rows = NULL;
-	struct PropertyTagArray_r *flagList = NULL;
-	ResolveNamedIDsData *named_ids_list = NULL;
-	guint named_ids_len = 0;
-	const gchar **users = NULL;
-	EMapiRecipient *recipient;
-	EMapiRecipient **recips;
-	uint32_t ii, jj, count = 0;
-	GHashTable *all_proptags;
-	GHashTableIter iter;
-	gpointer key, value;
-
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	count = 0;
-	for (recipient = recipients, ii = 0; recipient; recipient = recipient->next, ii++) {
-		if (!e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress)
-		    && !e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName))
-			g_debug ("%s: Cannot get email or display name for a recipient %d, skipping it", G_STRFUNC, ii);
-		else
-			count++;
-	}
+	enum MAPISTATUS ms;
+	EMapiObject *object;
+	uint16_t ui16, uj16, np_count = 0, *np_propID = NULL;
+	uint32_t ui32;
+	struct MAPINAMEID *np_nameid = NULL;
+	const bool *has_attachments;
+	struct SPropTagArray recipient_proptags;
+	struct SRowSet recipient_rows;
+	mapi_object_t attach_table;
 
-	if (!count)
-		return TRUE;
+	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (out_object != NULL, MAPI_E_INVALID_PARAMETER);
 
-	LOCK ();
+	mapi_object_init (&attach_table);
 
-	all_proptags = g_hash_table_new (g_direct_hash, g_direct_equal);
-	users = g_new0 (const gchar *, count + 1);
-	recips = g_new0 (EMapiRecipient *, count + 1);
+	object = e_mapi_object_new (mem_ctx);
 
-	for (ii = 0; ii < G_N_ELEMENTS (required_tags); ii++) {
-		g_hash_table_insert (all_proptags, GUINT_TO_POINTER (required_tags[ii]), GUINT_TO_POINTER (1));
+	ms = GetPropsAll (obj_message, MAPI_UNICODE, &object->properties);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "GetPropsAll", ms);
+		goto cleanup;
 	}
 
-	for (ii = 0, jj = 0, recipient = recipients; ii < count && recipient != NULL; ii++, recipient = recipient->next) {
-		users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress);
-		if (!users[ii])
-			users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName);
-		if (!users[ii]) {
-			ii--;
-		} else {
-			uint32_t kk;
-
-			recips[jj] = recipient;
-			jj++;
-
-			for (kk = 0; kk < recipient->properties.cValues; kk++) {
-				g_hash_table_insert (all_proptags, GUINT_TO_POINTER (recipient->properties.lpProps[kk].ulPropTag), GUINT_TO_POINTER (1));
-			}
-		}
+	/* to transform named ids to their PidLid or PidName tags, like the fast-transfer does */
+	ms = QueryNamedProperties (obj_message, 0, NULL, &np_count, &np_propID, &np_nameid);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "QueryNamedProperties", ms);
+		goto cleanup;
 	}
 
-	/* Attempt to resolve names from the server */
-	tags = NULL;
-	g_hash_table_iter_init (&iter, all_proptags);
-	while (g_hash_table_iter_next (&iter, &key, &value)) {
-		uint32_t proptag = GPOINTER_TO_UINT (key);
+	if (np_count && np_propID && np_nameid) {
+		for (ui16 = 0; ui16 < np_count; ui16++) {
+			uint32_t proptag = np_propID[ui16];
 
-		maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+			for (uj16 = 0; uj16 < object->properties.cValues; uj16++) {
+				if (object->properties.lpProps[uj16].ulPropTag == proptag) {
+					uint32_t lid = MAPI_E_RESERVED;
+					char *guid;
 
-		if (!tags)
-			tags = set_SPropTagArray (mem_ctx, 1, proptag);
-		else
-			SPropTagArray_add (mem_ctx, tags, proptag);
-	}
+					guid = GUID_string (mem_ctx, &(np_nameid[ui16].lpguid));
 
-	if (named_ids_list) {
-		if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
-			ms = MAPI_E_CALL_FAILED;
-			make_mapi_error (perror, "e_mapi_connection_resolve_named_props", ms);
-			goto cleanup;
-		}
+					if (np_nameid[ui16].ulKind == MNID_ID) {
+						if (e_mapi_nameid_lid_lookup_canonical (np_nameid[ui16].kind.lid, guid, &lid) != MAPI_E_SUCCESS)
+							lid = MAPI_E_RESERVED;
+					} else if (np_nameid[ui16].ulKind == MNID_STRING) {
+						if (e_mapi_nameid_string_lookup_canonical (np_nameid[ui16].kind.lpwstr.Name, guid, &lid) != MAPI_E_SUCCESS)
+							lid = MAPI_E_RESERVED;
+					}
 
-		for (ii = 0; ii < tags->cValues; ii++) {
-			uint32_t proptag = tags->aulPropTag[ii];
+					talloc_free (guid);
 
-			maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
+					if (lid != MAPI_E_RESERVED && (lid & 0xFFFF) == (proptag & 0xFFFF)) {
+						object->properties.lpProps[uj16].ulPropTag = lid;
+					}
 
-			tags->aulPropTag[ii] = proptag;
+					break;
+				}
+			}
 		}
 	}
 
-	ms = ResolveNames (priv->session, users, tags, &rows, &flagList, MAPI_UNICODE);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "ResolveNames", ms);
-		goto cleanup;
-	}
-
-	g_assert (count == flagList->cValues);
-
-	if (!rows) /* This happens when there are ZERO RESOLVED recipients */
-		rows = talloc_zero (mem_ctx, struct SRowSet);
+	talloc_free (np_propID);
+	talloc_free (np_nameid);
 
-	for (ii = 0, jj = 0; ii < count; ii++) {
-		recipient = recips[ii];
+	/* ensure certain properties */
+	if (!e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
+		uint8_t best_body = 0;
 
-		if (flagList->aulPropTag[ii] == MAPI_AMBIGUOUS) {
-			/* We should never get an ambiguous resolution as we use the email-id for resolving.
-			 * However, if we do still get an ambiguous entry, we can't handle it :-( */
-			ms = MAPI_E_AMBIGUOUS_RECIP;
-			/* Translators: %s is replaced with an email address which was found ambiguous on a remote server */
-			g_set_error (perror, E_MAPI_ERROR, ms, _("Recipient '%s' is ambiguous"), users[ii]);
-			goto cleanup;
-		} else if (flagList->aulPropTag[ii] == MAPI_UNRESOLVED) {
-			uint32_t last;
+		if (GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML) {
+			struct SBinary_short bin;
 
-			/* If the recipient is unresolved, consider it is a SMTP one */
-			rows->aRow = talloc_realloc (mem_ctx, rows->aRow, struct SRow, rows->cRows + 1);
-			last = rows->cRows;
-			rows->aRow[last].cValues = 0;
-			rows->aRow[last].lpProps = talloc_zero (mem_ctx, struct SPropValue);
-			if (!update_recipient_properties (conn, obj_folder, &rows->aRow[last], recipient, FALSE, mem_ctx, cancellable, perror)) {
-				ms = MAPI_E_CALL_FAILED;
-				goto cleanup;
-			}
-			rows->cRows += 1;
-		} else if (flagList->aulPropTag[ii] == MAPI_RESOLVED) {
-			if (!update_recipient_properties (conn, obj_folder, &rows->aRow[jj], recipient, TRUE, mem_ctx, cancellable, perror)) {
-				ms = MAPI_E_CALL_FAILED;
+			ms = fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagHtml, &bin, cancellable, perror);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "Object::fetch PidTagHtml", ms);
 				goto cleanup;
 			}
-			jj += 1;
-		}
-	}
 
-	/* Modify the recipient table */
-	ms = ModifyRecipients (obj_message, rows);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "ModifyRecipients", ms);
-		goto cleanup;
+			object->properties.cValues++;
+			object->properties.lpProps = talloc_realloc (mem_ctx,
+								     object->properties.lpProps,
+								     struct mapi_SPropValue,
+								     object->properties.cValues + 1);
+			object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagHtml;
+			object->properties.lpProps[object->properties.cValues - 1].value.bin = bin;
+			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+		}
 	}
 
- cleanup:
-	UNLOCK ();
+	if (!e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
+		struct SBinary_short bin;
 
-	g_free (users);
-	g_free (recips);
-	g_free (named_ids_list);
-	g_hash_table_destroy (all_proptags);
+		if (fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagBody, &bin, cancellable, NULL) == MAPI_E_SUCCESS) {
+			object->properties.cValues++;
+			object->properties.lpProps = talloc_realloc (mem_ctx,
+								     object->properties.lpProps,
+								     struct mapi_SPropValue,
+								     object->properties.cValues + 1);
+			object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagBody;
+			if (bin.cb > 0 && bin.lpb[bin.cb - 1] == 0)
+				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = (const char *) talloc_steal (object, bin.lpb);
+			else
+				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strndup (object, (char *) bin.lpb, bin.cb);
+			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+		}
+	}
 
-	return ms == MAPI_E_SUCCESS;
-}
+	if (!e_mapi_util_find_array_propval (&object->properties, PidNameContentClass)) {
+		uint32_t prop = PidNameContentClass;
 
-static gboolean
-delete_attachment_cb (EMapiConnection *conn,
-		      mapi_id_t fid,
-		      TALLOC_CTX *mem_ctx,
-		      struct SRow *srow,
-		      guint32 row_index,
-		      guint32 rows_total,
-		      gpointer user_data,
-		      GCancellable *cancellable,
-		      GError **perror)
-{
-	const uint32_t *attach_num;
-	mapi_object_t *obj_object = user_data;
-	enum MAPISTATUS ms;
+		prop = e_mapi_connection_resolve_named_prop (conn, mapi_object_get_id (eap->obj_folder), prop, cancellable, NULL);
+		if (prop != MAPI_E_RESERVED) {
+			struct SPropTagArray *tags;
+			struct SPropValue *lpProps = NULL;
+			uint32_t prop_count = 0;
 
-	g_return_val_if_fail (obj_object != NULL, FALSE);
+			tags = set_SPropTagArray (mem_ctx, 1, prop);
 
-	attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
-	g_return_val_if_fail (attach_num != NULL, FALSE);
+			if (GetProps (obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count) == MAPI_E_SUCCESS && lpProps) {
+				if (lpProps[0].ulPropTag == prop) {
+					object->properties.cValues++;
+					object->properties.lpProps = talloc_realloc (mem_ctx,
+										     object->properties.lpProps,
+										     struct mapi_SPropValue,
+										     object->properties.cValues + 1);
+					object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidNameContentClass;
+					object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strdup (object, lpProps[0].value.lpszW);
+					object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+				}
+			}
 
-	ms = DeleteAttach (obj_object, *attach_num);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "DeleteAttach", ms);
+			talloc_free (tags);
+			talloc_free (lpProps);
+		}
 	}
 
-	return ms == MAPI_E_SUCCESS;
-}
+	/* fetch attachments */
+	has_attachments = e_mapi_util_find_array_propval (&object->properties, PidTagHasAttachments);
+	if (has_attachments && *has_attachments) {
+		struct SPropTagArray *attach_columns;
+		struct FetchObjectAttachmentData foa;
 
-static gboolean
-delete_object_attachments (EMapiConnection *conn,
-			   mapi_object_t *obj_folder,
-			   mapi_object_t *obj_object,
-			   TALLOC_CTX *mem_ctx,
-			   GCancellable *cancellable,
-			   GError **perror)
-{
-	enum MAPISTATUS ms;
-	mapi_object_t obj_table;
-	struct SPropTagArray *proptags;
+		ms = GetAttachmentTable (obj_message, &attach_table);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "GetAttachmentTable", ms);
+			goto cleanup;
+		}
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+		attach_columns = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
+		ms = SetColumns (&attach_table, attach_columns);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "AttachTable::SetColumns", ms);
+			talloc_free (attach_columns);
+			goto cleanup;
+		}
+		talloc_free (attach_columns);
 
-	LOCK ();
+		foa.obj_message = obj_message;
+		foa.eap = eap;
+		foa.object = object;
 
-	mapi_object_init (&obj_table);
+		ms = foreach_tablerow (conn, mem_ctx, &attach_table, fetch_object_attachment_cb, &foa, cancellable, perror);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "AttachTable::foreach_tablerow", ms);
+			goto cleanup;
+		}
+	}
 
-	/* open attachment table */
-	ms = GetAttachmentTable (obj_object, &obj_table);
+	/* get recipients */
+	ms = GetRecipientTable (obj_message, &recipient_rows, &recipient_proptags);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetAttachmentTable", ms);
+		make_mapi_error (perror, "GetRecipientTable", ms);
 		goto cleanup;
 	}
 
-	proptags = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
+	if (recipient_rows.cRows > 0) {
+		uint32_t uj32, uk32;
+		EMapiRecipient *first_recipient = NULL;
 
-	ms = SetColumns (&obj_table, proptags);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetColumns", ms);
-		goto cleanup;
-	}
+		for (ui32 = 0; ui32 < recipient_rows.cRows; ui32++) {
+			struct SRow *row = &recipient_rows.aRow[ui32];
+			EMapiRecipient *recipient;
 
-	ms = foreach_tablerow (conn, mapi_object_get_id (obj_folder), mem_ctx, &obj_table, delete_attachment_cb, obj_object, cancellable, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "foreach_tablerow", ms);
+			recipient = e_mapi_recipient_new (object);
+			recipient->properties.cValues = row->cValues;
+			recipient->properties.lpProps = talloc_zero_array (recipient, struct mapi_SPropValue, recipient->properties.cValues + 1);
+
+			for (uj32 = 0, uk32 = 0; uj32 < row->cValues; uj32++, uk32++) {
+				if (may_skip_property (row->lpProps[uj32].ulPropTag) ||
+				    !e_mapi_utils_copy_to_mapi_SPropValue (recipient, &recipient->properties.lpProps[uk32], &row->lpProps[uj32])) {
+					uk32--;
+					recipient->properties.cValues--;
+					recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
+				}
+			}
+
+			recipient->properties.lpProps[recipient->properties.cValues].ulPropTag = 0;
+		}
+
+		object->recipients = first_recipient;
 	}
 
  cleanup:
-	mapi_object_release (&obj_table);
+	mapi_object_release (&attach_table);
 
-	UNLOCK ();
+	if (ms == MAPI_E_SUCCESS) {
+		*out_object = object;
+	} else {
+		*out_object = NULL;
+		e_mapi_object_free (object);
+	}
 
-	return ms == MAPI_E_SUCCESS;
+	return ms;
 }
 
-static gboolean update_message_with_object (EMapiConnection *conn,
-					    mapi_object_t *obj_folder,
-					    mapi_object_t *obj_message,
-					    EMapiObject *object,
-					    TALLOC_CTX *mem_ctx,
-					    GCancellable *cancellable,
-					    GError **perror);
-
-static gboolean
-add_object_attachments (EMapiConnection *conn,
-			mapi_object_t *obj_folder,
-			mapi_object_t *obj_message,
-			EMapiAttachment *attachments,
-			TALLOC_CTX *mem_ctx,
-			GCancellable *cancellable,
-			GError **perror)
+static enum MAPISTATUS
+e_mapi_connection_fetch_objects_internal (EMapiConnection *conn,
+					  TALLOC_CTX *mem_ctx,
+					  mapi_id_array_t *ids,
+					  struct EnsureAdditionalPropertiesData *eap,
+					  GCancellable *cancellable,
+					  GError **perror)
 {
-	enum MAPISTATUS ms = MAPI_E_SUCCESS;
-	EMapiAttachment *attachment;
+	enum MAPISTATUS ms;
+	guint32 idx;
+	mapi_container_list_t *element;
 
-	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_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (ids != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (eap != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (eap->obj_folder != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (eap->downloaded < ids->count, MAPI_E_INVALID_PARAMETER);
 
-	LOCK ();
+	for (idx = 0, element = ids->lpContainerList; idx < ids->count && idx < eap->downloaded && element; idx++) {
+		element = element->next;
+	}
 
-	for (attachment = attachments; attachment && ms == MAPI_E_SUCCESS; attachment = attachment->next) {
-		mapi_object_t obj_attach;
+	g_return_val_if_fail (idx < ids->count, MAPI_E_INVALID_PARAMETER);
+
+	ms = MAPI_E_SUCCESS;
+	while (element && ms == MAPI_E_SUCCESS) {
+		mapi_object_t obj_message;
+		EMapiObject *object = NULL;
+		GError *local_error = NULL;
 
 		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 			ms = MAPI_E_USER_CANCEL;
 			break;
 		}
 
-		mapi_object_init (&obj_attach);
+		mapi_object_init (&obj_message);
 
-		ms = CreateAttach (obj_message, &obj_attach);
+		ms = OpenMessage (eap->obj_folder, mapi_object_get_id (eap->obj_folder), element->id, &obj_message, 0 /* read-only */);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "CreateAttach", ms);
-			goto cleanup;
+			make_mapi_error (perror, "OpenMessage", ms);
+			mapi_object_release (&obj_message);
+			break;
 		}
 
-		if (!update_props_on_object (conn, obj_folder, &obj_attach, &attachment->properties, mem_ctx, cancellable, perror)) {
-			ms = MAPI_E_CALL_FAILED;
-			make_mapi_error (perror, "update_props_on_object", ms);
-			goto cleanup;
+		/* silently skip broken objects */
+		ms = e_mapi_connection_fetch_object_internal (conn, mem_ctx, &obj_message, eap, &object, cancellable, &local_error);
+		if (ms == MAPI_E_SUCCESS) {
+			if (!eap->cb (conn, mem_ctx, object, eap->downloaded, ids->count, eap->cb_user_data, cancellable, perror)) {
+				ms = MAPI_E_USER_CANCEL;
+				make_mapi_error (perror, "Object processing", ms);
+			}
+		} else {
+			e_mapi_debug_print ("%s: Skipping object %016" G_GINT64_MODIFIER "X because its fetch failed: %s",
+				G_STRFUNC, element->id, local_error ? local_error->message : mapi_get_errstr (ms));
+			ms = MAPI_E_SUCCESS;
 		}
 
-		if (attachment->embedded_object) {
-			mapi_object_t obj_emb_msg;
+		e_mapi_object_free (object);
+		mapi_object_release (&obj_message);
 
-			mapi_object_init (&obj_emb_msg);
+		eap->downloaded++;
 
-			ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "OpenEmbeddedMessage", ms);
-				goto cleanup;
-			}
+		element = element->next;
+	}
 
-			if (!update_message_with_object (conn, obj_folder, &obj_emb_msg, attachment->embedded_object, mem_ctx, cancellable, perror)) {
-				ms = MAPI_E_CALL_FAILED;
-				make_mapi_error (perror, "SaveChangesMessage", ms);
-				mapi_object_release (&obj_emb_msg);
-				goto cleanup;
-			}
+	return ms;
+}
 
-			ms = SaveChangesMessage (&obj_attach, &obj_emb_msg, KeepOpenReadOnly);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "SaveChangesMessage", ms);
-				mapi_object_release (&obj_emb_msg);
-				goto cleanup;
-			}
+/* deals with named IDs transparently, thus it's OK to check with PidLid and PidName constants only */
+gboolean
+e_mapi_connection_transfer_objects (EMapiConnection *conn,
+				    mapi_object_t *obj_folder,
+				    const GSList *mids,
+				    TransferObjectCB cb,
+				    gpointer cb_user_data,
+				    GCancellable *cancellable,
+				    GError **perror)
+{
+	enum MAPISTATUS ms;
+	TALLOC_CTX *mem_ctx;
+	mapi_id_array_t ids;
+	const GSList *iter;
+	struct EnsureAdditionalPropertiesData eap;
 
-			mapi_object_release (&obj_emb_msg);
-		}
+	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 (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SaveChangesAttachment", ms);
-			goto cleanup;
-		}
+	LOCK ();
+	mem_ctx = talloc_new (priv->session);
 
-	 cleanup:
-		mapi_object_release (&obj_attach);
+	ms = mapi_id_array_init (priv->mapi_ctx, &ids);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "mapi_id_array_init", ms);
+		goto cleanup;
+	}
+
+	for (iter = mids; iter; iter = iter->next) {
+		mapi_id_t *pmid = iter->data;
+
+		if (pmid)
+			mapi_id_array_add_id (&ids, *pmid);
 	}
 
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		mapi_id_array_release (&ids);
+		goto cleanup;
+	}
+
+	eap.cb = cb;
+	eap.cb_user_data = cb_user_data;
+	eap.obj_folder = obj_folder;
+	eap.downloaded = 0;
+
+	ms = e_mapi_fast_transfer_objects (conn, mem_ctx, obj_folder, &ids, ensure_additional_properties_cb, &eap, cancellable, perror);
+	if (ms == MAPI_E_CALL_FAILED) {
+		/* err, fallback to slow transfer, probably FXGetBuffer failed;
+		   see http://tracker.openchange.org/issues/378
+		*/
+
+		g_clear_error (perror);
+
+		e_mapi_debug_print ("%s: Failed to fast-transfer, fallback to slow fetch from %d of %d objects\n", G_STRFUNC, eap.downloaded, ids.count);
+
+		ms = e_mapi_connection_fetch_objects_internal (conn, mem_ctx, &ids, &eap, cancellable, perror);
+	}
+
+	mapi_id_array_release (&ids);
+
+ cleanup:
+	talloc_free (mem_ctx);
 	UNLOCK ();
 
 	return ms == MAPI_E_SUCCESS;
 }
 
-static gboolean
-update_message_with_object (EMapiConnection *conn,
-			    mapi_object_t *obj_folder,
-			    mapi_object_t *obj_message,
-			    EMapiObject *object,
-			    TALLOC_CTX *mem_ctx,
-			    GCancellable *cancellable,
-			    GError **perror)
+gboolean
+e_mapi_connection_transfer_object (EMapiConnection *conn,
+				   mapi_object_t *obj_folder,
+				   mapi_id_t message_id,
+				   TransferObjectCB cb,
+				   gpointer cb_user_data,
+				   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);
-	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	if (!update_props_on_object (conn, obj_folder, obj_message, &object->properties, mem_ctx, cancellable, perror))
-		return FALSE;
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-		return FALSE;
+	GSList *mids;
+	gboolean res;
 
-	/* do not touch recipients if not set */
-	if (object->recipients) {
-		/* remove current recipients... */
-		if (!delete_object_recipients (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
-			return FALSE;
+	mids = g_slist_append (NULL, &message_id);
+	res = e_mapi_connection_transfer_objects (conn, obj_folder, mids, cb, cb_user_data, cancellable, perror);
+	g_slist_free (mids);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-			return FALSE;
+	return res;
+}
 
-		/* ... and add new */
-		if (!add_object_recipients (conn, obj_folder, obj_message, object->recipients, mem_ctx, cancellable, perror))
-			return FALSE;
-	}
+struct GetSummaryData {
+	guint32 obj_index;
+	guint32 obj_total;
+	struct SPropValue *lpProps;
+	uint32_t prop_count;
+	TransferObjectCB cb;
+	gpointer cb_user_data;
+};
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-		return FALSE;
+static gboolean
+internal_get_summary_cb (EMapiConnection *conn,
+			 TALLOC_CTX *mem_ctx,
+			 /* const */ EMapiObject *object,
+			 guint32 obj_index,
+			 guint32 obj_total,
+			 gpointer user_data,
+			 GCancellable *cancellable,
+			 GError **perror)
+{
+	struct GetSummaryData *gsd = user_data;
 
-	/* remove current attachments... */
-	if (!delete_object_attachments (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
-		return FALSE;
+	g_return_val_if_fail (gsd != NULL, FALSE);
+	g_return_val_if_fail (gsd->cb != NULL, FALSE);
+	g_return_val_if_fail (object != NULL, FALSE);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-		return FALSE;
+	/* also include properties received from GetProps,
+	   as those like PR_MID are not included by default */
+	if (gsd->lpProps && gsd->prop_count > 0) {
+		uint32_t ii;
 
-	/* ... and add new */
-	if (object->attachments && !add_object_attachments (conn, obj_folder, obj_message, object->attachments, mem_ctx, cancellable, perror))
-		return FALSE;
+		for (ii = 0; ii < gsd->prop_count; ii++) {
+			/* skip errors and already included properties */
+			if ((gsd->lpProps[ii].ulPropTag & 0xFFFF) == PT_ERROR
+			    || e_mapi_util_find_array_propval (&object->properties, gsd->lpProps[ii].ulPropTag))
+				continue;
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
-		return FALSE;
+			object->properties.cValues++;
+			object->properties.lpProps = talloc_realloc (mem_ctx,
+					    object->properties.lpProps,
+					    struct mapi_SPropValue,
+					    object->properties.cValues + 1);
+			cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &gsd->lpProps[ii]);
+			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+		}
+	}
 
-	return TRUE;
+	return gsd->cb (conn, mem_ctx, object, gsd->obj_index, gsd->obj_total, gsd->cb_user_data, cancellable, perror);
 }
 
+/* transfers items summary, which is either PR_TRANSPORT_MESSAGE_HEADERS_UNICODE or
+   the object without attachment */
 gboolean
-e_mapi_connection_create_object (EMapiConnection *conn,
-				 mapi_object_t *obj_folder,
-				 uint32_t flags, /* bit-or of EMapiCreateFlags */
-				 WriteObjectCB write_object_cb,
-				 gpointer woc_data,
-				 mapi_id_t *out_mid,
-				 GCancellable *cancellable,
-				 GError **perror)
+e_mapi_connection_transfer_summary (EMapiConnection *conn,
+				    mapi_object_t *obj_folder,
+				    const GSList *mids,
+				    TransferObjectCB cb,
+				    gpointer cb_user_data,
+				    GCancellable *cancellable,
+				    GError **perror)
 {
 	enum MAPISTATUS ms;
 	TALLOC_CTX *mem_ctx;
-	EMapiObject *object = NULL;
-	mapi_object_t obj_message;
+	const GSList *iter;
+	guint32 index, total;
 
 	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 (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (out_mid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
-
-	*out_mid = 0;
-
 	mem_ctx = talloc_new (priv->session);
-	mapi_object_init (&obj_message);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	ms = MAPI_E_SUCCESS;
+	total = g_slist_length ((GSList *) mids);
+	for (iter = mids, index = 0; iter && ms == MAPI_E_SUCCESS; iter = iter->next, index++) {
+		mapi_id_t *pmid = iter->data;
 
-	if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror) || !object) {
-		ms = MAPI_E_CALL_FAILED;
-		make_mapi_error (perror, "write_object_cb", ms);
-		goto cleanup;
-	}
+		if (pmid) {
+			mapi_object_t obj_message;
+			struct SPropTagArray *tags;
+			struct SPropValue *lpProps = NULL;
+			uint32_t prop_count = 0, ii;
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+			mapi_object_init (&obj_message);
 
-	ms = CreateMessage (obj_folder, &obj_message);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "CreateMessage", ms);
-		goto cleanup;
-	}
+			ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), *pmid, &obj_message, 0);
+			if (ms != MAPI_E_SUCCESS && ms != MAPI_E_NOT_FOUND) {
+				make_mapi_error (perror, "OpenMessage", ms);
+				goto cleanup;
+			}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+			tags = set_SPropTagArray (mem_ctx, 6,
+				PR_FID,
+				PR_MID,
+				PR_MESSAGE_FLAGS,
+				PR_LAST_MODIFICATION_TIME,
+				PR_MESSAGE_CLASS,
+				PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
 
-	if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
-		ms = MAPI_E_CALL_FAILED;
-		make_mapi_error (perror, "update_message_with_object", ms);
-		goto cleanup;
-	}
+			ms = GetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count);
+			if (ms == MAPI_E_SUCCESS) {
+				ms = MAPI_E_NOT_FOUND;
+				if (lpProps && prop_count > 0) {
+					const gchar *headers = e_mapi_util_find_SPropVal_array_propval (lpProps, PR_TRANSPORT_MESSAGE_HEADERS_UNICODE);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+					if (headers && *headers) {
+						EMapiObject *object;
 
-	ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadWrite);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SaveChangesMessage", ms);
-		goto cleanup;
-	}
+						ms = MAPI_E_SUCCESS;
 
-	if ((flags & E_MAPI_CREATE_FLAG_SUBMIT) != 0) {
-		/* Mark message as ready to be sent */
-		ms = SubmitMessage (&obj_message);
-		if (ms != MAPI_E_SUCCESS) {
-			mapi_id_t mid;
-			make_mapi_error (perror, "SubmitMessage", ms);
+						object = e_mapi_object_new (mem_ctx);
+						for (ii = 0; ii < prop_count; ii++) {
+							object->properties.cValues++;
+							object->properties.lpProps = talloc_realloc (mem_ctx,
+									    object->properties.lpProps,
+									    struct mapi_SPropValue,
+									    object->properties.cValues + 1);
+							cast_mapi_SPropValue (mem_ctx, &object->properties.lpProps[object->properties.cValues - 1], &lpProps[ii]);
+							object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+						}
 
-			/*
-			The code is storing message right to Sent items instead of Outbox,
-			because fetching PR_ENTRYID or PR_IPM_SENTMAIL_ENTRYID didn't seem
-			to work in time of doing this change.
+						if (!cb (conn, mem_ctx, object, index, total, cb_user_data, cancellable, perror)) {
+							ms = MAPI_E_USER_CANCEL;
+							e_mapi_object_free (object);
+							mapi_object_release (&obj_message);
+							goto cleanup;
+						}
 
-			For more information and other possible (correct) approaches see:
-			https://bugzilla.gnome.org/show_bug.cgi?id=561794
-			*/
-			mid = mapi_object_get_id (&obj_message);
+						e_mapi_object_free (object);
+					}
+				}
+			}
 
-			mapi_object_release (&obj_message);
-			/* to not release a message object twice */
-			mapi_object_init (&obj_message);
+			if (ms == MAPI_E_NOT_FOUND) {
+				struct GetSummaryData gsd;
 
-			ms = DeleteMessage (obj_folder, &mid, 1);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "DeleteMessage", ms);
+				gsd.obj_index = index;
+				gsd.obj_total = total;
+				gsd.lpProps = lpProps;
+				gsd.prop_count = prop_count;
+				gsd.cb = cb;
+				gsd.cb_user_data = cb_user_data;
+
+				ms = e_mapi_fast_transfer_object (conn, mem_ctx, &obj_message, E_MAPI_FAST_TRANSFER_FLAG_RECIPIENTS, internal_get_summary_cb, &gsd, cancellable, perror);
+				if (ms != MAPI_E_SUCCESS) {
+					make_mapi_error (perror, "transfer_object", ms);
+					mapi_object_release (&obj_message);
+					goto cleanup;
+				}
 			}
 
+			mapi_object_release (&obj_message);
+			talloc_free (tags);
+		}
+
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			ms = MAPI_E_USER_CANCEL;
 			goto cleanup;
 		}
 	}
 
-	*out_mid = mapi_object_get_id (&obj_message);
+ cleanup:
+	talloc_free (mem_ctx);
+	UNLOCK ();
+
+	return ms == MAPI_E_SUCCESS;
+}
+
+typedef struct {
+	uint32_t proptag;
+	uint32_t cb;
+	const uint8_t *lpb; /* taken from the original mapi prop, no need to copy the memory */
+} EMapiStreamedProp;
+
+static gboolean
+convert_mapi_props_to_props (EMapiConnection *conn,
+			     mapi_object_t *obj_folder,
+			     const struct mapi_SPropValue_array *mapi_props,
+			     struct SPropValue **props,
+			     uint32_t *propslen,
+			     EMapiStreamedProp **streams, /* can be NULL for no streaming */
+			     guint *streamslen, /* can be NULL only if streams is NULL; is ignored if streams is NULL */
+			     TALLOC_CTX *mem_ctx,
+			     GCancellable *cancellable,
+			     GError **perror)
+{
+	uint16_t ii;
+	ResolveNamedIDsData *named_ids_list = NULL;
+	guint named_ids_len = 0;
+	gboolean res = TRUE;
+
+	e_return_val_mapi_error_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (mapi_props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (props != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (propslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	if (streams) {
+		e_return_val_mapi_error_if_fail (streamslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	}
+
+	for (ii = 0; ii < mapi_props->cValues; ii++) {
+		gboolean processed = FALSE;
+		uint32_t proptag = mapi_props->lpProps[ii].ulPropTag;
+		gconstpointer propdata = get_mapi_SPropValue_data (&mapi_props->lpProps[ii]);
 
- cleanup:
-	e_mapi_object_free (object);
-	mapi_object_release (&obj_message);
-	talloc_free (mem_ctx);
+		maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
 
-	UNLOCK ();
+		if (streams && propdata) {
+			/* copy anything longer than 1KB as streams; this doesn't count total packet size needed,
+			   but because this is usually useful only for PidTagBody, PidTagHtml, which are there
+			   only once, then no big deal
+			*/
 
-	return ms == MAPI_E_SUCCESS;
-}
+			uint32_t sz;
+			const gchar *str;
+			const struct SBinary_short *bin;
 
-gboolean
-e_mapi_connection_modify_object (EMapiConnection *conn,
-				 mapi_object_t *obj_folder,
-				 mapi_id_t mid,
-				 WriteObjectCB write_object_cb,
-				 gpointer woc_data,
-				 GCancellable *cancellable,
-				 GError **perror)
-{
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	EMapiObject *object = NULL;
-	mapi_object_t obj_message;
+			#define addstream() {										\
+					if (!*streams) {								\
+						*streams = g_new0 (EMapiStreamedProp, 1);				\
+						*streamslen = 0;							\
+					} else {									\
+						*streams = g_renew (EMapiStreamedProp, *streams, *streamslen + 1);	\
+					}										\
+															\
+					(*streams)[*streamslen].proptag = proptag;					\
+					(*streams)[*streamslen].cb = 0;							\
+					(*streams)[*streamslen].lpb = NULL;						\
+					(*streamslen) += 1;								\
+				}
 
-	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_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (mid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+			switch (proptag & 0xFFFF) {
+			case PT_BINARY:
+				bin = propdata;
+				if (bin->cb > MAX_PROPERTY_WRITE_SIZE) {
+					addstream ();
+					(*streams)[(*streamslen) - 1].cb = bin->cb;
+					(*streams)[(*streamslen) - 1].lpb = bin->lpb;
+					processed = TRUE;
+				}
+				break;
+			case PT_STRING8:
+				str = propdata;
+				sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
+				if (sz > MAX_PROPERTY_WRITE_SIZE) {
+					addstream ();
+					(*streams)[(*streamslen) - 1].cb = sz;
+					(*streams)[(*streamslen) - 1].lpb = (uint8_t *) str;
+					processed = TRUE;
+				}
+				break;
+			case PT_UNICODE:
+				str = propdata;
+				sz = get_mapi_property_size (&mapi_props->lpProps[ii]);
+				if (sz > MAX_PROPERTY_WRITE_SIZE) {
+					gchar *in_unicode;
+					gsize written = 0;
 
-	LOCK ();
+					addstream ();
 
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init (&obj_message);
+					in_unicode = g_convert (str, strlen (str), "UTF-16", "UTF-8", NULL, &written, NULL);
+					if (in_unicode && written > 0) {
+						uint8_t *bytes = talloc_zero_size (mem_ctx, written + 2);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+						/* skip Unicode marker, if there */
+						if (written >= 2 && (const guchar) in_unicode[0] == 0xFF && (const guchar) in_unicode[1] == 0xFE) {
+							memcpy (bytes, in_unicode + 2, written - 2);
+							written -= 2;
+						} else
+							memcpy (bytes, in_unicode, written);
 
-	if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror)) {
-		ms = MAPI_E_CALL_FAILED;
-		make_mapi_error (perror, "write_object_cb", ms);
-		goto cleanup;
-	}
+						/* null-terminated unicode string */
+						(*streams)[(*streamslen) - 1].lpb = bytes;
+						(*streams)[(*streamslen) - 1].cb = written + 2;
+					}
+					g_free (in_unicode);
+					processed = TRUE;
+				}
+				break;
+			}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+			#undef addstream
+		}
 
-	ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), mid, &obj_message, MAPI_MODIFY);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenMessage", ms);
-		goto cleanup;
+		if (!processed)
+			e_mapi_utils_add_spropvalue (mem_ctx, props, propslen, proptag, propdata);
 	}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	if (named_ids_list) {
+		res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
 
-	if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
-		ms = MAPI_E_CALL_FAILED;
-		make_mapi_error (perror, "update_message_with_object", ms);
-		goto cleanup;
-	}
+		if (res && *props) {
+			for (ii = 0; ii < *propslen; ii++) {
+				uint32_t proptag = (*props)[ii].ulPropTag;
 
-	ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadOnly);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SaveChangesMessage", ms);
-		goto cleanup;
-	}
+				maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
 
- cleanup:
-	e_mapi_object_free (object);
-	mapi_object_release (&obj_message);
-	talloc_free (mem_ctx);
+				(*props)[ii].ulPropTag = proptag;
+			}
+		}
 
-	UNLOCK ();
+		if (res && streams) {
+			for (ii = 0; ii < *streamslen; ii++) {
+				maybe_replace_named_id_tag (&((*streams)[ii].proptag), named_ids_list, named_ids_len);
+			}
+		}
+	}
 
-	return ms == MAPI_E_SUCCESS;
+	g_free (named_ids_list);
+
+	return res;
 }
 
-gboolean
-e_mapi_connection_fetch_items  (EMapiConnection *conn,
-				mapi_id_t fid,
-				BuildRestrictionsCB build_rs_cb,
-				gpointer build_rs_cb_data,
-				struct SSortOrderSet *sort_order,
-				BuildReadPropsCB build_props,
-				gpointer brp_data,
-				FetchCallback cb,
-				gpointer data,
-				guint32 options,
-				GCancellable *cancellable,
-				GError **perror)
+static gboolean
+write_streamed_prop (EMapiConnection *conn,
+		     mapi_object_t *obj_object,
+		     const EMapiStreamedProp *stream,
+		     GCancellable *cancellable,
+		     GError **perror)
 {
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_folder;
-	mapi_object_t obj_table;
-	struct SPropTagArray *SPropTagArray, *propsTagArray = NULL;
-	struct SRowSet SRowSet;
-	uint32_t count, i, cursor_pos = 0;
-	gboolean result = FALSE;
+	enum MAPISTATUS	ms;
+	uint32_t total_written;
+	gboolean done = FALSE;
+	mapi_object_t obj_stream;
 
 	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: folder-id %016" G_GINT64_MODIFIER "X ", G_STRLOC, G_STRFUNC, fid);
+	e_return_val_mapi_error_if_fail (obj_object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (stream != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
-	mapi_object_init(&obj_table);
 
-	/* Attempt to open the folder */
-	ms = open_folder (conn, 0, &fid, options, &obj_folder, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
+	mapi_object_init (&obj_stream);
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
 		goto cleanup;
 	}
 
-	/* Get a handle on the container */
-	ms = GetContentsTable (&obj_folder, &obj_table, TableFlags_UseUnicode, NULL);
+	/* OpenStream on required proptag */
+	ms = OpenStream (obj_object, stream->proptag, STREAM_ACCESS_READWRITE, &obj_stream);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetContentsTable", ms);
-		goto cleanup;
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
+		make_mapi_error (perror, "OpenStream", ms);
 		goto cleanup;
 	}
 
-	SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
-					  PR_FID,
-					  PR_MID,
-					  PR_LAST_MODIFICATION_TIME,
-					  PR_HASATTACH,
-					  PR_MESSAGE_FLAGS);
-
-	/* Set primary columns to be fetched */
-	ms = SetColumns (&obj_table, SPropTagArray);
+	/* Set the stream size */
+	ms = SetStreamSize (&obj_stream, stream->cb);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetColumns", ms);
-		goto cleanup;
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
+		make_mapi_error (perror, "SetStreamSize", ms);
 		goto cleanup;
 	}
 
-	if (build_rs_cb) {
-		struct mapi_SRestriction *restrictions = NULL;
-
-		if (!build_rs_cb (conn, fid, mem_ctx, &restrictions, build_rs_cb_data, cancellable, perror)) {
-			ms = MAPI_E_CALL_FAILED;
-			make_mapi_error (perror, "build_restrictions", ms);
-			goto cleanup;
-		}
-
-		if (restrictions) {
-			/* Applying any restriction that are set. */
-			ms = Restrict (&obj_table, restrictions, NULL);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "Restrict", ms);
-				goto cleanup;
-			}
-
-			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-				ms = MAPI_E_USER_CANCEL;
-				goto cleanup;
-			}
-		}
-	}
-
-	if (sort_order) {
-		ms = SortTable (&obj_table, sort_order);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SortTable", ms);
-			goto cleanup;
-		}
-	}
-
-	if (build_props) {
-		propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
-		if (!build_props (conn, fid, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
-			make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
-			goto cleanup;
-		}
+	total_written = 0;
+	/* Write stream */
+	while (!done) {
+		uint16_t cn_written = 0;
+		DATA_BLOB blob;
 
 		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 			ms = MAPI_E_USER_CANCEL;
 			goto cleanup;
 		}
-	}
 
-	/* Note : We maintain a cursor position. count parameter in QueryRows */
-	/* is more of a request and not gauranteed  */
-	do {
-		/* Number of items in the container */
-		ms = QueryPosition (&obj_table, &cursor_pos, &count);
+		blob.length = (stream->cb - total_written) < STREAM_MAX_WRITE_SIZE ?
+			      (stream->cb - total_written) : STREAM_MAX_WRITE_SIZE;
+		blob.data = (uint8_t *) (stream->lpb + total_written);
+
+		ms = WriteStream (&obj_stream, &blob, &cn_written);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "QueryPosition", ms);
-			goto cleanup;
+			make_mapi_error (perror, "WriteStream", ms);
+			done = TRUE;
+		} else if (cn_written == 0) {
+			done = TRUE;
+		} else {
+			total_written += cn_written;
+			if (total_written >= stream->cb)
+				done = TRUE;
 		}
+	}
 
-		if (!count)
-			break;
-
-		/* Fill the table columns with data from the rows */
-		ms = QueryRows (&obj_table, count, TBL_ADVANCE, &SRowSet);
+	if (ms == MAPI_E_SUCCESS) {
+		/* Commit the stream */
+		ms = CommitStream (&obj_stream);
 		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "QueryRows", ms);
+			make_mapi_error (perror, "CommitStream", ms);
 			goto cleanup;
 		}
+	}
 
-		for (i = 0; i < SRowSet.cRows; i++) {
-			mapi_object_t obj_message;
-			struct mapi_SPropValue_array properties_array = {0};
-			const mapi_id_t *pfid;
-			const mapi_id_t	*pmid;
-			const bool *has_attach = NULL;
-			const uint32_t *msg_flags;
-			GSList *attach_list = NULL;
-			GSList *recip_list = NULL;
-			GSList *stream_list = NULL;
-			gboolean cb_retval = false;
+ cleanup:
+	mapi_object_release (&obj_stream);
 
-			mapi_object_init(&obj_message);
+	UNLOCK ();
 
-			pfid = (const uint64_t *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_FID);
-			pmid = (const uint64_t *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_MID);
+	return ms == MAPI_E_SUCCESS;
+}
 
-			has_attach = (const bool *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_HASATTACH);
-			msg_flags = get_SPropValue_SRow_data (&SRowSet.aRow[i], PR_MESSAGE_FLAGS);
+static gboolean
+update_props_on_object (EMapiConnection *conn,
+			mapi_object_t *obj_folder,
+			mapi_object_t *obj_object,
+			const struct mapi_SPropValue_array *properties,
+			TALLOC_CTX *mem_ctx,
+			GCancellable *cancellable,
+			GError **perror)
+{
+	enum MAPISTATUS	ms;
+	struct SPropValue *props = NULL;
+	uint32_t propslen = 0;
+	EMapiStreamedProp *streams = NULL;
+	guint streamslen = 0;
 
-			if (options & MAPI_OPTIONS_DONT_OPEN_MESSAGE)
-				goto relax;
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-			ms = OpenMessage (&obj_folder, *pfid, *pmid, &obj_message, 0);
-			if (ms != MAPI_E_SUCCESS) {
-				make_mapi_error (perror, "OpenMessage", ms);
-				goto loop_cleanup;
-			}
+	LOCK ();
 
-			if (propsTagArray && propsTagArray->cValues) {
-				struct SPropValue *lpProps = NULL;
-				struct SPropTagArray *tags;
-				uint32_t prop_count = 0, k, ll;
-				/* we need to make a local copy of the tag array
-				 * since GetProps will modify the array on any
-				 * errors */
-				tags = set_SPropTagArray (mem_ctx, 0x1, PR_MSG_EDITOR_FORMAT);
-				for (k = 0; k < propsTagArray->cValues; k++)
-					SPropTagArray_add (mem_ctx, tags, propsTagArray->aulPropTag[k]);
-
-				ms = GetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, tags, &lpProps, &prop_count);
-				if (ms != MAPI_E_SUCCESS)
-					make_mapi_error (perror, "GetProps", ms);
-
-				properties_array.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue,
-									 prop_count + 1);
-				properties_array.cValues = prop_count;
-				for (k = 0, ll = 0; k < prop_count; k++, ll++) {
-					if ((lpProps[k].ulPropTag & 0xFFFF) == PT_MV_BINARY) {
-						uint32_t ci;
-
-						properties_array.lpProps[ll].ulPropTag = lpProps[k].ulPropTag;
-						properties_array.lpProps[ll].value.MVbin.cValues = lpProps[k].value.MVbin.cValues;
-						properties_array.lpProps[ll].value.MVbin.bin = (struct SBinary_short *) talloc_array (mem_ctx, struct Binary_r, properties_array.lpProps[ll].value.MVbin.cValues);
-						for (ci = 0; ci < properties_array.lpProps[ll].value.MVbin.cValues; ci++) {
-							properties_array.lpProps[ll].value.MVbin.bin[ci].cb = lpProps[k].value.MVbin.lpbin[ci].cb;
-							properties_array.lpProps[ll].value.MVbin.bin[ci].lpb = lpProps[k].value.MVbin.lpbin[ci].lpb;
-						}
-					} else if (may_skip_property (lpProps[k].ulPropTag)) {
-						ll--;
-						properties_array.cValues--;
-					} else {
-						cast_mapi_SPropValue (mem_ctx,
-								      &properties_array.lpProps[ll],&lpProps[k]);
-					}
-				}
-			} else {
-				ms = GetPropsAll (&obj_message, MAPI_UNICODE, &properties_array);
-				if (ms != MAPI_E_SUCCESS)
-					make_mapi_error (perror, "GetPropsAll", ms);
-			}
+	if (!convert_mapi_props_to_props (conn, obj_folder, properties, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "convert_mapi_props_to_props", ms);
+		goto cleanup;
+	}
 
-			if (has_attach && *has_attach && (MAPI_OPTIONS_FETCH_ATTACHMENTS & options)) {
-				e_mapi_util_get_attachments (conn, fid, mem_ctx, &obj_message, &attach_list, NULL);
-			}
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-			if (options & MAPI_OPTIONS_FETCH_RECIPIENTS) {
-				e_mapi_util_get_recipients (conn, mem_ctx, &obj_message, &recip_list, perror);
-			}
+	if (props) {
+		/* set properties for the item */
+		ms = SetProps (obj_object, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
 
-			/* get the main body stream no matter what */
-			if (options & MAPI_OPTIONS_FETCH_BODY_STREAM) {
-				e_mapi_util_read_body_stream (mem_ctx, &obj_message, &stream_list, &properties_array, (options & MAPI_OPTIONS_GETBESTBODY) != 0);
-			}
+		talloc_free (props);
 
- relax:
-			if (ms == MAPI_E_SUCCESS) {
-				FetchItemsCallbackData *item_data;
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "SetProps", ms);
+			goto cleanup;
+		}
+	}
 
-				if ((options & MAPI_OPTIONS_DONT_OPEN_MESSAGE) == 0) {
-					if ((options & MAPI_OPTIONS_FETCH_GENERIC_STREAMS) != 0) {
-						uint32_t z;
-						const uint32_t *cpid = e_mapi_util_find_array_propval (&properties_array, PR_INTERNET_CPID);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-						/* just to get all the other streams */
-						for (z = 0; z < properties_array.cValues; z++) {
-							if ((properties_array.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY)
-								e_mapi_util_read_generic_stream (mem_ctx, &obj_message, cpid, properties_array.lpProps[z].ulPropTag, &stream_list, &properties_array, NULL);
-						}
-					}
-				}
+	if (streams) {
+		guint ii;
 
-				/* NOTE: stream_list, recipient_list and attach_list
-				   should be freed by the callback */
-				item_data = g_new0 (FetchItemsCallbackData, 1);
-				item_data->conn = conn;
-				item_data->fid = *pfid;
-				item_data->mid = *pmid;
-				item_data->msg_flags = msg_flags ? *msg_flags : 0;
-				item_data->properties = &properties_array;
-				item_data->streams = stream_list;
-				item_data->recipients = recip_list;
-				item_data->attachments = attach_list;
-				item_data->total = count; //Total entries in the table.
-				item_data->index = cursor_pos + i; //cursor_pos + current_table_index
-
-				global_unlock ();
-				cb_retval = cb (item_data, data, cancellable, perror);
-				global_lock ();
-
-				g_free (item_data);
-			} else {
-				e_mapi_util_free_stream_list (&stream_list);
-				e_mapi_util_free_recipient_list (&recip_list);
-				e_mapi_util_free_attachment_list (&attach_list);
+		for (ii = 0; ii < streamslen; ii++) {
+			if (!write_streamed_prop (conn, obj_object, &streams[ii], cancellable, perror)) {
+				ms = MAPI_E_CALL_FAILED;
+				make_mapi_error (perror, "write_streamed_prop", ms);
+				break;
 			}
 
-			if (propsTagArray && propsTagArray->cValues)
-				talloc_free (properties_array.lpProps);
-
-		loop_cleanup:
-			if ((options & MAPI_OPTIONS_DONT_OPEN_MESSAGE) == 0)
-				mapi_object_release (&obj_message);
-
-			if (!cb_retval) break;
-		}
-
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
+			if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+				ms = MAPI_E_USER_CANCEL;
+				break;
+			}
 		}
-	} while (cursor_pos < count && ms == MAPI_E_SUCCESS);
-
-	result = ms == MAPI_E_SUCCESS;
 
+		g_free (streams);
+	}
  cleanup:
-	if (propsTagArray)
-		talloc_free (propsTagArray);
-	mapi_object_release(&obj_folder);
-	mapi_object_release(&obj_table);
-	talloc_free (mem_ctx);
 	UNLOCK ();
 
-	e_mapi_debug_print("%s: Leaving %s: folder-id %016" G_GINT64_MODIFIER "X ", G_STRLOC, G_STRFUNC, fid);
-
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
-/* obj_folder and obj_message are released only when obj_folder is not NULL and when returned TRUE */
-gboolean
-e_mapi_connection_fetch_object_props (EMapiConnection *conn,
-				      mapi_object_t *obj_folder,
-				      mapi_id_t fid,
-				      mapi_id_t mid,
-				      mapi_object_t *obj_message,
-				      BuildReadPropsCB build_props,
-				      gpointer brp_data,
-				      FetchCallback cb,
-				      gpointer data,
-				      guint32 options,
-				      GCancellable *cancellable,
-				      GError **perror)
+static gboolean
+update_recipient_properties (EMapiConnection *conn,
+			     mapi_object_t *obj_folder,
+			     struct SRow *aRow,
+			     EMapiRecipient *recipient,
+			     gboolean is_resolved,
+			     TALLOC_CTX *mem_ctx,
+			     GCancellable *cancellable,
+			     GError **perror)
 {
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	struct mapi_SPropValue_array properties_array;
-	struct SPropTagArray *propsTagArray = NULL;
-	GSList *attach_list = NULL;
-	GSList *recip_list = NULL;
-	GSList *stream_list = NULL;
-	gboolean result = FALSE;
-
-	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: folder %p message %p", G_STRLOC, G_STRFUNC, obj_folder, obj_message);
-
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
+	struct SPropValue *props = NULL;
+	uint32_t propslen = 0, ii;
 
-	if (build_props) {
-		propsTagArray = set_SPropTagArray (mem_ctx, 0x3,
-			PR_MESSAGE_CLASS,
-			PR_HASATTACH,
-			PR_MSG_EDITOR_FORMAT);
+	g_return_val_if_fail (recipient != NULL, FALSE);
 
-		if (!build_props (conn, fid, mem_ctx, propsTagArray, brp_data, cancellable, perror)) {
-			make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
-			goto cleanup;
-		}
+	if (!convert_mapi_props_to_props (conn, obj_folder, &recipient->properties, &props, &propslen, NULL, NULL, mem_ctx, cancellable, perror))
+		return FALSE;
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
+	for (ii = 0; ii < propslen; ii++) {
+		/* do not overwrite all properties, if recipient was resolved properly */
+		if (!is_resolved
+		    || props[ii].ulPropTag == PidTagRecipientType
+		    || props[ii].ulPropTag == PidTagSendInternetEncoding
+		    || props[ii].ulPropTag == PidTagRecipientFlags
+		    || props[ii].ulPropTag == PidTagRecipientTrackStatus)
+			SRow_addprop (aRow, props[ii]);
 	}
 
-	if (propsTagArray && propsTagArray->cValues) {
-		struct SPropValue *lpProps;
-		uint32_t prop_count = 0, k, ll;
-
-		lpProps = talloc_zero(mem_ctx, struct SPropValue);
+	return TRUE;
+}
 
-		ms = GetProps (obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, propsTagArray, &lpProps, &prop_count);
-		if (ms != MAPI_E_SUCCESS)
-			make_mapi_error (perror, "GetProps", ms);
+static gboolean
+delete_object_recipients (EMapiConnection *conn,
+			  mapi_object_t *obj_folder,
+			  mapi_object_t *obj_object,
+			  TALLOC_CTX *mem_ctx,
+			  GCancellable *cancellable,
+			  GError **perror)
+{
+	enum MAPISTATUS	ms;
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		/* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
-		properties_array.cValues = prop_count;
-		properties_array.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, prop_count + 1);
-		for (k = 0, ll = 0; k < prop_count; k++, ll++) {
-			if (may_skip_property (lpProps[k].ulPropTag)) {
-				ll--;
-				properties_array.cValues--;
-			} else {
-				cast_mapi_SPropValue (mem_ctx,
-						      &properties_array.lpProps[ll], &lpProps[k]);
-			}
-		}
-	} else {
-		ms = GetPropsAll (obj_message, MAPI_UNICODE, &properties_array);
-		if (ms != MAPI_E_SUCCESS)
-			make_mapi_error (perror, "GetPropsAll", ms);
+	LOCK ();
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
-	}
+	ms = RemoveAllRecipients (obj_object);
+	if (ms != MAPI_E_SUCCESS)
+		make_mapi_error (perror, "RemoveAllRecipients", ms);
 
-	/* Fetch attachments */
-	if (options & MAPI_OPTIONS_FETCH_ATTACHMENTS) {
-		const bool *has_attach = e_mapi_util_find_array_propval (&properties_array, PR_HASATTACH);
+	UNLOCK ();
 
-		if (has_attach && *has_attach)
-			e_mapi_util_get_attachments (conn, fid, mem_ctx, obj_message, &attach_list, NULL);
+	return ms == MAPI_E_SUCCESS;
+}
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
-	}
+static gboolean
+add_object_recipients (EMapiConnection *conn,
+		       mapi_object_t *obj_folder,
+		       mapi_object_t *obj_message,
+		       EMapiRecipient *recipients,
+		       TALLOC_CTX *mem_ctx,
+		       GCancellable *cancellable,
+		       GError **perror)
+{
+	const uint32_t required_tags[] = {PidTagEntryId,
+					  PidTagDisplayName,
+					  PidTagObjectType,
+					  PidTagDisplayType,
+					  PidTagTransmittableDisplayName,
+					  PidTagEmailAddress,
+					  PidTagAddressType,
+					  PidTagSendRichInfo,
+					  PidTag7BitDisplayName};
+	enum MAPISTATUS	ms;
+	struct SPropTagArray *tags;
+	struct SRowSet *rows = NULL;
+	struct PropertyTagArray_r *flagList = NULL;
+	ResolveNamedIDsData *named_ids_list = NULL;
+	guint named_ids_len = 0;
+	const gchar **users = NULL;
+	EMapiRecipient *recipient;
+	EMapiRecipient **recips;
+	uint32_t ii, jj, count = 0;
+	GHashTable *all_proptags;
+	GHashTableIter iter;
+	gpointer key, value;
 
-	/* Fetch recipients */
-	if (options & MAPI_OPTIONS_FETCH_RECIPIENTS) {
-		e_mapi_util_get_recipients (conn, mem_ctx, obj_message, &recip_list, NULL);
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
+	count = 0;
+	for (recipient = recipients, ii = 0; recipient; recipient = recipient->next, ii++) {
+		if (!e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress)
+		    && !e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName))
+			g_debug ("%s: Cannot get email or display name for a recipient %d, skipping it", G_STRFUNC, ii);
+		else
+			count++;
 	}
 
-	/* get the main body stream no matter what */
-	if (options & MAPI_OPTIONS_FETCH_BODY_STREAM) {
-		e_mapi_util_read_body_stream (mem_ctx, obj_message, &stream_list, &properties_array, (options & MAPI_OPTIONS_GETBESTBODY) != 0);
+	if (!count)
+		return TRUE;
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
+	LOCK ();
+
+	all_proptags = g_hash_table_new (g_direct_hash, g_direct_equal);
+	users = g_new0 (const gchar *, count + 1);
+	recips = g_new0 (EMapiRecipient *, count + 1);
+
+	for (ii = 0; ii < G_N_ELEMENTS (required_tags); ii++) {
+		g_hash_table_insert (all_proptags, GUINT_TO_POINTER (required_tags[ii]), GUINT_TO_POINTER (1));
 	}
 
-	if (ms == MAPI_E_SUCCESS) {
-		if ((options & MAPI_OPTIONS_FETCH_GENERIC_STREAMS)) {
-			uint32_t z;
+	for (ii = 0, jj = 0, recipient = recipients; ii < count && recipient != NULL; ii++, recipient = recipient->next) {
+		users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagPrimarySmtpAddress);
+		if (!users[ii])
+			users[ii] = e_mapi_util_find_array_propval (&recipient->properties, PidTagDisplayName);
+		if (!users[ii]) {
+			ii--;
+		} else {
+			uint32_t kk;
 
-			/* just to get all the other streams */
-			for (z = 0; z < properties_array.cValues; z++) {
-				if ((properties_array.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY) {
-					e_mapi_util_read_generic_stream (mem_ctx, obj_message, e_mapi_util_find_array_propval (&properties_array, PR_INTERNET_CPID), properties_array.lpProps[z].ulPropTag, &stream_list, &properties_array, NULL);
-				}
+			recips[jj] = recipient;
+			jj++;
 
-				if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-					ms = MAPI_E_USER_CANCEL;
-					goto cleanup;
-				}
+			for (kk = 0; kk < recipient->properties.cValues; kk++) {
+				g_hash_table_insert (all_proptags, GUINT_TO_POINTER (recipient->properties.lpProps[kk].ulPropTag), GUINT_TO_POINTER (1));
 			}
 		}
 	}
 
-	/* Release the objects so that the callback may use the store. */
-	if (obj_folder) {
-		/* obj_folder is not NULL, thus can do this */
-		mapi_object_release (obj_message);
-		mapi_object_release (obj_folder);
-	}
+	/* Attempt to resolve names from the server */
+	tags = NULL;
+	g_hash_table_iter_init (&iter, all_proptags);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		uint32_t proptag = GPOINTER_TO_UINT (key);
 
-	if (ms == MAPI_E_SUCCESS) {
-		FetchItemsCallbackData *item_data = g_new0 (FetchItemsCallbackData, 1);
-		item_data->conn = conn;
-		item_data->fid = fid;
-		item_data->mid = mid;
-		item_data->properties = &properties_array;
-		item_data->streams = stream_list;
-		item_data->recipients = recip_list;
-		item_data->attachments = attach_list;
-
-		/* NOTE: stream_list, recipient_list and attach_list should be freed by the callback */
-		global_unlock ();
-		cb (item_data, data, cancellable, perror);
-		global_lock ();
-
-		g_free (item_data);
-	} else {
-		e_mapi_util_free_stream_list (&stream_list);
-		e_mapi_util_free_recipient_list (&recip_list);
-		e_mapi_util_free_attachment_list (&attach_list);
+		maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+
+		if (!tags)
+			tags = set_SPropTagArray (mem_ctx, 1, proptag);
+		else
+			SPropTagArray_add (mem_ctx, tags, proptag);
 	}
 
-	result = ms == MAPI_E_SUCCESS;
+	if (named_ids_list) {
+		if (!e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror)) {
+			ms = MAPI_E_CALL_FAILED;
+			make_mapi_error (perror, "e_mapi_connection_resolve_named_props", ms);
+			goto cleanup;
+		}
 
-cleanup:
-	talloc_free (mem_ctx);
-	UNLOCK ();
+		for (ii = 0; ii < tags->cValues; ii++) {
+			uint32_t proptag = tags->aulPropTag[ii];
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+			maybe_replace_named_id_tag (&proptag, named_ids_list, named_ids_len);
 
-	return result;
-}
+			tags->aulPropTag[ii] = proptag;
+		}
+	}
 
-gboolean
-e_mapi_connection_fetch_item (EMapiConnection *conn,
-			      mapi_id_t fid,
-			      mapi_id_t mid,
-			      BuildReadPropsCB build_props,
-			      gpointer brp_data,
-			      FetchCallback cb,
-			      gpointer data,
-			      guint32 options,
-			      GCancellable *cancellable,
-			      GError **perror)
-{
-	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_folder;
-	mapi_object_t obj_message;
-	gboolean result = FALSE;
+	ms = ResolveNames (priv->session, users, tags, &rows, &flagList, MAPI_UNICODE);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "ResolveNames", ms);
+		goto cleanup;
+	}
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	g_assert (count == flagList->cValues);
 
-	e_mapi_debug_print("%s: Entering %s: folder-id %016" G_GINT64_MODIFIER "X message-id %016" G_GINT64_MODIFIER "X",
-				G_STRLOC, G_STRFUNC, fid, mid);
+	if (!rows) /* This happens when there are ZERO RESOLVED recipients */
+		rows = talloc_zero (mem_ctx, struct SRowSet);
 
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
-	mapi_object_init(&obj_message);
+	for (ii = 0, jj = 0; ii < count; ii++) {
+		recipient = recips[ii];
 
-	/* Attempt to open the folder */
-	ms = open_folder (conn, 0, &fid, options, &obj_folder, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
+		if (flagList->aulPropTag[ii] == MAPI_AMBIGUOUS) {
+			/* We should never get an ambiguous resolution as we use the email-id for resolving.
+			 * However, if we do still get an ambiguous entry, we can't handle it :-( */
+			ms = MAPI_E_AMBIGUOUS_RECIP;
+			/* Translators: %s is replaced with an email address which was found ambiguous on a remote server */
+			g_set_error (perror, E_MAPI_ERROR, ms, _("Recipient '%s' is ambiguous"), users[ii]);
+			goto cleanup;
+		} else if (flagList->aulPropTag[ii] == MAPI_UNRESOLVED) {
+			uint32_t last;
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
+			/* If the recipient is unresolved, consider it is a SMTP one */
+			rows->aRow = talloc_realloc (mem_ctx, rows->aRow, struct SRow, rows->cRows + 1);
+			last = rows->cRows;
+			rows->aRow[last].cValues = 0;
+			rows->aRow[last].lpProps = talloc_zero (mem_ctx, struct SPropValue);
+			if (!update_recipient_properties (conn, obj_folder, &rows->aRow[last], recipient, FALSE, mem_ctx, cancellable, perror)) {
+				ms = MAPI_E_CALL_FAILED;
+				goto cleanup;
+			}
+			rows->cRows += 1;
+		} else if (flagList->aulPropTag[ii] == MAPI_RESOLVED) {
+			if (!update_recipient_properties (conn, obj_folder, &rows->aRow[jj], recipient, TRUE, mem_ctx, cancellable, perror)) {
+				ms = MAPI_E_CALL_FAILED;
+				goto cleanup;
+			}
+			jj += 1;
+		}
 	}
 
-	/* Open the item */
-	ms = OpenMessage (&obj_folder, fid, mid, &obj_message, 0x0);
+	/* Modify the recipient table */
+	ms = ModifyRecipients (obj_message, rows);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenMessage", ms);
-		goto cleanup;
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
+		make_mapi_error (perror, "ModifyRecipients", ms);
 		goto cleanup;
 	}
 
-	result = e_mapi_connection_fetch_object_props (conn, &obj_folder, fid, mid, &obj_message, build_props, brp_data, cb, data, options, cancellable, perror);
-
  cleanup:
-	if (!result) {
-		mapi_object_release (&obj_message);
-		mapi_object_release (&obj_folder);
-	}
-	talloc_free (mem_ctx);
 	UNLOCK ();
 
-	e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	g_free (users);
+	g_free (recips);
+	g_free (named_ids_list);
+	g_hash_table_destroy (all_proptags);
 
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
-mapi_id_t
-e_mapi_connection_create_folder (EMapiConnection *conn,
-				 uint32_t olFolder,
-				 mapi_id_t pfid,
-				 guint32 fid_options,
-				 const gchar *name,
-				 GCancellable *cancellable,
-				 GError **perror)
+static gboolean
+delete_attachment_cb (EMapiConnection *conn,
+		      TALLOC_CTX *mem_ctx,
+		      struct SRow *srow,
+		      guint32 row_index,
+		      guint32 rows_total,
+		      gpointer user_data,
+		      GCancellable *cancellable,
+		      GError **perror)
 {
+	const uint32_t *attach_num;
+	mapi_object_t *obj_object = user_data;
 	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);
-
-	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;
-	}
-
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
-
-	/* Attempt to create the folder */
-	ms = CreateFolder (&obj_top, 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;
-	}
+	g_return_val_if_fail (obj_object != NULL, FALSE);
 
-	vals[0].value.lpszA = type;
-	vals[0].ulPropTag = PR_CONTAINER_CLASS;
+	attach_num = e_mapi_util_find_row_propval (srow, PidTagAttachNumber);
+	g_return_val_if_fail (attach_num != NULL, FALSE);
 
-	ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, vals, 1);
+	ms = DeleteAttach (obj_object, *attach_num);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetProps", ms);
-		goto cleanup;
-	}
-
-	fid = mapi_object_get_id (&obj_folder);
-	e_mapi_debug_print("Folder %s created with id %016" G_GINT64_MODIFIER "X ", name, fid);
-
-	g_static_rec_mutex_lock (&priv->folders_lock);
-
-	/* 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);
+		make_mapi_error (perror, "DeleteAttach", ms);
 	}
 
-	g_static_rec_mutex_unlock (&priv->folders_lock);
-
- cleanup:
-	mapi_object_release(&obj_folder);
-	mapi_object_release(&obj_top);
-
-	UNLOCK ();
-
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	/* Shouldn't we return (EMapiFolder *) instead of a plain fid ? */
-	return fid;
+	return ms == MAPI_E_SUCCESS;
 }
 
-gboolean
-e_mapi_connection_empty_folder (EMapiConnection *conn,
-				mapi_id_t fid,
-				guint32 fid_options,
-				GCancellable *cancellable,
-				GError **perror)
+static gboolean
+delete_object_attachments (EMapiConnection *conn,
+			   mapi_object_t *obj_folder,
+			   mapi_object_t *obj_object,
+			   TALLOC_CTX *mem_ctx,
+			   GCancellable *cancellable,
+			   GError **perror)
 {
 	enum MAPISTATUS ms;
-	mapi_object_t obj_folder;
-	gboolean result = FALSE;
+	mapi_object_t obj_table;
+	struct SPropTagArray *proptags;
 
 	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);
 
 	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);
+	mapi_object_init (&obj_table);
+
+	/* open attachment table */
+	ms = GetAttachmentTable (obj_object, &obj_table);
 	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "GetAttachmentTable", ms);
 		goto cleanup;
 	}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	proptags = set_SPropTagArray (mem_ctx, 1, PidTagAttachNumber);
 
-	/* Empty the contents of the folder */
-	ms = EmptyFolder (&obj_folder);
+	ms = SetColumns (&obj_table, proptags);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "EmptyFolder", ms);
+		make_mapi_error (perror, "SetColumns", ms);
 		goto cleanup;
 	}
 
-	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
-
-	result = TRUE;
+	ms = foreach_tablerow (conn, mem_ctx, &obj_table, delete_attachment_cb, obj_object, cancellable, perror);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "foreach_tablerow", ms);
+	}
 
  cleanup:
-	mapi_object_release(&obj_folder);
-	UNLOCK ();
+	mapi_object_release (&obj_table);
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	UNLOCK ();
 
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
-gboolean
-e_mapi_connection_remove_folder (EMapiConnection *conn,
-				 mapi_id_t fid,
-				 guint32 fid_options,
-				 GCancellable *cancellable,
-				 GError **perror)
+static gboolean update_message_with_object (EMapiConnection *conn,
+					    mapi_object_t *obj_folder,
+					    mapi_object_t *obj_message,
+					    EMapiObject *object,
+					    TALLOC_CTX *mem_ctx,
+					    GCancellable *cancellable,
+					    GError **perror);
+
+static gboolean
+add_object_attachments (EMapiConnection *conn,
+			mapi_object_t *obj_folder,
+			mapi_object_t *obj_message,
+			EMapiAttachment *attachments,
+			TALLOC_CTX *mem_ctx,
+			GCancellable *cancellable,
+			GError **perror)
 {
-	enum MAPISTATUS ms;
-	mapi_object_t obj_top;
-	mapi_object_t obj_folder;
-	EMapiFolder *folder;
-	gboolean result = FALSE;
-	GSList *l;
+	enum MAPISTATUS ms = MAPI_E_SUCCESS;
+	EMapiAttachment *attachment;
 
 	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_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	g_return_val_if_fail (fid != 0, FALSE);
+	LOCK ();
 
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+	for (attachment = attachments; attachment && ms == MAPI_E_SUCCESS; attachment = attachment->next) {
+		mapi_object_t obj_attach;
 
-	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 (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+			ms = MAPI_E_USER_CANCEL;
 			break;
-		else
-			folder = NULL;
-	}
+		}
 
-	e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+		mapi_object_init (&obj_attach);
 
-	LOCK ();
-	mapi_object_init(&obj_top);
-	mapi_object_init(&obj_folder);
+		ms = CreateAttach (obj_message, &obj_attach);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "CreateAttach", ms);
+			goto cleanup;
+		}
 
-	/* 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 (!update_props_on_object (conn, obj_folder, &obj_attach, &attachment->properties, mem_ctx, cancellable, perror)) {
+			ms = MAPI_E_CALL_FAILED;
+			make_mapi_error (perror, "update_props_on_object", ms);
+			goto cleanup;
+		}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+		if (attachment->embedded_object) {
+			mapi_object_t obj_emb_msg;
 
-	/* 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;
-	}
+			mapi_object_init (&obj_emb_msg);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+			ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "OpenEmbeddedMessage", ms);
+				goto cleanup;
+			}
 
-	/* Empty the contents of the folder */
-	ms = EmptyFolder (&obj_folder);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "EmptyFolder", ms);
-		goto cleanup;
-	}
+			if (!update_message_with_object (conn, obj_folder, &obj_emb_msg, attachment->embedded_object, mem_ctx, cancellable, perror)) {
+				ms = MAPI_E_CALL_FAILED;
+				make_mapi_error (perror, "SaveChangesMessage", ms);
+				mapi_object_release (&obj_emb_msg);
+				goto cleanup;
+			}
 
-	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
+			ms = SaveChangesMessage (&obj_attach, &obj_emb_msg, KeepOpenReadOnly);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "SaveChangesMessage", ms);
+				mapi_object_release (&obj_emb_msg);
+				goto cleanup;
+			}
 
-	/* 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;
-	}
+			mapi_object_release (&obj_emb_msg);
+		}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+		ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "SaveChangesAttachment", ms);
+			goto cleanup;
+		}
 
-	/* Call DeleteFolder on the folder to be removed */
-	ms = DeleteFolder (&obj_top, fid, DEL_FOLDERS, NULL);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "DeleteFolder", ms);
-		goto cleanup;
+	 cleanup:
+		mapi_object_release (&obj_attach);
 	}
 
-	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was deleted ", fid);
+	UNLOCK ();
 
-	result = TRUE;
+	return ms == MAPI_E_SUCCESS;
+}
 
- cleanup:
-	mapi_object_release(&obj_folder);
-	mapi_object_release(&obj_top);
+static gboolean
+update_message_with_object (EMapiConnection *conn,
+			    mapi_object_t *obj_folder,
+			    mapi_object_t *obj_message,
+			    EMapiObject *object,
+			    TALLOC_CTX *mem_ctx,
+			    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);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	g_static_rec_mutex_lock (&priv->folders_lock);
-	priv->folders = g_slist_remove (priv->folders, folder);
-	g_static_rec_mutex_unlock (&priv->folders_lock);
+	if (!update_props_on_object (conn, obj_folder, obj_message, &object->properties, mem_ctx, cancellable, perror))
+		return FALSE;
 
-	e_mapi_folder_free (folder);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		return FALSE;
 
-	UNLOCK ();
+	/* do not touch recipients if not set */
+	if (object->recipients) {
+		/* remove current recipients... */
+		if (!delete_object_recipients (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
+			return FALSE;
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+		if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+			return FALSE;
 
-	return result;
+		/* ... and add new */
+		if (!add_object_recipients (conn, obj_folder, obj_message, object->recipients, mem_ctx, cancellable, perror))
+			return FALSE;
+	}
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		return FALSE;
+
+	/* remove current attachments... */
+	if (!delete_object_attachments (conn, obj_folder, obj_message, mem_ctx, cancellable, perror))
+		return FALSE;
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		return FALSE;
+
+	/* ... and add new */
+	if (object->attachments && !add_object_attachments (conn, obj_folder, obj_message, object->attachments, mem_ctx, cancellable, perror))
+		return FALSE;
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+		return FALSE;
+
+	return TRUE;
 }
 
 gboolean
-e_mapi_connection_rename_folder (EMapiConnection *conn,
-				 mapi_id_t fid,
-				 guint32 fid_options,
-				 const gchar *new_name,
+e_mapi_connection_create_object (EMapiConnection *conn,
+				 mapi_object_t *obj_folder,
+				 uint32_t flags, /* bit-or of EMapiCreateFlags */
+				 WriteObjectCB write_object_cb,
+				 gpointer woc_data,
+				 mapi_id_t *out_mid,
 				 GCancellable *cancellable,
 				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	mapi_object_t obj_folder;
-	struct SPropValue *props = NULL;
 	TALLOC_CTX *mem_ctx;
-	gboolean result = FALSE;
+	EMapiObject *object = NULL;
+	mapi_object_t obj_message;
 
 	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_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (out_mid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+	LOCK ();
+
+	*out_mid = 0;
+
+	mem_ctx = talloc_new (priv->session);
+	mapi_object_init (&obj_message);
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
+
+	if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror) || !object) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "write_object_cb", ms);
+		goto cleanup;
+	}
 
-	LOCK ();
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-	/* Open the folder to be renamed */
-	ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
+	ms = CreateMessage (obj_folder, &obj_message);
 	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "CreateMessage", ms);
 		goto cleanup;
 	}
 
@@ -5109,71 +3254,98 @@ e_mapi_connection_rename_folder (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	props = talloc_zero(mem_ctx, struct SPropValue);
-	set_SPropValue_proptag (props, PR_DISPLAY_NAME_UNICODE, new_name);
+	if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "update_message_with_object", ms);
+		goto cleanup;
+	}
 
-	ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, 1);
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
+
+	ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadWrite);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetProps", ms);
+		make_mapi_error (perror, "SaveChangesMessage", ms);
 		goto cleanup;
 	}
 
-	result = TRUE;
+	if ((flags & E_MAPI_CREATE_FLAG_SUBMIT) != 0) {
+		/* Mark message as ready to be sent */
+		ms = SubmitMessage (&obj_message);
+		if (ms != MAPI_E_SUCCESS) {
+			mapi_id_t mid;
+			make_mapi_error (perror, "SubmitMessage", ms);
+
+			/*
+			The code is storing message right to Sent items instead of Outbox,
+			because fetching PR_ENTRYID or PR_IPM_SENTMAIL_ENTRYID didn't seem
+			to work in time of doing this change.
+
+			For more information and other possible (correct) approaches see:
+			https://bugzilla.gnome.org/show_bug.cgi?id=561794
+			*/
+			mid = mapi_object_get_id (&obj_message);
+
+			mapi_object_release (&obj_message);
+			/* to not release a message object twice */
+			mapi_object_init (&obj_message);
+
+			ms = DeleteMessage (obj_folder, &mid, 1);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "DeleteMessage", ms);
+			}
+
+			goto cleanup;
+		}
+	}
+
+	*out_mid = mapi_object_get_id (&obj_message);
 
  cleanup:
-	mapi_object_release(&obj_folder);
-	talloc_free(mem_ctx);
-	UNLOCK ();
+	e_mapi_object_free (object);
+	mapi_object_release (&obj_message);
+	talloc_free (mem_ctx);
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	UNLOCK ();
 
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
-/* moves folder 'src_fid' to folder 'des_fid' under name 'new_name' (no path in a new_name),
-   'src_parent_fid' is folder ID of a parent of the src_fid */
 gboolean
-e_mapi_connection_move_folder  (EMapiConnection *conn,
-				mapi_id_t src_fid,
-				mapi_id_t src_parent_fid,
-				guint32 src_fid_options,
-				mapi_id_t des_fid,
-				guint32 des_fid_options,
-				const gchar *new_name,
-				GCancellable *cancellable,
-				GError **perror)
+e_mapi_connection_modify_object (EMapiConnection *conn,
+				 mapi_object_t *obj_folder,
+				 mapi_id_t mid,
+				 WriteObjectCB write_object_cb,
+				 gpointer woc_data,
+				 GCancellable *cancellable,
+				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	mapi_object_t obj_src, obj_src_parent, obj_des;
-	gboolean result = FALSE;
+	TALLOC_CTX *mem_ctx;
+	EMapiObject *object = NULL;
+	mapi_object_t obj_message;
 
 	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 (src_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (src_parent_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (des_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (new_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (strchr (new_name, '/') == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (mid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
 
-	mapi_object_init (&obj_src);
-	mapi_object_init (&obj_src_parent);
-	mapi_object_init (&obj_des);
-
-	ms = open_folder (conn, 0, &src_fid, src_fid_options, &obj_src, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
+	mem_ctx = talloc_new (priv->session);
+	mapi_object_init (&obj_message);
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
 		ms = MAPI_E_USER_CANCEL;
 		goto cleanup;
 	}
 
-	ms = open_folder (conn, 0, &src_parent_fid, src_fid_options, &obj_src_parent, perror);
-	if (ms != MAPI_E_SUCCESS) {
+	if (!write_object_cb (conn, mem_ctx, &object, woc_data, cancellable, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "write_object_cb", ms);
 		goto cleanup;
 	}
 
@@ -5182,8 +3354,9 @@ e_mapi_connection_move_folder  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	ms = open_folder (conn, 0, &des_fid, des_fid_options, &obj_des, perror);
+	ms = OpenMessage (obj_folder, mapi_object_get_id (obj_folder), mid, &obj_message, MAPI_MODIFY);
 	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "OpenMessage", ms);
 		goto cleanup;
 	}
 
@@ -5192,118 +3365,149 @@ e_mapi_connection_move_folder  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	ms = MoveFolder (&obj_src, &obj_src_parent, &obj_des, (gchar *)new_name, TRUE);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "MoveFolder", ms);
+	if (!update_message_with_object (conn, obj_folder, &obj_message, object, mem_ctx, cancellable, perror)) {
+		ms = MAPI_E_CALL_FAILED;
+		make_mapi_error (perror, "update_message_with_object", ms);
 		goto cleanup;
 	}
 
-	result = TRUE;
+	ms = SaveChangesMessage (obj_folder, &obj_message, KeepOpenReadOnly);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "SaveChangesMessage", ms);
+		goto cleanup;
+	}
 
  cleanup:
-	mapi_object_release (&obj_des);
-	mapi_object_release (&obj_src_parent);
-	mapi_object_release (&obj_src);
+	e_mapi_object_free (object);
+	mapi_object_release (&obj_message);
+	talloc_free (mem_ctx);
 
 	UNLOCK ();
 
-	return result;
+	return ms == MAPI_E_SUCCESS;
 }
 
-/* named_ids_list contains pointers to ResolveNamedIDsData structure */
-gboolean
-e_mapi_connection_resolve_named_props  (EMapiConnection *conn,
-					mapi_id_t fid,
-					ResolveNamedIDsData *named_ids_list,
-					guint named_ids_n_elems,
-					GCancellable *cancellable,
-					GError **perror)
+mapi_id_t
+e_mapi_connection_create_folder (EMapiConnection *conn,
+				 uint32_t olFolder,
+				 mapi_id_t pfid,
+				 guint32 fid_options,
+				 const gchar *name,
+				 GCancellable *cancellable,
+				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
 	mapi_object_t obj_folder;
-	struct mapi_nameid *nameid;
-	struct SPropTagArray *SPropTagArray;
-	guint i, j;
-	GPtrArray *todo = NULL;
-	gboolean res = FALSE;
+	mapi_object_t obj_top;
+	struct SPropValue vals[1];
+	const gchar *type;
+	mapi_id_t fid = 0;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (named_ids_list != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (named_ids_n_elems > 0, MAPI_E_INVALID_PARAMETER, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	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);
+	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
 	LOCK ();
-	if (priv->named_ids) {
-		gint64 i64 = fid;
-		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+	mapi_object_init(&obj_top);
+	mapi_object_init(&obj_folder);
 
-		if (ids) {
-			for (i = 0; i < named_ids_n_elems; i++) {
-				ResolveNamedIDsData *data = &named_ids_list[i];
-				uint32_t propid;
+	/* 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;
+	}
 
-				propid = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (data->pidlid_propid)));
-				if (propid) {
-					data->propid = propid;
-				} else {
-					if (!todo)
-						todo = g_ptr_array_new ();
-					g_ptr_array_add (todo, data);
-				}
-			}
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-			if (!todo) {
-				UNLOCK ();
-				e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-				return TRUE;
-			}
-		}
+	/* Attempt to create the folder */
+	ms = CreateFolder (&obj_top, 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;
 	}
 
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init (&obj_folder);
+	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;
+
+	ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, vals, 1);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "SetProps", ms);
+		goto cleanup;
+	}
+
+	fid = mapi_object_get_id (&obj_folder);
+	e_mapi_debug_print("Folder %s created with id %016" G_GINT64_MODIFIER "X ", name, fid);
+
+	g_static_rec_mutex_lock (&priv->folders_lock);
+
+	/* 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);
+	}
+
+	g_static_rec_mutex_unlock (&priv->folders_lock);
 
-	nameid = mapi_nameid_new (mem_ctx);
-	SPropTagArray = talloc_zero (mem_ctx, struct SPropTagArray);
+ cleanup:
+	mapi_object_release(&obj_folder);
+	mapi_object_release(&obj_top);
 
-	/* Attempt to open the folder */
-	ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
-	if (ms != MAPI_E_SUCCESS) {
-		goto cleanup;
-	}
+	UNLOCK ();
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-	if (!todo) {
-		todo = g_ptr_array_new ();
-		for (i = 0; i < named_ids_n_elems; i++) {
-			g_ptr_array_add (todo, &named_ids_list[i]);
-		}
-	}
+	/* Shouldn't we return (EMapiFolder *) instead of a plain fid ? */
+	return fid;
+}
 
-	for (i = 0; i < todo->len; i++) {
-		ResolveNamedIDsData *data = todo->pdata[i];
+gboolean
+e_mapi_connection_empty_folder (EMapiConnection *conn,
+				mapi_id_t fid,
+				guint32 fid_options,
+				GCancellable *cancellable,
+				GError **perror)
+{
+	enum MAPISTATUS ms;
+	mapi_object_t obj_folder;
+	gboolean result = FALSE;
 
-		if (mapi_nameid_canonical_add (nameid, data->pidlid_propid) != MAPI_E_SUCCESS)
-			data->propid = MAPI_E_RESERVED;
-		else
-			data->propid = 0;
-	}
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
-	ms = mapi_nameid_GetIDsFromNames (nameid, &obj_folder, SPropTagArray);
+	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);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
 		goto cleanup;
 	}
 
@@ -5312,103 +3516,73 @@ e_mapi_connection_resolve_named_props  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	for (i = 0, j = 0; i < SPropTagArray->cValues && j < todo->len; i++) {
-		while (j < todo->len) {
-			ResolveNamedIDsData *data = todo->pdata[j];
-			if (data && data->propid == 0) {
-				if ((SPropTagArray->aulPropTag[i] & 0xFFFF) == PT_ERROR)
-					data->propid = MAPI_E_RESERVED;
-				else
-					data->propid = SPropTagArray->aulPropTag[i];
-				break;
-			}
-
-			j++;
-		}
+	/* Empty the contents of the folder */
+	ms = EmptyFolder (&obj_folder);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "EmptyFolder", ms);
+		goto cleanup;
 	}
 
-	if (priv->named_ids) {
-		gint64 i64 = fid;
-		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
-
-		if (!ids) {
-			gint64 *i64ptr = g_malloc (sizeof (gint64));
-
-			*i64ptr = fid;
-			ids = g_hash_table_new (g_direct_hash, g_direct_equal);
-
-			g_hash_table_insert (priv->named_ids, i64ptr, ids);
-		}
-
-		for (i = 0; i < todo->len; i++) {
-			ResolveNamedIDsData *data = todo->pdata[i];
-
-			g_hash_table_insert (ids, GUINT_TO_POINTER (data->pidlid_propid), GUINT_TO_POINTER (data->propid));
-		}
-	}
+	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
 
-	res = TRUE;
+	result = TRUE;
 
  cleanup:
-	if (todo)
-		g_ptr_array_free (todo, TRUE);
-	mapi_object_release (&obj_folder);
-	talloc_free (mem_ctx);
-
+	mapi_object_release(&obj_folder);
 	UNLOCK ();
 
-	e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-	return res;
+	return result;
 }
 
-/* returns MAPI_E_RESERVED on any error */
-uint32_t
-e_mapi_connection_resolve_named_prop (EMapiConnection *conn,
-				      mapi_id_t fid,
-				      uint32_t pidlid_propid,
-				      GCancellable *cancellable,
-				      GError **perror)
+gboolean
+e_mapi_connection_remove_folder (EMapiConnection *conn,
+				 mapi_id_t fid,
+				 guint32 fid_options,
+				 GCancellable *cancellable,
+				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
+	mapi_object_t obj_top;
 	mapi_object_t obj_folder;
-	struct mapi_nameid *nameid;
-	struct SPropTagArray *SPropTagArray;
-	uint32_t res = MAPI_E_RESERVED;
+	EMapiFolder *folder;
+	gboolean result = FALSE;
+	GSList *l;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, res);
+	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_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
-	LOCK ();
+	folder = NULL;
+	for (l = e_mapi_connection_peek_folders_list (conn); l; l = l->next) {
+		folder = l->data;
+		if (folder && folder->folder_id == fid)
+			break;
+		else
+			folder = NULL;
+	}
 
-	if (priv->named_ids) {
-		gint64 i64 = fid;
-		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+	e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-		if (ids) {
-			res = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (pidlid_propid)));
-			if (res != 0) {
-				UNLOCK ();
-				e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	LOCK ();
+	mapi_object_init(&obj_top);
+	mapi_object_init(&obj_folder);
 
-				return res;
-			}
+	/* 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.
+	 */
 
-			res = MAPI_E_RESERVED;
-		}
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
 	}
 
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
-
-	nameid = mapi_nameid_new(mem_ctx);
-	SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
-
-	/* Attempt to open the folder */
-	ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
+	/* 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;
 	}
@@ -5418,144 +3592,142 @@ e_mapi_connection_resolve_named_prop (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	mapi_nameid_canonical_add (nameid, pidlid_propid);
-
-	ms = mapi_nameid_GetIDsFromNames(nameid, &obj_folder, SPropTagArray);
+	/* Empty the contents of the folder */
+	ms = EmptyFolder (&obj_folder);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
+		make_mapi_error (perror, "EmptyFolder", ms);
 		goto cleanup;
 	}
 
-	res = SPropTagArray->aulPropTag[0];
-	if ((res & 0xFFFF) == PT_ERROR)
-		res = MAPI_E_RESERVED;
+	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
 
-	if (priv->named_ids) {
-		gint64 i64 = fid;
-		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+	/* 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 (!ids) {
-			gint64 *i64ptr = g_malloc (sizeof (gint64));
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-			*i64ptr = fid;
-			ids = g_hash_table_new (g_direct_hash, g_direct_equal);
+	/* Call DeleteFolder on the folder to be removed */
+	ms = DeleteFolder (&obj_top, fid, DEL_FOLDERS, NULL);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "DeleteFolder", ms);
+		goto cleanup;
+	}
 
-			g_hash_table_insert (priv->named_ids, i64ptr, ids);
-		}
+	e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was deleted ", fid);
 
-		g_hash_table_insert (ids, GUINT_TO_POINTER (pidlid_propid), GUINT_TO_POINTER (res));
-	}
+	result = TRUE;
 
  cleanup:
 	mapi_object_release(&obj_folder);
-	talloc_free(mem_ctx);
-
-	UNLOCK ();
-
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return res;
-}
-
-/* returns named id, aka PidLid/PidName for a given proptag, which might be previously
-   obtained as a result of e_mapi_connection_resolve_named_prop/s.
-   Returns MAPI_E_RESERVED when not found.
-*/
-uint32_t
-e_mapi_connection_unresolve_proptag_to_nameid (EMapiConnection *conn, mapi_id_t fid, uint32_t proptag)
-{
-	uint32_t res = MAPI_E_RESERVED;
-	/* to have this used in the below macros */
-	GError **perror = NULL;
+	mapi_object_release(&obj_top);
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
+	g_static_rec_mutex_lock (&priv->folders_lock);
+	priv->folders = g_slist_remove (priv->folders, folder);
+	g_static_rec_mutex_unlock (&priv->folders_lock);
 
-	if (priv->named_ids) {
-		gint64 i64 = fid;
-		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+	e_mapi_folder_free (folder);
 
-		if (ids) {
-			GHashTableIter iter;
-			gpointer stored_pidlid, stored_proptag, lookup_proptag = GUINT_TO_POINTER (proptag);
-			gboolean is_error = PT_ERROR == (proptag & 0xFFFF);
+	UNLOCK ();
 
-			g_hash_table_iter_init (&iter, ids);
-			while (g_hash_table_iter_next (&iter, &stored_pidlid, &stored_proptag)) {
-				if (stored_proptag == lookup_proptag || (is_error && (GPOINTER_TO_UINT (stored_proptag) & ~0xFFFF) == (proptag & ~0xFFFF))) {
-					res = GPOINTER_TO_UINT (stored_pidlid);
-					break;
-				}
-			}
-		}
-	}
+	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-	return res;
+	return result;
 }
 
-mapi_id_t
-e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
-					 uint32_t olFolder,
-					 GCancellable *cancellable,
-					 GError **perror)
+gboolean
+e_mapi_connection_rename_folder (EMapiConnection *conn,
+				 mapi_id_t fid,
+				 guint32 fid_options,
+				 const gchar *new_name,
+				 GCancellable *cancellable,
+				 GError **perror)
 {
 	enum MAPISTATUS ms;
-	mapi_id_t fid = 0;
+	mapi_object_t obj_folder;
+	struct SPropValue *props = NULL;
+	TALLOC_CTX *mem_ctx;
+	gboolean result = FALSE;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 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);
 
 	LOCK ();
+	mem_ctx = talloc_new (priv->session);
+	mapi_object_init(&obj_folder);
 
-	ms = GetDefaultFolder (&priv->msg_store, &fid, olFolder);
+	/* Open the folder to be renamed */
+	ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "GetDefaultFolder", ms);
 		goto cleanup;
 	}
 
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
+
+	props = talloc_zero(mem_ctx, struct SPropValue);
+	set_SPropValue_proptag (props, PR_DISPLAY_NAME_UNICODE, new_name);
+
+	ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, 1);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "SetProps", ms);
+		goto cleanup;
+	}
+
+	result = TRUE;
+
  cleanup:
+	mapi_object_release(&obj_folder);
+	talloc_free(mem_ctx);
 	UNLOCK ();
 
 	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-	return (ms == MAPI_E_SUCCESS ? fid : 0);
+	return result;
 }
 
-mapi_id_t
-e_mapi_connection_create_item  (EMapiConnection *conn,
-				uint32_t olFolder,
-				mapi_id_t fid,
-				BuildWritePropsCB build_props,
-				gpointer bwp_data,
-				GSList *recipients,
-				GSList *attachments,
-				GSList *generic_streams,
-				uint32_t options,
+/* moves folder 'src_fid' to folder 'des_fid' under name 'new_name' (no path in a new_name),
+   'src_parent_fid' is folder ID of a parent of the src_fid */
+gboolean
+e_mapi_connection_move_folder  (EMapiConnection *conn,
+				mapi_id_t src_fid,
+				mapi_id_t src_parent_fid,
+				guint32 src_fid_options,
+				mapi_id_t des_fid,
+				guint32 des_fid_options,
+				const gchar *new_name,
 				GCancellable *cancellable,
 				GError **perror)
 {
 	enum MAPISTATUS ms;
-	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_folder;
-	mapi_object_t obj_message;
-	struct SPropValue *props = NULL;
-	uint32_t propslen = 0;
-	mapi_id_t mid = 0;
+	mapi_object_t obj_src, obj_src_parent, obj_des;
+	gboolean result = FALSE;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 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 (src_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (src_parent_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (des_fid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (new_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (strchr (new_name, '/') == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
 	LOCK ();
 
-	mem_ctx = talloc_new (priv->session);
-	mapi_object_init(&obj_folder);
-	mapi_object_init(&obj_message);
+	mapi_object_init (&obj_src);
+	mapi_object_init (&obj_src_parent);
+	mapi_object_init (&obj_des);
 
-	/* Attempt to open the folder */
-	ms = open_folder (conn, olFolder, &fid, options, &obj_folder, perror);
+	ms = open_folder (conn, 0, &src_fid, src_fid_options, &obj_src, perror);
 	if (ms != MAPI_E_SUCCESS) {
 		goto cleanup;
 	}
@@ -5565,10 +3737,8 @@ e_mapi_connection_create_item  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	/* Create the item */
-	ms = CreateMessage (&obj_folder, &obj_message);
+	ms = open_folder (conn, 0, &src_parent_fid, src_fid_options, &obj_src_parent, perror);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "CreateMessage", ms);
 		goto cleanup;
 	}
 
@@ -5577,17 +3747,8 @@ e_mapi_connection_create_item  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	/* Add regular props using callback */
-	if (build_props && !build_props (conn, fid, mem_ctx, &props, &propslen, bwp_data, cancellable, perror)) {
-		e_mapi_debug_print ("%s: (%s): build_props failed! propslen = %d ", G_STRLOC, G_STRFUNC, propslen);
-		make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
-		goto cleanup;
-	}
-
-	/* set properties for the item */
-	ms = SetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
+	ms = open_folder (conn, 0, &des_fid, des_fid_options, &obj_des, perror);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetProps", ms);
 		goto cleanup;
 	}
 
@@ -5596,132 +3757,223 @@ e_mapi_connection_create_item  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	if (generic_streams) {
-		if (!e_mapi_util_write_generic_streams (&obj_message, generic_streams, perror))
-			goto cleanup;
+	ms = MoveFolder (&obj_src, &obj_src_parent, &obj_des, (gchar *)new_name, TRUE);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "MoveFolder", ms);
+		goto cleanup;
+	}
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
+	result = TRUE;
+
+ cleanup:
+	mapi_object_release (&obj_des);
+	mapi_object_release (&obj_src_parent);
+	mapi_object_release (&obj_src);
+
+	UNLOCK ();
+
+	return result;
+}
+
+/* named_ids_list contains pointers to ResolveNamedIDsData structure */
+gboolean
+e_mapi_connection_resolve_named_props  (EMapiConnection *conn,
+					mapi_id_t fid,
+					ResolveNamedIDsData *named_ids_list,
+					guint named_ids_n_elems,
+					GCancellable *cancellable,
+					GError **perror)
+{
+	enum MAPISTATUS ms;
+	TALLOC_CTX *mem_ctx;
+	mapi_object_t obj_folder;
+	struct mapi_nameid *nameid;
+	struct SPropTagArray *SPropTagArray;
+	guint i, j;
+	GPtrArray *todo = NULL;
+	gboolean res = FALSE;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (named_ids_list != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	e_return_val_mapi_error_if_fail (named_ids_n_elems > 0, MAPI_E_INVALID_PARAMETER, 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);
+
+	LOCK ();
+	if (priv->named_ids) {
+		gint64 i64 = fid;
+		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+
+		if (ids) {
+			for (i = 0; i < named_ids_n_elems; i++) {
+				ResolveNamedIDsData *data = &named_ids_list[i];
+				uint32_t propid;
+
+				propid = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (data->pidlid_propid)));
+				if (propid) {
+					data->propid = propid;
+				} else {
+					if (!todo)
+						todo = g_ptr_array_new ();
+					g_ptr_array_add (todo, data);
+				}
+			}
+
+			if (!todo) {
+				UNLOCK ();
+				e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+				return TRUE;
+			}
 		}
 	}
 
-	/* Set attachments if any */
-	if (attachments) {
-		if (!e_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_message, attachments, FALSE, perror))
-			goto cleanup;
+	mem_ctx = talloc_new (priv->session);
+	mapi_object_init (&obj_folder);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
+	nameid = mapi_nameid_new (mem_ctx);
+	SPropTagArray = talloc_zero (mem_ctx, struct SPropTagArray);
+
+	/* Attempt to open the folder */
+	ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
+	if (ms != MAPI_E_SUCCESS) {
+		goto cleanup;
 	}
 
-	/* Set recipients if any */
-	if (recipients) {
-		if (!e_mapi_util_modify_recipients (conn, mem_ctx, &obj_message, recipients, FALSE, perror))
-			goto cleanup;
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
+	if (!todo) {
+		todo = g_ptr_array_new ();
+		for (i = 0; i < named_ids_n_elems; i++) {
+			g_ptr_array_add (todo, &named_ids_list[i]);
 		}
 	}
 
-	/* Finally, save all changes */
-	ms = SaveChangesMessage (&obj_folder, &obj_message, KeepOpenReadWrite);
+	for (i = 0; i < todo->len; i++) {
+		ResolveNamedIDsData *data = todo->pdata[i];
+
+		if (mapi_nameid_canonical_add (nameid, data->pidlid_propid) != MAPI_E_SUCCESS)
+			data->propid = MAPI_E_RESERVED;
+		else
+			data->propid = 0;
+	}
+
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
+
+	ms = mapi_nameid_GetIDsFromNames (nameid, &obj_folder, SPropTagArray);
 	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SaveChangesMessage", ms);
+		make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
 		goto cleanup;
 	}
 
-	if (recipients && !(options & MAPI_OPTIONS_DONT_SUBMIT)) {
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
+	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+		ms = MAPI_E_USER_CANCEL;
+		goto cleanup;
+	}
+
+	for (i = 0, j = 0; i < SPropTagArray->cValues && j < todo->len; i++) {
+		while (j < todo->len) {
+			ResolveNamedIDsData *data = todo->pdata[j];
+			if (data && data->propid == 0) {
+				if ((SPropTagArray->aulPropTag[i] & 0xFFFF) == PT_ERROR)
+					data->propid = MAPI_E_RESERVED;
+				else
+					data->propid = SPropTagArray->aulPropTag[i];
+				break;
+			}
+
+			j++;
 		}
+	}
 
-		/* Mark message as ready to be sent */
-		ms = SubmitMessage (&obj_message);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SubmitMessage", ms);
+	if (priv->named_ids) {
+		gint64 i64 = fid;
+		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
 
-			/*
-			The code is storing message right to Sent items instead of Outbox,
-			because fetching PR_ENTRYID or PR_IPM_SENTMAIL_ENTRYID didn't seem
-			to work in time of doing this change.
+		if (!ids) {
+			gint64 *i64ptr = g_malloc (sizeof (gint64));
 
-			For more information and other possible (correct) approaches see:
-			https://bugzilla.gnome.org/show_bug.cgi?id=561794
-			*/
-			if ((options & MAPI_OPTIONS_DELETE_ON_SUBMIT_FAILURE) != 0) {
-				mid = mapi_object_get_id (&obj_message);
-				mapi_object_release(&obj_message);
-				/* to not release a message object twice */
-				mapi_object_init (&obj_message);
+			*i64ptr = fid;
+			ids = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-				ms = DeleteMessage (&obj_folder, &mid, 1);
-				if (ms != MAPI_E_SUCCESS) {
-					make_mapi_error (perror, "DeleteMessage", ms);
-				}
+			g_hash_table_insert (priv->named_ids, i64ptr, ids);
+		}
 
-				/* do not forget to set it back to 0, as the function failed */
-				mid = 0;
-			}
+		for (i = 0; i < todo->len; i++) {
+			ResolveNamedIDsData *data = todo->pdata[i];
 
-			goto cleanup;
+			g_hash_table_insert (ids, GUINT_TO_POINTER (data->pidlid_propid), GUINT_TO_POINTER (data->propid));
 		}
 	}
 
-	mid = mapi_object_get_id (&obj_message);
+	res = TRUE;
 
  cleanup:
-	mapi_object_release(&obj_message);
-	mapi_object_release(&obj_folder);
-	talloc_free(mem_ctx);
+	if (todo)
+		g_ptr_array_free (todo, TRUE);
+	mapi_object_release (&obj_folder);
+	talloc_free (mem_ctx);
 
 	UNLOCK ();
 
-	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-	return mid;
+	return res;
 }
 
-gboolean
-e_mapi_connection_modify_item  (EMapiConnection *conn,
-				uint32_t olFolder,
-				mapi_id_t fid,
-				mapi_id_t mid,
-				BuildWritePropsCB build_props,
-				gpointer bwp_data,
-				GSList *recipients,
-				GSList *attachments,
-				GSList *generic_streams,
-				uint32_t options,
-				GCancellable *cancellable,
-				GError **perror)
+/* returns MAPI_E_RESERVED on any error */
+uint32_t
+e_mapi_connection_resolve_named_prop (EMapiConnection *conn,
+				      mapi_id_t fid,
+				      uint32_t pidlid_propid,
+				      GCancellable *cancellable,
+				      GError **perror)
 {
 	enum MAPISTATUS ms;
 	TALLOC_CTX *mem_ctx;
 	mapi_object_t obj_folder;
-	mapi_object_t obj_message;
-	struct SPropValue *props = NULL;
-	uint32_t propslen = 0;
-	gboolean result = FALSE;
+	struct mapi_nameid *nameid;
+	struct SPropTagArray *SPropTagArray;
+	uint32_t res = MAPI_E_RESERVED;
 
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, res);
 
 	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
 	LOCK ();
 
+	if (priv->named_ids) {
+		gint64 i64 = fid;
+		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+
+		if (ids) {
+			res = GPOINTER_TO_UINT (g_hash_table_lookup (ids, GUINT_TO_POINTER (pidlid_propid)));
+			if (res != 0) {
+				UNLOCK ();
+				e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+
+				return res;
+			}
+
+			res = MAPI_E_RESERVED;
+		}
+	}
+
 	mem_ctx = talloc_new (priv->session);
 	mapi_object_init(&obj_folder);
-	mapi_object_init(&obj_message);
+
+	nameid = mapi_nameid_new(mem_ctx);
+	SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
 
 	/* Attempt to open the folder */
-	ms = open_folder (conn, olFolder, &fid, options, &obj_folder, perror);
+	ms = open_folder (conn, 0, &fid, 0, &obj_folder, perror);
 	if (ms != MAPI_E_SUCCESS) {
 		goto cleanup;
 	}
@@ -5731,104 +3983,108 @@ e_mapi_connection_modify_item  (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	/* Open the item to be modified */
-	ms = OpenMessage (&obj_folder, fid, mid, &obj_message, MAPI_MODIFY);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "OpenMessage", ms);
-		goto cleanup;
-	}
+	mapi_nameid_canonical_add (nameid, pidlid_propid);
 
-	/* Add regular props using callback */
-	if (build_props && !build_props (conn, fid, mem_ctx, &props, &propslen, bwp_data, cancellable, perror)) {
-		e_mapi_debug_print ("%s: (%s): Could not build props ", G_STRLOC, G_STRFUNC);
-		make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+	ms = mapi_nameid_GetIDsFromNames(nameid, &obj_folder, SPropTagArray);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "mapi_nameid_GetIDsFromNames", ms);
 		goto cleanup;
 	}
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+	res = SPropTagArray->aulPropTag[0];
+	if ((res & 0xFFFF) == PT_ERROR)
+		res = MAPI_E_RESERVED;
 
-	/* set properties for the item */
-	ms = SetProps (&obj_message, MAPI_PROPS_SKIP_NAMEDID_CHECK, props, propslen);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SetProps", ms);
-		goto cleanup;
-	}
+	if (priv->named_ids) {
+		gint64 i64 = fid;
+		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
 
-	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-		ms = MAPI_E_USER_CANCEL;
-		goto cleanup;
-	}
+		if (!ids) {
+			gint64 *i64ptr = g_malloc (sizeof (gint64));
 
-	if (generic_streams) {
-		if (!e_mapi_util_write_generic_streams (&obj_message, generic_streams, perror))
-			goto cleanup;
+			*i64ptr = fid;
+			ids = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
+			g_hash_table_insert (priv->named_ids, i64ptr, ids);
 		}
+
+		g_hash_table_insert (ids, GUINT_TO_POINTER (pidlid_propid), GUINT_TO_POINTER (res));
 	}
 
-	/* Set attachments if any */
-	if (attachments) {
-		if (!e_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_message, attachments, TRUE, perror))
-			goto cleanup;
+ cleanup:
+	mapi_object_release(&obj_folder);
+	talloc_free(mem_ctx);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
-	} else {
-		e_mapi_util_delete_attachments (mem_ctx, &obj_message, NULL);
-	}
+	UNLOCK ();
 
-	/* Set recipients if any */
-	if (recipients) {
-		if (!e_mapi_util_modify_recipients (conn, mem_ctx, &obj_message, recipients, TRUE, perror))
-			goto cleanup;
+	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
-	}
+	return res;
+}
 
-	/* Finally, save all changes */
-	ms = SaveChangesMessage (&obj_folder, &obj_message, KeepOpenReadWrite);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "SaveChangesMessage", ms);
-		goto cleanup;
-	}
+/* returns named id, aka PidLid/PidName for a given proptag, which might be previously
+   obtained as a result of e_mapi_connection_resolve_named_prop/s.
+   Returns MAPI_E_RESERVED when not found.
+*/
+uint32_t
+e_mapi_connection_unresolve_proptag_to_nameid (EMapiConnection *conn, mapi_id_t fid, uint32_t proptag)
+{
+	uint32_t res = MAPI_E_RESERVED;
+	/* to have this used in the below macros */
+	GError **perror = NULL;
 
-	if (recipients && !(options & MAPI_OPTIONS_DONT_SUBMIT)) {
-		if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
-			ms = MAPI_E_USER_CANCEL;
-			goto cleanup;
-		}
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, res);
 
-		/* Mark message as ready to be sent */
-		ms = SubmitMessage (&obj_message);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SubmitMessage", ms);
-			goto cleanup;
+	if (priv->named_ids) {
+		gint64 i64 = fid;
+		GHashTable *ids = g_hash_table_lookup (priv->named_ids, &i64);
+
+		if (ids) {
+			GHashTableIter iter;
+			gpointer stored_pidlid, stored_proptag, lookup_proptag = GUINT_TO_POINTER (proptag);
+			gboolean is_error = PT_ERROR == (proptag & 0xFFFF);
+
+			g_hash_table_iter_init (&iter, ids);
+			while (g_hash_table_iter_next (&iter, &stored_pidlid, &stored_proptag)) {
+				if (stored_proptag == lookup_proptag || (is_error && (GPOINTER_TO_UINT (stored_proptag) & ~0xFFFF) == (proptag & ~0xFFFF))) {
+					res = GPOINTER_TO_UINT (stored_pidlid);
+					break;
+				}
+			}
 		}
 	}
 
-	result = TRUE;
+	return res;
+}
 
- cleanup:
-	mapi_object_release(&obj_message);
-	mapi_object_release(&obj_folder);
-	talloc_free(mem_ctx);
+mapi_id_t
+e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
+					 uint32_t olFolder,
+					 GCancellable *cancellable,
+					 GError **perror)
+{
+	enum MAPISTATUS ms;
+	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);
+
+	LOCK ();
+
+	ms = GetDefaultFolder (&priv->msg_store, &fid, olFolder);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "GetDefaultFolder", ms);
+		goto cleanup;
+	}
 
+ cleanup:
 	UNLOCK ();
 
 	e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
-	return result;
+	return (ms == MAPI_E_SUCCESS ? fid : 0);
 }
 
 gboolean
@@ -6022,7 +4278,7 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
 				uint32_t olFolder,
 				mapi_id_t fid,
 				guint32 fid_options,
-				GSList *mids,
+				const GSList *mids,
 				GCancellable *cancellable,
 				GError **perror)
 {
@@ -6031,7 +4287,7 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
 	mapi_object_t obj_folder;
 	uint32_t i;
 	mapi_id_t *id_messages;
-	GSList *tmp = mids;
+	const GSList *tmp = mids;
 	gboolean result = FALSE;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
@@ -6044,10 +4300,10 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
 	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++) {
-		struct id_list *data = tmp->data;
-		id_messages[i] = data->id;
+	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 */
@@ -6092,7 +4348,6 @@ struct GetFolderHierarchyCBData
 
 static gboolean
 get_folder_hierarchy_cb (EMapiConnection *conn,
-			 mapi_id_t fid,
 			 TALLOC_CTX *mem_ctx,
 			 struct SRow *srow,
 			 guint32 row_index,
@@ -6213,7 +4468,7 @@ get_child_folders (EMapiConnection *conn,
 	gfh.cb = cb;
 	gfh.cb_user_data = cb_user_data;
 
-	ms = foreach_tablerow (conn, folder_id, mem_ctx, &obj_table, get_folder_hierarchy_cb, &gfh, cancellable, perror);
+	ms = foreach_tablerow (conn, mem_ctx, &obj_table, get_folder_hierarchy_cb, &gfh, cancellable, perror);
 
  cleanup:
 	talloc_free (spropTagArray);
@@ -7231,3 +5486,149 @@ e_mapi_rename_profile (struct mapi_context *mapi_ctx,
 }
 
 /* profile related functions - end */
+
+EMapiRecipient *
+e_mapi_recipient_new (TALLOC_CTX *mem_ctx)
+{
+	EMapiRecipient *recipient;
+
+	recipient = talloc_zero (mem_ctx, EMapiRecipient);
+	g_assert (recipient != NULL);
+
+	recipient->properties.cValues = 0;
+	recipient->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+	recipient->next = NULL;
+
+	g_assert (recipient->properties.lpProps != NULL);
+
+	return recipient;
+}
+
+void
+e_mapi_recipient_free (EMapiRecipient *recipient)
+{
+	if (!recipient)
+		return;
+
+	talloc_free (recipient->properties.lpProps);
+	talloc_free (recipient);
+}
+
+EMapiAttachment *
+e_mapi_attachment_new (TALLOC_CTX *mem_ctx)
+{
+	EMapiAttachment *attachment;
+
+	attachment = talloc_zero (mem_ctx, EMapiAttachment);
+	g_assert (attachment != NULL);
+
+	attachment->properties.cValues = 0;
+	attachment->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+	attachment->embedded_object = NULL;
+	attachment->next = NULL;
+
+	g_assert (attachment->properties.lpProps != NULL);
+
+	return attachment;
+}
+
+void
+e_mapi_attachment_free (EMapiAttachment *attachment)
+{
+	if (!attachment)
+		return;
+
+	e_mapi_object_free (attachment->embedded_object);
+	talloc_free (attachment->properties.lpProps);
+	talloc_free (attachment);
+}
+
+EMapiObject *
+e_mapi_object_new (TALLOC_CTX *mem_ctx)
+{
+	EMapiObject *object;
+
+	object = talloc_zero (mem_ctx, EMapiObject);
+	g_assert (object != NULL);
+
+	object->properties.cValues = 0;
+	object->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+	object->recipients = NULL;
+	object->attachments = NULL;
+	object->parent = NULL;
+
+	g_assert (object->properties.lpProps != NULL);
+
+	return object;
+}
+
+void
+e_mapi_object_free (EMapiObject *object)
+{
+	EMapiRecipient *recipient;
+	EMapiAttachment *attachment;
+
+	if (!object)
+		return;
+
+	recipient = object->recipients;
+	while (recipient) {
+		EMapiRecipient *r = recipient;
+
+		recipient = recipient->next;
+		e_mapi_recipient_free (r);
+	}
+
+	attachment = object->attachments;
+	while (attachment) {
+		EMapiAttachment *a = attachment;
+
+		attachment = attachment->next;
+		e_mapi_attachment_free (a);
+	}
+
+	talloc_free (object->properties.lpProps);
+	talloc_free (object);
+}
+
+void
+e_mapi_object_add_recipient (EMapiObject *object,
+			     EMapiRecipient *recipient)
+{
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (recipient != NULL);
+	g_return_if_fail (recipient->next == NULL);
+
+	if (!object->recipients) {
+		object->recipients = recipient;
+	} else {
+		EMapiRecipient *recip = object->recipients;
+
+		while (recip->next) {
+			recip = recip->next;
+		}
+
+		recip->next = recipient;
+	}
+}
+
+void
+e_mapi_object_add_attachment (EMapiObject *object,
+			      EMapiAttachment *attachment)
+{
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (attachment != NULL);
+	g_return_if_fail (attachment->next == NULL);
+
+	if (!object->attachments) {
+		object->attachments = attachment;
+	} else {
+		EMapiAttachment *attach = object->attachments;
+
+		while (attach->next) {
+			attach = attach->next;
+		}
+
+		attach->next = attachment;
+	}
+}
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 5b05942..2c9b6ea 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -61,82 +61,6 @@ typedef enum {
 	MAPI_OPTIONS_DELETE_ON_SUBMIT_FAILURE = 1<<9
 } ExchangeMAPIOptions;
 
-/* Flags for push notification APIs*/
-typedef enum {
-	MAPI_EVENTS_USE_STORE = 1<<0,
-	MAPI_EVENTS_USE_PF_STORE = 1<<1,
-	MAPI_EVENTS_FOLDER = 1<<2,
-} ExchangeMAPIEventsOptions;
-
-#define MAPI_OPTIONS_FETCH_ALL MAPI_OPTIONS_FETCH_ATTACHMENTS | \
-			       MAPI_OPTIONS_FETCH_RECIPIENTS | \
-			       MAPI_OPTIONS_FETCH_BODY_STREAM | \
-			       MAPI_OPTIONS_FETCH_GENERIC_STREAMS
-
-typedef struct {
-	GByteArray *value;
-	uint32_t proptag;
-} ExchangeMAPIStream;
-
-typedef struct {
-	GByteArray *value;
-	uint32_t proptag;
-	uint32_t editor_format;
-} ExchangeMAPIBodyStream;
-
-typedef struct {
-	/* MANDATORY */
-	TALLOC_CTX *mem_ctx;
-	const gchar *email_id;
-	const gchar *display_name;
-
-	/* It is ideal to set all these properties on all recipients
-	 * as we never know if a recipient would be resolved or not. */
-	struct {
-		/* These are properties which would be set on the
-		 * recipients regardless if the recipient is resolved or not */
-		uint32_t req_cValues;
-		struct SPropValue *req_lpProps;
-
-		/* These are properties which would be set on the
-		 * recipients only if the recipient is MAPI_UNRESOLVED */
-		uint32_t ext_cValues;
-		struct SPropValue *ext_lpProps;
-	} in;
-
-	/* These are properties which would be set on the
-	 * recipients after GetRecipientTable() */
-	struct SRow out_SRow;
-} ExchangeMAPIRecipient;
-
-struct _MailItem;
-
-typedef struct {
-	uint32_t cValues;
-	struct SPropValue *lpProps;
-	GSList *streams;
-	GSList *objects;
-	struct _MailItem *mail; /* not NULL when writing mail attachment; in this case are other members ignored */
-} ExchangeMAPIAttachment;
-
-typedef struct {
-	EMapiConnection *conn;
-	struct mapi_SPropValue_array *properties;
-	mapi_id_t fid;
-	mapi_id_t mid;
-	uint32_t msg_flags; /* used only with fetch_items */
-	GSList *attachments;
-	GSList *recipients;
-	GSList *gallist;
-	GSList *streams;
-	guint total; /*Total number of results*/
-	guint index; /*Index of this Item*/
-} FetchItemsCallbackData;
-
-struct id_list {
-	mapi_id_t id;
-};
-
 typedef struct {
 	uint32_t pidlid_propid; /* PidLid or PidName legacy property named ID to resolve */
 	uint32_t propid;	/* resolved prop ID; equals to MAPI_E_RESERVED when not found or other error */
@@ -199,10 +123,6 @@ typedef enum {
 } EMapiCreateFlags;
 
 /* callbacks return whether to continue in transfer of the next object */
-typedef gboolean (*FetchCallback)		(FetchItemsCallbackData *item_data,
-						 gpointer data,
-						 GCancellable *cancellable,
-						 GError **perror);
 typedef gboolean (*FetchGALCallback)		(EMapiConnection *conn,
 						 uint32_t row_index,
 						 uint32_t n_rows,
@@ -210,14 +130,6 @@ typedef gboolean (*FetchGALCallback)		(EMapiConnection *conn,
 						 gpointer data,
 						 GCancellable *cancellable,
 						 GError **perror);
-typedef gboolean (*BuildWritePropsCB)		(EMapiConnection *conn,
-						 mapi_id_t fid,
-						 TALLOC_CTX *mem_ctx,
-						 struct SPropValue **values,
-						 uint32_t *n_values,
-						 gpointer data,
-						 GCancellable *cancellable,
-						 GError **perror);
 typedef gboolean (*BuildReadPropsCB)		(EMapiConnection *conn,
 						 mapi_id_t fid,
 						 TALLOC_CTX *mem_ctx,
@@ -226,14 +138,12 @@ typedef gboolean (*BuildReadPropsCB)		(EMapiConnection *conn,
 						 GCancellable *cancellable,
 						 GError **perror);
 typedef gboolean (*BuildRestrictionsCB)		(EMapiConnection *conn,
-						 mapi_id_t fid,
 						 TALLOC_CTX *mem_ctx,
 						 struct mapi_SRestriction **restrictions,
 						 gpointer user_data,
 						 GCancellable *cancellable,
 						 GError **perror);
 typedef gboolean (*ListObjectsCB)		(EMapiConnection *conn,
-						 mapi_id_t fid,
 						 TALLOC_CTX *mem_ctx,
 						 const ListObjectsData *object_data,
 						 guint32 obj_index,
@@ -256,7 +166,6 @@ typedef gboolean (*WriteObjectCB)		(EMapiConnection *conn,
 						 GCancellable *cancellable,
 						 GError **perror);
 typedef gboolean (*GetFolderPropertiesCB)	(EMapiConnection *conn,
-						 mapi_id_t fid,
 						 TALLOC_CTX *mem_ctx,
 						 /* const */ struct mapi_SPropValue_array *properties,
 						 gpointer user_data,
@@ -376,43 +285,6 @@ gboolean		e_mapi_connection_modify_object		(EMapiConnection *conn,
 								 GCancellable *cancellable,
 								 GError **perror);
 
-gboolean		e_mapi_connection_fetch_object_props	(EMapiConnection *conn,
-								 mapi_object_t *obj_folder,
-								 mapi_id_t fid,
-								 mapi_id_t mid,
-								 mapi_object_t *obj_message,
-								 BuildReadPropsCB build_props,
-								 gpointer brp_data,
-								 FetchCallback cb,
-								 gpointer data,
-								 guint32 options,
-								 GCancellable *cancellable,
-								 GError **perror);
-
-gboolean		e_mapi_connection_fetch_item		(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 mapi_id_t mid,
-								 BuildReadPropsCB build_props,
-								 gpointer brp_data,
-								 FetchCallback cb,
-								 gpointer data,
-								 guint32 options,
-								 GCancellable *cancellable,
-								 GError **perror);
-
-gboolean		e_mapi_connection_fetch_items		(EMapiConnection *conn,
-								 mapi_id_t fid,
-								 BuildRestrictionsCB build_rs_cb,
-								 gpointer build_rs_cb_data,
-								 struct SSortOrderSet *sort_order,
-								 BuildReadPropsCB build_props,
-								 gpointer brp_data,
-								 FetchCallback cb,
-								 gpointer data,
-								 guint32 options,
-								 GCancellable *cancellable,
-								 GError **perror);
-
 gboolean		e_mapi_connection_fetch_gal		(EMapiConnection *conn,
 								 BuildRestrictionsCB build_rs_cb,
 								 gpointer build_rs_cb_data,
@@ -464,30 +336,6 @@ mapi_id_t		e_mapi_connection_get_default_folder_id	(EMapiConnection *conn,
 								 uint32_t olFolder,
 								 GCancellable *cancellable,
 								 GError **perror);
-mapi_id_t		e_mapi_connection_create_item		(EMapiConnection *conn,
-								 uint32_t olFolder,
-								 mapi_id_t fid,
-								 BuildWritePropsCB build_props,
-								 gpointer bwp_data,
-								 GSList *recipients,
-								 GSList *attachments,
-								 GSList *generic_streams,
-								 uint32_t options,
-								 GCancellable *cancellable,
-								 GError **perror);
-
-gboolean		e_mapi_connection_modify_item		(EMapiConnection *conn,
-								 uint32_t olFolder,
-								 mapi_id_t fid,
-								 mapi_id_t mid,
-								 BuildWritePropsCB build_props,
-								 gpointer bwp_data,
-								 GSList *recipients,
-								 GSList *attachments,
-								 GSList *generic_streams,
-								 uint32_t options,
-								 GCancellable *cancellable,
-								 GError **perror);
 
 gboolean		e_mapi_connection_set_flags		(EMapiConnection *conn,
 								 uint32_t olFolder,
@@ -501,7 +349,7 @@ gboolean		e_mapi_connection_remove_items		(EMapiConnection *conn,
 								 uint32_t olFolder,
 								 mapi_id_t fid,
 								 guint32 fid_options,
-								 GSList *mids,
+								 const GSList *mids, /* data is (mapi_id_t *) */
 								 GCancellable *cancellable,
 								 GError **perror);
 gboolean		e_mapi_connection_copy_items		(EMapiConnection *conn,
diff --git a/src/libexchangemapi/e-mapi-fast-transfer.c b/src/libexchangemapi/e-mapi-fast-transfer.c
index 1170820..30ba551 100644
--- a/src/libexchangemapi/e-mapi-fast-transfer.c
+++ b/src/libexchangemapi/e-mapi-fast-transfer.c
@@ -58,152 +58,6 @@ struct _EMapiFXParserClosure {
 	EMapiObject *object;
 };
 
-EMapiRecipient *
-e_mapi_recipient_new (TALLOC_CTX *mem_ctx)
-{
-	EMapiRecipient *recipient;
-
-	recipient = talloc_zero (mem_ctx, EMapiRecipient);
-	g_assert (recipient != NULL);
-
-	recipient->properties.cValues = 0;
-	recipient->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
-	recipient->next = NULL;
-
-	g_assert (recipient->properties.lpProps != NULL);
-
-	return recipient;
-}
-
-void
-e_mapi_recipient_free (EMapiRecipient *recipient)
-{
-	if (!recipient)
-		return;
-
-	talloc_free (recipient->properties.lpProps);
-	talloc_free (recipient);
-}
-
-EMapiAttachment *
-e_mapi_attachment_new (TALLOC_CTX *mem_ctx)
-{
-	EMapiAttachment *attachment;
-
-	attachment = talloc_zero (mem_ctx, EMapiAttachment);
-	g_assert (attachment != NULL);
-
-	attachment->properties.cValues = 0;
-	attachment->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
-	attachment->embedded_object = NULL;
-	attachment->next = NULL;
-
-	g_assert (attachment->properties.lpProps != NULL);
-
-	return attachment;
-}
-
-void
-e_mapi_attachment_free (EMapiAttachment *attachment)
-{
-	if (!attachment)
-		return;
-
-	e_mapi_object_free (attachment->embedded_object);
-	talloc_free (attachment->properties.lpProps);
-	talloc_free (attachment);
-}
-
-EMapiObject *
-e_mapi_object_new (TALLOC_CTX *mem_ctx)
-{
-	EMapiObject *object;
-
-	object = talloc_zero (mem_ctx, EMapiObject);
-	g_assert (object != NULL);
-
-	object->properties.cValues = 0;
-	object->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
-	object->recipients = NULL;
-	object->attachments = NULL;
-	object->parent = NULL;
-
-	g_assert (object->properties.lpProps != NULL);
-
-	return object;
-}
-
-void
-e_mapi_object_free (EMapiObject *object)
-{
-	EMapiRecipient *recipient;
-	EMapiAttachment *attachment;
-
-	if (!object)
-		return;
-
-	recipient = object->recipients;
-	while (recipient) {
-		EMapiRecipient *r = recipient;
-
-		recipient = recipient->next;
-		e_mapi_recipient_free (r);
-	}
-
-	attachment = object->attachments;
-	while (attachment) {
-		EMapiAttachment *a = attachment;
-
-		attachment = attachment->next;
-		e_mapi_attachment_free (a);
-	}
-
-	talloc_free (object->properties.lpProps);
-	talloc_free (object);
-}
-
-void
-e_mapi_object_add_recipient (EMapiObject *object,
-			     EMapiRecipient *recipient)
-{
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (recipient != NULL);
-	g_return_if_fail (recipient->next == NULL);
-
-	if (!object->recipients) {
-		object->recipients = recipient;
-	} else {
-		EMapiRecipient *recip = object->recipients;
-
-		while (recip->next) {
-			recip = recip->next;
-		}
-
-		recip->next = recipient;
-	}
-}
-
-void
-e_mapi_object_add_attachment (EMapiObject *object,
-			      EMapiAttachment *attachment)
-{
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (attachment != NULL);
-	g_return_if_fail (attachment->next == NULL);
-
-	if (!object->attachments) {
-		object->attachments = attachment;
-	} else {
-		EMapiAttachment *attach = object->attachments;
-
-		while (attach->next) {
-			attach = attach->next;
-		}
-
-		attach->next = attachment;
-	}
-}
-
 static void
 e_mapi_object_finish_read (EMapiObject *object)
 {
diff --git a/src/libexchangemapi/e-mapi-mail-utils.c b/src/libexchangemapi/e-mapi-mail-utils.c
index a4e5333..5b69940 100644
--- a/src/libexchangemapi/e-mapi-mail-utils.c
+++ b/src/libexchangemapi/e-mapi-mail-utils.c
@@ -34,734 +34,274 @@
 extern gint camel_application_is_exiting;
 
 void
-mail_item_free (MailItem *item)
-{
-	g_free (item->header.subject);
-	g_free (item->header.from);
-
-	g_free (item->header.to);
-	g_free (item->header.cc);
-	g_free (item->header.bcc);
-
-	g_free (item->header.references);
-	g_free (item->header.message_id);
-	g_free (item->header.in_reply_to);
-	g_free (item->header.content_class);
-	g_free (item->header.transport_headers);
-
-	e_mapi_util_free_attachment_list (&item->attachments);
-	e_mapi_util_free_stream_list (&item->generic_streams);
-	e_mapi_util_free_recipient_list (&item->recipients);
-
-	g_free (item->msg_class);
-	g_free (item->pid_name_content_type);
-
-	g_free (item);
-}
-
-gboolean
-fetch_props_to_mail_item_cb (FetchItemsCallbackData *item_data,
-			     gpointer data,
-			     GCancellable *cancellable,
-			     GError **perror)
+e_mapi_mail_utils_decode_email_address (EMapiConnection *conn,
+					struct mapi_SPropValue_array *properties,
+					const uint32_t *name_proptags,
+					guint name_proptags_len,
+					const uint32_t *smtp_proptags,
+					guint smtp_proptags_len,
+					uint32_t email_type_proptag,
+					uint32_t email_proptag,
+					gchar **name,
+					gchar **email)
 {
-	long *flags = NULL;
-	struct FILETIME *delivery_date = NULL;
-	const gchar *msg_class = NULL, *content_class = NULL;
-	ExchangeMAPIStream *body = NULL;
-	uint32_t content_class_pid;
-
-	MailItem *item;
-	MailItem **i = (MailItem **)data;
-	guint32 j = 0;
-
-	g_return_val_if_fail (item_data != NULL, FALSE);
-	g_return_val_if_fail (data != NULL, FALSE);
-
-	if (camel_debug_start("mapi:folder")) {
-		e_mapi_debug_dump_properties (item_data->conn, item_data->fid, item_data->properties, 3);
-		camel_debug_end();
-	}
-
-	content_class_pid = e_mapi_connection_resolve_named_prop (item_data->conn, item_data->fid, PidNameContentClass, cancellable, perror);
-	if (content_class_pid == MAPI_E_RESERVED)
-		content_class_pid = 0;
-
-	item = g_new0 (MailItem , 1);
-	item->fid = item_data->fid;
-	item->mid = item_data->mid;
-
-	/*Hold a reference to Recipient List*/
-	item->recipients = item_data->recipients;
-
-	for (j = 0; j < item_data->properties->cValues; j++) {
+	gint ii;
+	const gchar *cname = NULL, *cemail = NULL;
+	const gchar *addr_type, *email_addr;
 
-		gconstpointer prop_data = get_mapi_SPropValue_data(&item_data->properties->lpProps[j]);
+	g_return_if_fail (conn != NULL);
+	g_return_if_fail (properties != NULL);
+	g_return_if_fail (name_proptags_len == 0 || name_proptags != NULL);
+	g_return_if_fail (smtp_proptags_len == 0 || smtp_proptags != NULL);
+	g_return_if_fail (name != NULL);
+	g_return_if_fail (email != NULL);
 
-		if (fetch_read_item_common_data (item, item_data->properties->lpProps[j].ulPropTag, prop_data))
-			continue;
+	*name = NULL;
+	*email = NULL;
 
-		switch (item_data->properties->lpProps[j].ulPropTag) {
-		case PR_MESSAGE_CLASS:
-		case PR_MESSAGE_CLASS_UNICODE:
-			msg_class = (const gchar *) prop_data;
-			break;
-		case PR_MESSAGE_DELIVERY_TIME:
-			delivery_date = (struct FILETIME *) prop_data;
-			break;
-		case PR_MESSAGE_FLAGS:
-			flags = (long *) prop_data;
-			break;
-		default:
-			if (content_class_pid != 0 && item_data->properties->lpProps[j].ulPropTag == content_class_pid)
-				content_class = (const gchar *) prop_data;
-			break;
-		}
+	for (ii = 0; ii < name_proptags_len && !cname; ii++) {
+		cname = e_mapi_util_find_array_propval (properties, name_proptags[ii]);
 	}
 
-	item->msg_class = g_strdup (msg_class);
-	item->header.content_class = g_strdup (content_class);
-
-	item->is_cal = FALSE;
-	if (msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX)) {
-		guint8 *appointment_body_str = (guint8 *) e_mapi_cal_util_camel_helper (item_data->conn, item_data->fid, item_data->mid, NULL, msg_class,
-												item_data->streams, item_data->recipients, item_data->attachments);
-
-		if (appointment_body_str && *appointment_body_str) {
-			body = g_new0(ExchangeMAPIStream, 1);
-			body->proptag = PR_BODY_UNICODE;
-			body->value = g_byte_array_new ();
-			body->value = g_byte_array_append (body->value, appointment_body_str, strlen ((const gchar *)appointment_body_str));
+	addr_type = e_mapi_util_find_array_propval (properties, email_type_proptag);
+	email_addr = e_mapi_util_find_array_propval (properties, email_proptag);
 
-			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
-			item->is_cal = TRUE;
-		}
+	if (addr_type && g_ascii_strcasecmp (addr_type, "SMTP") == 0)
+		cemail = email_addr;
 
-		g_free (appointment_body_str);
+	for (ii = 0; ii < smtp_proptags_len && !cemail; ii++) {
+		cemail = e_mapi_util_find_array_propval (properties, smtp_proptags[ii]);
 	}
 
-	if (!item->is_cal) {
-		/* always prefer unicode version, as that can be properly read */
-		if (!(body = e_mapi_util_find_stream (item_data->streams, PR_BODY_UNICODE)))
-			body = e_mapi_util_find_stream (item_data->streams, PR_BODY);
-
-		if (body)
-			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
-
-		body = e_mapi_util_find_stream (item_data->streams, PR_HTML);
-		if (body)
-			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
+	if (!cemail && addr_type && g_ascii_strcasecmp (addr_type, "EX") == 0 && email_addr) {
+		*email = e_mapi_connection_ex_to_smtp (conn, email_addr, name, NULL, NULL);
 	}
 
-	if (delivery_date) {
-		item->header.recieved_time = e_mapi_util_filetime_to_time_t (delivery_date);
+	if (!*email) {
+		*name = g_strdup (cname);
+		*email = g_strdup (cemail);
 	}
-
-	if (flags && (*flags & MSGFLAG_READ) != 0)
-		item->header.flags |= CAMEL_MESSAGE_SEEN;
-	if (flags && (*flags & MSGFLAG_HASATTACH) != 0)
-		item->header.flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
-	item->attachments = item_data->attachments;
-
-	*i = item;
-
-	if (camel_application_is_exiting)
-		return FALSE;
-
-	return TRUE;
 }
 
-gboolean
-fetch_read_item_common_data (MailItem *item, uint32_t propTag, gconstpointer prop_data)
+void
+e_mapi_mail_utils_decode_email_address1 (EMapiConnection *conn,
+					 struct mapi_SPropValue_array *properties,
+					 uint32_t name_proptag,
+					 uint32_t email_proptag,
+					 uint32_t email_type_proptag,
+					 gchar **name,
+					 gchar **email)
 {
-	gboolean found = TRUE;
-
-	#define sv(_x,_y) G_STMT_START { g_free (_x); _x = _y; } G_STMT_END
-
-	switch (propTag) {
-	case PR_INTERNET_CPID: {
-		const uint32_t *ui32 = (const uint32_t *) prop_data;
-		if (ui32)
-			item->header.cpid = *ui32;
-		} break;
-	/* FIXME : Instead of duping. Use talloc_steal to reuse the memory */
-	case PR_SUBJECT:
-		sv (item->header.subject, g_strdup (prop_data));
-		break;
-	case PR_SUBJECT_UNICODE :
-		sv (item->header.subject, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_TO :
-		sv (item->header.to, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_TO_UNICODE :
-		sv (item->header.to, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_CC:
-		sv (item->header.cc, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_CC_UNICODE:
-		sv (item->header.cc, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_BCC:
-		sv (item->header.bcc, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_BCC_UNICODE:
-		sv (item->header.bcc, g_strdup (prop_data));
-		break;
-	case PR_SENT_REPRESENTING_NAME:
-		sv (item->header.from, g_strdup (prop_data));
-		break;
-	case PR_SENT_REPRESENTING_NAME_UNICODE:
-		sv (item->header.from, g_strdup (prop_data));
-		break;
-	case PR_SENT_REPRESENTING_EMAIL_ADDRESS:
-		sv (item->header.from_email, g_strdup (prop_data));
-		break;
-	case PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE:
-		sv (item->header.from_email, g_strdup (prop_data));
-		break;
-	case PR_SENT_REPRESENTING_ADDRTYPE:
-		sv (item->header.from_type, g_strdup (prop_data));
-		break;
-	case PR_SENT_REPRESENTING_ADDRTYPE_UNICODE:
-		sv (item->header.from_type, g_strdup (prop_data));
-		break;
-	case PR_MESSAGE_SIZE:
-		item->header.size = *(glong *)prop_data;
-		break;
-	case PR_INTERNET_MESSAGE_ID:
-		item->header.message_id = g_strdup (prop_data);
-		break;
-	case PR_INTERNET_REFERENCES:
-		item->header.references = g_strdup (prop_data);
-		break;
-	case PR_IN_REPLY_TO_ID:
-		item->header.in_reply_to = g_strdup (prop_data);
-		break;
-	case PR_TRANSPORT_MESSAGE_HEADERS:
-		sv (item->header.transport_headers, g_strdup (prop_data));
-		break;
-	case PR_TRANSPORT_MESSAGE_HEADERS_UNICODE:
-		sv (item->header.transport_headers, g_strdup (prop_data));
-		break;
-	default:
-		found = FALSE;
-		break;
-	}
+	uint32_t names[1];
 
-	#undef sv
+	names[0] = name_proptag;
 
-	return found;
+	e_mapi_mail_utils_decode_email_address (conn, properties, names, 1, NULL, 0, email_type_proptag, email_proptag, name, email);
 }
 
-gboolean
-mapi_mail_get_item_prop_list (EMapiConnection *conn,
-			      mapi_id_t fid,
-			      TALLOC_CTX *mem_ctx,
-			      struct SPropTagArray *props,
-			      gpointer data,
-			      GCancellable *cancellable,
-			      GError **perror)
+void
+e_mapi_mail_utils_decode_recipients (EMapiConnection *conn,
+				     EMapiRecipient *recipients,
+				     CamelAddress *to_addr,
+				     CamelAddress *cc_addr,
+				     CamelAddress *bcc_addr)
 {
-	static const uint32_t item_props[] = {
-		PR_FID,
-		PR_MID,
-		PR_INTERNET_CPID,
-
-		PR_TRANSPORT_MESSAGE_HEADERS_UNICODE,
-		PR_MESSAGE_CLASS,
-		PR_MESSAGE_SIZE,
-		PR_MESSAGE_FLAGS,
-		PR_MESSAGE_DELIVERY_TIME,
-		PR_MSG_EDITOR_FORMAT,
-
-		PR_SUBJECT_UNICODE,
-		PR_CONVERSATION_TOPIC_UNICODE,
-
-		/*Properties used for message threading.*/
-		PR_INTERNET_MESSAGE_ID,
-		PR_INTERNET_REFERENCES,
-		PR_IN_REPLY_TO_ID,
-
-		PR_BODY,
-		PR_BODY_UNICODE,
-		PR_HTML,
-
-		PR_DISPLAY_TO_UNICODE,
-		PR_DISPLAY_CC_UNICODE,
-		PR_DISPLAY_BCC_UNICODE,
-
-		PR_CREATION_TIME,
-		PR_LAST_MODIFICATION_TIME,
-		PR_PRIORITY,
-		PR_SENSITIVITY,
-		PR_START_DATE,
-		PR_END_DATE,
-		PR_RESPONSE_REQUESTED,
-		PR_OWNER_APPT_ID,
-		PR_PROCESSED,
-
-		PR_SENT_REPRESENTING_NAME_UNICODE,
-		PR_SENT_REPRESENTING_ADDRTYPE_UNICODE,
-		PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE,
-
-		PR_SENDER_NAME_UNICODE,
-		PR_SENDER_ADDRTYPE_UNICODE,
-		PR_SENDER_EMAIL_ADDRESS_UNICODE,
-
-		PR_RCVD_REPRESENTING_NAME_UNICODE,
-		PR_RCVD_REPRESENTING_ADDRTYPE_UNICODE,
-		PR_RCVD_REPRESENTING_EMAIL_ADDRESS_UNICODE
+	const uint32_t name_proptags[] = {
+		PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
+		PidTagNickname,
+		PidTagDisplayName,
+		PidTagRecipientDisplayName,
+		PidTag7BitDisplayName
 	};
 
-	/* do not make this array static, the function modifies it on run */
-	ResolveNamedIDsData nids[] = {
-		{ PidNameContentClass, 0 }
+	const uint32_t email_proptags[] = {
+		PidTagPrimarySmtpAddress,
+		PidTagSmtpAddress
 	};
 
-	g_return_val_if_fail (props != NULL, FALSE);
-
-	if (!e_mapi_utils_add_props_to_props_array (mem_ctx, props, item_props, G_N_ELEMENTS (item_props)))
-		return FALSE;
-
-	return e_mapi_utils_add_named_ids_to_props_array (conn, fid, mem_ctx, props, nids, G_N_ELEMENTS (nids), cancellable, perror);
-}
-
-static gboolean
-name_is_email_user (const gchar *name, const gchar *email_id)
-{
-	gint name_len, email_len;
-
-	if (!name || !email_id)
-		return FALSE;
-
-	if (!*name || !*email_id || g_ascii_strcasecmp (email_id, name) == 0)
-		return TRUE;
-
-	name_len = strlen (name);
-	email_len = strlen (email_id);
-
-	return name_len < email_len && g_ascii_strncasecmp (email_id, name, name_len) == 0 && email_id[name_len] == '@';
-}
-
-static void
-mapi_mime_set_recipient_list (EMapiConnection *conn, CamelMimeMessage *msg, MailItem *item)
-{
-	GSList *l = NULL;
-	CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
-
-	if (!item->recipients || item->header.transport_headers)
-		return;
-
-	to_addr = camel_internet_address_new ();
-	cc_addr = camel_internet_address_new ();
-	bcc_addr = camel_internet_address_new ();
-
-	for (l = item->recipients; l; l=l->next) {
-		gchar *display_name = NULL;
-		const gchar *name = NULL;
-		uint32_t rcpt_type = MAPI_TO;
-		uint32_t *type = NULL;
-		struct SRow *aRow;
-		ExchangeMAPIRecipient *recip = (ExchangeMAPIRecipient *)(l->data);
-
-		/* Build a SRow structure */
-		aRow = &recip->out_SRow;
-
-		/*Name is probably available in one of these props.*/
-		name = recip->display_name;
-		name = name ? name : e_mapi_util_find_row_propval (aRow, PR_DISPLAY_NAME_UNICODE);
-		name = name ? name : e_mapi_util_find_row_propval (aRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
-		if (!name) {
-			name = e_mapi_util_find_row_propval (aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
-			if (name && !strchr (name, '@')) {
-				gchar *to_free;
-
-				to_free = e_mapi_connection_ex_to_smtp (conn, recip->email_id, &display_name, NULL, NULL);
-				g_free (to_free);
-			}
-		}
+	EMapiRecipient *recipient;
 
-		type = (uint32_t *) e_mapi_util_find_row_propval (aRow, PR_RECIPIENT_TYPE);
+	g_return_if_fail (conn != NULL);
+	g_return_if_fail (to_addr != NULL);
+	g_return_if_fail (cc_addr != NULL);
+	g_return_if_fail (bcc_addr != NULL);
 
-		if (!display_name && name && (!recip->email_id || !name_is_email_user (name, recip->email_id)))
-			display_name = g_strdup (name);
-		rcpt_type = (type ? *type : MAPI_TO);
+	for (recipient = recipients; recipient; recipient = recipient->next) {
+		const uint32_t *recip_type = e_mapi_util_find_array_propval (&recipient->properties, PidTagRecipientType);
+		gchar *name = NULL, *email = NULL;
+		CamelAddress *addr = NULL;
 
-		if (!display_name && (!recip->email_id || !*recip->email_id))
-			break;
+		if (!recip_type)
+			continue;
 
-		switch (rcpt_type) {
+		switch (*recip_type) {
 		case MAPI_TO:
-			camel_internet_address_add (to_addr, display_name, recip->email_id ? recip->email_id : "");
+			addr = to_addr;
 			break;
 		case MAPI_CC:
-			camel_internet_address_add (cc_addr, display_name, recip->email_id ? recip->email_id : "");
+			addr = cc_addr;
 			break;
 		case MAPI_BCC:
-			camel_internet_address_add (bcc_addr, display_name, recip->email_id ? recip->email_id : "");
+			addr = bcc_addr;
+			break;
+		default:
 			break;
 		}
 
-		g_free (display_name);
-	}
+		if (!addr)
+			continue;
 
-	if (l != NULL) {
-		/* some recipient didn't have set email or
-		   display name, fallback to PR_DISPLAY_TO/_CC/_BCC */
-		camel_address_remove (CAMEL_ADDRESS (to_addr), -1);
-		camel_address_remove (CAMEL_ADDRESS (cc_addr), -1);
-		camel_address_remove (CAMEL_ADDRESS (bcc_addr), -1);
-
-		if (item->header.to && *item->header.to)
-			camel_address_decode (CAMEL_ADDRESS (to_addr), item->header.to);
-		if (item->header.cc && *item->header.cc)
-			camel_address_decode (CAMEL_ADDRESS (cc_addr), item->header.cc);
-		if (item->header.bcc && *item->header.bcc)
-			camel_address_decode (CAMEL_ADDRESS (bcc_addr), item->header.bcc);
-	}
+		e_mapi_mail_utils_decode_email_address (conn, &recipient->properties,
+					name_proptags, G_N_ELEMENTS (name_proptags),
+					email_proptags, G_N_ELEMENTS (email_proptags),
+					PidTagAddressType, PidTagEmailAddress,
+					&name, &email);
 
-	/*Add to message*/
-	camel_mime_message_set_recipients (msg, "To", to_addr);
-	camel_mime_message_set_recipients (msg, "Cc", cc_addr);
-	camel_mime_message_set_recipients (msg, "Bcc", bcc_addr);
+		camel_internet_address_add (CAMEL_INTERNET_ADDRESS (addr), name, email ? email : "");
 
-	g_object_unref (to_addr);
-	g_object_unref (cc_addr);
-	g_object_unref (bcc_addr);
+		g_free (name);
+		g_free (email);
+	}
 }
 
 static void
-mapi_mime_set_msg_headers (EMapiConnection *conn, CamelMimeMessage *msg, MailItem *item)
+build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t proptag)
 {
-	gchar *temp_str = NULL;
-	time_t recieved_time;
-	CamelInternetAddress *addr = NULL;
-	gint offset = 0;
-	time_t actual_time;
-
-	/* Setting headers from PR_TRANSPORT_MESSAGE_HEADERS */
-	if (item->header.transport_headers) {
-		CamelMimePart *part = camel_mime_part_new ();
-		CamelStream *stream;
-		CamelMimeParser *parser;
-
-		stream = camel_stream_mem_new_with_buffer (item->header.transport_headers, strlen (item->header.transport_headers));
-		parser = camel_mime_parser_new ();
-		camel_mime_parser_init_with_stream (parser, stream, NULL);
-		camel_mime_parser_scan_from (parser, FALSE);
-		g_object_unref (stream);
-
-		if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
-			struct _camel_header_raw *h;
-
-			for (h = part->headers; h; h = h->next) {
-				const gchar *value = h->value;
-
-				/* skip all headers describing content of a message,
-				   because it's overwritten on message decomposition */
-				if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
-					continue;
-
-				while (value && camel_mime_is_lwsp (*value))
-					value++;
-
-				camel_medium_add_header (CAMEL_MEDIUM (msg), h->name, value);
-			}
-		}
-
-		g_object_unref (parser);
-		g_object_unref (part);
-	} else {
-		recieved_time = item->header.recieved_time;
-		actual_time = camel_header_decode_date (ctime(&recieved_time), &offset);
-		camel_mime_message_set_date (msg, actual_time, offset);
-	}
-
-	if (item->header.content_class)
-		camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", item->header.content_class);
-
-	/* Overwrite headers if we have specific properties available*/
-	temp_str = item->header.subject;
-	if (temp_str)
-		camel_mime_message_set_subject (msg, temp_str);
-
-	if (item->header.from) {
-		if ((item->header.from_type != NULL) && !g_utf8_collate (item->header.from_type, "EX")) {
-			gchar *from_email;
-
-			from_email = e_mapi_connection_ex_to_smtp (conn, item->header.from_email, NULL, NULL, NULL);
-			g_free (item->header.from_email);
-			item->header.from_email = from_email;
-		}
-
-		item->header.from_email = item->header.from_email ?
-			item->header.from_email : item->header.from;
-
-		/* add reply to */
-		addr = camel_internet_address_new();
-		camel_internet_address_add(addr, item->header.from, item->header.from_email);
-		camel_mime_message_set_reply_to(msg, addr);
-
-		/* add from */
-		addr = camel_internet_address_new();
-		camel_internet_address_add(addr, item->header.from, item->header.from_email);
-		camel_mime_message_set_from(msg, addr);
-	}
-
-	/* Threading */
-	if (item->header.message_id)
-		camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", item->header.message_id);
-
-	if (item->header.references)
-		camel_medium_add_header (CAMEL_MEDIUM (msg), "References", item->header.references);
-
-	if (item->header.in_reply_to)
-		camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", item->header.in_reply_to);
+	gconstpointer value;
 
-}
+	g_return_if_fail (part != NULL);
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (proptag == PidTagHtml || proptag == PidTagBody);
 
-static CamelMimePart *
-mapi_mime_msg_body (MailItem *item, const ExchangeMAPIStream *body)
-{
-	CamelMimePart *part = camel_mime_part_new ();
 	camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
 
-	if (body && body->value && body->value->len > 0) {
+	value = e_mapi_util_find_array_propval (&object->properties, proptag);
+	if (value) {
 		const gchar *type = NULL;
-		gchar *buff = NULL;
-		gboolean strip_last_null;
+		gchar *buff = NULL, *in_utf8;
+		const uint32_t *pcpid = e_mapi_util_find_array_propval (&object->properties, PidTagInternetCodepage);
 
-		if (item->is_cal)
-			type = "text/calendar";
-		else
-			type = (body->proptag == PR_BODY || body->proptag == PR_BODY_UNICODE) ?
-				"text/plain" : "text/html";
+		if (proptag == PidTagBody) {
+			type = "text/plain";
+		} else {
+			type = "text/html";
+		}
 
-		if (item->header.cpid && (body->proptag & 0xFFFF) != PT_UNICODE) {
-			if (item->header.cpid == 20127)
+		proptag = e_mapi_util_find_array_proptag (&object->properties, proptag);
+		if (pcpid && *pcpid && (proptag & 0xFFFF) != PT_UNICODE) {
+			uint32_t cpid = *pcpid;
+	
+			if (cpid == 20127)
 				buff = g_strdup_printf ("%s; charset=\"us-ascii\"", type);
-			else if (item->header.cpid >= 28591 && item->header.cpid <= 28599)
-				buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, item->header.cpid % 10);
-			else if (item->header.cpid == 28603)
+			else if (cpid >= 28591 && cpid <= 28599)
+				buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, cpid % 10);
+			else if (cpid == 28603)
 				buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
-			else if (item->header.cpid == 28605)
+			else if (cpid == 28605)
 				buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
-			else if (item->header.cpid == 65000)
+			else if (cpid == 65000)
 				buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
-			else if (item->header.cpid == 65001)
+			else if (cpid == 65001)
 				buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
 			else
-				buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, item->header.cpid);
+				buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, cpid);
 			type = buff;
 		}
 
-		strip_last_null = body->value->len > 0 && body->value->data[body->value->len - 1] == '\0';
-		camel_mime_part_set_content (part, (const gchar *) body->value->data, body->value->len + (strip_last_null ? -1 : 0), type);
+		in_utf8 = NULL;
+
+		if (proptag == PidTagHtml) {
+			const struct SBinary_short *html_bin = value;
+
+			if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, html_bin->lpb, html_bin->cb, &in_utf8))
+				camel_mime_part_set_content (part, in_utf8, strlen (in_utf8), type);
+			else
+				camel_mime_part_set_content (part, (const gchar *) html_bin->lpb, html_bin->cb, type);
+			
+		} else {
+			const gchar *str = value;
+
+			if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, (const guint8 *) str, strlen (str), &in_utf8))
+				str = in_utf8;
+
+			camel_mime_part_set_content (part, str, strlen (str), type);
+		}
 
+		g_free (in_utf8);
 		g_free (buff);
 	} else
 		camel_mime_part_set_content (part, " ", strlen (" "), "text/plain");
-
-	return part;
 }
 
-#if 0
-
-/* GCompareFunc. Used for ordering body types in a GSList.*/
-static gint
-sort_bodies_cb (gconstpointer a, gconstpointer b)
+static gboolean
+is_apple_attach (EMapiAttachment *attach, guint32 *data_len, guint32 *resource_len)
 {
-	static const gint desired_order[] = { PR_BODY, PR_BODY_UNICODE, PR_HTML };
-	const ExchangeMAPIStream *stream_a = a, *stream_b = b;
-	gint aidx, bidx;
-
-	if (a == b)
-		return 0;
-	if (!a)
-		return -1;
-	if (!b)
-		return 1;
-
-	for (aidx = 0; aidx < G_N_ELEMENTS (desired_order); aidx++) {
-		if (desired_order[aidx] == stream_a->proptag)
-			break;
-	}
+	gboolean is_apple = FALSE;
+	const struct SBinary_short *encoding_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachEncoding);
+	guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
 
-	for (bidx = 0; bidx < G_N_ELEMENTS (desired_order); bidx++) {
-		if (desired_order[bidx] == stream_b->proptag)
-			break;
+	if (encoding_bin && encoding_bin->lpb && encoding_bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
+		gint idx;
+
+		is_apple = TRUE;
+		for (idx = 0; idx < encoding_bin->cb && is_apple; idx++) {
+			is_apple = apple_enc_magic[idx] == encoding_bin->lpb[idx];
+		}
 	}
 
-	return aidx - bidx;
-}
+	if (is_apple) {
+		/* check boundaries too */
+		const struct SBinary_short *data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
 
-#endif
-
-/* Adds parts to multipart. Convenience function. */
-static void
-mapi_mime_multipart_add_attachments (CamelMultipart *multipart, GSList *attachs)
-{
-	CamelMimePart *part;
-	while (attachs) {
-		part = attachs->data;
-		camel_multipart_add_part (multipart, part);
-		g_object_unref (part);
-		attachs = attachs->next;
-	}
-}
-
-/* Process body stream and related objects into a MIME mulitpart */
-static CamelMultipart *
-mapi_mime_build_multipart_related (MailItem *item, const ExchangeMAPIStream *stream,
-				   GSList *inline_attachs)
-{
-	CamelMimePart *part;
-	CamelMultipart *m_related = camel_multipart_new ();
-	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
-	camel_multipart_set_boundary (m_related, NULL);
-
-	part = mapi_mime_msg_body (item, stream);
-	camel_multipart_add_part (m_related, part);
-	g_object_unref (part);
-
-	mapi_mime_multipart_add_attachments (m_related, inline_attachs);
-
-	return m_related;
-}
-
-/* Process multiple body types and pack them in a MIME mulitpart */
-static CamelMultipart *
-mapi_mime_build_multipart_alternative (MailItem *item, GSList *body_parts, GSList *inline_attachs)
-{
-	CamelMimePart *part;
-	CamelMultipart *m_alternative = camel_multipart_new ();
-	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative),
-					  "multipart/alternative");
-	camel_multipart_set_boundary (m_alternative, NULL);
-
-	while (body_parts) {
-		const ExchangeMAPIStream *stream = (ExchangeMAPIStream *) body_parts->data;
-		part = camel_mime_part_new ();
-		if ((stream->proptag == PR_HTML)
-		    && inline_attachs) {
-			CamelMultipart *m_related;
-			m_related = mapi_mime_build_multipart_related (item, stream,
-								       inline_attachs);
-			camel_medium_set_content (CAMEL_MEDIUM (part),
-						  CAMEL_DATA_WRAPPER (m_related));
-			g_object_unref (m_related);
-		} else
-			part = mapi_mime_msg_body (item, stream);
-
-		camel_multipart_add_part (m_alternative, part);
-		g_object_unref (part);
-
-		body_parts = body_parts->next;
-	}
-
-	return m_alternative;
-}
-
-static CamelMultipart *
-mapi_mime_build_multipart_mixed (CamelMultipart *content, GSList *attachs)
-{
-	CamelMimePart *part = camel_mime_part_new ();
-	CamelMultipart *m_mixed = camel_multipart_new ();
-	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed),
-					  "multipart/mixed");
-	camel_multipart_set_boundary (m_mixed, NULL);
-
-	camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
-	camel_multipart_add_part (m_mixed, part);
-
-	if (attachs)
-		mapi_mime_multipart_add_attachments (m_mixed, attachs);
-
-	return m_mixed;
-}
-
-static gboolean
-is_apple_attachment (ExchangeMAPIAttachment *attach, guint32 *data_len, guint32 *resource_len)
-{
-	gboolean is_apple = FALSE;
-	ExchangeMAPIStream *enc_stream = e_mapi_util_find_stream (attach->streams, PR_ATTACH_ENCODING);
-	guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
-
-	if (enc_stream && enc_stream->value && enc_stream->value->len == G_N_ELEMENTS (apple_enc_magic)) {
-		gint idx;
-
-		is_apple = TRUE;
-		for (idx = 0; idx < enc_stream->value->len && is_apple; idx++) {
-			is_apple = apple_enc_magic[idx] == enc_stream->value->data[idx];
-		}
-	} else {
-		const struct Binary_r *bin = e_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_ENCODING);
-		if (bin && bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
-			gint idx;
-
-			is_apple = TRUE;
-			for (idx = 0; idx < bin->cb && is_apple; idx++) {
-				is_apple = apple_enc_magic[idx] == bin->lpb[idx];
-			}
-		}
-	}
-
-	if (is_apple) {
-		/* check boundaries too */
-		ExchangeMAPIStream *data_stream = e_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
-
-		is_apple = data_stream && data_stream->value && data_stream->value->len > 128;
+		is_apple = data_bin && data_bin->lpb && data_bin->cb > 128;
 
 		if (is_apple) {
-			const guint8 *bin = data_stream->value->data;
+			const guint8 *bin = data_bin->lpb;
 
 			/* in big-endian format */
 			*data_len = (bin[83] << 24) | (bin[84] << 16) | (bin[85] << 8) | (bin[86]);
 			*resource_len = (bin[87] << 24) | (bin[88] << 16) | (bin[89] << 8) | (bin[90]);
 
 			/* +/- mod 128 (but the first 128 is a header length) */
-			is_apple = 128 + *data_len + *resource_len <= data_stream->value->len && bin[1] < 64;
+			is_apple = 128 + *data_len + *resource_len <= data_bin->cb && bin[1] < 64;
 		}
 	}
 
 	return is_apple;
 }
 
-/*Takes raw attachment streams and converts to MIME Parts. Parts are added to
-  either inline / non-inline lists.*/
 static void
-mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gchar *msg_class, GSList *attachments, GSList **inline_attachs, GSList **noninline)
+classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const gchar *msg_class, GSList **inline_attachments, GSList **noninline_attachments)
 {
-	/* SMIME encrypted are without ending dot */
+	EMapiAttachment *attach;
 	gboolean is_smime = msg_class && strstr (msg_class, ".SMIME.") > msg_class;
 
-	for (;attachments != NULL; attachments = attachments->next) {
-		ExchangeMAPIAttachment *attach = (ExchangeMAPIAttachment *)attachments->data;
-		ExchangeMAPIStream *stream = NULL;
+	g_return_if_fail (inline_attachments != NULL);
+	g_return_if_fail (noninline_attachments != NULL);
+
+	for (attach = attachments; attach != NULL; attach = attach->next) {
 		const gchar *filename, *mime_type, *content_id = NULL;
 		CamelContentType *content_type;
 		CamelMimePart *part;
 		const uint32_t *ui32;
+		const struct SBinary_short *data_bin;
 		gboolean is_apple;
 		guint32 apple_data_len = 0, apple_resource_len = 0;
 
-		stream = e_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
-
-		if (!stream || stream->value->len <= 0) {
+		data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
+		if (!data_bin && !attach->embedded_object) {
+			g_debug ("%s: Skipping attachment without data and without embedded object", G_STRFUNC);
 			continue;
 		}
 
-		is_apple = is_apple_attachment (attach, &apple_data_len, &apple_resource_len);
+		is_apple = is_apple_attach (attach, &apple_data_len, &apple_resource_len);
 
-		/*Content-Type*/
-		ui32 = (const uint32_t *) e_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_METHOD);
+		/* Content-Type */
+		ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMethod);
 		if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG) {
 			mime_type = "message/rfc822";
 		} else {
-			mime_type = (const gchar *) e_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_MIME_TAG);
+			mime_type = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMimeTag);
 			if (!mime_type)
 				mime_type = "application/octet-stream";
 		}
@@ -774,20 +314,16 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 
 		part = camel_mime_part_new ();
 
-		filename = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach->lpProps,
-											 PR_ATTACH_LONG_FILENAME_UNICODE);
-
-		if (!(filename && *filename))
-			filename = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach->lpProps,
-												 PR_ATTACH_FILENAME_UNICODE);
+		filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachLongFilename);
+		if (!filename || !*filename)
+			filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachFilename);
 		camel_mime_part_set_filename (part, filename);
 		camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
 
 		if (is_apple) {
-			ExchangeMAPIStream *strm;
 			CamelMultipart *mp;
-			uint32_t proptag;
 			gchar *apple_filename;
+			const struct SBinary_short *mac_info_bin;
 
 			mp = camel_multipart_new ();
 			camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/appledouble");
@@ -795,15 +331,9 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 
 			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
 
-			strm = NULL;
-			proptag = e_mapi_connection_resolve_named_prop (conn, fid, PidNameAttachmentMacInfo, NULL, NULL);
-			if (proptag != MAPI_E_RESERVED)
-				strm = e_mapi_util_find_stream (attach->streams, proptag);
-			if (!strm)
-				strm = e_mapi_util_find_stream (attach->streams, PidNameAttachmentMacInfo);
-
-			if (strm && strm->value && strm->value->len > 0) {
-				camel_mime_part_set_content (part, (const gchar *) strm->value->data, strm->value->len, mime_type);
+			mac_info_bin = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacInfo);
+			if (mac_info_bin && mac_info_bin->lpb && mac_info_bin->cb > 0) {
+				camel_mime_part_set_content (part, (const gchar *) mac_info_bin->lpb, mac_info_bin->cb, mime_type);
 			} else {
 				/* RFC 1740 */
 				guint8 header[] = {
@@ -824,7 +354,7 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 				header[37] = (apple_resource_len      ) & 0xFF;
 
 				g_byte_array_append (arr, header, G_N_ELEMENTS (header));
-				g_byte_array_append (arr, stream->value->data + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
+				g_byte_array_append (arr, data_bin->lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
 
 				camel_mime_part_set_content (part, (const gchar *) arr->data, arr->len, mime_type);
 
@@ -836,15 +366,15 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 
 			part = camel_mime_part_new ();
 
-			apple_filename = g_strndup ((gchar *)stream->value->data + 2, stream->value->data[1]);
+			apple_filename = g_strndup ((const gchar *) data_bin->lpb + 2, data_bin->lpb[1]);
 			camel_mime_part_set_filename (part, (apple_filename && *apple_filename) ? apple_filename : filename);
 			g_free (apple_filename);
 
-			mime_type = e_mapi_util_find_SPropVal_array_namedid (attach->lpProps, conn, fid, PidNameAttachmentMacContentType);
+			mime_type = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacContentType);
 			if (!mime_type)
 				mime_type = "application/octet-stream";
 
-			camel_mime_part_set_content (part, (const gchar *) stream->value->data + 128, apple_data_len, mime_type);
+			camel_mime_part_set_content (part, (const gchar *) data_bin->lpb + 128, apple_data_len, mime_type);
 			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
 			camel_multipart_add_part (mp, part);
 			g_object_unref (part);
@@ -857,7 +387,7 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 			CamelStream *mem;
 
 			mem = camel_stream_mem_new ();
-			camel_stream_write (mem, (const gchar *) stream->value->data, stream->value->len, NULL, NULL);
+			camel_stream_write (mem, (const gchar *) data_bin->lpb, data_bin->cb, NULL, NULL);
 			g_seekable_seek (G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
 
 			parser = camel_mime_parser_new ();
@@ -881,7 +411,33 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 		} 
 
 		if (!is_smime && !is_apple) {
-			camel_mime_part_set_content (part, (const gchar *) stream->value->data, stream->value->len, mime_type);
+			if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG && attach->embedded_object) {
+				CamelMimeMessage *embedded_msg;
+
+				embedded_msg = e_mapi_mail_utils_object_to_message (conn, attach->embedded_object);
+				if (embedded_msg) {
+					CamelStream *mem;
+					GByteArray *data;
+
+					data = g_byte_array_new ();
+
+					mem = camel_stream_mem_new ();
+					camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), data);
+					camel_data_wrapper_write_to_stream_sync (
+						CAMEL_DATA_WRAPPER (embedded_msg), mem, NULL, NULL);
+
+					g_object_unref (mem);
+					g_object_unref (embedded_msg);
+
+					camel_mime_part_set_content (part, (const gchar *) data->data, data->len, mime_type);
+
+					g_byte_array_free (data, TRUE);
+				} else {
+					camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
+				}
+			} else {
+				camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
+			}
 
 			content_type = camel_mime_part_get_content_type (part);
 			if (content_type && camel_content_type_is (content_type, "text", "*"))
@@ -890,1946 +446,821 @@ mapi_mime_classify_attachments (EMapiConnection *conn, mapi_id_t fid, const gcha
 				camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
 		}
 
-		/*Content-ID*/
-		content_id = (const gchar *) e_mapi_util_find_SPropVal_array_propval(attach->lpProps,
-											   PR_ATTACH_CONTENT_ID);
+		/* Content-ID */
+		content_id = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachContentId);
+
 		/* TODO : Add disposition */
 		if (content_id && !is_apple && !is_smime) {
 			camel_mime_part_set_content_id (part, content_id);
-			*inline_attachs = g_slist_append (*inline_attachs, part);
+			*inline_attachments = g_slist_append (*inline_attachments, part);
 		} else
-			*noninline = g_slist_append (*noninline, part);
+			*noninline_attachments = g_slist_append (*noninline_attachments, part);
 	}
 }
 
-CamelMimeMessage *
-mapi_mail_item_to_mime_message (EMapiConnection *conn, MailItem *item)
+static void
+add_multipart_attachments (CamelMultipart *multipart, GSList *attachments)
 {
-	CamelMimeMessage *msg = NULL;
-	CamelMultipart *multipart_body = NULL;
+	CamelMimePart *part;
+	while (attachments) {
+		part = attachments->data;
+		camel_multipart_add_part (multipart, part);
+		attachments = attachments->next;
+	}
+}
 
-	GSList *attach_list = NULL;
-	GSList *inline_attachs =  NULL; /*Used for mulitpart/related*/
-	GSList *noninline_attachs = NULL;
+static CamelMultipart *
+build_multipart_related (EMapiObject *object, GSList *inline_attachments)
+{
+	CamelMimePart *part;
+	CamelMultipart *m_related = camel_multipart_new ();
+	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
+	camel_multipart_set_boundary (m_related, NULL);
 
-	gboolean build_alternative = FALSE;
-	gboolean build_related = FALSE;
-	gboolean skip_set_content = FALSE;
+	if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
+		part = camel_mime_part_new ();
+		build_body_part_content (part, object, PidTagHtml);
+		camel_multipart_add_part (m_related, part);
+		g_object_unref (part);
+	} else if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
+		part = camel_mime_part_new ();
+		build_body_part_content (part, object, PidTagBody);
+		camel_multipart_add_part (m_related, part);
+		g_object_unref (part);
+	}
 
-	g_return_val_if_fail (conn != NULL, NULL);
-	g_return_val_if_fail (item != NULL, NULL);
+	add_multipart_attachments (m_related, inline_attachments);
 
-	attach_list = item->attachments;
-	msg = camel_mime_message_new ();
+	return m_related;
+}
 
-	mapi_mime_set_recipient_list (conn, msg, item);
-	mapi_mime_set_msg_headers (conn, msg, item);
-	mapi_mime_classify_attachments (conn, item->fid, item->msg_class, attach_list, &inline_attachs, &noninline_attachs);
+static CamelMultipart *
+build_multipart_alternative (EMapiObject *object, GSList *inline_attachments)
+{
+	CamelMimePart *part;
+	CamelMultipart *m_alternative;
 
-	build_alternative = g_slist_length (item->msg.body_parts) > 1;
-	build_related = !build_alternative && inline_attachs;
+	m_alternative = camel_multipart_new ();
+	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative), "multipart/alternative");
+	camel_multipart_set_boundary (m_alternative, NULL);
 
-	if (build_alternative) {
-		multipart_body = mapi_mime_build_multipart_alternative (item, item->msg.body_parts,
-									inline_attachs);
-	} else if (build_related) {
-		multipart_body = mapi_mime_build_multipart_related (item,
-								    item->msg.body_parts ? item->msg.body_parts->data : NULL,
-								    inline_attachs);
-	} else { /* Simple multipart/mixed */
-		CamelMimePart *part;
-		multipart_body = camel_multipart_new ();
-		camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body),
-						  "multipart/mixed");
-		camel_multipart_set_boundary (multipart_body, NULL);
-		part = mapi_mime_msg_body (item, item->msg.body_parts ? item->msg.body_parts->data : NULL);
-		camel_multipart_add_part (multipart_body, part);
+	if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
+		part = camel_mime_part_new ();
+		build_body_part_content (part, object, PidTagBody);
+		camel_multipart_add_part (m_alternative, part);
 		g_object_unref (part);
 	}
 
-	if (noninline_attachs) { /* multipart/mixed */
-		if (build_alternative || build_related) {
-			multipart_body = mapi_mime_build_multipart_mixed (multipart_body, noninline_attachs);
-		} else if (g_slist_length (noninline_attachs) == 1 && item->msg_class && strstr (item->msg_class, ".SMIME") > item->msg_class) {
-			CamelMimePart *part = noninline_attachs->data;
-
-			skip_set_content = TRUE;
-
-			camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
+	if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
+		part = camel_mime_part_new ();
+		if (inline_attachments) {
+			CamelMultipart *m_related;
 
-			if (!strstr (item->msg_class, ".SMIME.")) {
-				/* encrypted */
-				camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
-				camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
-			} else {
-				/* signed */
-				camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
-			}
+			m_related = build_multipart_related (object, inline_attachments);
+			camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (m_related));
+			g_object_unref (m_related);
 		} else {
-			mapi_mime_multipart_add_attachments (multipart_body, noninline_attachs);
+			build_body_part_content (part, object, PidTagHtml);
 		}
+		camel_multipart_add_part (m_alternative, part);
+		g_object_unref (part);
 	}
 
-	if (!skip_set_content)
-		camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart_body));
-
-	g_object_unref (multipart_body);
-	g_slist_free (inline_attachs);
-	g_slist_free (noninline_attachs);
-
-	return msg;
+	return m_alternative;
 }
 
-void
-e_mapi_mail_utils_decode_email_address (EMapiConnection *conn,
-					struct mapi_SPropValue_array *properties,
-					const uint32_t *name_proptags,
-					guint name_proptags_len,
-					const uint32_t *smtp_proptags,
-					guint smtp_proptags_len,
-					uint32_t email_type_proptag,
-					uint32_t email_proptag,
-					gchar **name,
-					gchar **email)
+static CamelMultipart *
+build_multipart_mixed (CamelMultipart *content, GSList *attachments)
 {
-	gint ii;
-	const gchar *cname = NULL, *cemail = NULL;
-	const gchar *addr_type, *email_addr;
-
-	g_return_if_fail (conn != NULL);
-	g_return_if_fail (properties != NULL);
-	g_return_if_fail (name_proptags_len == 0 || name_proptags != NULL);
-	g_return_if_fail (smtp_proptags_len == 0 || smtp_proptags != NULL);
-	g_return_if_fail (name != NULL);
-	g_return_if_fail (email != NULL);
-
-	*name = NULL;
-	*email = NULL;
+	CamelMimePart *part = camel_mime_part_new ();
+	CamelMultipart *m_mixed = camel_multipart_new ();
+	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed), "multipart/mixed");
+	camel_multipart_set_boundary (m_mixed, NULL);
 
-	for (ii = 0; ii < name_proptags_len && !cname; ii++) {
-		cname = e_mapi_util_find_array_propval (properties, name_proptags[ii]);
-	}
+	camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
+	camel_multipart_add_part (m_mixed, part);
+	g_object_unref (part);
 
-	addr_type = e_mapi_util_find_array_propval (properties, email_type_proptag);
-	email_addr = e_mapi_util_find_array_propval (properties, email_proptag);
+	add_multipart_attachments (m_mixed, attachments);
 
-	if (addr_type && g_ascii_strcasecmp (addr_type, "SMTP") == 0)
-		cemail = email_addr;
+	return m_mixed;
+}
 
-	for (ii = 0; ii < smtp_proptags_len && !cemail; ii++) {
-		cemail = e_mapi_util_find_array_propval (properties, smtp_proptags[ii]);
-	}
-
-	if (!cemail && addr_type && g_ascii_strcasecmp (addr_type, "EX") == 0 && email_addr) {
-		*email = e_mapi_connection_ex_to_smtp (conn, email_addr, name, NULL, NULL);
-	}
-
-	if (!*email) {
-		*name = g_strdup (cname);
-		*email = g_strdup (cemail);
-	}
-}
-
-void
-e_mapi_mail_utils_decode_email_address1 (EMapiConnection *conn,
-					 struct mapi_SPropValue_array *properties,
-					 uint32_t name_proptag,
-					 uint32_t email_proptag,
-					 uint32_t email_type_proptag,
-					 gchar **name,
-					 gchar **email)
-{
-	uint32_t names[1];
-
-	names[0] = name_proptag;
-
-	e_mapi_mail_utils_decode_email_address (conn, properties, names, 1, NULL, 0, email_type_proptag, email_proptag, name, email);
-}
-
-void
-e_mapi_mail_utils_decode_recipients (EMapiConnection *conn,
-				     EMapiRecipient *recipients,
-				     CamelAddress *to_addr,
-				     CamelAddress *cc_addr,
-				     CamelAddress *bcc_addr)
-{
-	const uint32_t name_proptags[] = {
-		PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
-		PidTagNickname,
-		PidTagDisplayName,
-		PidTagRecipientDisplayName,
-		PidTag7BitDisplayName
-	};
-
-	const uint32_t email_proptags[] = {
-		PidTagPrimarySmtpAddress,
-		PidTagSmtpAddress
-	};
-
-	EMapiRecipient *recipient;
-
-	g_return_if_fail (conn != NULL);
-	g_return_if_fail (to_addr != NULL);
-	g_return_if_fail (cc_addr != NULL);
-	g_return_if_fail (bcc_addr != NULL);
-
-	for (recipient = recipients; recipient; recipient = recipient->next) {
-		const uint32_t *recip_type = e_mapi_util_find_array_propval (&recipient->properties, PidTagRecipientType);
-		gchar *name = NULL, *email = NULL;
-		CamelAddress *addr = NULL;
-
-		if (!recip_type)
-			continue;
-
-		switch (*recip_type) {
-		case MAPI_TO:
-			addr = to_addr;
-			break;
-		case MAPI_CC:
-			addr = cc_addr;
-			break;
-		case MAPI_BCC:
-			addr = bcc_addr;
-			break;
-		default:
-			break;
-		}
-
-		if (!addr)
-			continue;
-
-		e_mapi_mail_utils_decode_email_address (conn, &recipient->properties,
-					name_proptags, G_N_ELEMENTS (name_proptags),
-					email_proptags, G_N_ELEMENTS (email_proptags),
-					PidTagAddressType, PidTagEmailAddress,
-					&name, &email);
-
-		camel_internet_address_add (CAMEL_INTERNET_ADDRESS (addr), name, email ? email : "");
-
-		g_free (name);
-		g_free (email);
-	}
-}
-
-static void
-build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t proptag)
-{
-	gconstpointer value;
-
-	g_return_if_fail (part != NULL);
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (proptag == PidTagHtml || proptag == PidTagBody);
-
-	camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
-
-	value = e_mapi_util_find_array_propval (&object->properties, proptag);
-	if (value) {
-		const gchar *type = NULL;
-		gchar *buff = NULL, *in_utf8;
-		const uint32_t *pcpid = e_mapi_util_find_array_propval (&object->properties, PidTagInternetCodepage);
-
-		if (proptag == PidTagBody) {
-			type = "text/plain";
-		} else {
-			type = "text/html";
-		}
-
-		proptag = e_mapi_util_find_array_proptag (&object->properties, proptag);
-		if (pcpid && *pcpid && (proptag & 0xFFFF) != PT_UNICODE) {
-			uint32_t cpid = *pcpid;
-	
-			if (cpid == 20127)
-				buff = g_strdup_printf ("%s; charset=\"us-ascii\"", type);
-			else if (cpid >= 28591 && cpid <= 28599)
-				buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, cpid % 10);
-			else if (cpid == 28603)
-				buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
-			else if (cpid == 28605)
-				buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
-			else if (cpid == 65000)
-				buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
-			else if (cpid == 65001)
-				buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
-			else
-				buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, cpid);
-			type = buff;
-		}
-
-		in_utf8 = NULL;
-
-		if (proptag == PidTagHtml) {
-			const struct SBinary_short *html_bin = value;
-
-			if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, html_bin->lpb, html_bin->cb, &in_utf8))
-				camel_mime_part_set_content (part, in_utf8, strlen (in_utf8), type);
-			else
-				camel_mime_part_set_content (part, (const gchar *) html_bin->lpb, html_bin->cb, type);
-			
-		} else {
-			const gchar *str = value;
-
-			if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, (const guint8 *) str, strlen (str), &in_utf8))
-				str = in_utf8;
-
-			camel_mime_part_set_content (part, str, strlen (str), type);
-		}
-
-		g_free (in_utf8);
-		g_free (buff);
-	} else
-		camel_mime_part_set_content (part, " ", strlen (" "), "text/plain");
-}
-
-static gboolean
-is_apple_attach (EMapiAttachment *attach, guint32 *data_len, guint32 *resource_len)
-{
-	gboolean is_apple = FALSE;
-	const struct SBinary_short *encoding_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachEncoding);
-	guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
-
-	if (encoding_bin && encoding_bin->lpb && encoding_bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
-		gint idx;
-
-		is_apple = TRUE;
-		for (idx = 0; idx < encoding_bin->cb && is_apple; idx++) {
-			is_apple = apple_enc_magic[idx] == encoding_bin->lpb[idx];
-		}
-	}
-
-	if (is_apple) {
-		/* check boundaries too */
-		const struct SBinary_short *data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
-
-		is_apple = data_bin && data_bin->lpb && data_bin->cb > 128;
-
-		if (is_apple) {
-			const guint8 *bin = data_bin->lpb;
-
-			/* in big-endian format */
-			*data_len = (bin[83] << 24) | (bin[84] << 16) | (bin[85] << 8) | (bin[86]);
-			*resource_len = (bin[87] << 24) | (bin[88] << 16) | (bin[89] << 8) | (bin[90]);
-
-			/* +/- mod 128 (but the first 128 is a header length) */
-			is_apple = 128 + *data_len + *resource_len <= data_bin->cb && bin[1] < 64;
-		}
-	}
-
-	return is_apple;
-}
-
-static void
-classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const gchar *msg_class, GSList **inline_attachments, GSList **noninline_attachments)
-{
-	EMapiAttachment *attach;
-	gboolean is_smime = msg_class && strstr (msg_class, ".SMIME.") > msg_class;
-
-	g_return_if_fail (inline_attachments != NULL);
-	g_return_if_fail (noninline_attachments != NULL);
-
-	for (attach = attachments; attach != NULL; attach = attach->next) {
-		const gchar *filename, *mime_type, *content_id = NULL;
-		CamelContentType *content_type;
-		CamelMimePart *part;
-		const uint32_t *ui32;
-		const struct SBinary_short *data_bin;
-		gboolean is_apple;
-		guint32 apple_data_len = 0, apple_resource_len = 0;
-
-		data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
-		if (!data_bin && !attach->embedded_object) {
-			g_debug ("%s: Skipping attachment without data and without embedded object", G_STRFUNC);
-			continue;
-		}
-
-		is_apple = is_apple_attach (attach, &apple_data_len, &apple_resource_len);
-
-		/* Content-Type */
-		ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMethod);
-		if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG) {
-			mime_type = "message/rfc822";
-		} else {
-			mime_type = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMimeTag);
-			if (!mime_type)
-				mime_type = "application/octet-stream";
-		}
-
-		if (is_apple) {
-			mime_type = "application/applefile";
-		} else if (strstr (mime_type, "apple") != NULL) {
-			mime_type = "application/octet-stream";
-		}
-
-		part = camel_mime_part_new ();
-
-		filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachLongFilename);
-		if (!filename || !*filename)
-			filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachFilename);
-		camel_mime_part_set_filename (part, filename);
-		camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
-
-		if (is_apple) {
-			CamelMultipart *mp;
-			gchar *apple_filename;
-			const struct SBinary_short *mac_info_bin;
-
-			mp = camel_multipart_new ();
-			camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/appledouble");
-			camel_multipart_set_boundary (mp, NULL);
-
-			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-
-			mac_info_bin = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacInfo);
-			if (mac_info_bin && mac_info_bin->lpb && mac_info_bin->cb > 0) {
-				camel_mime_part_set_content (part, (const gchar *) mac_info_bin->lpb, mac_info_bin->cb, mime_type);
-			} else {
-				/* RFC 1740 */
-				guint8 header[] = {
-					0x00, 0x05, 0x16, 0x07, /* magic */
-					0x00, 0x02, 0x00, 0x00, /* version */
-					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* filler */
-					0x00, 0x01, /* number of entries */
-					0x00, 0x00, 0x00, 0x02, /* entry ID - resource fork */
-					0x00, 0x00, 0x00, 0x26, /* entry offset - 38th byte*/
-					0x00, 0x00, 0x00, 0x00  /* entry length */
-				};
-
-				GByteArray *arr = g_byte_array_sized_new (apple_resource_len + G_N_ELEMENTS (header));
-
-				header[34] = (apple_resource_len >> 24) & 0xFF;
-				header[35] = (apple_resource_len >> 16) & 0xFF;
-				header[36] = (apple_resource_len >>  8) & 0xFF;
-				header[37] = (apple_resource_len      ) & 0xFF;
-
-				g_byte_array_append (arr, header, G_N_ELEMENTS (header));
-				g_byte_array_append (arr, data_bin->lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
-
-				camel_mime_part_set_content (part, (const gchar *) arr->data, arr->len, mime_type);
-
-				g_byte_array_free (arr, TRUE);
-			}
-
-			camel_multipart_add_part (mp, part);
-			g_object_unref (part);
-
-			part = camel_mime_part_new ();
-
-			apple_filename = g_strndup ((const gchar *) data_bin->lpb + 2, data_bin->lpb[1]);
-			camel_mime_part_set_filename (part, (apple_filename && *apple_filename) ? apple_filename : filename);
-			g_free (apple_filename);
-
-			mime_type = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacContentType);
-			if (!mime_type)
-				mime_type = "application/octet-stream";
-
-			camel_mime_part_set_content (part, (const gchar *) data_bin->lpb + 128, apple_data_len, mime_type);
-			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-			camel_multipart_add_part (mp, part);
-			g_object_unref (part);
-
-			part = camel_mime_part_new ();
-			camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (mp));
-			g_object_unref (mp);
-		} else if (is_smime) {
-			CamelMimeParser *parser;
-			CamelStream *mem;
-
-			mem = camel_stream_mem_new ();
-			camel_stream_write (mem, (const gchar *) data_bin->lpb, data_bin->cb, NULL, NULL);
-			g_seekable_seek (G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
-
-			parser = camel_mime_parser_new ();
-			camel_mime_parser_scan_from (parser, FALSE);
-			camel_mime_parser_scan_pre_from (parser, FALSE);
-			camel_mime_parser_init_with_stream (parser, mem, NULL);
-
-			if (camel_mime_parser_step (parser, NULL, NULL) == CAMEL_MIME_PARSER_STATE_HEADER
-			    && camel_mime_parser_content_type (parser) != NULL) {
-				g_object_unref (part);
-				part = camel_mime_part_new ();
-
-				camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (part), camel_mime_parser_content_type (parser));
-				camel_mime_part_construct_content_from_parser (part, parser, NULL, NULL);
-			} else {
-				is_smime = FALSE;
-			}
-
-			g_object_unref (parser);
-			g_object_unref (mem);
-		} 
-
-		if (!is_smime && !is_apple) {
-			if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG && attach->embedded_object) {
-				CamelMimeMessage *embedded_msg;
-
-				embedded_msg = e_mapi_mail_utils_object_to_message (conn, attach->embedded_object);
-				if (embedded_msg) {
-					CamelStream *mem;
-					GByteArray *data;
-
-					data = g_byte_array_new ();
-
-					mem = camel_stream_mem_new ();
-					camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), data);
-					camel_data_wrapper_write_to_stream_sync (
-						CAMEL_DATA_WRAPPER (embedded_msg), mem, NULL, NULL);
-
-					g_object_unref (mem);
-					g_object_unref (embedded_msg);
-
-					camel_mime_part_set_content (part, (const gchar *) data->data, data->len, mime_type);
-
-					g_byte_array_free (data, TRUE);
-				} else {
-					camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
-				}
-			} else {
-				camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
-			}
-
-			content_type = camel_mime_part_get_content_type (part);
-			if (content_type && camel_content_type_is (content_type, "text", "*"))
-				camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
-			else if (!ui32 || *ui32 != ATTACH_EMBEDDED_MSG)
-				camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-		}
-
-		/* Content-ID */
-		content_id = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachContentId);
-
-		/* TODO : Add disposition */
-		if (content_id && !is_apple && !is_smime) {
-			camel_mime_part_set_content_id (part, content_id);
-			*inline_attachments = g_slist_append (*inline_attachments, part);
-		} else
-			*noninline_attachments = g_slist_append (*noninline_attachments, part);
-	}
-}
-
-static void
-add_multipart_attachments (CamelMultipart *multipart, GSList *attachments)
-{
-	CamelMimePart *part;
-	while (attachments) {
-		part = attachments->data;
-		camel_multipart_add_part (multipart, part);
-		attachments = attachments->next;
-	}
-}
-
-static CamelMultipart *
-build_multipart_related (EMapiObject *object, GSList *inline_attachments)
-{
-	CamelMimePart *part;
-	CamelMultipart *m_related = camel_multipart_new ();
-	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
-	camel_multipart_set_boundary (m_related, NULL);
-
-	if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
-		part = camel_mime_part_new ();
-		build_body_part_content (part, object, PidTagHtml);
-		camel_multipart_add_part (m_related, part);
-		g_object_unref (part);
-	} else if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
-		part = camel_mime_part_new ();
-		build_body_part_content (part, object, PidTagBody);
-		camel_multipart_add_part (m_related, part);
-		g_object_unref (part);
-	}
-
-	add_multipart_attachments (m_related, inline_attachments);
-
-	return m_related;
-}
-
-static CamelMultipart *
-build_multipart_alternative (EMapiObject *object, GSList *inline_attachments)
-{
-	CamelMimePart *part;
-	CamelMultipart *m_alternative;
-
-	m_alternative = camel_multipart_new ();
-	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative), "multipart/alternative");
-	camel_multipart_set_boundary (m_alternative, NULL);
-
-	if (e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
-		part = camel_mime_part_new ();
-		build_body_part_content (part, object, PidTagBody);
-		camel_multipart_add_part (m_alternative, part);
-		g_object_unref (part);
-	}
-
-	if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml)) {
-		part = camel_mime_part_new ();
-		if (inline_attachments) {
-			CamelMultipart *m_related;
-
-			m_related = build_multipart_related (object, inline_attachments);
-			camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (m_related));
-			g_object_unref (m_related);
-		} else {
-			build_body_part_content (part, object, PidTagHtml);
-		}
-		camel_multipart_add_part (m_alternative, part);
-		g_object_unref (part);
-	}
-
-	return m_alternative;
-}
-
-static CamelMultipart *
-build_multipart_mixed (CamelMultipart *content, GSList *attachments)
-{
-	CamelMimePart *part = camel_mime_part_new ();
-	CamelMultipart *m_mixed = camel_multipart_new ();
-	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed), "multipart/mixed");
-	camel_multipart_set_boundary (m_mixed, NULL);
-
-	camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
-	camel_multipart_add_part (m_mixed, part);
-	g_object_unref (part);
-
-	add_multipart_attachments (m_mixed, attachments);
-
-	return m_mixed;
-}
-
-static gchar *
-build_ical_string (EMapiConnection *conn,
-		   EMapiObject *object,
-		   const gchar *msg_class)
-{
-	gchar *ical_string = NULL, *use_uid;
-	icalcomponent_kind ical_kind = ICAL_NO_COMPONENT;
-	icalproperty_method ical_method = ICAL_METHOD_NONE;
-	const uint64_t *pmid;
-	ECalComponent *comp;
-	icalcomponent *icalcomp;
-	GSList *detached_components = NULL, *iter;
-
-	g_return_val_if_fail (conn != NULL, NULL);
-	g_return_val_if_fail (object != NULL, NULL);
-	g_return_val_if_fail (msg_class != NULL, NULL);
-
-	if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST)) {
-		ical_method = ICAL_METHOD_REQUEST;
-		ical_kind = ICAL_VEVENT_COMPONENT;
-	} else if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED)) {
-		ical_method = ICAL_METHOD_CANCEL;
-		ical_kind = ICAL_VEVENT_COMPONENT;
-	} else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
-		ical_method = ICAL_METHOD_REPLY;
-		ical_kind = ICAL_VEVENT_COMPONENT;
-	} else {
-		return NULL;
-	}
-
-	pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
-	if (pmid)
-		use_uid = e_mapi_util_mapi_id_to_string (*pmid);
-	else
-		use_uid = e_cal_component_gen_uid ();
-
-	comp = e_mapi_cal_util_object_to_comp (conn, object, ical_kind, ical_method == ICAL_METHOD_REPLY, NULL, use_uid, &detached_components);
-
-	g_free (use_uid);
-
-	if (!comp)
-		return NULL;
-
-	icalcomp = e_cal_util_new_top_level ();
-	icalcomponent_set_method (icalcomp, ical_method);
-	if (comp)
-		icalcomponent_add_component (icalcomp,
-			icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp)));
-	for (iter = detached_components; iter; iter = g_slist_next (iter)) {
-		icalcomponent_add_component (icalcomp,
-				icalcomponent_new_clone (e_cal_component_get_icalcomponent (iter->data)));
-	}
-
-	ical_string = icalcomponent_as_ical_string_r (icalcomp);
-
-	icalcomponent_free (icalcomp);
-	g_slist_free_full (detached_components, g_object_unref);
-	g_object_unref (comp);
-
-	return ical_string;
-}
-
-CamelMimeMessage *
-e_mapi_mail_utils_object_to_message (EMapiConnection *conn, /* const */ EMapiObject *object)
-{
-	CamelMimeMessage *msg;
-	CamelMultipart *multipart_body = NULL;
-	GSList *inline_attachments, *noninline_attachments;
-	gboolean build_alternative, build_related, build_calendar;
-	const gchar *str, *msg_class;
-	gboolean skip_set_content = FALSE;
-	gchar *ical_string = NULL;
-
-	g_return_val_if_fail (conn != NULL, NULL);
-	g_return_val_if_fail (object != NULL, NULL);
-
-	msg = camel_mime_message_new ();
-
-	str = e_mapi_util_find_array_propval (&object->properties, PidTagTransportMessageHeaders);
-	if (str && *str) {
-		CamelMimePart *part = camel_mime_part_new ();
-		CamelStream *stream;
-		CamelMimeParser *parser;
-
-		stream = camel_stream_mem_new_with_buffer (str, strlen (str));
-		parser = camel_mime_parser_new ();
-		camel_mime_parser_init_with_stream (parser, stream, NULL);
-		camel_mime_parser_scan_from (parser, FALSE);
-		g_object_unref (stream);
-
-		if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
-			struct _camel_header_raw *h;
-
-			for (h = part->headers; h; h = h->next) {
-				const gchar *value = h->value;
-
-				/* skip all headers describing content of a message,
-				   because it's overwritten on message decomposition */
-				if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
-					continue;
-
-				while (value && camel_mime_is_lwsp (*value))
-					value++;
-
-				camel_medium_add_header (CAMEL_MEDIUM (msg), h->name, value);
-			}
-		}
-
-		g_object_unref (parser);
-		g_object_unref (part);
-	} else {
-		CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
-		const struct FILETIME *delivery_time;
-		gchar *name, *email;
-
-		to_addr = camel_internet_address_new ();
-		cc_addr = camel_internet_address_new ();
-		bcc_addr = camel_internet_address_new ();
-
-		e_mapi_mail_utils_decode_recipients (conn, object->recipients, (CamelAddress *) to_addr, (CamelAddress *) cc_addr, (CamelAddress *) bcc_addr);
-
-		camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_TO, to_addr);
-		camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_CC, cc_addr);
-		camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_BCC, bcc_addr);
-
-		g_object_unref (to_addr);
-		g_object_unref (cc_addr);
-		g_object_unref (bcc_addr);
-
-		delivery_time = e_mapi_util_find_array_propval (&object->properties, PidTagMessageDeliveryTime);
-		if (delivery_time) {
-			time_t received_time, actual_time;
-			gint offset = 0;
-
-			received_time = e_mapi_util_filetime_to_time_t (delivery_time);
-			actual_time = camel_header_decode_date (ctime (&received_time), &offset);
-			camel_mime_message_set_date (msg, actual_time, offset);
-		}
-
-		str = e_mapi_util_find_array_propval (&object->properties, PidTagSubject);
-		if (str)
-			camel_mime_message_set_subject (msg, str);
-
-		name = NULL;
-		email = NULL;
-
-		e_mapi_mail_utils_decode_email_address1 (conn, &object->properties,
-			PidTagSentRepresentingName,
-			PidTagSentRepresentingEmailAddress,
-			PidTagSentRepresentingAddressType,
-			&name, &email);
-
-		if (email && *email) {
-			CamelInternetAddress *addr;
-
-			addr = camel_internet_address_new();
-			camel_internet_address_add (addr, name, email);
-			camel_mime_message_set_from (msg, addr);
-		}
-		
-		g_free (name);
-		g_free (email);
-
-		/* Threading */
-		str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetMessageId);
-		if (str)
-			camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", str);
-
-		str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetReferences);
-		if (str)
-			camel_medium_add_header (CAMEL_MEDIUM (msg), "References", str);
-
-		str = e_mapi_util_find_array_propval (&object->properties, PidTagInReplyToId);
-		if (str)
-			camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", str);
-	}
-
-	str = e_mapi_util_find_array_propval (&object->properties, PidNameContentClass);
-	if (str)
-		camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", str);
-
-	inline_attachments = NULL;
-	noninline_attachments = NULL;
-	msg_class = e_mapi_util_find_array_propval (&object->properties, PidTagMessageClass);
-	classify_attachments (conn, object->attachments, msg_class, &inline_attachments, &noninline_attachments);
-
-	build_calendar = msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX);
-	if (build_calendar) {
-		ical_string = build_ical_string (conn, object, msg_class);
-		if (!ical_string)
-			build_calendar = FALSE;
-	}
-
-	build_alternative = !build_calendar
-		&& e_mapi_util_find_array_propval (&object->properties, PidTagHtml)
-		&& e_mapi_util_find_array_propval (&object->properties, PidTagBody);
-	build_related = !build_calendar && !build_alternative && inline_attachments;
-
-	if (build_calendar) {
-		g_return_val_if_fail (ical_string != NULL, msg);
-
-		camel_mime_part_set_content (CAMEL_MIME_PART (msg), ical_string, strlen (ical_string), "text/calendar");
-	} else if (build_alternative) {
-		multipart_body = build_multipart_alternative (object, inline_attachments);
-	} else if (build_related) {
-		multipart_body = build_multipart_related (object, inline_attachments);
-	} else if (noninline_attachments) {
-		/* Simple multipart/mixed */
-		CamelMimePart *part = camel_mime_part_new ();
-
-		multipart_body = camel_multipart_new ();
-		camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body), "multipart/mixed");
-		camel_multipart_set_boundary (multipart_body, NULL);
-		if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
-			build_body_part_content (part, object, PidTagHtml);
-		else
-			build_body_part_content (part, object, PidTagBody);
-		camel_multipart_add_part (multipart_body, part);
-		g_object_unref (part);
-	} else {
-		/* Flat message */
-		if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
-			build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagHtml);
-		else
-			build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagBody);
-	}
-
-	if (noninline_attachments) { /* multipart/mixed */
-		if (build_alternative || build_related || build_calendar) {
-			multipart_body = build_multipart_mixed (multipart_body, noninline_attachments);
-		} else if (g_slist_length (noninline_attachments) == 1 && msg_class && strstr (msg_class, ".SMIME") > msg_class) {
-			CamelMimePart *part = noninline_attachments->data;
-
-			skip_set_content = TRUE;
-
-			camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
-
-			if (!strstr (msg_class, ".SMIME.")) {
-				/* encrypted */
-				camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
-				camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
-			} else {
-				/* signed */
-				camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
-			}
-		} else {
-			add_multipart_attachments (multipart_body, noninline_attachments);
-		}
-	}
-
-	if (!skip_set_content && multipart_body)
-		camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart_body));
-
-	if (multipart_body)
-		g_object_unref (multipart_body);
-	g_slist_free_full (inline_attachments, g_object_unref);
-	g_slist_free_full (noninline_attachments, g_object_unref);
-	g_free (ical_string);
-
-	return msg;
-}
-
-static void
-e_mapi_mail_add_recipients (EMapiObject *object,
-			    CamelInternetAddress *addresses,
-			    OlMailRecipientType recip_type)
-{
-	gint ii;
-	const gchar *name = NULL, *email = NULL;
-
-	g_return_if_fail (object != NULL);
-
-	for (ii = 0; addresses && camel_internet_address_get (addresses, ii, &name, &email); ii++) {
-		EMapiRecipient *recipient;
-		uint32_t ui32 = 0;
-		bool bl;
-
-		recipient = e_mapi_recipient_new (object);
-		e_mapi_object_add_recipient (object, recipient);
-
-		#define set_value(pt,vl) {								\
-			if (!e_mapi_utils_add_property (&recipient->properties, pt, vl, recipient)) {	\
-				g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);		\
-													\
-				return;									\
-			}										\
-		}
-
-		ui32 = recip_type;
-		set_value (PidTagRecipientType, &ui32);
-
-		if (!name || !*name)
-			name = email;
-
-		if (name && *name) {
-			set_value (PidTagDisplayName, name);
-			set_value (PidTagRecipientDisplayName, name);
-		}
-		if (email && *email) {
-			set_value (PidTagAddressType, "SMTP");
-			set_value (PidTagEmailAddress, email);
-
-			set_value (PidTagSmtpAddress, email);
-			set_value (PidTagPrimarySmtpAddress, email);
-		}
-
-		ui32 = 0;
-		set_value (PidTagSendInternetEncoding, &ui32);
-
-		ui32 = DT_MAILUSER;
-		set_value (PidTagDisplayType, &ui32);
-
-		ui32 = MAPI_MAILUSER;
-		set_value (PidTagObjectType, &ui32);
-
-		bl = false;
-		set_value (PidTagSendRichInfo, &bl);
-
-		#undef set_value
-
-		name = NULL;
-		email = NULL;
-	}
-}
-
-static CamelStream *
-get_content_stream (CamelMimePart *part, GCancellable *cancellable)
-{
-	CamelStream *content_stream;
-	CamelStream *filter_stream = NULL;
-	CamelMimeFilterWindows *windows = NULL;
-	CamelDataWrapper *dw;
-
-	g_return_val_if_fail (part != NULL, NULL);
-
-	dw = camel_medium_get_content (CAMEL_MEDIUM (part));
-	g_return_val_if_fail (dw != NULL, NULL);
-
-	content_stream = camel_stream_mem_new();
-
-	if (camel_mime_part_get_content_type (part)) {
-		const gchar *charset = camel_content_type_param (camel_mime_part_get_content_type (part), "charset");
-
-		if (charset && *charset && g_ascii_strcasecmp (charset, "utf8") != 0 && g_ascii_strcasecmp (charset, "utf-8") != 0) {
-			if (g_ascii_strncasecmp (charset, "iso-8859-", 9) == 0) {
-				CamelStream *null;
-
-				/* Since a few Windows mailers like to claim they sent
-				 * out iso-8859-# encoded text when they really sent
-				 * out windows-cp125#, do some simple sanity checking
-				 * before we move on... */
-
-				null = camel_stream_null_new ();
-				filter_stream = camel_stream_filter_new (null);
-				g_object_unref (null);
-
-				windows = (CamelMimeFilterWindows *)camel_mime_filter_windows_new (charset);
-				camel_stream_filter_add (
-					CAMEL_STREAM_FILTER (filter_stream),
-					CAMEL_MIME_FILTER (windows));
-
-				camel_data_wrapper_decode_to_stream_sync (
-					dw, (CamelStream *)filter_stream, cancellable, NULL);
-				camel_stream_flush ((CamelStream *)filter_stream, cancellable, NULL);
-				g_object_unref (filter_stream);
-
-				charset = camel_mime_filter_windows_real_charset (windows);
-			}
-
-			if (charset && *charset) {
-				CamelMimeFilter *filter;
-
-				filter_stream = camel_stream_filter_new (content_stream);
-
-				if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
-					camel_stream_filter_add (
-						CAMEL_STREAM_FILTER (filter_stream),
-						CAMEL_MIME_FILTER (filter));
-					g_object_unref (filter);
-				} else {
-					g_object_unref (filter_stream);
-					filter_stream = NULL;
-				}
-			}
-		}
-	}
-
-	if (filter_stream) {
-		camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) filter_stream, cancellable, NULL);
-		camel_stream_flush (filter_stream, cancellable, NULL);
-		g_object_unref (filter_stream);
-	} else {
-		camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
-	}
-
-	if (windows)
-		g_object_unref (windows);
-
-	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
-
-	return content_stream;
-}
-
-static void
-e_mapi_mail_content_stream_to_bin (CamelStream *content_stream,
-				   struct SBinary_short *bin,
-				   TALLOC_CTX *mem_ctx,
-				   GCancellable *cancellable)
-{
-	guint8 *buf;
-	guint32	read_size;
-
-	g_return_if_fail (content_stream != NULL);
-	g_return_if_fail (bin != NULL);
-	g_return_if_fail (mem_ctx != NULL);
-
-	buf = g_new0 (guint8 , STREAM_SIZE);
-
-	bin->cb = 0;
-	bin->lpb = NULL;
-
-	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
-	while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
-		bin->lpb = talloc_realloc (mem_ctx, bin->lpb, uint8_t, bin->cb + read_size);
-		memcpy (bin->lpb + bin->cb, buf, read_size);
-		bin->cb += read_size;
-	}
-
-	g_free (buf);
-}
-
-#define set_attach_value(pt,vl) {						\
-	if (!e_mapi_utils_add_property (&attach->properties, pt, vl, attach)) {	\
-		g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);	\
-		return FALSE;							\
-	}									\
-}
-
-static gboolean
-e_mapi_mail_add_attach (EMapiObject *object,
-			CamelMimePart *part,
-			CamelStream *content_stream,
-			GCancellable *cancellable)
-{
-	EMapiAttachment *attach;
-	CamelContentType *content_type;
-	const gchar *content_id;
-	const gchar *filename;
-	struct SBinary_short bin;
-	uint32_t ui32;
-
-	g_return_val_if_fail (object != NULL, FALSE);
-	g_return_val_if_fail (part != NULL, FALSE);
-	g_return_val_if_fail (content_stream != NULL, FALSE);
-
-	attach = e_mapi_attachment_new (object);
-	e_mapi_object_add_attachment (object, attach);
-
-	ui32 = ATTACH_BY_VALUE;
-	set_attach_value (PidTagAttachMethod, &ui32);
-	ui32 = -1;
-	set_attach_value (PidTagRenderingPosition, &ui32);
-
-	filename = camel_mime_part_get_filename (part);
-	if (filename) {
-		set_attach_value (PidTagAttachFilename, filename);
-		set_attach_value (PidTagAttachLongFilename, filename);
-	}
-
-	content_id = camel_mime_part_get_content_id (part);
-	if (content_id)
-		set_attach_value (PidTagAttachContentId, content_id);
-
-	content_type  = camel_mime_part_get_content_type (part);
-	if (content_type) {
-		gchar *ct = camel_content_type_simple (content_type);
-		if (ct)
-			set_attach_value (PidTagAttachMimeTag, ct);
-		g_free (ct);
-	}
-
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
-	set_attach_value (PidTagAttachDataBinary, &bin);
-
-	return TRUE;
-}
-
-static gboolean
-e_mapi_mail_add_body (EMapiObject *object,
-		      CamelStream *content_stream,
-		      uint32_t proptag,
-		      GCancellable *cancellable)
-{
-	struct SBinary_short bin = { 0 };
-	gchar *str;
-
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, object, cancellable);
-	str = talloc_strndup (object, (const gchar *) bin.lpb, bin.cb);
-	talloc_free (bin.lpb);
-
-	if ((proptag & 0xFFFF) == PT_BINARY) {
-		bin.lpb = (uint8_t *) (str ? str : "");
-		bin.cb = strlen ((const gchar *) bin.lpb) + 1;
-		/* include trailing zero ................ ^^^ */
-
-		return e_mapi_utils_add_property (&object->properties, proptag, &bin, object);
-	} else if (str) {
-		if (!e_mapi_utils_add_property (&object->properties, proptag, str, object)) {
-			talloc_free (str);
-			return FALSE;
-		}
-
-		talloc_free (str);
-	} else {
-		return e_mapi_utils_add_property (&object->properties, proptag, "", object);
-	}
-
-	return TRUE;
-}
-
-static gboolean
-e_mapi_mail_do_smime_encrypted (EMapiObject *object,
-				CamelMedium *message,
-				gchar **pmsg_class,
-				gchar **ppid_name_content_type,
-				GCancellable *cancellable)
-{
-	EMapiAttachment *attach;
-	CamelStream *content_stream;
-	CamelDataWrapper *dw;
-	CamelContentType *type;
-	uint32_t ui32;
-	struct SBinary_short bin;
-	gchar *content_type_str;
-
-	g_return_val_if_fail (object != NULL, FALSE);
-	g_return_val_if_fail (message != NULL, FALSE);
-	g_return_val_if_fail (pmsg_class != NULL, FALSE);
-	g_return_val_if_fail (ppid_name_content_type != NULL, FALSE);
-
-	g_free (*pmsg_class);
-	*pmsg_class = g_strdup ("IPM.Note.SMIME");
-
-	type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
-	dw = camel_medium_get_content (message);
-	content_type_str = camel_content_type_format (type);
-
-	g_free (*ppid_name_content_type);
-	*ppid_name_content_type = content_type_str; /* will be freed within the caller */
-
-	content_stream = camel_stream_mem_new ();
-	camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
-
-	attach = e_mapi_attachment_new (object);
-	e_mapi_object_add_attachment (object, attach);
-
-	ui32 = ATTACH_BY_VALUE;
-	set_attach_value (PidTagAttachMethod, &ui32);
-	ui32 = -1;
-	set_attach_value (PidTagRenderingPosition, &ui32);
-	set_attach_value (PidTagAttachMimeTag, content_type_str);
-	set_attach_value (PidTagAttachFilename, "SMIME.txt");
-	set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
-	set_attach_value (PidTagDisplayName, "SMIME.txt");
-
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
-	set_attach_value (PidTagAttachDataBinary, &bin);
-
-	g_object_unref (content_stream);
-
-	return TRUE;
-}
-
-static gboolean
-e_mapi_mail_do_smime_signed (EMapiObject *object,
-			     CamelMultipart *multipart,
-			     gchar **pmsg_class,
-			     GCancellable *cancellable)
+static gchar *
+build_ical_string (EMapiConnection *conn,
+		   EMapiObject *object,
+		   const gchar *msg_class)
 {
-	EMapiAttachment *attach;
-	CamelMimePart *content, *signature;
-	CamelStream *content_stream;
-	CamelContentType *type;
-	CamelDataWrapper *dw;
-	uint32_t ui32;
-	struct SBinary_short bin;
-	gchar *content_type_str;
-
-	g_free (*pmsg_class);
-	*pmsg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
-
-	content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
-	signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
-
-	g_return_val_if_fail (content != NULL, FALSE);
-	g_return_val_if_fail (signature != NULL, FALSE);
+	gchar *ical_string = NULL, *use_uid;
+	icalcomponent_kind ical_kind = ICAL_NO_COMPONENT;
+	icalproperty_method ical_method = ICAL_METHOD_NONE;
+	const uint64_t *pmid;
+	ECalComponent *comp;
+	icalcomponent *icalcomp;
+	GSList *detached_components = NULL, *iter;
 
-	content_stream = get_content_stream (content, cancellable);
-	type = camel_mime_part_get_content_type (content);
+	g_return_val_if_fail (conn != NULL, NULL);
+	g_return_val_if_fail (object != NULL, NULL);
+	g_return_val_if_fail (msg_class != NULL, NULL);
 
-	if (camel_content_type_is (type, "text", "plain")) {
-		e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
-	} else if (camel_content_type_is (type, "text", "html")) {
-		e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
+	if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST)) {
+		ical_method = ICAL_METHOD_REQUEST;
+		ical_kind = ICAL_VEVENT_COMPONENT;
+	} else if (!g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED)) {
+		ical_method = ICAL_METHOD_CANCEL;
+		ical_kind = ICAL_VEVENT_COMPONENT;
+	} else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
+		ical_method = ICAL_METHOD_REPLY;
+		ical_kind = ICAL_VEVENT_COMPONENT;
 	} else {
-		e_mapi_mail_add_attach (object, content, content_stream, cancellable);
+		return NULL;
 	}
 
-	if (content_stream)
-		g_object_unref (content_stream);
-
-	content_stream = camel_stream_mem_new ();
-	dw = CAMEL_DATA_WRAPPER (multipart);
-	type = camel_data_wrapper_get_mime_type_field (dw);
-	content_type_str = camel_content_type_format (type);
-
-	#define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
-	wstr("Content-Type: ");
-	wstr(content_type_str);
-	wstr("\n\n");
-	#undef wstr
+	pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
+	if (pmid)
+		use_uid = e_mapi_util_mapi_id_to_string (*pmid);
+	else
+		use_uid = e_cal_component_gen_uid ();
 
-	g_free (content_type_str);
+	comp = e_mapi_cal_util_object_to_comp (conn, object, ical_kind, ical_method == ICAL_METHOD_REPLY, NULL, use_uid, &detached_components);
 
-	camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+	g_free (use_uid);
 
-	attach = e_mapi_attachment_new (object);
-	e_mapi_object_add_attachment (object, attach);
+	if (!comp)
+		return NULL;
 
-	ui32 = ATTACH_BY_VALUE;
-	set_attach_value (PidTagAttachMethod, &ui32);
-	ui32 = -1;
-	set_attach_value (PidTagRenderingPosition, &ui32);
-	set_attach_value (PidTagAttachMimeTag, "multipart/signed");
-	set_attach_value (PidTagAttachFilename, "SMIME.txt");
-	set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
-	set_attach_value (PidTagDisplayName, "SMIME.txt");
+	icalcomp = e_cal_util_new_top_level ();
+	icalcomponent_set_method (icalcomp, ical_method);
+	if (comp)
+		icalcomponent_add_component (icalcomp,
+			icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp)));
+	for (iter = detached_components; iter; iter = g_slist_next (iter)) {
+		icalcomponent_add_component (icalcomp,
+				icalcomponent_new_clone (e_cal_component_get_icalcomponent (iter->data)));
+	}
 
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
-	set_attach_value (PidTagAttachDataBinary, &bin);
+	ical_string = icalcomponent_as_ical_string_r (icalcomp);
 
-	g_object_unref (content_stream);
+	icalcomponent_free (icalcomp);
+	g_slist_free_full (detached_components, g_object_unref);
+	g_object_unref (comp);
 
-	return TRUE;
+	return ical_string;
 }
 
-static gboolean
-e_mapi_mail_do_multipart (EMapiObject *object,
-			  CamelMultipart *mp,
-			  gboolean *is_first,
-			  GCancellable *cancellable)
+CamelMimeMessage *
+e_mapi_mail_utils_object_to_message (EMapiConnection *conn, /* const */ EMapiObject *object)
 {
-	CamelDataWrapper *dw;
-	CamelStream *content_stream;
-	CamelContentType *type;
-	CamelMimePart *part;
-	gint nn, ii;
+	CamelMimeMessage *msg;
+	CamelMultipart *multipart_body = NULL;
+	GSList *inline_attachments, *noninline_attachments;
+	gboolean build_alternative, build_related, build_calendar;
+	const gchar *str, *msg_class;
+	gboolean skip_set_content = FALSE;
+	gchar *ical_string = NULL;
 
-	g_return_val_if_fail (is_first != NULL, FALSE);
+	g_return_val_if_fail (conn != NULL, NULL);
+	g_return_val_if_fail (object != NULL, NULL);
 
-	nn = camel_multipart_get_number (mp);
-	for (ii = 0; ii < nn; ii++) {
-		/* getting part */
-		part = camel_multipart_get_part (mp, ii);
-		if (!part)
-			continue;
+	msg = camel_mime_message_new ();
 
-		dw = camel_medium_get_content (CAMEL_MEDIUM (part));
-		if (CAMEL_IS_MULTIPART (dw)) {
-			/* recursive */
-			if (!e_mapi_mail_do_multipart (object, CAMEL_MULTIPART (dw), is_first, cancellable))
-				return FALSE;
-			continue;
-		}
+	str = e_mapi_util_find_array_propval (&object->properties, PidTagTransportMessageHeaders);
+	if (str && *str) {
+		CamelMimePart *part = camel_mime_part_new ();
+		CamelStream *stream;
+		CamelMimeParser *parser;
 
-		if (CAMEL_IS_MIME_MESSAGE (dw)) {
-			CamelMimeMessage *message;
-			EMapiObject *embedded = NULL;
-			EMapiAttachment *attach;
+		stream = camel_stream_mem_new_with_buffer (str, strlen (str));
+		parser = camel_mime_parser_new ();
+		camel_mime_parser_init_with_stream (parser, stream, NULL);
+		camel_mime_parser_scan_from (parser, FALSE);
+		g_object_unref (stream);
 
-			attach = e_mapi_attachment_new (object);
-			message = CAMEL_MIME_MESSAGE (dw);
-			if (e_mapi_mail_utils_message_to_object (message, 0, E_MAPI_CREATE_FLAG_NONE, &embedded, attach, cancellable, NULL)) {
-				uint32_t ui32;
-				const gchar *str;
+		if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
+			struct _camel_header_raw *h;
 
-				e_mapi_object_add_attachment (object, attach);
-				attach->embedded_object = embedded;
-				embedded->parent = object;
+			for (h = part->headers; h; h = h->next) {
+				const gchar *value = h->value;
 
-				ui32 = ATTACH_EMBEDDED_MSG;
-				set_attach_value (PidTagAttachMethod, &ui32);
-				ui32 = 0;
-				set_attach_value (PidTagRenderingPosition, &ui32);
-				set_attach_value (PidTagAttachMimeTag, "message/rfc822");
+				/* skip all headers describing content of a message,
+				   because it's overwritten on message decomposition */
+				if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
+					continue;
 
-				str = camel_mime_message_get_subject (message);
-				if (str)
-					set_attach_value (PidTagAttachFilename, str);
-				continue;
-			} else {
-				e_mapi_attachment_free (attach);
+				while (value && camel_mime_is_lwsp (*value))
+					value++;
+
+				camel_medium_add_header (CAMEL_MEDIUM (msg), h->name, value);
 			}
 		}
 
-		content_stream = get_content_stream (part, cancellable);
-		type = camel_mime_part_get_content_type (part);
+		g_object_unref (parser);
+		g_object_unref (part);
+	} else {
+		CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
+		const struct FILETIME *delivery_time;
+		gchar *name, *email;
 
-		if (ii == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
-			e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
-			*is_first = FALSE;
-		} else if (camel_content_type_is (type, "text", "html")) {
-			e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
-		} else {
-			e_mapi_mail_add_attach (object, part, content_stream, cancellable);
-		}
+		to_addr = camel_internet_address_new ();
+		cc_addr = camel_internet_address_new ();
+		bcc_addr = camel_internet_address_new ();
 
-		if (content_stream)
-			g_object_unref (content_stream);
-	}
+		e_mapi_mail_utils_decode_recipients (conn, object->recipients, (CamelAddress *) to_addr, (CamelAddress *) cc_addr, (CamelAddress *) bcc_addr);
 
-	return TRUE;
-}
+		camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_TO, to_addr);
+		camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_CC, cc_addr);
+		camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_BCC, bcc_addr);
 
-#undef set_attach_value
+		g_object_unref (to_addr);
+		g_object_unref (cc_addr);
+		g_object_unref (bcc_addr);
 
-gboolean
-e_mapi_mail_utils_message_to_object (struct _CamelMimeMessage *message,
-				     guint32 message_camel_flags,
-				     EMapiCreateFlags create_flags,
-				     EMapiObject **pobject,
-				     TALLOC_CTX *mem_ctx,
-				     GCancellable *cancellable,
-				     GError **perror)
-{
-	EMapiObject *object;
-	CamelContentType *content_type;
-	CamelInternetAddress *addresses;
-	const gchar *namep = NULL, *addressp = NULL;
-	const gchar *str;
-	gchar *msg_class = NULL;
-	gchar *pid_name_content_type = NULL;
-	gint ii = 0;
-	uint32_t ui32;
-	bool bl;
+		delivery_time = e_mapi_util_find_array_propval (&object->properties, PidTagMessageDeliveryTime);
+		if (delivery_time) {
+			time_t received_time, actual_time;
+			gint offset = 0;
 
-	g_return_val_if_fail (message != NULL, FALSE);
-	g_return_val_if_fail (pobject != NULL, FALSE);
-	g_return_val_if_fail (*pobject == NULL, FALSE);
-	g_return_val_if_fail (mem_ctx != NULL, FALSE);
+			received_time = e_mapi_util_filetime_to_time_t (delivery_time);
+			actual_time = camel_header_decode_date (ctime (&received_time), &offset);
+			camel_mime_message_set_date (msg, actual_time, offset);
+		}
 
-	content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
-	g_return_val_if_fail (content_type != NULL, FALSE);
+		str = e_mapi_util_find_array_propval (&object->properties, PidTagSubject);
+		if (str)
+			camel_mime_message_set_subject (msg, str);
 
-	/* headers */
-	if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
-		/* though invalid, then possible, to pass in a message without any 'from' */
-		CamelInternetAddress *from = camel_mime_message_get_from (message);
-		if (!from || !camel_internet_address_get (from, 0, &namep, &addressp))
-			namep = NULL;
-	}
+		name = NULL;
+		email = NULL;
 
-	object = e_mapi_object_new (mem_ctx);
+		e_mapi_mail_utils_decode_email_address1 (conn, &object->properties,
+			PidTagSentRepresentingName,
+			PidTagSentRepresentingEmailAddress,
+			PidTagSentRepresentingAddressType,
+			&name, &email);
 
-	#define set_value(pt,vl) {							\
-		if (!e_mapi_utils_add_property (&object->properties, pt, vl, object)) {	\
-			e_mapi_object_free (object);					\
-			g_free (msg_class);						\
-			g_free (pid_name_content_type);					\
-											\
-			g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);	\
-											\
-			return FALSE;							\
-		}									\
-	}
+		if (email && *email) {
+			CamelInternetAddress *addr;
+
+			addr = camel_internet_address_new();
+			camel_internet_address_add (addr, name, email);
+			camel_mime_message_set_from (msg, addr);
+		}
+		
+		g_free (name);
+		g_free (email);
 
-	ui32 = 65001; /* UTF8 - also used with PR_HTML */
-	set_value (PidTagInternetCodepage, &ui32);
+		/* Threading */
+		str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetMessageId);
+		if (str)
+			camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", str);
 
-	if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
-		ui32 = 0;
-		if (message_camel_flags & CAMEL_MESSAGE_SEEN)
-			ui32 |= MSGFLAG_READ;
-		if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
-			ui32 |= MSGFLAG_HASATTACH;
-	} else {
-		ui32 = MSGFLAG_UNSENT;
-	}
-	set_value (PidTagMessageFlags, &ui32);
+		str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetReferences);
+		if (str)
+			camel_medium_add_header (CAMEL_MEDIUM (msg), "References", str);
 
-	bl = false;
-	set_value (PidTagSendRichInfo, &bl);
+		str = e_mapi_util_find_array_propval (&object->properties, PidTagInReplyToId);
+		if (str)
+			camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", str);
+	}
 
-	/* PidTagConversationTopic and PidTagNormalizedSubject, together with PidTagSubjectPrefix
-	   are computed from PidTagSubject by a server */
-	str = camel_mime_message_get_subject (message);
+	str = e_mapi_util_find_array_propval (&object->properties, PidNameContentClass);
 	if (str)
-		set_value (PidTagSubject, str);
+		camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", str);
 
-	/* some properties may not be set when submitting a message */
-	if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
-		time_t msg_time = 0;
-		gint msg_time_offset = 0;
-		GArray *headers;
+	inline_attachments = NULL;
+	noninline_attachments = NULL;
+	msg_class = e_mapi_util_find_array_propval (&object->properties, PidTagMessageClass);
+	classify_attachments (conn, object->attachments, msg_class, &inline_attachments, &noninline_attachments);
 
-		if (namep && *namep)
-			set_value (PidTagSentRepresentingName, namep);
+	build_calendar = msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX);
+	if (build_calendar) {
+		ical_string = build_ical_string (conn, object, msg_class);
+		if (!ical_string)
+			build_calendar = FALSE;
+	}
 
-		if (addressp && *addressp) {
-			set_value (PidTagSentRepresentingAddressType, "SMTP");
-			set_value (PidTagSentRepresentingEmailAddress, addressp);
-		}
+	build_alternative = !build_calendar
+		&& e_mapi_util_find_array_propval (&object->properties, PidTagHtml)
+		&& e_mapi_util_find_array_propval (&object->properties, PidTagBody);
+	build_related = !build_calendar && !build_alternative && inline_attachments;
 
-		msg_time = camel_mime_message_get_date (message, &msg_time_offset);
-		if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
-			msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
-		if (msg_time != 0) {
-			struct FILETIME msg_date = { 0 };
+	if (build_calendar) {
+		g_return_val_if_fail (ical_string != NULL, msg);
 
-			e_mapi_util_time_t_to_filetime (msg_time, &msg_date);
+		camel_mime_part_set_content (CAMEL_MIME_PART (msg), ical_string, strlen (ical_string), "text/calendar");
+	} else if (build_alternative) {
+		multipart_body = build_multipart_alternative (object, inline_attachments);
+	} else if (build_related) {
+		multipart_body = build_multipart_related (object, inline_attachments);
+	} else if (noninline_attachments) {
+		/* Simple multipart/mixed */
+		CamelMimePart *part = camel_mime_part_new ();
 
-			set_value (PidTagMessageDeliveryTime, &msg_date);
-		}
+		multipart_body = camel_multipart_new ();
+		camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body), "multipart/mixed");
+		camel_multipart_set_boundary (multipart_body, NULL);
+		if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
+			build_body_part_content (part, object, PidTagHtml);
+		else
+			build_body_part_content (part, object, PidTagBody);
+		camel_multipart_add_part (multipart_body, part);
+		g_object_unref (part);
+	} else {
+		/* Flat message */
+		if (e_mapi_util_find_array_propval (&object->properties, PidTagHtml))
+			build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagHtml);
+		else
+			build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagBody);
+	}
 
-		headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
-		if (headers) {
-			GString *hstr = g_string_new ("");
+	if (noninline_attachments) { /* multipart/mixed */
+		if (build_alternative || build_related || build_calendar) {
+			multipart_body = build_multipart_mixed (multipart_body, noninline_attachments);
+		} else if (g_slist_length (noninline_attachments) == 1 && msg_class && strstr (msg_class, ".SMIME") > msg_class) {
+			CamelMimePart *part = noninline_attachments->data;
 
-			for (ii = 0; ii < headers->len; ii++) {
-				CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, ii);
+			skip_set_content = TRUE;
 
-				if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
-					continue;
+			camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
 
-				g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
+			if (!strstr (msg_class, ".SMIME.")) {
+				/* encrypted */
+				camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
+				camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
+			} else {
+				/* signed */
+				camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
 			}
-
-			camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
-
-			if (hstr->len && hstr->str)
-				set_value (PidTagTransportMessageHeaders, hstr->str);
-
-			g_string_free (hstr, TRUE);
+		} else {
+			add_multipart_attachments (multipart_body, noninline_attachments);
 		}
 	}
 
-	str = camel_medium_get_header ((CamelMedium *) message, "References");
-	if (str)
-		set_value (PidTagInternetReferences, str);
-
-	str = camel_medium_get_header ((CamelMedium *) message, "In-Reply-To");
-	if (str)
-		set_value (PidTagInReplyToId, str);
+	if (!skip_set_content && multipart_body)
+		camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart_body));
 
-	str = camel_medium_get_header ((CamelMedium *) message, "Message-ID");
-	if (str)
-		set_value (PidTagInternetMessageId, str);
+	if (multipart_body)
+		g_object_unref (multipart_body);
+	g_slist_free_full (inline_attachments, g_object_unref);
+	g_slist_free_full (noninline_attachments, g_object_unref);
+	g_free (ical_string);
 
-	addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
-	e_mapi_mail_add_recipients (object, addresses, olTo);
+	return msg;
+}
 
-	addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
-	e_mapi_mail_add_recipients (object, addresses, olCC);
+static void
+e_mapi_mail_add_recipients (EMapiObject *object,
+			    CamelInternetAddress *addresses,
+			    OlMailRecipientType recip_type)
+{
+	gint ii;
+	const gchar *name = NULL, *email = NULL;
 
-	addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
-	e_mapi_mail_add_recipients (object, addresses, olBCC);
+	g_return_if_fail (object != NULL);
 
-	if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") ||
-	    camel_content_type_is (content_type, "application", "pkcs7-mime")) {
-		e_mapi_mail_do_smime_encrypted (object, CAMEL_MEDIUM (message), &msg_class, &pid_name_content_type, cancellable);
-	} else {
-		CamelDataWrapper *dw = NULL;
-		CamelStream *content_stream;
-		CamelMultipart *multipart;
+	for (ii = 0; addresses && camel_internet_address_get (addresses, ii, &name, &email); ii++) {
+		EMapiRecipient *recipient;
+		uint32_t ui32 = 0;
+		bool bl;
 
-		/* contents body */
-		dw = camel_medium_get_content (CAMEL_MEDIUM (message));
-		if (CAMEL_IS_MULTIPART (dw)) {
-			gboolean is_first = TRUE;
+		recipient = e_mapi_recipient_new (object);
+		e_mapi_object_add_recipient (object, recipient);
 
-			multipart = CAMEL_MULTIPART (dw);
+		#define set_value(pt,vl) {								\
+			if (!e_mapi_utils_add_property (&recipient->properties, pt, vl, recipient)) {	\
+				g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);		\
+													\
+				return;									\
+			}										\
+		}
 
-			if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
-				e_mapi_mail_do_smime_signed (object, multipart, &msg_class, cancellable);
-			} else {
-				e_mapi_mail_do_multipart (object, multipart, &is_first, cancellable);
-			}
-		} else if (dw) {
-			CamelContentType *type;
-			CamelMimePart *part = CAMEL_MIME_PART (message);
+		ui32 = recip_type;
+		set_value (PidTagRecipientType, &ui32);
 
-			content_stream = get_content_stream (part, cancellable);
-			type = camel_data_wrapper_get_mime_type_field (dw);
+		if (!name || !*name)
+			name = email;
 
-			if (camel_content_type_is (type, "text", "plain")) {
-				e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
-			} else if (camel_content_type_is (type, "text", "html")) {
-				e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
-			} else {
-				e_mapi_mail_add_attach (object, part, content_stream, cancellable);
-			}
+		if (name && *name) {
+			set_value (PidTagDisplayName, name);
+			set_value (PidTagRecipientDisplayName, name);
+		}
+		if (email && *email) {
+			set_value (PidTagAddressType, "SMTP");
+			set_value (PidTagEmailAddress, email);
 
-			if (content_stream)
-				g_object_unref (content_stream);
+			set_value (PidTagSmtpAddress, email);
+			set_value (PidTagPrimarySmtpAddress, email);
 		}
-	}
 
-	if (msg_class)
-		set_value (PidTagMessageClass, msg_class);
+		ui32 = 0;
+		set_value (PidTagSendInternetEncoding, &ui32);
 
-	if (pid_name_content_type)
-		set_value (PidNameContentType, pid_name_content_type);
+		ui32 = DT_MAILUSER;
+		set_value (PidTagDisplayType, &ui32);
 
-	g_free (msg_class);
-	g_free (pid_name_content_type);
+		ui32 = MAPI_MAILUSER;
+		set_value (PidTagObjectType, &ui32);
 
-	*pobject = object;
+		bl = false;
+		set_value (PidTagSendRichInfo, &bl);
 
-	#undef set_value
+		#undef set_value
 
-	return TRUE;
+		name = NULL;
+		email = NULL;
+	}
 }
 
-static void
-mail_item_add_recipient (const gchar *recipients, OlMailRecipientType type, GSList **recipient_list)
+static CamelStream *
+get_content_stream (CamelMimePart *part, GCancellable *cancellable)
 {
-	ExchangeMAPIRecipient *recipient;
-	uint32_t val = 0;
-	uint8_t bVal;
-	const gchar *str = NULL;
+	CamelStream *content_stream;
+	CamelStream *filter_stream = NULL;
+	CamelMimeFilterWindows *windows = NULL;
+	CamelDataWrapper *dw;
+
+	g_return_val_if_fail (part != NULL, NULL);
+
+	dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+	g_return_val_if_fail (dw != NULL, NULL);
+
+	content_stream = camel_stream_mem_new();
 
-	if (!recipients)
-		return;
+	if (camel_mime_part_get_content_type (part)) {
+		const gchar *charset = camel_content_type_param (camel_mime_part_get_content_type (part), "charset");
 
-	recipient = g_new0 (ExchangeMAPIRecipient, 1);
+		if (charset && *charset && g_ascii_strcasecmp (charset, "utf8") != 0 && g_ascii_strcasecmp (charset, "utf-8") != 0) {
+			if (g_ascii_strncasecmp (charset, "iso-8859-", 9) == 0) {
+				CamelStream *null;
 
-	recipient->email_id = recipients;
+				/* Since a few Windows mailers like to claim they sent
+				 * out iso-8859-# encoded text when they really sent
+				 * out windows-cp125#, do some simple sanity checking
+				 * before we move on... */
 
-	/* this memory should be freed somewhere, perhaps in the existing
-	 * e_mapi_util_free_recipient_list() */
-	recipient->in.req_cValues = 2;
-	recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
+				null = camel_stream_null_new ();
+				filter_stream = camel_stream_filter_new (null);
+				g_object_unref (null);
 
-	set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_RECIPIENT_TYPE, (gconstpointer ) &type);
+				windows = (CamelMimeFilterWindows *)camel_mime_filter_windows_new (charset);
+				camel_stream_filter_add (
+					CAMEL_STREAM_FILTER (filter_stream),
+					CAMEL_MIME_FILTER (windows));
 
-	val = 0;
-	set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
+				camel_data_wrapper_decode_to_stream_sync (
+					dw, (CamelStream *)filter_stream, cancellable, NULL);
+				camel_stream_flush ((CamelStream *)filter_stream, cancellable, NULL);
+				g_object_unref (filter_stream);
 
-	/* External recipient properties - set them only when the recipient is unresolved */
-	recipient->in.ext_cValues = 8;
-	recipient->in.ext_lpProps = g_new0 (struct SPropValue, recipient->in.ext_cValues + 1);
+				charset = camel_mime_filter_windows_real_charset (windows);
+			}
 
-	val = DT_MAILUSER;
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[0]), PR_DISPLAY_TYPE, (gconstpointer )&val);
-	val = MAPI_MAILUSER;
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[1]), PR_OBJECT_TYPE, (gconstpointer )&val);
-	str = "SMTP";
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[2]), PR_ADDRTYPE_UNICODE, (gconstpointer )(str));
-	str = recipient->email_id;
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[3]), PR_SMTP_ADDRESS_UNICODE, (gconstpointer )(str));
-	/* FIXME: Please add the correct names here instead of the e-mail ID */
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[4]), PR_GIVEN_NAME_UNICODE, (gconstpointer )(str));
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[5]), PR_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[6]), PR_7BIT_DISPLAY_NAME_UNICODE, (gconstpointer )(str));
+			if (charset && *charset) {
+				CamelMimeFilter *filter;
 
-	bVal = FALSE;
-	set_SPropValue_proptag (&(recipient->in.ext_lpProps[7]), PR_SEND_RICH_INFO, &bVal);
+				filter_stream = camel_stream_filter_new (content_stream);
 
-	*recipient_list = g_slist_append (*recipient_list, recipient);
-}
+				if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
+					camel_stream_filter_add (
+						CAMEL_STREAM_FILTER (filter_stream),
+						CAMEL_MIME_FILTER (filter));
+					g_object_unref (filter);
+				} else {
+					g_object_unref (filter_stream);
+					filter_stream = NULL;
+				}
+			}
+		}
+	}
 
-static void
-mail_item_set_from(MailItem *item, const gchar *from_name, const gchar *from_email)
-{
-	if (item->header.from)
-		g_free (item->header.from);
-	if (item->header.from_email)
-		g_free (item->header.from_email);
+	if (filter_stream) {
+		camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) filter_stream, cancellable, NULL);
+		camel_stream_flush (filter_stream, cancellable, NULL);
+		g_object_unref (filter_stream);
+	} else {
+		camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+	}
 
-	item->header.from = g_strdup (from_name);
-	item->header.from_email = g_strdup (from_email);
-}
+	if (windows)
+		g_object_unref (windows);
 
-static void
-mail_item_set_subject(MailItem *item, const gchar *subject)
-{
-	if (item->header.subject)
-		g_free (item->header.subject);
+	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
 
-	item->header.subject = g_strdup (subject);
+	return content_stream;
 }
 
-#define MAX_READ_SIZE 0x1000
-
 static void
-mail_item_set_body_stream (MailItem *item, CamelStream *body, MailItemPartType part_type, GCancellable *cancellable)
+e_mapi_mail_content_stream_to_bin (CamelStream *content_stream,
+				   struct SBinary_short *bin,
+				   TALLOC_CTX *mem_ctx,
+				   GCancellable *cancellable)
 {
-	guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
-	guint32	read_size = 0, i;
-	ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
-	gboolean contains_only_7bit = TRUE, is_null_terminated = FALSE;
-
-	g_seekable_seek (G_SEEKABLE (body), 0, G_SEEK_SET, NULL, NULL);
+	guint8 *buf;
+	guint32	read_size;
 
-	stream->value = g_byte_array_new ();
+	g_return_if_fail (content_stream != NULL);
+	g_return_if_fail (bin != NULL);
+	g_return_if_fail (mem_ctx != NULL);
 
-	while (read_size = camel_stream_read (body, (gchar *)buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
-		stream->value = g_byte_array_append (stream->value, buf, read_size);
+	buf = g_new0 (guint8 , STREAM_SIZE);
 
-		is_null_terminated = buf [read_size - 1] == 0;
+	bin->cb = 0;
+	bin->lpb = NULL;
 
-		for (i = 0; i < read_size && contains_only_7bit; i++) {
-			contains_only_7bit = buf[i] < 128;
-		}
+	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
+	while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
+		bin->lpb = talloc_realloc (mem_ctx, bin->lpb, uint8_t, bin->cb + read_size);
+		memcpy (bin->lpb + bin->cb, buf, read_size);
+		bin->cb += read_size;
 	}
 
 	g_free (buf);
+}
 
-	switch (part_type) {
-	case PART_TYPE_TEXT_HTML :
-		stream->proptag = PR_HTML;
-		break;
-	case PART_TYPE_PLAIN_TEXT:
-		stream->proptag = PR_BODY_UNICODE;
-		break;
-	}
-
-	if (stream->value->len < MAX_READ_SIZE && contains_only_7bit) {
-		if (!is_null_terminated)
-			g_byte_array_append (stream->value, (const guint8 *)"", 1);
-
-		item->msg.body_parts = g_slist_append (item->msg.body_parts, stream);
-	} else if (stream->proptag == PR_HTML) {
-		/* PR_HTML shouldn't be in UTF-16 */
-		if (!is_null_terminated)
-			g_byte_array_append (stream->value, (const guint8 *)"", 1);
-
-		item->generic_streams = g_slist_append (item->generic_streams, stream);
-	} else {
-		gsize written = 0;
-		gchar *in_unicode;
-
-		if (is_null_terminated)
-			stream->value->len--;
-
-		/* convert to unicode, because stream is supposed to be in it */
-		in_unicode = g_convert ((const gchar *)stream->value->data, stream->value->len, "UTF-16", "UTF-8", NULL, &written, NULL);
-		if (in_unicode && written > 0) {
-			g_byte_array_set_size (stream->value, 0);
-			/* skip Unicode marker, if there */
-			if (written >= 2 && (const guchar) in_unicode[0] == 0xFF && (const guchar) in_unicode[1] == 0xFE)
-				g_byte_array_append (stream->value, (const guint8 *) in_unicode + 2, written - 2);
-			else
-				g_byte_array_append (stream->value, (const guint8 *) in_unicode, written);
-
-			/* null-terminated unicode string */
-			g_byte_array_append (stream->value, (const guint8 *)"", 1);
-			g_byte_array_append (stream->value, (const guint8 *)"", 1);
-		}
-		g_free (in_unicode);
-
-		item->generic_streams = g_slist_append (item->generic_streams, stream);
-	}
-
+#define set_attach_value(pt,vl) {						\
+	if (!e_mapi_utils_add_property (&attach->properties, pt, vl, attach)) {	\
+		g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);	\
+		return FALSE;							\
+	}									\
 }
 
 static gboolean
-mail_item_add_attach (MailItem *item, CamelMimePart *part, CamelStream *content_stream, GCancellable *cancellable)
+e_mapi_mail_add_attach (EMapiObject *object,
+			CamelMimePart *part,
+			CamelStream *content_stream,
+			GCancellable *cancellable)
 {
-	guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
-	const gchar *content_id = NULL;
-	guint32	read_size, flag, i = 0;
+	EMapiAttachment *attach;
 	CamelContentType *content_type;
+	const gchar *content_id;
+	const gchar *filename;
+	struct SBinary_short bin;
+	uint32_t ui32;
 
-	ExchangeMAPIAttachment *item_attach;
-	ExchangeMAPIStream *stream;
-
-	const gchar *filename = camel_mime_part_get_filename (part);
-
-	item_attach = g_new0 (ExchangeMAPIAttachment, 1);
-
-	item_attach->lpProps = g_new0 (struct SPropValue, 6 + 1);
+	g_return_val_if_fail (object != NULL, FALSE);
+	g_return_val_if_fail (part != NULL, FALSE);
+	g_return_val_if_fail (content_stream != NULL, FALSE);
 
-	flag = ATTACH_BY_VALUE;
-	set_SPropValue_proptag(&(item_attach->lpProps[i++]), PR_ATTACH_METHOD, (gconstpointer ) (&flag));
+	attach = e_mapi_attachment_new (object);
+	e_mapi_object_add_attachment (object, attach);
 
-	/* MSDN Documentation: When the supplied offset is -1 (0xFFFFFFFF), the
-	 * attachment is not rendered using the PR_RENDERING_POSITION property.
-	 * All values other than -1 indicate the position within PR_BODY at which
-	 * the attachment is to be rendered.
-	 */
-	flag = 0xFFFFFFFF;
-	set_SPropValue_proptag(&(item_attach->lpProps[i++]), PR_RENDERING_POSITION, (gconstpointer ) (&flag));
+	ui32 = ATTACH_BY_VALUE;
+	set_attach_value (PidTagAttachMethod, &ui32);
+	ui32 = -1;
+	set_attach_value (PidTagRenderingPosition, &ui32);
 
+	filename = camel_mime_part_get_filename (part);
 	if (filename) {
-		set_SPropValue_proptag(&(item_attach->lpProps[i++]),
-				       PR_ATTACH_FILENAME_UNICODE,
-				       (gconstpointer ) g_strdup(filename));
-
-		set_SPropValue_proptag(&(item_attach->lpProps[i++]),
-				       PR_ATTACH_LONG_FILENAME_UNICODE,
-				       (gconstpointer ) g_strdup(filename));
+		set_attach_value (PidTagAttachFilename, filename);
+		set_attach_value (PidTagAttachLongFilename, filename);
 	}
 
-	/* mime type : multipart/related */
 	content_id = camel_mime_part_get_content_id (part);
-	if (content_id) {
-		set_SPropValue_proptag(&(item_attach->lpProps[i++]),
-				       PR_ATTACH_CONTENT_ID,
-				       (gconstpointer ) g_strdup(content_id));
-	}
+	if (content_id)
+		set_attach_value (PidTagAttachContentId, content_id);
 
 	content_type  = camel_mime_part_get_content_type (part);
 	if (content_type) {
 		gchar *ct = camel_content_type_simple (content_type);
-		if (ct) {
-			set_SPropValue_proptag (&(item_attach->lpProps[i++]),
-					PR_ATTACH_MIME_TAG,
-					(gconstpointer ) ct);
-		}
+		if (ct)
+			set_attach_value (PidTagAttachMimeTag, ct);
+		g_free (ct);
 	}
 
-	item_attach->cValues = i;
+	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
+	set_attach_value (PidTagAttachDataBinary, &bin);
 
-	stream = g_new0 (ExchangeMAPIStream, 1);
-	stream->proptag = PR_ATTACH_DATA_BIN;
-	stream->value = g_byte_array_new ();
+	return TRUE;
+}
 
-	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
-	while (read_size = camel_stream_read(content_stream, (gchar *)buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
-		stream->value = g_byte_array_append (stream->value, buf, read_size);
-	}
+static gboolean
+e_mapi_mail_add_body (EMapiObject *object,
+		      CamelStream *content_stream,
+		      uint32_t proptag,
+		      GCancellable *cancellable)
+{
+	struct SBinary_short bin = { 0 };
+	gchar *str;
+
+	e_mapi_mail_content_stream_to_bin (content_stream, &bin, object, cancellable);
+	str = talloc_strndup (object, (const gchar *) bin.lpb, bin.cb);
+	talloc_free (bin.lpb);
 
-	item_attach->streams = g_slist_append (item_attach->streams, stream);
-	item->attachments = g_slist_append(item->attachments, item_attach);
+	if ((proptag & 0xFFFF) == PT_BINARY) {
+		bin.lpb = (uint8_t *) (str ? str : "");
+		bin.cb = strlen ((const gchar *) bin.lpb) + 1;
+		/* include trailing zero ................ ^^^ */
 
-	g_free (buf);
+		return e_mapi_utils_add_property (&object->properties, proptag, &bin, object);
+	} else if (str) {
+		if (!e_mapi_utils_add_property (&object->properties, proptag, str, object)) {
+			talloc_free (str);
+			return FALSE;
+		}
+
+		talloc_free (str);
+	} else {
+		return e_mapi_utils_add_property (&object->properties, proptag, "", object);
+	}
 
 	return TRUE;
 }
 
-static void
-mapi_do_smime_signed (MailItem *item, CamelMultipart *multipart, GCancellable *cancellable, GError **error)
+static gboolean
+e_mapi_mail_do_smime_encrypted (EMapiObject *object,
+				CamelMedium *message,
+				gchar **pmsg_class,
+				gchar **ppid_name_content_type,
+				GCancellable *cancellable)
 {
-	CamelMimePart *content, *signature;
-	ExchangeMAPIAttachment *item_attach;
-	ExchangeMAPIStream *stream;
+	EMapiAttachment *attach;
 	CamelStream *content_stream;
-	CamelContentType *type;
 	CamelDataWrapper *dw;
+	CamelContentType *type;
 	uint32_t ui32;
-	guint8 *buf;
-	guint32	read_size;
+	struct SBinary_short bin;
 	gchar *content_type_str;
 
-	g_free (item->msg_class);
-	item->msg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
-
-	content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
-	signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
-
-	g_return_if_fail (content != NULL);
-	g_return_if_fail (signature != NULL);
-
-	content_stream = get_content_stream (content, cancellable);
-	type = camel_mime_part_get_content_type (content);
-
-	if (camel_content_type_is (type, "text", "plain")) {
-		mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
-	} else if (camel_content_type_is (type, "text", "html")) {
-		mail_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML, cancellable);
-	} else {
-		mail_item_add_attach (item, content, content_stream, cancellable);
-	}
+	g_return_val_if_fail (object != NULL, FALSE);
+	g_return_val_if_fail (message != NULL, FALSE);
+	g_return_val_if_fail (pmsg_class != NULL, FALSE);
+	g_return_val_if_fail (ppid_name_content_type != NULL, FALSE);
 
-	if (content_stream)
-		g_object_unref (content_stream);
+	g_free (*pmsg_class);
+	*pmsg_class = g_strdup ("IPM.Note.SMIME");
 
-	content_stream = camel_stream_mem_new ();
-	dw = CAMEL_DATA_WRAPPER (multipart);
-	type = camel_data_wrapper_get_mime_type_field (dw);
+	type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
+	dw = camel_medium_get_content (message);
 	content_type_str = camel_content_type_format (type);
 
-	#define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
-	wstr("Content-Type: ");
-	wstr(content_type_str);
-	wstr("\n\n");
-	#undef wstr
-
-	g_free (content_type_str);
+	g_free (*ppid_name_content_type);
+	*ppid_name_content_type = content_type_str; /* will be freed within the caller */
 
-	camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+	content_stream = camel_stream_mem_new ();
+	camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
 
-	item_attach = g_new0 (ExchangeMAPIAttachment, 1);
-	item_attach->lpProps = g_new0 (struct SPropValue, 6 + 1);
-	item_attach->cValues = 6;
+	attach = e_mapi_attachment_new (object);
+	e_mapi_object_add_attachment (object, attach);
 
 	ui32 = ATTACH_BY_VALUE;
-	set_SPropValue_proptag (&(item_attach->lpProps[0]), PR_ATTACH_METHOD, &ui32);
+	set_attach_value (PidTagAttachMethod, &ui32);
 	ui32 = -1;
-	set_SPropValue_proptag (&(item_attach->lpProps[1]), PR_RENDERING_POSITION, &ui32);
-	set_SPropValue_proptag (&(item_attach->lpProps[2]), PR_ATTACH_MIME_TAG, "multipart/signed");
-	set_SPropValue_proptag (&(item_attach->lpProps[3]), PR_ATTACH_FILENAME_UNICODE, "SMIME.txt");
-	set_SPropValue_proptag (&(item_attach->lpProps[4]), PR_ATTACH_LONG_FILENAME_UNICODE, "SMIME.txt");
-	set_SPropValue_proptag (&(item_attach->lpProps[5]), PR_DISPLAY_NAME_UNICODE, "SMIME.txt");
-
-	stream = g_new0 (ExchangeMAPIStream, 1);
-	stream->proptag = PR_ATTACH_DATA_BIN;
-	stream->value = g_byte_array_new ();
-
-	buf = g_new0 (guint8 , STREAM_SIZE);
+	set_attach_value (PidTagRenderingPosition, &ui32);
+	set_attach_value (PidTagAttachMimeTag, content_type_str);
+	set_attach_value (PidTagAttachFilename, "SMIME.txt");
+	set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
+	set_attach_value (PidTagDisplayName, "SMIME.txt");
 
-	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
-	while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
-		stream->value = g_byte_array_append (stream->value, buf, read_size);
-	}
+	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
+	set_attach_value (PidTagAttachDataBinary, &bin);
 
-	g_free (buf);
 	g_object_unref (content_stream);
 
-	item_attach->streams = g_slist_append (item_attach->streams, stream);
-	item->attachments = g_slist_append (item->attachments, item_attach);
+	return TRUE;
 }
 
-static void
-mapi_do_smime_encrypted (MailItem *item, CamelMedium *message, GCancellable *cancellable, GError **error)
+static gboolean
+e_mapi_mail_do_smime_signed (EMapiObject *object,
+			     CamelMultipart *multipart,
+			     gchar **pmsg_class,
+			     GCancellable *cancellable)
 {
-	ExchangeMAPIAttachment *item_attach;
-	ExchangeMAPIStream *stream;
+	EMapiAttachment *attach;
+	CamelMimePart *content, *signature;
 	CamelStream *content_stream;
-	CamelDataWrapper *dw;
 	CamelContentType *type;
+	CamelDataWrapper *dw;
 	uint32_t ui32;
-	guint8 *buf;
-	guint32	read_size;
+	struct SBinary_short bin;
 	gchar *content_type_str;
 
-	g_free (item->msg_class);
-	item->msg_class = g_strdup ("IPM.Note.SMIME");
+	g_free (*pmsg_class);
+	*pmsg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
 
-	type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
-	dw = camel_medium_get_content (message);
+	content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
+	signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
+
+	g_return_val_if_fail (content != NULL, FALSE);
+	g_return_val_if_fail (signature != NULL, FALSE);
+
+	content_stream = get_content_stream (content, cancellable);
+	type = camel_mime_part_get_content_type (content);
+
+	if (camel_content_type_is (type, "text", "plain")) {
+		e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
+	} else if (camel_content_type_is (type, "text", "html")) {
+		e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
+	} else {
+		e_mapi_mail_add_attach (object, content, content_stream, cancellable);
+	}
+
+	if (content_stream)
+		g_object_unref (content_stream);
 
+	content_stream = camel_stream_mem_new ();
+	dw = CAMEL_DATA_WRAPPER (multipart);
+	type = camel_data_wrapper_get_mime_type_field (dw);
 	content_type_str = camel_content_type_format (type);
 
-	g_free (item->pid_name_content_type);
-	item->pid_name_content_type = content_type_str; /* will be freed with the MailItem structure */
+	#define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
+	wstr("Content-Type: ");
+	wstr(content_type_str);
+	wstr("\n\n");
+	#undef wstr
+
+	g_free (content_type_str);
 
-	content_stream = camel_stream_mem_new ();
-	camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
+	camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
 
-	item_attach = g_new0 (ExchangeMAPIAttachment, 1);
-	item_attach->lpProps = g_new0 (struct SPropValue, 6 + 1);
-	item_attach->cValues = 6;
+	attach = e_mapi_attachment_new (object);
+	e_mapi_object_add_attachment (object, attach);
 
 	ui32 = ATTACH_BY_VALUE;
-	set_SPropValue_proptag (&(item_attach->lpProps[0]), PR_ATTACH_METHOD, &ui32);
+	set_attach_value (PidTagAttachMethod, &ui32);
 	ui32 = -1;
-	set_SPropValue_proptag (&(item_attach->lpProps[1]), PR_RENDERING_POSITION, &ui32);
-	set_SPropValue_proptag (&(item_attach->lpProps[2]), PR_ATTACH_MIME_TAG, content_type_str);
-	set_SPropValue_proptag (&(item_attach->lpProps[3]), PR_ATTACH_FILENAME_UNICODE, "SMIME.txt");
-	set_SPropValue_proptag (&(item_attach->lpProps[4]), PR_ATTACH_LONG_FILENAME_UNICODE, "SMIME.txt");
-	set_SPropValue_proptag (&(item_attach->lpProps[5]), PR_DISPLAY_NAME_UNICODE, "SMIME.txt");
-
-	stream = g_new0 (ExchangeMAPIStream, 1);
-	stream->proptag = PR_ATTACH_DATA_BIN;
-	stream->value = g_byte_array_new ();
-
-	buf = g_new0 (guint8 , STREAM_SIZE);
+	set_attach_value (PidTagRenderingPosition, &ui32);
+	set_attach_value (PidTagAttachMimeTag, "multipart/signed");
+	set_attach_value (PidTagAttachFilename, "SMIME.txt");
+	set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
+	set_attach_value (PidTagDisplayName, "SMIME.txt");
 
-	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
-	while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
-		stream->value = g_byte_array_append (stream->value, buf, read_size);
-	}
+	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
+	set_attach_value (PidTagAttachDataBinary, &bin);
 
-	g_free (buf);
 	g_object_unref (content_stream);
 
-	item_attach->streams = g_slist_append (item_attach->streams, stream);
-	item->attachments = g_slist_append (item->attachments, item_attach);
+	return TRUE;
 }
 
 static gboolean
-mapi_do_multipart (CamelMultipart *mp, MailItem *item, gboolean *is_first, GCancellable *cancellable)
+e_mapi_mail_do_multipart (EMapiObject *object,
+			  CamelMultipart *mp,
+			  gboolean *is_first,
+			  GCancellable *cancellable)
 {
 	CamelDataWrapper *dw;
 	CamelStream *content_stream;
 	CamelContentType *type;
 	CamelMimePart *part;
-	gint n_part, i_part;
+	gint nn, ii;
 
 	g_return_val_if_fail (is_first != NULL, FALSE);
 
-	n_part = camel_multipart_get_number(mp);
-	for (i_part = 0; i_part < n_part; i_part++) {
+	nn = camel_multipart_get_number (mp);
+	for (ii = 0; ii < nn; ii++) {
 		/* getting part */
-		part = camel_multipart_get_part(mp, i_part);
+		part = camel_multipart_get_part (mp, ii);
+		if (!part)
+			continue;
+
 		dw = camel_medium_get_content (CAMEL_MEDIUM (part));
-		if (CAMEL_IS_MULTIPART(dw)) {
+		if (CAMEL_IS_MULTIPART (dw)) {
 			/* recursive */
-			if (!mapi_do_multipart (CAMEL_MULTIPART (dw), item, is_first, cancellable))
+			if (!e_mapi_mail_do_multipart (object, CAMEL_MULTIPART (dw), is_first, cancellable))
 				return FALSE;
 			continue;
 		}
 
 		if (CAMEL_IS_MIME_MESSAGE (dw)) {
 			CamelMimeMessage *message;
-			CamelInternetAddress *message_from;
-			CamelAddress *use_from = NULL;
-			MailItem *mail;
+			EMapiObject *embedded = NULL;
+			EMapiAttachment *attach;
 
+			attach = e_mapi_attachment_new (object);
 			message = CAMEL_MIME_MESSAGE (dw);
-			message_from = camel_mime_message_get_from (message);
-			if (message_from)
-				use_from = CAMEL_ADDRESS (message_from);
-			mail = mapi_mime_message_to_mail_item (message, 0, use_from, cancellable, NULL);
-			if (mail) {
-				ExchangeMAPIAttachment *item_attach = g_new0 (ExchangeMAPIAttachment, 1);
+			if (e_mapi_mail_utils_message_to_object (message, 0, E_MAPI_CREATE_FLAG_NONE, &embedded, attach, cancellable, NULL)) {
+				uint32_t ui32;
+				const gchar *str;
+
+				e_mapi_object_add_attachment (object, attach);
+				attach->embedded_object = embedded;
+				embedded->parent = object;
 
-				item_attach->mail = mail;
-				item->attachments = g_slist_append (item->attachments, item_attach);
+				ui32 = ATTACH_EMBEDDED_MSG;
+				set_attach_value (PidTagAttachMethod, &ui32);
+				ui32 = 0;
+				set_attach_value (PidTagRenderingPosition, &ui32);
+				set_attach_value (PidTagAttachMimeTag, "message/rfc822");
 
+				str = camel_mime_message_get_subject (message);
+				if (str)
+					set_attach_value (PidTagAttachFilename, str);
 				continue;
+			} else {
+				e_mapi_attachment_free (attach);
 			}
 		}
 
 		content_stream = get_content_stream (part, cancellable);
+		type = camel_mime_part_get_content_type (part);
 
-		type = camel_mime_part_get_content_type(part);
-
-		if (i_part == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
-			mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
+		if (ii == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
+			e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
 			*is_first = FALSE;
 		} else if (camel_content_type_is (type, "text", "html")) {
-			mail_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML, cancellable);
+			e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
 		} else {
-			mail_item_add_attach (item, part, content_stream, cancellable);
+			e_mapi_mail_add_attach (object, part, content_stream, cancellable);
 		}
 
 		if (content_stream)
@@ -2839,225 +1270,201 @@ mapi_do_multipart (CamelMultipart *mp, MailItem *item, gboolean *is_first, GCanc
 	return TRUE;
 }
 
-static void
-mail_item_set_time (time_t *item_time, time_t camel_time, gint camel_offset)
-{
-	if (camel_time == CAMEL_MESSAGE_DATE_CURRENT) {
-		*item_time = 0;
-	} else {
-		/* Convert to UTC */
-		/*camel_time -= (camel_offset / 100) * 60 * 60;
-		camel_time -= (camel_offset % 100) * 60;*/
-		*item_time = camel_time;
-	}
-}
+#undef set_attach_value
 
-MailItem *
-mapi_mime_message_to_mail_item (CamelMimeMessage *message, gint32 message_camel_flags, CamelAddress *from, GCancellable *cancellable, GError **error)
+gboolean
+e_mapi_mail_utils_message_to_object (struct _CamelMimeMessage *message,
+				     guint32 message_camel_flags,
+				     EMapiCreateFlags create_flags,
+				     EMapiObject **pobject,
+				     TALLOC_CTX *mem_ctx,
+				     GCancellable *cancellable,
+				     GError **perror)
 {
-	CamelDataWrapper *dw = NULL;
-	CamelStream *content_stream;
-	CamelMultipart *multipart;
+	EMapiObject *object;
 	CamelContentType *content_type;
-	CamelInternetAddress *to, *cc, *bcc;
-	MailItem *item = g_new0 (MailItem, 1);
-	const gchar *namep = NULL;
-	const gchar *addressp = NULL;
-	time_t msg_time = 0;
-	gint msg_time_offset = 0;
-	GArray *headers;
+	CamelInternetAddress *addresses;
+	const gchar *namep = NULL, *addressp = NULL;
+	const gchar *str;
+	gchar *msg_class = NULL;
+	gchar *pid_name_content_type = NULL;
+	gint ii = 0;
+	uint32_t ui32;
+	bool bl;
 
-	GSList *recipient_list = NULL;
-	gint i = 0;
+	g_return_val_if_fail (message != NULL, FALSE);
+	g_return_val_if_fail (pobject != NULL, FALSE);
+	g_return_val_if_fail (*pobject == NULL, FALSE);
+	g_return_val_if_fail (mem_ctx != NULL, FALSE);
 
-	/* headers */
+	content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
+	g_return_val_if_fail (content_type != NULL, FALSE);
 
-	if (from) {
-		if (!camel_internet_address_get ((CamelInternetAddress *)from, 0, &namep, &addressp)) {
-			g_warning ("%s: Invalid 'from' passed in", G_STRFUNC);
-			g_free (item);
-			return NULL;
-		}
-	} else {
+	/* headers */
+	if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
 		/* though invalid, then possible, to pass in a message without any 'from' */
-		namep = NULL;
+		CamelInternetAddress *from = camel_mime_message_get_from (message);
+		if (!from || !camel_internet_address_get (from, 0, &namep, &addressp))
+			namep = NULL;
 	}
 
-	item->header.flags = 0;
-	if (message_camel_flags & CAMEL_MESSAGE_SEEN)
-		item->header.flags |= MSGFLAG_READ;
-	if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
-		item->header.flags |= MSGFLAG_HASATTACH;
-
-	mail_item_set_from (item, namep, addressp);
-
-	msg_time = camel_mime_message_get_date (message, &msg_time_offset);
-	if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
-		msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
-	mail_item_set_time (&item->header.recieved_time, msg_time, msg_time_offset);
+	object = e_mapi_object_new (mem_ctx);
 
-	to = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_TO);
-	for (i = 0; to && camel_internet_address_get (to, i, &namep, &addressp); i++) {
-		mail_item_add_recipient (addressp, olTo, &recipient_list);
+	#define set_value(pt,vl) {							\
+		if (!e_mapi_utils_add_property (&object->properties, pt, vl, object)) {	\
+			e_mapi_object_free (object);					\
+			g_free (msg_class);						\
+			g_free (pid_name_content_type);					\
+											\
+			g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);	\
+											\
+			return FALSE;							\
+		}									\
 	}
 
-	cc = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_CC);
-	for (i = 0; cc && camel_internet_address_get (cc, i, &namep, &addressp); i++) {
-		mail_item_add_recipient (addressp, olCC, &recipient_list);
-	}
+	ui32 = 65001; /* UTF8 - also used with PR_HTML */
+	set_value (PidTagInternetCodepage, &ui32);
 
-	bcc = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_BCC);
-	for (i = 0; bcc && camel_internet_address_get (bcc, i, &namep, &addressp); i++) {
-		mail_item_add_recipient (addressp, olBCC, &recipient_list);
+	if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
+		ui32 = 0;
+		if (message_camel_flags & CAMEL_MESSAGE_SEEN)
+			ui32 |= MSGFLAG_READ;
+		if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
+			ui32 |= MSGFLAG_HASATTACH;
+	} else {
+		ui32 = MSGFLAG_UNSENT;
 	}
+	set_value (PidTagMessageFlags, &ui32);
 
-	if (camel_mime_message_get_subject(message)) {
-		mail_item_set_subject(item, camel_mime_message_get_subject(message));
-	}
+	bl = false;
+	set_value (PidTagSendRichInfo, &bl);
 
-	headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
-	if (headers) {
-		GString *hstr = g_string_new ("");
-		gint i;
+	/* PidTagConversationTopic and PidTagNormalizedSubject, together with PidTagSubjectPrefix
+	   are computed from PidTagSubject by a server */
+	str = camel_mime_message_get_subject (message);
+	if (str)
+		set_value (PidTagSubject, str);
 
-		for (i = 0; i < headers->len; i++) {
-			CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, i);
+	/* some properties may not be set when submitting a message */
+	if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
+		time_t msg_time = 0;
+		gint msg_time_offset = 0;
+		GArray *headers;
 
-			if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
-				continue;
+		if (namep && *namep)
+			set_value (PidTagSentRepresentingName, namep);
 
-			g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
+		if (addressp && *addressp) {
+			set_value (PidTagSentRepresentingAddressType, "SMTP");
+			set_value (PidTagSentRepresentingEmailAddress, addressp);
 		}
 
-		camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
-
-		item->header.transport_headers = g_string_free (hstr, hstr->len == 0);
-	}
-
-	/*Add message threading properties */
-	item->header.references = g_strdup (camel_medium_get_header ((CamelMedium *) message, "References"));
-	item->header.in_reply_to = g_strdup (camel_medium_get_header ((CamelMedium *) message, "In-Reply-To"));
-	item->header.message_id = g_strdup (camel_medium_get_header ((CamelMedium *) message, "Message-ID"));
+		msg_time = camel_mime_message_get_date (message, &msg_time_offset);
+		if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
+			msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
+		if (msg_time != 0) {
+			struct FILETIME msg_date = { 0 };
 
-	item->recipients = recipient_list;
+			e_mapi_util_time_t_to_filetime (msg_time, &msg_date);
 
-	content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
-	g_return_val_if_fail (content_type != NULL, item);
+			set_value (PidTagMessageDeliveryTime, &msg_date);
+		}
 
-	if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") || camel_content_type_is (content_type, "application", "pkcs7-mime")) {
-		mapi_do_smime_encrypted (item, CAMEL_MEDIUM (message), cancellable, error);
-	} else {
-		/* contents body */
-		dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+		headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
+		if (headers) {
+			GString *hstr = g_string_new ("");
 
-		if (CAMEL_IS_MULTIPART (dw)) {
-			gboolean is_first = TRUE;
+			for (ii = 0; ii < headers->len; ii++) {
+				CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, ii);
 
-			multipart = CAMEL_MULTIPART (dw);
+				if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
+					continue;
 
-			if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
-				mapi_do_smime_signed (item, multipart, cancellable, error);
-			} else {
-				mapi_do_multipart (multipart, item, &is_first, cancellable);
+				g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
 			}
-		} else if (dw) {
-			content_stream = get_content_stream ((CamelMimePart *) message, cancellable);
 
-			mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
+			camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
+
+			if (hstr->len && hstr->str)
+				set_value (PidTagTransportMessageHeaders, hstr->str);
 
-			if (content_stream)
-				g_object_unref (content_stream);
+			g_string_free (hstr, TRUE);
 		}
 	}
 
-	return item;
-}
+	str = camel_medium_get_header ((CamelMedium *) message, "References");
+	if (str)
+		set_value (PidTagInternetReferences, str);
 
-gboolean
-mapi_mail_utils_create_item_build_props (EMapiConnection *conn,
-					 mapi_id_t fid,
-					 TALLOC_CTX *mem_ctx,
-					 struct SPropValue **values,
-					 uint32_t *n_values,
-					 gpointer data,
-					 GCancellable *cancellable,
-					 GError **perror)
-{
+	str = camel_medium_get_header ((CamelMedium *) message, "In-Reply-To");
+	if (str)
+		set_value (PidTagInReplyToId, str);
 
-	MailItem *item = (MailItem *) data;
-	GSList *l;
-	bool send_rich_info;
-	uint32_t cpid;
+	str = camel_medium_get_header ((CamelMedium *) message, "Message-ID");
+	if (str)
+		set_value (PidTagInternetMessageId, str);
 
-	#define set_value(hex, val) G_STMT_START { \
-		if (!e_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, val)) \
-			return FALSE;	\
-		} G_STMT_END
+	addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
+	e_mapi_mail_add_recipients (object, addresses, olTo);
 
-	if (item->msg_class) {
-		set_value (PR_MESSAGE_CLASS, item->msg_class);
-	}
-	
-	if (item->pid_name_content_type) {
-		if (!e_mapi_utils_add_spropvalue_namedid (conn, fid, mem_ctx, values, n_values, PidNameContentType, item->pid_name_content_type, cancellable, perror))
-			return FALSE;
-	}
+	addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
+	e_mapi_mail_add_recipients (object, addresses, olCC);
 
-	cpid = 65001; /* UTF8 - also used with PR_HTML */
-	set_value (PR_INTERNET_CPID, &cpid);
-	set_value (PR_SUBJECT_UNICODE, item->header.subject);
-	/* PR_CONVERSATION_TOPIC_UNICODE and PR_NORMALIZED_SUBJECT_UNICODE, together with PR_SUBJECT_PREFIX_UNICODE
-	   are computed from PR_SUBJECT by the server */
+	addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
+	e_mapi_mail_add_recipients (object, addresses, olBCC);
 
-	send_rich_info = false;
-	set_value (PR_SEND_RICH_INFO, &send_rich_info);
+	if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") ||
+	    camel_content_type_is (content_type, "application", "pkcs7-mime")) {
+		e_mapi_mail_do_smime_encrypted (object, CAMEL_MEDIUM (message), &msg_class, &pid_name_content_type, cancellable);
+	} else {
+		CamelDataWrapper *dw = NULL;
+		CamelStream *content_stream;
+		CamelMultipart *multipart;
 
-	set_value (PR_MESSAGE_FLAGS, &item->header.flags);
+		/* contents body */
+		dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+		if (CAMEL_IS_MULTIPART (dw)) {
+			gboolean is_first = TRUE;
 
-	if (item->header.from && *item->header.from)
-		set_value (PR_SENT_REPRESENTING_NAME_UNICODE, item->header.from);
+			multipart = CAMEL_MULTIPART (dw);
 
-	if (item->header.from_email && *item->header.from_email) {
-		set_value (PR_SENT_REPRESENTING_ADDRTYPE_UNICODE, "SMTP");
-		set_value (PR_SENT_REPRESENTING_EMAIL_ADDRESS_UNICODE, item->header.from_email);
-	}
+			if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
+				e_mapi_mail_do_smime_signed (object, multipart, &msg_class, cancellable);
+			} else {
+				e_mapi_mail_do_multipart (object, multipart, &is_first, cancellable);
+			}
+		} else if (dw) {
+			CamelContentType *type;
+			CamelMimePart *part = CAMEL_MIME_PART (message);
 
-	if (item->header.recieved_time != 0) {
-		struct FILETIME msg_date = { 0 };
+			content_stream = get_content_stream (part, cancellable);
+			type = camel_data_wrapper_get_mime_type_field (dw);
 
-		e_mapi_util_time_t_to_filetime (item->header.recieved_time, &msg_date);
+			if (camel_content_type_is (type, "text", "plain")) {
+				e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
+			} else if (camel_content_type_is (type, "text", "html")) {
+				e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
+			} else {
+				e_mapi_mail_add_attach (object, part, content_stream, cancellable);
+			}
 
-		set_value (PR_MESSAGE_DELIVERY_TIME, &msg_date);
+			if (content_stream)
+				g_object_unref (content_stream);
+		}
 	}
 
-	if (item->header.transport_headers && *item->header.transport_headers)
-		set_value (PR_TRANSPORT_MESSAGE_HEADERS_UNICODE, item->header.transport_headers);
-
-	/* Message threading information */
-	if (item->header.references)
-		set_value (PR_INTERNET_REFERENCES, item->header.references);
-
-	if (item->header.in_reply_to)
-		set_value (PR_IN_REPLY_TO_ID, item->header.in_reply_to);
+	if (msg_class)
+		set_value (PidTagMessageClass, msg_class);
 
-	if (item->header.message_id)
-		set_value (PR_INTERNET_MESSAGE_ID, item->header.message_id);
+	if (pid_name_content_type)
+		set_value (PidNameContentType, pid_name_content_type);
 
-	for (l = item->msg.body_parts; l; l = l->next) {
-		ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
-		struct SBinary_short *bin = g_new0 (struct SBinary_short, 1);
+	g_free (msg_class);
+	g_free (pid_name_content_type);
 
-		bin->cb = stream->value->len;
-		bin->lpb = (uint8_t *)stream->value->data;
-		if (stream->proptag == PR_HTML)
-			set_value (stream->proptag, bin);
-		else if (stream->proptag == PR_BODY_UNICODE)
-			set_value (stream->proptag, stream->value->data);
-	}
+	*pobject = object;
 
-	/*  FIXME : */
-	/* editor = EDITOR_FORMAT_PLAINTEXT; */
-	/* set_value (PR_MSG_EDITOR_FORMAT, &editor); */
+	#undef set_value
 
 	return TRUE;
 }
diff --git a/src/libexchangemapi/e-mapi-mail-utils.h b/src/libexchangemapi/e-mapi-mail-utils.h
index 01518fc..1cf2357 100644
--- a/src/libexchangemapi/e-mapi-mail-utils.h
+++ b/src/libexchangemapi/e-mapi-mail-utils.h
@@ -31,77 +31,9 @@
 
 #include <e-mapi-connection.h>
 
-typedef enum  {
-	PART_TYPE_PLAIN_TEXT=1,
-	PART_TYPE_TEXT_HTML
-} MailItemPartType;
-
-typedef struct {
-	gchar *subject;
-	gchar *from;
-	gchar *from_email;
-	gchar *from_type;
-
-	gchar *references;
-	gchar *message_id;
-	gchar *in_reply_to;
-	/*TODO : Obsolete this. Moved to recipient list*/
-	gchar *to;
-	gchar *cc;
-	gchar *bcc;
-
-	gint flags;
-	glong size;
-	time_t recieved_time;
-	time_t send_time;
-	guint cpid; /* codepage id */
-	gchar *transport_headers;
-	gchar *content_class;
-} MailItemHeader;
-
-typedef struct {
-	GSList *body_parts;
-} MailItemMessage;
-
-typedef struct _MailItem {
-	mapi_id_t fid;
-	mapi_id_t mid;
-	gchar *msg_class;
-	gchar *pid_name_content_type; /* for PidNameContentType */
-
-	MailItemHeader header;
-	MailItemMessage msg;
-
-	gboolean is_cal;
-
-	GSList *recipients;
-	GSList *attachments;
-	GSList *generic_streams;
-} MailItem;
-
-void mail_item_free (MailItem *item);
-
-/* fetch callback, the 'data' is pointer to a MailItem pointer, where new MailItem will be placed */
-gboolean fetch_props_to_mail_item_cb (FetchItemsCallbackData *item_data,
-				      gpointer data,
-				      GCancellable *cancellable,
-				      GError **perror);
-
-/* returns TRUE when filled an entry in the MailItem based on the propTag and its value */
-gboolean fetch_read_item_common_data (MailItem *item, uint32_t propTag, gconstpointer prop_data);
-
-gboolean mapi_mail_get_item_prop_list (EMapiConnection *conn,
-				       mapi_id_t fid,
-				       TALLOC_CTX *mem_ctx,
-				       struct SPropTagArray *props, gpointer data,
-				       GCancellable *cancellable,
-				       GError **perror);
-
 struct _CamelAddress;
 struct _CamelMimeMessage;
 
-struct _CamelMimeMessage *mapi_mail_item_to_mime_message (EMapiConnection *conn, MailItem *item);
-
 struct _CamelMimeMessage *e_mapi_mail_utils_object_to_message	(EMapiConnection *conn,
 								 /* const */ EMapiObject *object);
 
@@ -136,16 +68,4 @@ void			e_mapi_mail_utils_decode_recipients	(EMapiConnection *conn,
 								 struct _CamelAddress *cc,
 								 struct _CamelAddress *bcc);
 
-MailItem *mapi_mime_message_to_mail_item (struct _CamelMimeMessage *message, gint32 message_camel_flags, struct _CamelAddress *from, GCancellable *cancellable, GError **error);
-
-/* uses MailItem * as 'data' pointer */
-gboolean  mapi_mail_utils_create_item_build_props (EMapiConnection *conn,
-						   mapi_id_t fid,
-						   TALLOC_CTX *mem_ctx,
-						   struct SPropValue **values,
-						   uint32_t *n_values,
-						   gpointer data,
-						   GCancellable *cancellable,
-						   GError **perror);
-
 #endif /* E_MAPI_MAIL_UTILS */
diff --git a/src/libexchangemapi/e-mapi-utils.c b/src/libexchangemapi/e-mapi-utils.c
index 2a25502..dbda865 100644
--- a/src/libexchangemapi/e-mapi-utils.c
+++ b/src/libexchangemapi/e-mapi-utils.c
@@ -106,25 +106,6 @@ e_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t pro
 	return (get_SPropValue(values, proptag));
 }
 
-gconstpointer
-e_mapi_util_find_SPropVal_array_namedid (struct SPropValue *values, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
-	uint32_t proptag;
-	gconstpointer res = NULL;
-
-	g_return_val_if_fail (values != NULL, NULL);
-	g_return_val_if_fail (conn != NULL, NULL);
-
-	proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
-	if (proptag != MAPI_E_RESERVED)
-		res = e_mapi_util_find_SPropVal_array_propval (values, proptag);
-
-	if (!res)
-		res = e_mapi_util_find_SPropVal_array_propval (values, namedid);
-
-	return res;
-}
-
 /*
  * Retrieve the property value for a given SRow and property tag.
  *
@@ -277,129 +258,6 @@ e_mapi_util_find_array_datetime_propval (struct timeval *tv, struct mapi_SPropVa
 	return get_mapi_SPropValue_array_date_timeval (tv, properties, proptag);
 }
 
-enum MAPISTATUS
-e_mapi_util_find_array_datetime_namedid (struct timeval *tv, struct mapi_SPropValue_array *properties, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
-	enum MAPISTATUS res = MAPI_E_NOT_FOUND;
-	uint32_t proptag;
-
-	g_return_val_if_fail (tv != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (properties != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
-
-	proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
-	if (proptag != MAPI_E_RESERVED)
-		res = e_mapi_util_find_array_datetime_propval (tv, properties, proptag);
-
-	if (res == MAPI_E_NOT_FOUND)
-		res = e_mapi_util_find_array_datetime_propval (tv, properties, namedid);
-
-	return res;
-}
-
-ExchangeMAPIStream *
-e_mapi_util_find_stream (GSList *stream_list, uint32_t proptag)
-{
-	GSList *l = stream_list;
-
-	for (; l != NULL; l = l->next) {
-		ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
-		if (stream->proptag == proptag)
-			return stream;
-	}
-
-	return NULL;
-}
-
-ExchangeMAPIStream *
-e_mapi_util_find_stream_namedid (GSList *stream_list, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid)
-{
-	uint32_t proptag;
-	gconstpointer res = NULL;
-
-	g_return_val_if_fail (conn != NULL, NULL);
-
-	if (!stream_list)
-		return NULL;
-
-	proptag = e_mapi_connection_resolve_named_prop (conn, fid, namedid, NULL, NULL);
-	if (proptag != MAPI_E_RESERVED)
-		res = e_mapi_util_find_stream (stream_list, proptag);
-
-	if (!res)
-		res = e_mapi_util_find_stream (stream_list, namedid);
-
-	return (ExchangeMAPIStream *) res;
-}
-
-void
-e_mapi_util_free_attachment_list (GSList **attach_list)
-{
-	GSList *l = *attach_list;
-
-	if (!l)
-		return;
-
-	for (; l != NULL; l = l->next) {
-		ExchangeMAPIAttachment *attachment = (ExchangeMAPIAttachment *) (l->data);
-
-		if (attachment->mail) {
-			mail_item_free (attachment->mail);
-		} else {
-			g_free (attachment->lpProps);
-			e_mapi_util_free_stream_list (&(attachment->streams));
-		}
-
-		g_free (attachment);
-		l->data = NULL;
-	}
-	g_slist_free (*attach_list);
-	*attach_list = NULL;
-}
-
-void
-e_mapi_util_free_recipient_list (GSList **recip_list)
-{
-	GSList *l = *recip_list;
-
-	if (!l)
-		return;
-
-	for (; l != NULL; l = l->next) {
-		ExchangeMAPIRecipient *recipient = (ExchangeMAPIRecipient *) (l->data);
-
-		talloc_free (recipient->mem_ctx);
-		if (recipient->in.ext_cValues)
-			g_free (recipient->in.ext_lpProps);
-		if (recipient->in.req_cValues)
-			g_free (recipient->in.req_lpProps);
-/*		if (recipient->out_SRow.cValues)
-			g_free (recipient->out_SRow.lpProps);
-*/		g_free (recipient);
-	}
-	g_slist_free (*recip_list);
-	*recip_list = NULL;
-}
-
-void
-e_mapi_util_free_stream_list (GSList **stream_list)
-{
-	GSList *l = *stream_list;
-
-	if (!l)
-		return;
-
-	for (; l != NULL; l = l->next) {
-		ExchangeMAPIStream *stream = (ExchangeMAPIStream *) (l->data);
-		g_byte_array_free (stream->value, TRUE);
-		stream->value = NULL;
-		g_free (stream);
-		stream = NULL;
-	}
-	g_slist_free (*stream_list);
-	*stream_list = NULL;
-}
-
 static void
 e_mapi_util_bin_append_uint16 (TALLOC_CTX *mem_ctx, struct Binary_r *bin, const uint16_t val)
 {
@@ -770,69 +628,6 @@ e_mapi_util_recip_entryid_decode (EMapiConnection *conn, const struct Binary_r *
 }
 
 /**
- * exchange_lf_to_crlf:
- * @in: input text in UNIX ("\n") format
- *
- * Creates a copy of @in with all LFs converted to CRLFs.
- *
- * Return value: the converted text, which the caller must free.
- **/
-gchar *
-exchange_lf_to_crlf (const gchar *in)
-{
-	gint len;
-	const gchar *s;
-	gchar *out, *d;
-
-	g_return_val_if_fail (in != NULL, NULL);
-
-	len = strlen (in);
-	for (s = strchr (in, '\n'); s; s = strchr (s + 1, '\n'))
-		len++;
-
-	out = g_malloc (len + 1);
-	for (s = in, d = out; *s; s++) {
-		if (*s == '\n')
-			*d++ = '\r';
-		*d++ = *s;
-	}
-	*d = '\0';
-
-	return out;
-}
-
-/**
- * exchange_crlf_to_lf:
- * @in: input text in network ("\r\n") format
- *
- * Creates a copy of @in with all CRLFs converted to LFs. (Actually,
- * it just strips CRs, so any raw CRs will be removed.)
- *
- * Return value: the converted text, which the caller must free.
- **/
-gchar *
-exchange_crlf_to_lf (const gchar *in)
-{
-	const gchar *s;
-	gchar *out;
-	GString *str;
-
-	g_return_val_if_fail (in != NULL, NULL);
-
-	str = g_string_new ("");
-
-	for (s = in; *s; s++) {
-		if (*s != '\r')
-			str = g_string_append_c (str, *s);
-	}
-
-	out = str->str;
-	g_string_free (str, FALSE);
-
-	return out;
-}
-
-/**
  * e_mapi_util_profiledata_from_settings:
  * @empd: destination for profile settings
  * @settings: a #CamelMapiSettings
@@ -1359,7 +1154,6 @@ e_mapi_utils_ensure_utf8_string (uint32_t proptag,
 */
 gboolean
 e_mapi_utils_build_last_modify_restriction (EMapiConnection *conn,
-					    mapi_id_t fid,
 					    TALLOC_CTX *mem_ctx,
 					    struct mapi_SRestriction **restrictions,
 					    gpointer user_data,
@@ -1396,7 +1190,6 @@ e_mapi_utils_build_last_modify_restriction (EMapiConnection *conn,
 
 gboolean
 e_mapi_utils_get_folder_basic_properties_cb (EMapiConnection *conn,
-					     mapi_id_t fid,
 					     TALLOC_CTX *mem_ctx,
 					     /* const */ struct mapi_SPropValue_array *properties,
 					     gpointer user_data,
diff --git a/src/libexchangemapi/e-mapi-utils.h b/src/libexchangemapi/e-mapi-utils.h
index 04c9459..25f6a39 100644
--- a/src/libexchangemapi/e-mapi-utils.h
+++ b/src/libexchangemapi/e-mapi-utils.h
@@ -32,7 +32,6 @@ gchar *  e_mapi_util_mapi_id_to_string (mapi_id_t id);
 gboolean e_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id);
 
 gconstpointer	e_mapi_util_find_SPropVal_array_propval (struct SPropValue *values, uint32_t proptag);
-gconstpointer	e_mapi_util_find_SPropVal_array_namedid (struct SPropValue *values, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
 gconstpointer	e_mapi_util_find_row_propval (struct SRow *aRow, uint32_t proptag);
 gconstpointer	e_mapi_util_find_row_namedid (struct SRow *aRow, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
 gconstpointer	e_mapi_util_find_array_propval (struct mapi_SPropValue_array *properties, uint32_t proptag);
@@ -40,22 +39,11 @@ gconstpointer	e_mapi_util_find_array_namedid (struct mapi_SPropValue_array *prop
 uint32_t	e_mapi_util_find_array_proptag (struct mapi_SPropValue_array *properties, uint32_t proptag);
 
 enum MAPISTATUS e_mapi_util_find_array_datetime_propval (struct timeval *tv, struct mapi_SPropValue_array *properties, uint32_t proptag);
-enum MAPISTATUS e_mapi_util_find_array_datetime_namedid (struct timeval *tv, struct mapi_SPropValue_array *properties, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
-
-ExchangeMAPIStream *e_mapi_util_find_stream (GSList *stream_list, uint32_t proptag);
-ExchangeMAPIStream *e_mapi_util_find_stream_namedid (GSList *stream_list, EMapiConnection *conn, mapi_id_t fid, uint32_t namedid);
-
-void e_mapi_util_free_attachment_list (GSList **attach_list);
-void e_mapi_util_free_recipient_list (GSList **recip_list);
-void e_mapi_util_free_stream_list (GSList **stream_list);
 
 void	 e_mapi_util_recip_entryid_generate_smtp (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *display_name, const gchar *email);
 void	 e_mapi_util_recip_entryid_generate_ex  (TALLOC_CTX *mem_ctx, struct Binary_r *entryid, const gchar *exchange_dn);
 gboolean e_mapi_util_recip_entryid_decode (EMapiConnection *conn, const struct Binary_r *entyrid, gchar **display_name, gchar **email);
 
-gchar *exchange_lf_to_crlf (const gchar *in);
-gchar *exchange_crlf_to_lf (const gchar *in);
-
 void e_mapi_util_profiledata_from_settings (EMapiProfileData *empd, CamelMapiSettings *settings);
 gchar *		e_mapi_util_profile_name			(struct mapi_context *mapi_ctx,
 								 const EMapiProfileData *empd,
@@ -117,7 +105,6 @@ gboolean	e_mapi_utils_create_mapi_context		(struct mapi_context **mapi_ctx,
 void		e_mapi_utils_destroy_mapi_context		(struct mapi_context *mapi_ctx);
 
 gboolean	e_mapi_utils_build_last_modify_restriction	(EMapiConnection *conn,
-								 mapi_id_t fid,
 								 TALLOC_CTX *mem_ctx,
 								 struct mapi_SRestriction **restrictions,
 								 gpointer user_data, /* const time_t * */
@@ -131,7 +118,6 @@ struct FolderBasicPropertiesData
 };
 
 gboolean	e_mapi_utils_get_folder_basic_properties_cb	(EMapiConnection *conn,
-								 mapi_id_t fid,
 								 TALLOC_CTX *mem_ctx,
 								 /* const */ struct mapi_SPropValue_array *properties,
 								 gpointer user_data, /* struct FolderBasicPropertiesData * */



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