[evolution-mapi] Bug #618514 - Forwarded messages as attachments encoded incorrectly



commit 918f7d4d7561aa905023aeeb9f3d792ea1cd0165
Author: Milan Crha <mcrha redhat com>
Date:   Tue Mar 8 14:47:52 2011 +0100

    Bug #618514 - Forwarded messages as attachments encoded incorrectly

 src/camel/Makefile.am                          |    2 -
 src/camel/camel-mapi-folder.c                  |    5 +-
 src/camel/camel-mapi-transport.c               |    5 +-
 src/camel/camel-mapi-utils.c                   |  590 ------------------------
 src/camel/camel-mapi-utils.h                   |   41 --
 src/libexchangemapi/exchange-mapi-connection.c |  372 +++++++++------
 src/libexchangemapi/exchange-mapi-connection.h |    3 +
 src/libexchangemapi/exchange-mapi-mail-utils.c |  562 ++++++++++++++++++++++
 src/libexchangemapi/exchange-mapi-mail-utils.h |   11 +-
 src/libexchangemapi/exchange-mapi-utils.c      |   17 +-
 10 files changed, 814 insertions(+), 794 deletions(-)
---
diff --git a/src/camel/Makefile.am b/src/camel/Makefile.am
index fc7d125..fd81779 100644
--- a/src/camel/Makefile.am
+++ b/src/camel/Makefile.am
@@ -19,7 +19,6 @@ libcamelmapi_la_SOURCES = 			\
         camel-mapi-store.c	                \
 	camel-mapi-store-summary.c         	\
 	camel-mapi-summary.c	         	\
-	camel-mapi-utils.c			\
 	camel-mapi-notifications.c		\
 	camel-mapi-transport.c			
 
@@ -29,7 +28,6 @@ noinst_HEADERS =         			\
 	camel-mapi-store-summary.h         	\
 	camel-mapi-summary.h	         	\
 	camel-mapi-transport.h			\
-	camel-mapi-utils.h			\
 	camel-mapi-notifications.h		\
 	camel-mapi-private.h
 
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 750a852..76d3956 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -42,7 +42,6 @@
 #include "camel-mapi-folder.h"
 #include "camel-mapi-private.h"
 #include "camel-mapi-summary.h"
-#include "camel-mapi-utils.h"
 
 #define DEBUG_FN( ) printf("----%p %s\n", g_thread_self(), G_STRFUNC);
 #define SUMMARY_FETCH_BATCH_COUNT 150
