[evolution-mapi] Bug #618514 - Forwarded messages as attachments encoded incorrectly
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug #618514 - Forwarded messages as attachments encoded incorrectly
- Date: Tue, 8 Mar 2011 13:49:26 +0000 (UTC)
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]