[evolution-mapi] Bug #599311 - Doesn't show email attachments



commit f0376d03f32308a0d403f20ed7e53879a222ebd4
Author: Milan Crha <mcrha redhat com>
Date:   Wed May 12 17:38:35 2010 +0200

    Bug #599311 - Doesn't show email attachments

 src/camel/camel-mapi-folder.c                  |  711 +-----------------------
 src/camel/camel-mapi-folder.h                  |   55 --
 src/camel/camel-mapi-transport.c               |    7 +-
 src/camel/camel-mapi-utils.c                   |   37 +-
 src/camel/camel-mapi-utils.h                   |    6 +-
 src/libexchangemapi/Makefile.am                |   13 +-
 src/libexchangemapi/exchange-mapi-cal-utils.c  |   10 +-
 src/libexchangemapi/exchange-mapi-cal-utils.h  |    2 +-
 src/libexchangemapi/exchange-mapi-connection.c |  216 ++++++--
 src/libexchangemapi/exchange-mapi-connection.h |    7 +
 src/libexchangemapi/exchange-mapi-mail-utils.c |  720 ++++++++++++++++++++++++
 src/libexchangemapi/exchange-mapi-mail-utils.h |   90 +++
 src/libexchangemapi/exchange-mapi-utils.h      |    1 -
 13 files changed, 1045 insertions(+), 830 deletions(-)
---
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index cc23dc8..1c45a9c 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -35,6 +35,7 @@
 #include <exchange-mapi-utils.h>
 #include <exchange-mapi-folder.h>
 #include <exchange-mapi-cal-utils.h>
+#include "exchange-mapi-mail-utils.h"
 
 #include "camel-mapi-store.h"
 #include "camel-mapi-store-summary.h"
@@ -68,7 +69,6 @@ typedef struct {
 
 /*For collecting summary info from server*/
 
-static CamelMimeMessage *mapi_folder_item_to_msg( CamelFolder *folder, MapiItem *item, CamelException *ex );
 static void mapi_update_cache (CamelFolder *folder, GSList *list, CamelFolderChangeInfo **changeinfo,
 			       CamelException *ex, gboolean uid_flag);
 
@@ -150,111 +150,6 @@ mapi_refresh_info(CamelFolder *folder, CamelException *ex)
 	return !camel_exception_is_set (ex);
 }
 