@@ -1113,12 +1112,12 @@ mapi_folder_append_message_sync (CamelFolder *folder,
 	/* Convert MIME to Item */
 	from = (CamelAddress *) camel_mime_message_get_from (message);
 
-	item = camel_mapi_utils_mime_to_item (message, info ? camel_message_info_flags (info) : 0, from, cancellable, error);
+	item = mapi_mime_message_to_mail_item (message, info ? camel_message_info_flags (info) : 0, from, cancellable, error);
 	if (item == NULL)
 		return FALSE;
 
 	mid = exchange_mapi_connection_create_item (camel_mapi_store_get_exchange_connection (mapi_store), -1, fid,
-					 camel_mapi_utils_create_item_build_props, item,
+					 mapi_mail_utils_create_item_build_props, item,
 					 item->recipients, item->attachments,
 					 item->generic_streams, MAPI_OPTIONS_DONT_SUBMIT, &mapi_error);
 
diff --git a/src/camel/camel-mapi-transport.c b/src/camel/camel-mapi-transport.c
index b5908b3..1c5ccc9 100644
--- a/src/camel/camel-mapi-transport.c
+++ b/src/camel/camel-mapi-transport.c
@@ -42,7 +42,6 @@
 #include "camel-mapi-store.h"
 #include "camel-mapi-folder.h"
 #include "camel-mapi-store-summary.h"
-#include "camel-mapi-utils.h"
 #define d(x)
 
 #include <exchange-mapi-defs.h>
@@ -74,7 +73,7 @@ mapi_message_item_send (ExchangeMapiConnection *conn, MailItem *item, GError **p
 	#undef unset
 
 	mid = exchange_mapi_connection_create_item (conn, olFolderSentMail, fid,
-					 camel_mapi_utils_create_item_build_props, item,
+					 mapi_mail_utils_create_item_build_props, item,
 					 item->recipients, item->attachments, item->generic_streams, MAPI_OPTIONS_DELETE_ON_SUBMIT_FAILURE, perror);
 
 	return mid;
@@ -115,7 +114,7 @@ mapi_send_to_sync (CamelTransport *transport,
 	}
 
 	/* Convert MIME to MailItem, attacment lists and recipient list.*/
-	item = camel_mapi_utils_mime_to_item (message, 0, from, cancellable, NULL);
+	item = mapi_mime_message_to_mail_item (message, 0, from, cancellable, NULL);
 
 	/* send */
 	st = mapi_message_item_send (conn, item, error);
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index bf7806f..794b535 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -767,6 +767,138 @@ exchange_mapi_util_write_generic_streams (mapi_object_t *obj_message, GSList *st
 	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 *) exchange_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_DISPLAY_NAME_UNICODE);
+		dn = (dn) ? dn : "";
+		email = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_SMTP_ADDRESS_UNICODE);
+		email = (email) ? email : "";
+		exchange_mapi_util_entryid_generate_oneoff (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
+exchange_mapi_util_modify_recipients (ExchangeMapiConnection *conn, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message , GSList *recipients, gboolean remove_existing, GError **perror)
+{
+	enum MAPISTATUS	ms;
+	struct SPropTagArray	*SPropTagArray = NULL;
+	struct SRowSet		*SRowSet = NULL;
+	#ifdef HAVE_LIBMAPI_CONTEXT_PARAM
+	struct PropertyTagArray_r *FlagList = NULL;
+	#else
+	struct SPropTagArray	*FlagList = NULL;
+	#endif
+	GSList			*l;
+	const gchar		**users = NULL;
+	uint32_t		i, j, count = 0;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+	g_debug("%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;
+	}
+
+	/* 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 :-( */
+			g_debug ("%s: %s() - '%s' is ambiguous ", G_STRLOC, G_STRFUNC, recipient->email_id);
+		} 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 (remove_existing) {
+		ms = RemoveAllRecipients (obj_message);
+		if (ms != MAPI_E_SUCCESS) {
+			make_mapi_error (perror, "RemoveAllRecipients", ms);
+			goto cleanup;
+		}
+	}
+
+	/* Modify the recipient table */
+	ms = ModifyRecipients (obj_message, SRowSet);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "ModifyRecipients", ms);
+		goto cleanup;
+	}
+
+cleanup:
+	g_free (users);
+
+	g_debug("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+
+	return TRUE;
+}
+
 static gboolean
 exchange_mapi_util_delete_attachments (mapi_object_t *obj_message, GError **perror)
 {
@@ -842,9 +974,8 @@ cleanup:
 
 /* Returns TRUE if all attachments were written succcesfully, else returns FALSE */
 static gboolean
-exchange_mapi_util_set_attachments (mapi_object_t *obj_message, GSList *attach_list, gboolean remove_existing, GError **perror)
+exchange_mapi_util_set_attachments (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message, GSList *attach_list, gboolean remove_existing, GError **perror)
 {
-//	TALLOC_CTX	*mem_ctx;
 	GSList		*l;
 	enum MAPISTATUS	ms;
 	gboolean	status = FALSE;
@@ -854,8 +985,6 @@ exchange_mapi_util_set_attachments (mapi_object_t *obj_message, GSList *attach_l
 	if (remove_existing)
 		exchange_mapi_util_delete_attachments (obj_message, NULL);
 
-//	mem_ctx = talloc_init ("ExchangeMAPI_SetAttachments");
-
 	for (l = attach_list; l; l = l->next) {
 		ExchangeMAPIAttachment *attachment = (ExchangeMAPIAttachment *) (l->data);
 		mapi_object_t		obj_attach;
@@ -869,16 +998,95 @@ exchange_mapi_util_set_attachments (mapi_object_t *obj_message, GSList *attach_l
 			goto cleanup;
 		}
 
-		/* SetProps */
-		ms = SetProps (&obj_attach, attachment->lpProps, attachment->cValues);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "SetProps", ms);
-			goto cleanup;
-		}
+		if (attachment->mail) {
+			struct SPropValue *props = NULL;
+			uint32_t propslen = 0, ui32;
+			MailItem *item = attachment->mail;
+			mapi_object_t obj_emb_msg;
 
-		/* If there are any streams to be set, write them. */
-		if (!exchange_mapi_util_write_generic_streams (&obj_attach, attachment->streams, perror))
-			goto cleanup;
+			ui32 = ATTACH_EMBEDDED_MSG;
+			exchange_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_METHOD, &ui32);
+			ui32 = 0;
+			exchange_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_RENDERING_POSITION, &ui32);
+			exchange_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_MIME_TAG, "message/rfc822");
+			if (item->header.subject)
+				exchange_mapi_utils_add_spropvalue (mem_ctx, &props, &propslen, PR_ATTACH_FILENAME_UNICODE, item->header.subject);
+
+			/* set properties for the item */
+			ms = SetProps (&obj_attach, props, propslen);
+			if (ms != MAPI_E_SUCCESS) {
+				mapi_object_release (&obj_emb_msg);
+				make_mapi_error (perror, "SetProps", ms);
+				goto cleanup;
+			}
+
+			props = NULL;
+			propslen = 0;
+
+			mapi_object_init (&obj_emb_msg);
+
+			ms = OpenEmbeddedMessage (&obj_attach, &obj_emb_msg, MAPI_CREATE);
+			if (ms != MAPI_E_SUCCESS) {
+				make_mapi_error (perror, "OpenEmbeddedMessage", ms);
+				goto cleanup;
+			}
+
+			if (!mapi_mail_utils_create_item_build_props (conn, fid, mem_ctx, &props, &propslen, item)) {
+				make_mapi_error (perror, "build_props", MAPI_E_CALL_FAILED);
+				goto cleanup;
+			}
+
+			/* set properties for the item */
+			ms = SetProps (&obj_emb_msg, props, propslen);
+			if (ms != MAPI_E_SUCCESS) {
+				mapi_object_release (&obj_emb_msg);
+				make_mapi_error (perror, "SetProps", ms);
+				goto cleanup;
+			}
+
+			if (item->generic_streams) {
+				if (!exchange_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 (!exchange_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 (!exchange_mapi_util_modify_recipients (conn, mem_ctx, &obj_emb_msg, item->recipients, FALSE, perror)) {
+					mapi_object_release (&obj_emb_msg);
+					goto cleanup;
+				}
+			}
+
+			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, 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 (!exchange_mapi_util_write_generic_streams (&obj_attach, attachment->streams, perror))
+				goto cleanup;
+		}
 
 		/* message->SaveChangesAttachment() */
 		ms = SaveChangesAttachment (obj_message, &obj_attach, KeepOpenReadWrite);
@@ -893,8 +1101,6 @@ exchange_mapi_util_set_attachments (mapi_object_t *obj_message, GSList *attach_l
 		mapi_object_release(&obj_attach);
 	}
 
-//	talloc_free (mem_ctx);
-
 	g_debug("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
 	return status;
@@ -1278,138 +1484,6 @@ cleanup:
 	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 *) exchange_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_DISPLAY_NAME_UNICODE);