-void
-mapi_item_free (MapiItem *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);
-
-	exchange_mapi_util_free_attachment_list (&item->attachments);
-	exchange_mapi_util_free_stream_list (&item->generic_streams);
-	exchange_mapi_util_free_recipient_list (&item->recipients);
-
-	g_free (item);
-}
-
-static gboolean
-read_item_common (MapiItem *item, uint32_t ulPropTag, gconstpointer prop_data)
-{
-	gboolean found = TRUE;
-
-	#define sv(_x,_y) G_STMT_START { g_free (_x); _x = _y; } G_STMT_END
-
-	switch (ulPropTag) {
-	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, utf8tolinux (prop_data));
-		break;
-	case PR_SUBJECT_UNICODE :
-		sv (item->header.subject, g_strdup (prop_data));
-		break;
-	case PR_DISPLAY_TO :
-		sv (item->header.to, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (prop_data));
-		break;
-	case PR_TRANSPORT_MESSAGE_HEADERS_UNICODE:
-		sv (item->header.transport_headers, g_strdup (prop_data));
-		break;
-	default:
-		found = FALSE;
-		break;
-	}
-
-	#undef sv
-
-	return found;
-}
-
 static gboolean
 fetch_items_summary_cb (FetchItemsCallbackData *item_data, gpointer data)
 {
@@ -270,7 +165,7 @@ fetch_items_summary_cb (FetchItemsCallbackData *item_data, gpointer data)
 	guint32 j = 0;
 	NTTIME ntdate;
 
-	MapiItem *item = g_new0(MapiItem , 1);
+	MailItem *item = g_new0(MailItem , 1);
 
 	if (camel_debug_start("mapi:folder")) {
 		exchange_mapi_debug_property_dump (item_data->properties);
@@ -286,7 +181,7 @@ fetch_items_summary_cb (FetchItemsCallbackData *item_data, gpointer data)
 	for (j = 0; j < item_data->properties->cValues; j++) {
 		gconstpointer prop_data = get_mapi_SPropValue_data(&item_data->properties->lpProps[j]);
 
-		if (read_item_common (item, item_data->properties->lpProps[j].ulPropTag, prop_data))
+		if (fetch_read_item_common_data (item, item_data->properties->lpProps[j].ulPropTag, prop_data))
 			continue;
 
 		switch (item_data->properties->lpProps[j].ulPropTag) {
@@ -339,7 +234,7 @@ fetch_items_summary_cb (FetchItemsCallbackData *item_data, gpointer data)
 	if ((item_data->index % SUMMARY_FETCH_BATCH_COUNT == 0) ||
 	     item_data->index == item_data->total-1) {
 		mapi_update_cache (fi_data->folder, *slist, &fi_data->changes, NULL, false);
-		g_slist_foreach (*slist, (GFunc)mapi_item_free, NULL);
+		g_slist_foreach (*slist, (GFunc)mail_item_free, NULL);
 		g_slist_free (*slist);
 		*slist = NULL;
 	}
@@ -464,8 +359,8 @@ mapi_update_cache (CamelFolder *folder, GSList *list, CamelFolderChangeInfo **ch
 		camel_folder_get_name (folder));
 
 	for (; item_list != NULL; item_list = g_slist_next (item_list) ) {
-		MapiItem *temp_item;
-		MapiItem *item;
+		MailItem *temp_item;
+		MailItem *item;
 		gchar *msg_uid;
 		guint64 id;
 
@@ -473,7 +368,7 @@ mapi_update_cache (CamelFolder *folder, GSList *list, CamelFolderChangeInfo **ch
 		status_flags = 0;
 
 		if (uid_flag == FALSE) {
-			temp_item = (MapiItem *)item_list->data;
+			temp_item = (MailItem *)item_list->data;
 			id = temp_item->mid;
 			item = temp_item;
 		}
@@ -1181,589 +1076,11 @@ end1:
 	if (is_locked)
 		camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
-	g_slist_foreach (fetch_data->items_list, (GFunc) mapi_item_free, NULL);
+	g_slist_foreach (fetch_data->items_list, (GFunc) mail_item_free, NULL);
 	g_slist_free (fetch_data->items_list);
 	g_free (fetch_data);
 }
 
-static gboolean
-mapi_camel_get_item_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data)
-{
-	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,
-		/*Fixme : If this property is fetched, it garbles everything else. */
-		/*PR_BODY_HTML, */
-		/*PR_BODY_HTML_UNICODE, */
-
-		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
-	};
-
-	g_return_val_if_fail (props != NULL, FALSE);
-
-	return exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, item_props, G_N_ELEMENTS (item_props));
-}
-
-static gboolean
-fetch_item_cb (FetchItemsCallbackData *item_data, gpointer data)
-{
-	long *flags;
-	struct FILETIME *delivery_date;
-	const gchar *msg_class;
-	NTTIME ntdate;
-	ExchangeMAPIStream *body;
-
-	MapiItem *item = g_new0(MapiItem , 1);
-	MapiItem **i = (MapiItem **)data;
-	guint32 j = 0;
-
-	if (camel_debug_start("mapi:folder")) {
-		exchange_mapi_debug_property_dump (item_data->properties);
-		camel_debug_end();
-	}
-
-	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++) {
-
-		gconstpointer prop_data = get_mapi_SPropValue_data(&item_data->properties->lpProps[j]);
-
-		if (read_item_common (item, item_data->properties->lpProps[j].ulPropTag, prop_data))
-			continue;
-
-		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:
-			break;
-		}
-	}
-
-	item->is_cal = FALSE;
-	if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX)) {
-		guint8 *appointment_body_str = (guint8 *) exchange_mapi_cal_util_camel_helper (item_data->conn, item_data->fid, item_data->mid, 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));
-
-			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
-			item->is_cal = TRUE;
-		}
-
-		g_free (appointment_body_str);
-	}
-
-	if (!item->is_cal) {
-		/* always prefer unicode version, as that can be properly read */
-		if (!(body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY_UNICODE)))
-			body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY);
-
-		if (body)
-			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
-
-		body = exchange_mapi_util_find_stream (item_data->streams, PR_HTML);
-		if (body)
-			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
-	}
-
-	if (delivery_date) {
-		ntdate = delivery_date->dwHighDateTime;
-		ntdate = ntdate << 32;
-		ntdate |= delivery_date->dwLowDateTime;
-		item->header.recieved_time = nt_time_to_unix(ntdate);
-	}
-
-	if ((*flags & MSGFLAG_READ) != 0)
-		item->header.flags |= CAMEL_MESSAGE_SEEN;
-	if ((*flags & MSGFLAG_HASATTACH) != 0)
-		item->header.flags |= CAMEL_MESSAGE_ATTACHMENTS;
-
-	item->attachments = item_data->attachments;
-
-	*i = item;
-
-	return TRUE;
-}
-
-static void
-mapi_mime_set_recipient_list (CamelMimeMessage *msg, MapiItem *item)
-{
-	GSList *l = NULL;
-	CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
-
-	g_return_if_fail (item->recipients != NULL);
-
-	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;
-		const gchar *name = NULL;
-		uint32_t rcpt_type = MAPI_TO;
-		uint32_t *type = NULL;
-		struct SRow *aRow;
-		ExchangeMAPIRecipient *recip = (ExchangeMAPIRecipient *)(l->data);
-
-		/*Can't continue when there is no email-id*/
-		if (!recip->email_id)
-			continue;
-
-		/* Build a SRow structure */
-		aRow = &recip->out_SRow;
-
-		/*Name is probably available in one of these props.*/
-		name = (const gchar *) exchange_mapi_util_find_row_propval (aRow, PR_DISPLAY_NAME_UNICODE);
-		name = name ? name : (const gchar *) exchange_mapi_util_find_row_propval (aRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
-		name = name ? name : (const gchar *) exchange_mapi_util_find_row_propval (aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
-
-		type = (uint32_t *) exchange_mapi_util_find_row_propval (aRow, PR_RECIPIENT_TYPE);
-
-		/*Fallbacks. Not good*/
-		display_name = name ? g_strdup (name) : g_strdup (recip->email_id);
-		rcpt_type = (type ? *type : MAPI_TO);
-
-		switch (rcpt_type) {
-		case MAPI_TO:
-			camel_internet_address_add (to_addr, display_name, recip->email_id);
-			break;
-		case MAPI_CC:
-			camel_internet_address_add (cc_addr, display_name, recip->email_id);
-			break;
-		case MAPI_BCC:
-			camel_internet_address_add (bcc_addr, display_name, recip->email_id);
-			break;
-		}
-
-		g_free (display_name);
-	}
-
-	/*Add to message*/
-	/*Note : To field is added from PR_TRANSPORT_MESSAGE_HEADERS
-	  But, in sent_items folder we don't get TRANSPORT_MESSAGE_HEADERS */
-	if (!item->header.transport_headers) {
-		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);
-	}
-
-	/*TODO : Unref *_addr ? */
-}
-
-static void
-mapi_mime_set_msg_headers (CamelFolder *folder, CamelMimeMessage *msg, MapiItem *item)
-{
-	gchar *temp_str = NULL;
-	const gchar *from_email;
-	time_t recieved_time;
-	CamelInternetAddress *addr = NULL;
-	CamelMapiStore *mapi_store;
-	CamelStore *parent_store;
-	gint offset = 0;
-	time_t actual_time;
-
-	parent_store = camel_folder_get_parent_store (folder);
-	mapi_store = CAMEL_MAPI_STORE (parent_store);
-
-	/* 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);
-		camel_mime_parser_scan_from (parser, FALSE);
-		g_object_unref (stream);
-
-		if (camel_mime_part_construct_from_parser (part, parser) != -1) {
-			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);
-	}
-
-	/* Overwrite headers if we have specific properties available*/
-	temp_str = item->header.subject;
-	if (temp_str)
-		camel_mime_message_set_subject (msg, temp_str);
-
-	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.from) {
-		if ((item->header.from_type != NULL) && !g_utf8_collate (item->header.from_type, "EX")) {
-			camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
-			from_email = exchange_mapi_connection_ex_to_smtp (camel_mapi_store_get_exchange_connection (mapi_store), item->header.from_email);
-			camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
-			g_free (item->header.from_email);
-			item->header.from_email = g_strdup (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);
-
-}
-
-static CamelMimePart *
-mapi_mime_msg_body (MapiItem *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) {
-		const gchar * type = NULL;
-		gchar *buff = NULL;
-
-		if (item->is_cal)
-			type = "text/calendar";
-		else
-			type = (body->proptag == PR_BODY || body->proptag == PR_BODY_UNICODE) ?
-				"text/plain" : "text/html";
-
-		if (item->header.cpid) {
-			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)
-				buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
-			else if (item->header.cpid == 28605)
-				buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
-			else if (item->header.cpid == 65000)
-				buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
-			else if (item->header.cpid == 65001)
-				buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
-			else
-				buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, item->header.cpid);
-			type = buff;
-		}
-
-		camel_mime_part_set_content (part, (const gchar *) body->value->data, body->value->len, type);
-
-		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 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;
-	}
-
-	for (bidx = 0; bidx < G_N_ELEMENTS (desired_order); bidx++) {
-		if (desired_order[bidx] == stream_b->proptag)
-			break;
-	}
-
-	return aidx - bidx;
-}
-
-#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 (MapiItem *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 (MapiItem *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 || stream->proptag == PR_BODY_HTML_UNICODE)
-		    && 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);
-	}
-
-	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;
-}
-
-/*Takes raw attachment streams and converts to MIME Parts. Parts are added to
-  either inline / non-inline lists.*/
-static void
-mapi_mime_classify_attachments (GSList *attachments, GSList **inline_attachs, GSList **noninline)
-{
-	for (;attachments != NULL; attachments = attachments->next) {
-		ExchangeMAPIAttachment *attach = (ExchangeMAPIAttachment *)attachments->data;
-		ExchangeMAPIStream *stream = NULL;
-		const gchar *filename, *mime_type, *content_id = NULL;
-		CamelContentType *content_type;
-		CamelMimePart *part;
-
-		stream = exchange_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
-
-		if (!stream || stream->value->len <= 0) {
-			continue;
-		}
-
-		part = camel_mime_part_new ();
-
-		filename = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
-											 PR_ATTACH_LONG_FILENAME_UNICODE);
-
-		if (!(filename && *filename))
-			filename = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
-												 PR_ATTACH_FILENAME_UNICODE);
-		camel_mime_part_set_filename(part, g_strdup(filename));
-		camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
-
-		/*Content-Type*/
-		mime_type = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_MIME_TAG);
-		if (!mime_type)
-			mime_type = "application/octet-stream";
-
-		camel_mime_part_set_content (part, (const gchar *) stream->value->data, stream->value->len, 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
-			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-
-		/*Content-ID*/
-		content_id = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
-											   PR_ATTACH_CONTENT_ID);
-		/* TODO : Add disposition */
-		if (content_id) {
-			camel_mime_part_set_content_id (part, content_id);
-			*inline_attachs = g_slist_append (*inline_attachs, part);
-		} else
-			*noninline = g_slist_append (*noninline, part);
-	}
-}
-
-static CamelMimeMessage *
-mapi_folder_item_to_msg( CamelFolder *folder, MapiItem *item, CamelException *ex )
-{
-	CamelMimeMessage *msg = NULL;
-	CamelMultipart *multipart_body = NULL;
-
-	GSList *attach_list = NULL;
-	GSList *inline_attachs =  NULL; /*Used for mulitpart/related*/
-	GSList *noninline_attachs = NULL;
-
-	gboolean build_alternative = FALSE;
-	gboolean build_related = FALSE;
-
-	attach_list = item->attachments;
-	msg = camel_mime_message_new ();
-
-	mapi_mime_set_recipient_list (msg, item);
-	mapi_mime_set_msg_headers (folder, msg, item);
-	mapi_mime_classify_attachments (attach_list, &inline_attachs, &noninline_attachs);
-
-	build_alternative = (g_slist_length (item->msg.body_parts) > 1) && inline_attachs;
-	build_related = !build_alternative && inline_attachs;
-
-	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->data,
-								    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);
-		g_object_unref (part);
-	}
-
-	if (noninline_attachs) { /* multipart/mixed */
-		multipart_body = mapi_mime_build_multipart_mixed (multipart_body,
-								  noninline_attachs);
-	}
-
-	camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart_body));
-	g_object_unref (multipart_body);
-
-	return msg;
-}
-
 static CamelMimeMessage *
 mapi_folder_get_message( CamelFolder *folder, const gchar *uid, CamelException *ex )
 {
@@ -1775,7 +1092,7 @@ mapi_folder_get_message( CamelFolder *folder, const gchar *uid, CamelException *
 	CamelStore *parent_store;
 	mapi_id_t id_folder;
 	mapi_id_t id_message;
-	MapiItem *item = NULL;
+	MailItem *item = NULL;
 	guint32 options = 0;
 
 	parent_store = camel_folder_get_parent_store (folder);
@@ -1852,8 +1169,8 @@ mapi_folder_get_message( CamelFolder *folder, const gchar *uid, CamelException *
 
 	camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 	exchange_mapi_connection_fetch_item (camel_mapi_store_get_exchange_connection (mapi_store), id_folder, id_message,
-					mapi_camel_get_item_prop_list, NULL,
-					fetch_item_cb, &item,
+					mapi_mail_get_item_prop_list, NULL,
+					fetch_props_to_mail_item_cb, &item,
 					options);
 	camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
@@ -1863,8 +1180,8 @@ mapi_folder_get_message( CamelFolder *folder, const gchar *uid, CamelException *
 		return NULL;
 	}
 
-	msg = mapi_folder_item_to_msg (folder, item, ex);
-	mapi_item_free (item);
+	msg = mapi_mail_item_to_mime_message (camel_mapi_store_get_exchange_connection (mapi_store), item);
+	mail_item_free (item);
 
 	if (!msg) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Could not get message"));
@@ -2148,7 +1465,7 @@ mapi_append_message (CamelFolder *folder, CamelMimeMessage *message,
 	CamelAddress *from = NULL;
 	CamelStoreInfo *si;
 	CamelStore *parent_store;
-	MapiItem *item = NULL;
+	MailItem *item = NULL;
 	mapi_id_t fid = 0, mid = 0;
 	const gchar *folder_id;
 	const gchar *full_name;
diff --git a/src/camel/camel-mapi-folder.h b/src/camel/camel-mapi-folder.h
index 09d49d5..94773be 100644
--- a/src/camel/camel-mapi-folder.h
+++ b/src/camel/camel-mapi-folder.h
@@ -55,61 +55,6 @@
 
 G_BEGIN_DECLS
 
-typedef enum  {
-	MAPI_ITEM_TYPE_MAIL=1,
-	MAPI_ITEM_TYPE_APPOINTMENT,
-	MAPI_ITEM_TYPE_CONTACT,
-	MAPI_ITEM_TYPE_JOURNAL,
-	MAPI_ITEM_TYPE_TASK
-} MapiItemType;
-
-typedef enum  {
-	PART_TYPE_PLAIN_TEXT=1,
-	PART_TYPE_TEXT_HTML
-} MapiItemPartType;
-
-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;
-} MapiItemHeader;
-
-typedef struct {
-	GSList *body_parts;
-} MapiItemMessage;
-
-typedef struct  {
-	mapi_id_t fid;
-	mapi_id_t mid;
-
-	MapiItemHeader header;
-	MapiItemMessage msg;
-
-	gboolean is_cal;
-
-	GSList *recipients;
-	GSList *attachments;
-	GSList *generic_streams;
-}MapiItem;
-
-void mapi_item_free (MapiItem *item);
-
 typedef struct _CamelMapiFolder CamelMapiFolder;
 typedef struct _CamelMapiFolderClass CamelMapiFolderClass;
 typedef struct _CamelMapiFolderPrivate CamelMapiFolderPrivate;
diff --git a/src/camel/camel-mapi-transport.c b/src/camel/camel-mapi-transport.c
index 827a833..bf8c1e6 100644
--- a/src/camel/camel-mapi-transport.c
+++ b/src/camel/camel-mapi-transport.c
@@ -46,6 +46,7 @@
 #define d(x) x
 
 #include <exchange-mapi-defs.h>
+#include "exchange-mapi-mail-utils.h"
 
 #define STREAM_SIZE 4000
 
@@ -57,7 +58,7 @@ G_DEFINE_TYPE (CamelMapiTransport, camel_mapi_transport, CAMEL_TYPE_TRANSPORT)
 
 /*CreateItem would return the MID of the new message or '0' if we fail.*/
 static mapi_id_t
-mapi_message_item_send (ExchangeMapiConnection *conn, MapiItem *item)
+mapi_message_item_send (ExchangeMapiConnection *conn, MailItem *item)
 {
 	guint64 fid = 0;
 	mapi_id_t mid = 0;
@@ -74,7 +75,7 @@ mapi_send_to (CamelTransport *transport, CamelMimeMessage *message,
 	      CamelAddress *from, CamelAddress *recipients, CamelException *ex)
 {
 	ExchangeMapiConnection *conn;
-	MapiItem *item = NULL;
+	MailItem *item = NULL;
 	const gchar *namep;
 	const gchar *addressp;
 	mapi_id_t st = 0;
@@ -95,7 +96,7 @@ mapi_send_to (CamelTransport *transport, CamelMimeMessage *message,
 		return FALSE;
 	}
 
-	/* Convert MIME to MAPIItem, attacment lists and recipient list.*/
+	/* Convert MIME to MailItem, attacment lists and recipient list.*/
 	item = camel_mapi_utils_mime_to_item (message, from, ex);
 
 	/* send */
diff --git a/src/camel/camel-mapi-utils.c b/src/camel/camel-mapi-utils.c
index 660063c..89af5d0 100644
--- a/src/camel/camel-mapi-utils.c
+++ b/src/camel/camel-mapi-utils.c
@@ -38,6 +38,7 @@
 
 #include <exchange-mapi-defs.h>
 #include "exchange-mapi-utils.h"
+#include "exchange-mapi-mail-utils.h"
 
 #include "camel-mapi-store.h"
 #include "camel-mapi-folder.h"
@@ -49,7 +50,7 @@
 #define STREAM_SIZE 4000
 
 static void
-mapi_item_add_recipient (const gchar *recipients, OlMailRecipientType type, GSList **recipient_list)
+mail_item_add_recipient (const gchar *recipients, OlMailRecipientType type, GSList **recipient_list)
 {
 	ExchangeMAPIRecipient *recipient;
 	uint32_t val = 0;
@@ -97,7 +98,7 @@ mapi_item_add_recipient (const gchar *recipients, OlMailRecipientType type, GSLi
 }
 
 static void
-mapi_item_set_from(MapiItem *item, const gchar *from)
+mail_item_set_from(MailItem *item, const gchar *from)
 {
 	if (item->header.from)
 		g_free (item->header.from);
@@ -106,7 +107,7 @@ mapi_item_set_from(MapiItem *item, const gchar *from)
 }
 
 static void
-mapi_item_set_subject(MapiItem *item, const gchar *subject)
+mail_item_set_subject(MailItem *item, const gchar *subject)
 {
 	if (item->header.subject)
 		g_free (item->header.subject);
@@ -117,7 +118,7 @@ mapi_item_set_subject(MapiItem *item, const gchar *subject)
 #define MAX_READ_SIZE 0x1000
 
 static void
-mapi_item_set_body_stream (MapiItem *item, CamelStream *body, MapiItemPartType part_type)
+mail_item_set_body_stream (MailItem *item, CamelStream *body, MailItemPartType part_type)
 {
 	guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
 	guint32	read_size = 0, i;
@@ -179,7 +180,7 @@ mapi_item_set_body_stream (MapiItem *item, CamelStream *body, MapiItemPartType p
 }
 
 static gboolean
-mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_stream)
+mail_item_add_attach (MailItem *item, CamelMimePart *part, CamelStream *content_stream)
 {
 	guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
 	const gchar *content_id = NULL;
@@ -252,7 +253,7 @@ mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_
 }
 
 static gboolean
-mapi_do_multipart (CamelMultipart *mp, MapiItem *item, gboolean *is_first)
+mapi_do_multipart (CamelMultipart *mp, MailItem *item, gboolean *is_first)
 {
 	CamelDataWrapper *dw;
 	CamelStream *content_stream;
@@ -291,19 +292,19 @@ mapi_do_multipart (CamelMultipart *mp, MapiItem *item, gboolean *is_first)
 		type = camel_mime_part_get_content_type(part);
 
 		if (i_part == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
-			mapi_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT);
+			mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT);
 			*is_first = FALSE;
 		} else if (camel_content_type_is (type, "text", "html")) {
-			mapi_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML);
+			mail_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML);
 		} else {
-			mapi_item_add_attach (item, part, content_stream);
+			mail_item_add_attach (item, part, content_stream);
 		}
 	}
 
 	return TRUE;
 }
 
-MapiItem *
+MailItem *
 camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, CamelException *ex)
 {
 	CamelDataWrapper *dw = NULL;
@@ -311,7 +312,7 @@ camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, Ca
 	CamelStream *content_stream;
 	CamelMultipart *multipart;
 	CamelInternetAddress *to, *cc, *bcc;
-	MapiItem *item = g_new0 (MapiItem, 1);
+	MailItem *item = g_new0 (MailItem, 1);
 	const gchar *namep;
 	const gchar *addressp;
 	const gchar *content_type;
@@ -333,25 +334,25 @@ camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, Ca
 		namep = NULL;
 	}
 
-	mapi_item_set_from (item, namep);
+	mail_item_set_from (item, namep);
 
 	to = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_TO);
 	for (i = 0; to && camel_internet_address_get (to, i, &namep, &addressp); i++) {
-		mapi_item_add_recipient (addressp, olTo, &recipient_list);
+		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++) {
-		mapi_item_add_recipient (addressp, olCC, &recipient_list);
+		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++) {
-		mapi_item_add_recipient (addressp, olBCC, &recipient_list);
+		mail_item_add_recipient (addressp, olBCC, &recipient_list);
 	}
 
 	if (camel_mime_message_get_subject(message)) {
-		mapi_item_set_subject(item, camel_mime_message_get_subject(message));
+		mail_item_set_subject(item, camel_mime_message_get_subject(message));
 	}
 
 	/*Add message threading properties */