-		dn = (dn) ? dn : "";
-		email = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval (recipient->in.ext_lpProps, PR_SMTP_ADDRESS_UNICODE);
-		email = (email) ? email : "";
-		exchange_mapi_util_entryid_generate_oneoff (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
-exchange_mapi_util_modify_recipients (ExchangeMapiConnection *conn, TALLOC_CTX *mem_ctx, mapi_object_t *obj_message , GSList *recipients, gboolean remove_existing, GError **perror)
-{
-	enum MAPISTATUS	ms;
-	struct SPropTagArray	*SPropTagArray = NULL;
-	struct SRowSet		*SRowSet = NULL;
-	#ifdef HAVE_LIBMAPI_CONTEXT_PARAM
-	struct PropertyTagArray_r *FlagList = NULL;
-	#else
-	struct SPropTagArray	*FlagList = NULL;
-	#endif
-	GSList			*l;
-	const gchar		**users = NULL;
-	uint32_t		i, j, count = 0;
-
-	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
-	e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
-	g_debug("%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;
-	}
-
-	/* 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 :-( */
-			g_debug ("%s: %s() - '%s' is ambiguous ", G_STRLOC, G_STRFUNC, recipient->email_id);
-		} 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 (remove_existing) {
-		ms = RemoveAllRecipients (obj_message);
-		if (ms != MAPI_E_SUCCESS) {
-			make_mapi_error (perror, "RemoveAllRecipients", ms);
-			goto cleanup;
-		}
-	}
-
-	/* Modify the recipient table */
-	ms = ModifyRecipients (obj_message, SRowSet);
-	if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "ModifyRecipients", ms);
-		goto cleanup;
-	}
-
-cleanup:
-	g_free (users);
-
-	g_debug("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
-	return TRUE;
-}
-
 static enum MAPISTATUS
 open_folder (ExchangeMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 fid_options, mapi_object_t *obj_folder, GError **perror)
 {
@@ -2609,7 +2683,7 @@ exchange_mapi_connection_create_item (ExchangeMapiConnection *conn, uint32_t olF
 
 	/* Set attachments if any */
 	if (attachments) {
-		if (!exchange_mapi_util_set_attachments (&obj_message, attachments, FALSE, perror))
+		if (!exchange_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_message, attachments, FALSE, perror))
 			goto cleanup;
 	}
 
@@ -2734,7 +2808,7 @@ exchange_mapi_connection_modify_item (ExchangeMapiConnection *conn, uint32_t olF
 
 	/* Set attachments if any */
 	if (attachments) {
-		if (!exchange_mapi_util_set_attachments (&obj_message, attachments, TRUE, perror))
+		if (!exchange_mapi_util_set_attachments (conn, fid, mem_ctx, &obj_message, attachments, TRUE, perror))
 			goto cleanup;
 	} else {
 		exchange_mapi_util_delete_attachments (&obj_message, NULL);
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index 6c3d298..7531b7c 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -107,11 +107,14 @@ typedef struct {
 	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 {
diff --git a/src/libexchangemapi/exchange-mapi-mail-utils.c b/src/libexchangemapi/exchange-mapi-mail-utils.c
index 323a132..7e6da23 100644
--- a/src/libexchangemapi/exchange-mapi-mail-utils.c
+++ b/src/libexchangemapi/exchange-mapi-mail-utils.c
@@ -930,3 +930,565 @@ mapi_mail_item_to_mime_message (ExchangeMapiConnection *conn, MailItem *item)
 
 	return msg;
 }
+
+#define STREAM_SIZE 4000
+
+static void
+mail_item_add_recipient (const gchar *recipients, OlMailRecipientType type, GSList **recipient_list)
+{
+	ExchangeMAPIRecipient *recipient;
+	uint32_t val = 0;
+	uint8_t bVal;
+	const gchar *str = NULL;
+
+	if (!recipients)
+		return;
+
+	recipient = g_new0 (ExchangeMAPIRecipient, 1);
+
+	recipient->email_id = recipients;
+
+	/* this memory should be freed somewhere, perhaps in the existing
+	 * exchange_mapi_util_free_recipient_list() */
+	recipient->in.req_cValues = 2;
+	recipient->in.req_lpProps = g_new0 (struct SPropValue, recipient->in.req_cValues + 1);
+
+	set_SPropValue_proptag (&(recipient->in.req_lpProps[0]), PR_RECIPIENT_TYPE, (gconstpointer ) &type);
+
+	val = 0;
+	set_SPropValue_proptag (&(recipient->in.req_lpProps[1]), PR_SEND_INTERNET_ENCODING, (gconstpointer )&val);
+
+	/* 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);
+
+	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));
+
+	bVal = FALSE;
+	set_SPropValue_proptag (&(recipient->in.ext_lpProps[7]), PR_SEND_RICH_INFO, &bVal);
+
+	*recipient_list = g_slist_append (*recipient_list, recipient);
+}
+
+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);
+
+	item->header.from = g_strdup (from_name);
+	item->header.from_email = g_strdup (from_email);
+}
+
+static void
+mail_item_set_subject(MailItem *item, const gchar *subject)
+{
+	if (item->header.subject)
+		g_free (item->header.subject);
+
+	item->header.subject = g_strdup (subject);
+}
+
+#define MAX_READ_SIZE 0x1000
+
+static void
+mail_item_set_body_stream (MailItem *item, CamelStream *body, MailItemPartType part_type, 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);
+
+	stream->value = g_byte_array_new ();
+
+	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);
+
+		is_null_terminated = buf [read_size - 1] == 0;
+
+		for (i = 0; i < read_size && contains_only_7bit; i++) {
+			contains_only_7bit = buf[i] < 128;
+		}
+	}
+
+	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);
+	}
+
+}
+
+static gboolean
+mail_item_add_attach (MailItem *item, 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;
+	CamelContentType *content_type;
+
+	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);
+
+	flag = ATTACH_BY_VALUE;
+	set_SPropValue_proptag(&(item_attach->lpProps[i++]), 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(&(item_attach->lpProps[i++]), PR_RENDERING_POSITION, (gconstpointer ) (&flag));
+
+	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));
+	}
+
+	/* 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));
+	}
+
+	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);
+		}
+	}
+
+	item_attach->cValues = i;
+
+	stream = g_new0 (ExchangeMAPIStream, 1);
+	stream->proptag = PR_ATTACH_DATA_BIN;
+	stream->value = g_byte_array_new ();
+
+	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);
+	}
+
+	item_attach->streams = g_slist_append (item_attach->streams, stream);
+	item->attachments = g_slist_append(item->attachments, item_attach);
+
+	return TRUE;
+}
+
+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);
+	}
+
+	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
+
+	return content_stream;
+}
+
+static gboolean
+mapi_do_multipart (CamelMultipart *mp, MailItem *item, gboolean *is_first, GCancellable *cancellable)
+{
+	CamelDataWrapper *dw;
+	CamelStream *content_stream;
+	CamelContentType *type;
+	CamelMimePart *part;
+	gint n_part, i_part;
+	const gchar *filename;
+	const gchar *description;
+	const gchar *content_id;
+
+	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++) {
+		/* getting part */
+		part = camel_multipart_get_part(mp, i_part);
+		dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+		if (CAMEL_IS_MULTIPART(dw)) {
+			/* recursive */
+			if (!mapi_do_multipart (CAMEL_MULTIPART (dw), item, is_first, cancellable))
+				return FALSE;
+			continue;
+		}
+
+		if (CAMEL_IS_MIME_MESSAGE (dw)) {
+			CamelMimeMessage *message;
+			CamelInternetAddress *message_from;
+			CamelAddress *use_from = NULL;
+			MailItem *mail;
+
+			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);
+
+				item_attach->mail = mail;
+				item->attachments = g_slist_append (item->attachments, item_attach);
+
+				continue;
+			}
+		}
+
+		/* filename */
+		filename = camel_mime_part_get_filename(part);
+
+		content_stream = get_content_stream (part, cancellable);
+
+		description = camel_mime_part_get_description(part);
+		content_id = camel_mime_part_get_content_id(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);
+			*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);
+		} else {
+			mail_item_add_attach (item, part, content_stream, cancellable);
+		}
+
+		if (content_stream)
+			g_object_unref (content_stream);
+	}
+
+	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;
+	}
+}
+
+MailItem *
+mapi_mime_message_to_mail_item (CamelMimeMessage *message, gint32 message_camel_flags, CamelAddress *from, GCancellable *cancellable, GError **error)
+{
+	CamelDataWrapper *dw = NULL;
+	CamelStream *content_stream;
+	CamelMultipart *multipart;
+	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;
+
+	GSList *recipient_list = NULL;
+	gint i = 0;
+
+	/* headers */
+
+	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 {
+		/* though invalid, then possible, to pass in a message without any 'from' */
+		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);
+
+	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);
+	}
+
+	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);
+	}
+
+	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 (camel_mime_message_get_subject(message)) {
+		mail_item_set_subject(item, camel_mime_message_get_subject(message));
+	}
+
+	headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
+	if (headers) {
+		GString *hstr = g_string_new ("");
+		gint i;
+
+		for (i = 0; i < headers->len; i++) {
+			CamelMediumHeader *h = &g_array_index (headers, CamelMediumHeader, i);
+
+			if (!h->name || !*h->name || g_ascii_strncasecmp (h->name, "X-Evolution", 11) == 0)
+				continue;
+
+			g_string_append_printf (hstr, "%s: %s\n", h->name, h->value ? h->value : "");
+		}
+
+		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"));
+
+	/* contents body */
+	multipart = (CamelMultipart *)camel_medium_get_content (CAMEL_MEDIUM (message));
+
+	if (CAMEL_IS_MULTIPART(multipart)) {
+		gboolean is_first = TRUE;
+		if (!mapi_do_multipart (CAMEL_MULTIPART(multipart), item, &is_first, cancellable))
+			printf("camel message multi part error\n");
+	} else {
+		dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+		if (dw) {
+			content_stream = get_content_stream ((CamelMimePart *) message, cancellable);
+
+			mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT, cancellable);
+
+			if (content_stream)
+				g_object_unref (content_stream);
+		}
+	}
+
+	item->recipients = recipient_list;
+
+	return item;
+}
+
+gboolean
+mapi_mail_utils_create_item_build_props (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropValue **values, uint32_t *n_values, gpointer data)
+{
+
+	MailItem *item = (MailItem *) data;
+	GSList *l;
+	bool send_rich_info;
+	uint32_t cpid;
+
+	#define set_value(hex, val) G_STMT_START { \
+		if (!exchange_mapi_utils_add_spropvalue (mem_ctx, values, n_values, hex, val)) \
+			return FALSE;	\
+		} G_STMT_END
+
+	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 */
+
+	send_rich_info = false;
+	set_value (PR_SEND_RICH_INFO, &send_rich_info);
+
+	set_value (PR_MESSAGE_FLAGS, &item->header.flags);
+
+	if (item->header.from && *item->header.from)
+		set_value (PR_SENT_REPRESENTING_NAME_UNICODE, item->header.from);
+
+	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 (item->header.recieved_time != 0) {
+		struct FILETIME msg_date = { 0 };
+
+		exchange_mapi_util_time_t_to_filetime (item->header.recieved_time, &msg_date);
+
+		set_value (PR_MESSAGE_DELIVERY_TIME, &msg_date);
+	}
+
+	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 (item->header.message_id)
+		set_value (PR_INTERNET_MESSAGE_ID, item->header.message_id);
+
+	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);
+
+		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);
+	}
+
+	/*  FIXME : */
+	/* editor = EDITOR_FORMAT_PLAINTEXT; */
+	/* set_value (PR_MSG_EDITOR_FORMAT, &editor); */
+
+	return TRUE;
+}
diff --git a/src/libexchangemapi/exchange-mapi-mail-utils.h b/src/libexchangemapi/exchange-mapi-mail-utils.h
index f9d7e3b..67ca9bf 100644
--- a/src/libexchangemapi/exchange-mapi-mail-utils.h
+++ b/src/libexchangemapi/exchange-mapi-mail-utils.h
@@ -25,6 +25,8 @@
 #endif
 
 #include <glib.h>