@@ -375,7 +376,7 @@ camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, Ca
 			content_stream = (CamelStream *)camel_stream_mem_new();
 			content_size = camel_data_wrapper_decode_to_stream(dw, (CamelStream *)content_stream);
 
-			mapi_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT);
+			mail_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT);
 		}
 	}
 
@@ -388,7 +389,7 @@ gboolean
 camel_mapi_utils_create_item_build_props (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropValue **values, uint32_t *n_values, gpointer data)
 {
 
-	MapiItem *item = (MapiItem *) data;
+	MailItem *item = (MailItem *) data;
 	GSList *l;
 	bool send_rich_info;
 	uint32_t msgflag;
diff --git a/src/camel/camel-mapi-utils.h b/src/camel/camel-mapi-utils.h
index d28cfae..26ec846 100644
--- a/src/camel/camel-mapi-utils.h
+++ b/src/camel/camel-mapi-utils.h
@@ -26,7 +26,11 @@
 
 G_BEGIN_DECLS
 
-MapiItem *
+#include <exchange-mapi-connection.h>
+#include <exchange-mapi-mail-utils.h>
+#include <camel/camel.h>
+
+MailItem *
 camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, CamelException *ex);
 
 gboolean
diff --git a/src/libexchangemapi/Makefile.am b/src/libexchangemapi/Makefile.am
index 5466880..f4d5213 100644
--- a/src/libexchangemapi/Makefile.am
+++ b/src/libexchangemapi/Makefile.am
@@ -6,7 +6,8 @@ AM_CPPFLAGS =						\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)			\
 	$(LIBEDATASERVER_CFLAGS)			\
 	$(LIBECAL_CFLAGS)				\
-	$(LIBMAPI_CFLAGS)
+	$(LIBMAPI_CFLAGS)				\
+	$(CAMEL_CFLAGS)
 
 
 lib_LTLIBRARIES = libexchangemapi-1.0.la
@@ -28,14 +29,17 @@ libexchangemapi_1_0_la_SOURCES =		\
 	exchange-mapi-cal-tz-utils.c		\
 	exchange-mapi-cal-tz-utils.h		\
 	exchange-mapi-cal-recur-utils.c		\
-	exchange-mapi-cal-recur-utils.h
+	exchange-mapi-cal-recur-utils.h		\
+	exchange-mapi-mail-utils.c		\
+	exchange-mapi-mail-utils.h
 
 
 libexchangemapi_1_0_la_LIBADD =			\
 	$(EVOLUTION_DATA_SERVER_LIBS)		\
 	$(LIBEDATASERVER_LIBS)			\
 	$(LIBECAL_LIBS)				\
-	$(LIBMAPI_LIBS)
+	$(LIBMAPI_LIBS)				\
+	$(CAMEL_LIBS)
 
 libexchangemapi_1_0_la_LDFLAGS = $(NO_UNDEFINED)
 
@@ -48,7 +52,8 @@ libexchangemapiinclude_HEADERS = 		\
 	exchange-mapi-utils.h			\
 	exchange-mapi-cal-utils.h		\
 	exchange-mapi-cal-tz-utils.h		\