+#include <gio/gio.h>
+
 #include <libmapi/libmapi.h>
 
 #include <exchange-mapi-connection.h>
@@ -61,7 +63,7 @@ typedef struct {
 	GSList *body_parts;
 } MailItemMessage;
 
-typedef struct  {
+typedef struct _MailItem {
 	mapi_id_t fid;
 	mapi_id_t mid;
 	gchar *msg_class;
@@ -74,7 +76,7 @@ typedef struct  {
 	GSList *recipients;
 	GSList *attachments;
 	GSList *generic_streams;
-}MailItem;
+} MailItem;
 
 void mail_item_free (MailItem *item);
 
@@ -89,4 +91,9 @@ gboolean mapi_mail_get_item_prop_list (ExchangeMapiConnection *conn, mapi_id_t f
 struct _CamelMimeMessage;
 struct _CamelMimeMessage *mapi_mail_item_to_mime_message (ExchangeMapiConnection *conn, MailItem *item);
 
+struct _CamelAddress;
+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 (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropValue **values, uint32_t *n_values, gpointer data);
+
 #endif /* EXCHANGE_MAPI_MAIL_UTILS */
diff --git a/src/libexchangemapi/exchange-mapi-utils.c b/src/libexchangemapi/exchange-mapi-utils.c
index d5adddc..c4b20f7 100644
--- a/src/libexchangemapi/exchange-mapi-utils.c
+++ b/src/libexchangemapi/exchange-mapi-utils.c
@@ -25,7 +25,11 @@
 #include <config.h>
 #endif
 
+#include <glib.h>
+#include <gio/gio.h>
+
 #include "exchange-mapi-utils.h"
+#include "exchange-mapi-mail-utils.h"
 
 #ifdef G_OS_WIN32
 /* Undef the similar macro from pthread.h, it doesn't check if
@@ -324,11 +328,16 @@ exchange_mapi_util_free_attachment_list (GSList **attach_list)
 
 	for (; l != NULL; l = l->next) {
 		ExchangeMAPIAttachment *attachment = (ExchangeMAPIAttachment *) (l->data);
-		/* FIXME: more stuff here */
-		g_free (attachment->lpProps);
-		exchange_mapi_util_free_stream_list (&(attachment->streams));
+
+		if (attachment->mail) {
+			mail_item_free (attachment->mail);
+		} else {
+			g_free (attachment->lpProps);
+			exchange_mapi_util_free_stream_list (&(attachment->streams));
+		}
+
 		g_free (attachment);
-		attachment = NULL;
+		l->data = NULL;
 	}
 	g_slist_free (*attach_list);
 	*attach_list = NULL;



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