-	exchange-mapi-cal-recur-utils.h
+	exchange-mapi-cal-recur-utils.h		\
+	exchange-mapi-mail-utils.h
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libexchangemapi-$(EVO_MAPI_API_VERSION).pc
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.c b/src/libexchangemapi/exchange-mapi-cal-utils.c
index f930053..f329b88 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.c
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.c
@@ -1344,7 +1344,7 @@ fetch_camel_cal_comp_cb (FetchItemsCallbackData *item_data, gpointer data)
 }
 
 gchar *
-exchange_mapi_cal_util_camel_helper (ExchangeMapiConnection *conn, mapi_id_t orig_fid, mapi_id_t orig_mid, const gchar *msg_class,
+exchange_mapi_cal_util_camel_helper (ExchangeMapiConnection *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 };
@@ -1367,7 +1367,13 @@ exchange_mapi_cal_util_camel_helper (ExchangeMapiConnection *conn, mapi_id_t ori
 	} else
 		return NULL;
 
-	exchange_mapi_connection_fetch_item (conn, orig_fid, orig_mid,
+	if (obj_message)
+		exchange_mapi_connection_fetch_object_props (conn, NULL, orig_fid, obj_message,
+					exchange_mapi_cal_utils_get_props_cb, GINT_TO_POINTER (fccd.kind),
+					fetch_camel_cal_comp_cb, &fccd,
+					MAPI_OPTIONS_FETCH_ALL);
+	else
+		exchange_mapi_connection_fetch_item (conn, orig_fid, orig_mid,
 					exchange_mapi_cal_utils_get_props_cb, GINT_TO_POINTER (fccd.kind),
 					fetch_camel_cal_comp_cb, &fccd,
 					MAPI_OPTIONS_FETCH_ALL);
diff --git a/src/libexchangemapi/exchange-mapi-cal-utils.h b/src/libexchangemapi/exchange-mapi-cal-utils.h
index 2d110e9..196abd8 100644
--- a/src/libexchangemapi/exchange-mapi-cal-utils.h
+++ b/src/libexchangemapi/exchange-mapi-cal-utils.h
@@ -91,7 +91,7 @@ void
 exchange_mapi_cal_util_generate_globalobjectid (gboolean is_clean, const gchar *uid, struct Binary_r *sb);
 
 gchar *
-exchange_mapi_cal_util_camel_helper (ExchangeMapiConnection *conn, mapi_id_t fid, mapi_id_t mid, const gchar *msg_class,
+exchange_mapi_cal_util_camel_helper (ExchangeMapiConnection *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
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index e503bc9..e6dba42 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -26,9 +26,12 @@
 #include <config.h>
 #endif
 
+#include <camel/camel.h>
+
 #include "exchange-mapi-connection.h"
 #include "exchange-mapi-folder.h"
 #include "exchange-mapi-utils.h"
+#include "exchange-mapi-mail-utils.h"
 #include <param.h>
 
 #define DEFAULT_PROF_PATH ".evolution/mapi-profiles.ldb"
@@ -802,9 +805,48 @@ exchange_mapi_util_set_attachments (mapi_object_t *obj_message, GSList *attach_l
 	return status;
 }
 
+static GByteArray *
+obj_message_to_camel_mime (ExchangeMapiConnection *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);
+
+	if (!exchange_mapi_connection_fetch_object_props (conn, NULL, fid, obj_msg, mapi_mail_get_item_prop_list, NULL,
+					fetch_props_to_mail_item_cb, &item,
+					MAPI_OPTIONS_FETCH_ALL | MAPI_OPTIONS_GETBESTBODY)
+	    || item == NULL) {
+		if (item)
+			mail_item_free (item);
+
+		return NULL;
+	}
+
+	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 ();
+
+		mem = camel_stream_mem_new ();
+		camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), res);
+		camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (msg), mem);
+
+		g_object_unref (mem);
+		g_object_unref (msg);
+	}
+
+	return res;
+}
+
 /* Returns TRUE if all attachments were read succcesfully, else returns FALSE */
 static gboolean
-exchange_mapi_util_get_attachments (mapi_object_t *obj_message, GSList **attach_list)
+exchange_mapi_util_get_attachments (ExchangeMapiConnection *conn, mapi_id_t fid, mapi_object_t *obj_message, GSList **attach_list)
 {
 	enum MAPISTATUS		retval;
 	TALLOC_CTX		*mem_ctx;
@@ -880,19 +922,64 @@ exchange_mapi_util_get_attachments (mapi_object_t *obj_message, GSList **attach_
 		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++)
+		for (z=0; z < properties.cValues; z++) {
 			cast_SPropValue (&properties.lpProps[z], &(attachment->lpProps[z]));
 
+			if ((attachment->lpProps[z].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[z].ulPropTag & 0xFFFF0000) | PT_UNICODE);
+				if (MAPI_E_SUCCESS == GetProps (&obj_attach, tags, &lpProps, &prop_count) && prop_count == 1 && lpProps) {
+					if ((lpProps->ulPropTag & 0xFFFF) == PT_UNICODE)
+						attachment->lpProps[z] = *lpProps;
+				}
+				MAPIFreeBuffer (tags);
+			}
+		}
+
 		/* just to get all the other streams */
 		for (z=0; z < properties.cValues; z++) {
 			if ((properties.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY)
 				exchange_mapi_util_read_generic_stream (&obj_attach, properties.lpProps[z].ulPropTag, &(attachment->streams));
 		}
 
-		/* HACK */
 		ui32 = (const uint32_t *) get_SPropValue_SRow_data(&rows_attach.aRow[i_row_attach], PR_ATTACH_METHOD);
-		if (ui32 && *ui32 == ATTACH_BY_VALUE)
+		if (ui32 && *ui32 == ATTACH_BY_VALUE) {
 			exchange_mapi_util_read_generic_stream (&obj_attach, PR_ATTACH_DATA_BIN, &(attachment->streams));
+		} 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);
+					struct mapi_SPropValue_array properties_array;
+
+					stream->value = bytes;
+
+					/* Build a mapi_SPropValue_array structure */
+					properties_array.cValues = 1;
+					properties_array.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, properties_array.cValues + 1);
+					properties_array.lpProps[0].ulPropTag = PR_ATTACH_DATA_BIN;
+					/* This call is needed in case the read stream was a named prop. */
+					mapi_SPropValue_array_named (obj_message, &properties_array);
+
+					stream->proptag = properties_array.lpProps[0].ulPropTag;
+
+					attachment->streams = g_slist_append (attachment->streams, stream);
+				}
+			}
+
+			mapi_object_release (&obj_emb_msg);
+		}
 
 		*attach_list = g_slist_append (*attach_list, attachment);
 
@@ -1390,7 +1477,7 @@ exchange_mapi_connection_fetch_items   (ExchangeMapiConnection *conn, mapi_id_t
 			}
 
 			if (has_attach && *has_attach && (MAPI_OPTIONS_FETCH_ATTACHMENTS & options)) {
-				exchange_mapi_util_get_attachments (&obj_message, &attach_list);
+				exchange_mapi_util_get_attachments (conn, fid, &obj_message, &attach_list);
 			}
 
 			if (options & MAPI_OPTIONS_FETCH_RECIPIENTS)
@@ -1499,45 +1586,30 @@ exchange_mapi_connection_fetch_items   (ExchangeMapiConnection *conn, mapi_id_t
 	return result;
 }
 
+/* obj_folder and obj_message are released only when obj_folder is not NULL and when returned TRUE */
 gboolean
-exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid, mapi_id_t mid,
+exchange_mapi_connection_fetch_object_props (ExchangeMapiConnection *conn, mapi_object_t *obj_folder, mapi_id_t fid, mapi_object_t *obj_message,
 				     BuildReadPropsCB build_props, gpointer brp_data,
 				     FetchCallback cb, gpointer data,
 				     guint32 options)
 {
 	enum MAPISTATUS retval;
 	TALLOC_CTX *mem_ctx;
-	mapi_object_t obj_folder;
-	mapi_object_t obj_message;
 	struct mapi_SPropValue_array properties_array;
-	struct SPropTagArray *propsTagArray;
+	struct SPropTagArray *propsTagArray = NULL;
 	GSList *attach_list = NULL;
 	GSList *recip_list = NULL;
 	GSList *stream_list = NULL;
 	gboolean result = FALSE;
+	mapi_id_t mid;
 
 	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
 	g_return_val_if_fail (priv->session != NULL, FALSE);
 
-	g_debug("%s: Entering %s: folder-id %016" G_GINT64_MODIFIER "X message-id %016" G_GINT64_MODIFIER "X",
-				G_STRLOC, G_STRFUNC, fid, mid);
+	g_debug("%s: Entering %s: folder %p message %p", G_STRLOC, G_STRFUNC, obj_folder, obj_message);
 
 	LOCK ();
-	mem_ctx = talloc_init("ExchangeMAPI_FetchItem");
-	mapi_object_init(&obj_folder);
-	mapi_object_init(&obj_message);
-
-	if ((options & MAPI_OPTIONS_USE_PFSTORE) != 0) {
-		if (!ensure_public_store (priv))
-			goto cleanup;
-	}
-
-	/* Attempt to open the folder */
-	retval = OpenFolder (((options & MAPI_OPTIONS_USE_PFSTORE) != 0 ? &priv->public_store : &priv->msg_store), fid, &obj_folder);
-	if (retval != MAPI_E_SUCCESS) {
-		mapi_errstr("OpenFolder", GetLastError());
-		goto cleanup;
-	}
+	mem_ctx = talloc_init("ExchangeMAPI_FetchObjectProps");
 
 	if (build_props) {
 		propsTagArray = set_SPropTagArray (mem_ctx, 0x1, PR_MESSAGE_CLASS);
@@ -1547,24 +1619,17 @@ exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid
 		}
 	}
 
-	/* Open the item */
-	retval = OpenMessage(&obj_folder, fid, mid, &obj_message, 0x0);
-	if (retval != MAPI_E_SUCCESS) {
-		mapi_errstr("OpenMessage", GetLastError());
-		goto cleanup;
-	}
-
 	/* Fetch attachments */
 	if (options & MAPI_OPTIONS_FETCH_ATTACHMENTS)
-		exchange_mapi_util_get_attachments (&obj_message, &attach_list);
+		exchange_mapi_util_get_attachments (conn, fid, obj_message, &attach_list);
 
 	/* Fetch recipients */
 	if (options & MAPI_OPTIONS_FETCH_RECIPIENTS)
-		exchange_mapi_util_get_recipients (&obj_message, &recip_list);
+		exchange_mapi_util_get_recipients (obj_message, &recip_list);
 
 	/* get the main body stream no matter what */
 	if (options & MAPI_OPTIONS_FETCH_BODY_STREAM)
-		exchange_mapi_util_read_body_stream (&obj_message, &stream_list,
+		exchange_mapi_util_read_body_stream (obj_message, &stream_list,
 			options & MAPI_OPTIONS_GETBESTBODY);
 
 	if (propsTagArray && propsTagArray->cValues) {
@@ -1572,7 +1637,7 @@ exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid
 		uint32_t prop_count = 0, k;
 
 		lpProps = talloc_zero(mem_ctx, struct SPropValue);
-		retval = GetProps (&obj_message, propsTagArray, &lpProps, &prop_count);
+		retval = GetProps (obj_message, propsTagArray, &lpProps, &prop_count);
 
 		/* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
 		properties_array.cValues = prop_count;
@@ -1581,7 +1646,7 @@ exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid
 			cast_mapi_SPropValue(&properties_array.lpProps[k], &lpProps[k]);
 
 	} else
-		retval = GetPropsAll (&obj_message, &properties_array);
+		retval = GetPropsAll (obj_message, &properties_array);
 
 	if (retval == MAPI_E_SUCCESS) {
 		uint32_t z;
@@ -1589,14 +1654,19 @@ exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid
 		/* just to get all the other streams */
 		for (z=0; z < properties_array.cValues; z++)
 			if ((properties_array.lpProps[z].ulPropTag & 0xFFFF) == PT_BINARY && (options & MAPI_OPTIONS_FETCH_GENERIC_STREAMS))
-				exchange_mapi_util_read_generic_stream (&obj_message, properties_array.lpProps[z].ulPropTag, &stream_list);
+				exchange_mapi_util_read_generic_stream (obj_message, properties_array.lpProps[z].ulPropTag, &stream_list);
 
-		mapi_SPropValue_array_named(&obj_message, &properties_array);
+		mapi_SPropValue_array_named (obj_message, &properties_array);
 	}
 
+	mid = mapi_object_get_id (obj_message);
+
 	/* Release the objects so that the callback may use the store. */
-	mapi_object_release(&obj_message);
-	mapi_object_release(&obj_folder);
+	if (obj_folder) {
+		/* obj_folder is not NULL, thus can do this */
+		mapi_object_release (obj_message);
+		mapi_object_release (obj_folder);
+	}
 
 	if (retval == MAPI_E_SUCCESS) {
 		FetchItemsCallbackData *item_data = g_new0 (FetchItemsCallbackData, 1);
@@ -1618,20 +1688,70 @@ exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid
 		exchange_mapi_util_free_attachment_list (&attach_list);
 	}
 
-//	if (propsTagArray->cValues)
-//		talloc_free (properties_array.lpProps);
-
 	result = TRUE;
 
 cleanup:
+	talloc_free (mem_ctx);
+	UNLOCK ();
+
+	g_debug("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+
+	return result;
+}
+
+gboolean
+exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid, mapi_id_t mid,
+				     BuildReadPropsCB build_props, gpointer brp_data,
+				     FetchCallback cb, gpointer data,
+				     guint32 options)
+{
+	enum MAPISTATUS retval;
+	TALLOC_CTX *mem_ctx;
+	mapi_object_t obj_folder;
+	mapi_object_t obj_message;
+	gboolean result = FALSE;
+
+	CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+	g_return_val_if_fail (priv->session != NULL, FALSE);
+
+	g_debug("%s: Entering %s: folder-id %016" G_GINT64_MODIFIER "X message-id %016" G_GINT64_MODIFIER "X",
+				G_STRLOC, G_STRFUNC, fid, mid);
+
+	LOCK ();
+	mem_ctx = talloc_init("ExchangeMAPI_FetchItem");
+	mapi_object_init(&obj_folder);
+	mapi_object_init(&obj_message);
+
+	if ((options & MAPI_OPTIONS_USE_PFSTORE) != 0) {
+		if (!ensure_public_store (priv))
+			goto cleanup;
+	}
+
+	/* Attempt to open the folder */
+	retval = OpenFolder (((options & MAPI_OPTIONS_USE_PFSTORE) != 0 ? &priv->public_store : &priv->msg_store), fid, &obj_folder);
+	if (retval != MAPI_E_SUCCESS) {
+		mapi_errstr("OpenFolder", GetLastError());
+		goto cleanup;
+	}
+
+	/* Open the item */
+	retval = OpenMessage(&obj_folder, fid, mid, &obj_message, 0x0);
+	if (retval != MAPI_E_SUCCESS) {
+		mapi_errstr("OpenMessage", GetLastError());
+		goto cleanup;
+	}
+
+	result = exchange_mapi_connection_fetch_object_props (conn, &obj_folder, fid, &obj_message, build_props, brp_data, cb, data, options);
+
+cleanup:
 	if (!result) {
-		mapi_object_release(&obj_message);
-		mapi_object_release(&obj_folder);
+		mapi_object_release (&obj_message);
+		mapi_object_release (&obj_folder);
 	}
 	talloc_free (mem_ctx);
 	UNLOCK ();
 
-	g_debug("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+	g_debug ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
 	return result;
 }
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index b75e1f8..42e3c0e 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -153,6 +153,13 @@ ExchangeMapiConnection *exchange_mapi_connection_find (const gchar *profile);
 gboolean		exchange_mapi_connection_reconnect (ExchangeMapiConnection *conn, const gchar *password);
 gboolean		exchange_mapi_connection_close (ExchangeMapiConnection *conn);
 gboolean		exchange_mapi_connection_connected (ExchangeMapiConnection *conn);
+
+gboolean		exchange_mapi_connection_fetch_object_props (
+					ExchangeMapiConnection *conn, mapi_object_t *obj_folder, mapi_id_t fid, mapi_object_t *obj_message,
+					BuildReadPropsCB build_props, gpointer brp_data,
+					FetchCallback cb, gpointer data,
+					guint32 options);
+
 gboolean		exchange_mapi_connection_fetch_item (ExchangeMapiConnection *conn, mapi_id_t fid, mapi_id_t mid,
 					BuildReadPropsCB build_props, gpointer brp_data,
 					FetchCallback cb, gpointer data,
diff --git a/src/libexchangemapi/exchange-mapi-mail-utils.c b/src/libexchangemapi/exchange-mapi-mail-utils.c
new file mode 100644
index 0000000..9d671fc
--- /dev/null
+++ b/src/libexchangemapi/exchange-mapi-mail-utils.c
@@ -0,0 +1,720 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <camel/camel.h>
+
+#include "exchange-mapi-defs.h"
+#include "exchange-mapi-utils.h"
+#include "exchange-mapi-cal-utils.h"
+#include "exchange-mapi-mail-utils.h"
+
+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);
+
+	exchange_mapi_util_free_attachment_list (&item->attachments);
+	exchange_mapi_util_free_stream_list (&item->generic_streams);
+	exchange_mapi_util_free_recipient_list (&item->recipients);
+
+	g_free (item);
+}
+
+gboolean
+fetch_props_to_mail_item_cb (FetchItemsCallbackData *item_data, gpointer data)
+{
+	long *flags;
+	struct FILETIME *delivery_date;
+	const gchar *msg_class;
+	NTTIME ntdate;
+	ExchangeMAPIStream *body;
+
+	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")) {
+		exchange_mapi_debug_property_dump (item_data->properties);
+		camel_debug_end();
+	}
+
+	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++) {
+
+		gconstpointer prop_data = get_mapi_SPropValue_data(&item_data->properties->lpProps[j]);
+
+		if (fetch_read_item_common_data (item, item_data->properties->lpProps[j].ulPropTag, prop_data))
+			continue;
+
+		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:
+			break;
+		}
+	}
+
+	item->is_cal = FALSE;
+	if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX)) {
+		guint8 *appointment_body_str = (guint8 *) exchange_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));
+
+			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
+			item->is_cal = TRUE;
+		}
+
+		g_free (appointment_body_str);
+	}
+
+	if (!item->is_cal) {
+		/* always prefer unicode version, as that can be properly read */
+		if (!(body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY_UNICODE)))
+			body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY);
+
+		if (body)
+			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
+
+		body = exchange_mapi_util_find_stream (item_data->streams, PR_HTML);
+		if (body)
+			item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
+	}
+
+	if (delivery_date) {
+		ntdate = delivery_date->dwHighDateTime;
+		ntdate = ntdate << 32;
+		ntdate |= delivery_date->dwLowDateTime;
+		item->header.recieved_time = nt_time_to_unix(ntdate);
+	}
+
+	if ((*flags & MSGFLAG_READ) != 0)
+		item->header.flags |= CAMEL_MESSAGE_SEEN;
+	if ((*flags & MSGFLAG_HASATTACH) != 0)
+		item->header.flags |= CAMEL_MESSAGE_ATTACHMENTS;
+
+	item->attachments = item_data->attachments;
+
+	*i = item;
+
+	return TRUE;
+}
+
+gboolean
+fetch_read_item_common_data (MailItem *item, uint32_t propTag, gconstpointer prop_data)
+{
+	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, utf8tolinux (prop_data));
+		break;
+	case PR_SUBJECT_UNICODE :
+		sv (item->header.subject, g_strdup (prop_data));
+		break;
+	case PR_DISPLAY_TO :
+		sv (item->header.to, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (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, utf8tolinux (prop_data));
+		break;
+	case PR_TRANSPORT_MESSAGE_HEADERS_UNICODE:
+		sv (item->header.transport_headers, g_strdup (prop_data));
+		break;
+	default:
+		found = FALSE;
+		break;
+	}
+
+	#undef sv
+
+	return found;
+}
+
+gboolean
+mapi_mail_get_item_prop_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data)
+{
+	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,
+		/*Fixme : If this property is fetched, it garbles everything else. */
+		/*PR_BODY_HTML, */
+		/*PR_BODY_HTML_UNICODE, */
+
+		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
+	};
+
+	g_return_val_if_fail (props != NULL, FALSE);
+
+	return exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, item_props, G_N_ELEMENTS (item_props));
+}
+
+
+static void
+mapi_mime_set_recipient_list (CamelMimeMessage *msg, MailItem *item)
+{
+	GSList *l = NULL;
+	CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
+
+	g_return_if_fail (item->recipients != NULL);
+
+	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;
+		const gchar *name = NULL;
+		uint32_t rcpt_type = MAPI_TO;
+		uint32_t *type = NULL;
+		struct SRow *aRow;
+		ExchangeMAPIRecipient *recip = (ExchangeMAPIRecipient *)(l->data);
+
+		/*Can't continue when there is no email-id*/
+		if (!recip->email_id)
+			continue;
+
+		/* Build a SRow structure */
+		aRow = &recip->out_SRow;
+
+		/*Name is probably available in one of these props.*/
+		name = (const gchar *) exchange_mapi_util_find_row_propval (aRow, PR_DISPLAY_NAME_UNICODE);
+		name = name ? name : (const gchar *) exchange_mapi_util_find_row_propval (aRow, PR_RECIPIENT_DISPLAY_NAME_UNICODE);
+		name = name ? name : (const gchar *) exchange_mapi_util_find_row_propval (aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
+
+		type = (uint32_t *) exchange_mapi_util_find_row_propval (aRow, PR_RECIPIENT_TYPE);
+
+		/*Fallbacks. Not good*/
+		display_name = name ? g_strdup (name) : g_strdup (recip->email_id);
+		rcpt_type = (type ? *type : MAPI_TO);
+
+		switch (rcpt_type) {
+		case MAPI_TO:
+			camel_internet_address_add (to_addr, display_name, recip->email_id);
+			break;
+		case MAPI_CC:
+			camel_internet_address_add (cc_addr, display_name, recip->email_id);
+			break;
+		case MAPI_BCC:
+			camel_internet_address_add (bcc_addr, display_name, recip->email_id);
+			break;
+		}
+
+		g_free (display_name);
+	}
+
+	/*Add to message*/
+	/*Note : To field is added from PR_TRANSPORT_MESSAGE_HEADERS
+	  But, in sent_items folder we don't get TRANSPORT_MESSAGE_HEADERS */
+	if (!item->header.transport_headers) {
+		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);
+	}
+
+	/*TODO : Unref *_addr ? */
+}
+
+static void
+mapi_mime_set_msg_headers (ExchangeMapiConnection *conn, CamelMimeMessage *msg, MailItem *item)
+{
+	gchar *temp_str = NULL;
+	const gchar *from_email;
+	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);
+		camel_mime_parser_scan_from (parser, FALSE);
+		g_object_unref (stream);
+
+		if (camel_mime_part_construct_from_parser (part, parser) != -1) {
+			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);
+	}
+
+	/* Overwrite headers if we have specific properties available*/
+	temp_str = item->header.subject;
+	if (temp_str)
+		camel_mime_message_set_subject (msg, temp_str);
+
+	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.from) {
+		if ((item->header.from_type != NULL) && !g_utf8_collate (item->header.from_type, "EX")) {
+			from_email = exchange_mapi_connection_ex_to_smtp (conn, item->header.from_email);
+			g_free (item->header.from_email);
+			item->header.from_email = g_strdup (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);
+
+}
+
+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) {
+		const gchar * type = NULL;
+		gchar *buff = NULL;
+
+		if (item->is_cal)
+			type = "text/calendar";
+		else
+			type = (body->proptag == PR_BODY || body->proptag == PR_BODY_UNICODE) ?
+				"text/plain" : "text/html";
+
+		if (item->header.cpid) {
+			if (item->header.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)
+				buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
+			else if (item->header.cpid == 28605)
+				buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
+			else if (item->header.cpid == 65000)
+				buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
+			else if (item->header.cpid == 65001)
+				buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
+			else
+				buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, item->header.cpid);
+			type = buff;
+		}
+
+		camel_mime_part_set_content (part, (const gchar *) body->value->data, body->value->len, type);
+
+		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 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;
+	}
+
+	for (bidx = 0; bidx < G_N_ELEMENTS (desired_order); bidx++) {
+		if (desired_order[bidx] == stream_b->proptag)
+			break;
+	}
+
+	return aidx - bidx;
+}
+
+#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 || stream->proptag == PR_BODY_HTML_UNICODE)
+		    && 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);
+	}
+
+	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;
+}
+
+/*Takes raw attachment streams and converts to MIME Parts. Parts are added to
+  either inline / non-inline lists.*/
+static void
+mapi_mime_classify_attachments (GSList *attachments, GSList **inline_attachs, GSList **noninline)
+{
+	for (;attachments != NULL; attachments = attachments->next) {
+		ExchangeMAPIAttachment *attach = (ExchangeMAPIAttachment *)attachments->data;
+		ExchangeMAPIStream *stream = NULL;
+		const gchar *filename, *mime_type, *content_id = NULL;
+		CamelContentType *content_type;
+		CamelMimePart *part;
+
+		stream = exchange_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
+
+		if (!stream || stream->value->len <= 0) {
+			continue;
+		}
+
+		part = camel_mime_part_new ();
+
+		filename = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
+											 PR_ATTACH_LONG_FILENAME_UNICODE);
+
+		if (!(filename && *filename))
+			filename = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
+												 PR_ATTACH_FILENAME_UNICODE);
+		camel_mime_part_set_filename(part, g_strdup(filename));
+		camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
+
+		/*Content-Type*/
+		mime_type = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_MIME_TAG);
+		if (!mime_type) {
+			const uint32_t *ui32 = (const uint32_t *) exchange_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_METHOD);
+			if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG)
+				mime_type = "message/rfc822";
+		}
+		if (!mime_type)
+			mime_type = "application/octet-stream";
+
+		camel_mime_part_set_content (part, (const gchar *) stream->value->data, stream->value->len, 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
+			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
+
+		/*Content-ID*/
+		content_id = (const gchar *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
+											   PR_ATTACH_CONTENT_ID);
+		/* TODO : Add disposition */
+		if (content_id) {
+			camel_mime_part_set_content_id (part, content_id);
+			*inline_attachs = g_slist_append (*inline_attachs, part);
+		} else
+			*noninline = g_slist_append (*noninline, part);
+	}
+}
+
+CamelMimeMessage *
+mapi_mail_item_to_mime_message (ExchangeMapiConnection *conn, MailItem *item)
+{
+	CamelMimeMessage *msg = NULL;
+	CamelMultipart *multipart_body = NULL;
+
+	GSList *attach_list = NULL;
+	GSList *inline_attachs =  NULL; /*Used for mulitpart/related*/
+	GSList *noninline_attachs = NULL;
+
+	gboolean build_alternative = FALSE;
+	gboolean build_related = FALSE;
+
+	g_return_val_if_fail (conn != NULL, NULL);
+	g_return_val_if_fail (item != NULL, NULL);
+
+	attach_list = item->attachments;
+	msg = camel_mime_message_new ();
+
+	mapi_mime_set_recipient_list (msg, item);
+	mapi_mime_set_msg_headers (conn, msg, item);
+	mapi_mime_classify_attachments (attach_list, &inline_attachs, &noninline_attachs);
+
+	build_alternative = (g_slist_length (item->msg.body_parts) > 1) && inline_attachs;
+	build_related = !build_alternative && inline_attachs;
+
+	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->data,
+								    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);
+		g_object_unref (part);
+	}
+
+	if (noninline_attachs) { /* multipart/mixed */
+		multipart_body = mapi_mime_build_multipart_mixed (multipart_body,
+								  noninline_attachs);
+	}
+
+	camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart_body));
+	g_object_unref (multipart_body);
+
+	return msg;
+}
diff --git a/src/libexchangemapi/exchange-mapi-mail-utils.h b/src/libexchangemapi/exchange-mapi-mail-utils.h
new file mode 100644
index 0000000..295e926
--- /dev/null
+++ b/src/libexchangemapi/exchange-mapi-mail-utils.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef EXCHANGE_MAPI_MAIL_UTILS_H
+#define EXCHANGE_MAPI_MAIL_UTILS_H 
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <libmapi/libmapi.h>
+
+#include <exchange-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;
+} MailItemHeader;
+
+typedef struct {
+	GSList *body_parts;
+} MailItemMessage;
+
+typedef struct  {
+	mapi_id_t fid;
+	mapi_id_t mid;
+
+	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);
+
+/* 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 (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data);
+
+struct _CamelMimeMessage;
+struct _CamelMimeMessage *mapi_mail_item_to_mime_message (ExchangeMapiConnection *conn, MailItem *item);
+
+#endif /* EXCHANGE_MAPI_MAIL_UTILS */
diff --git a/src/libexchangemapi/exchange-mapi-utils.h b/src/libexchangemapi/exchange-mapi-utils.h
index 7c78145..57a37b0 100644
--- a/src/libexchangemapi/exchange-mapi-utils.h
+++ b/src/libexchangemapi/exchange-mapi-utils.h
@@ -80,4 +80,3 @@ gboolean exchange_mapi_utils_add_spropvalue_named_id (ExchangeMapiConnection *co
 uint32_t exchange_mapi_utils_push_crc32 (uint32_t crc32, uint8_t *bytes, uint32_t n_bytes);
 
 #endif
-



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