"Fossies" - the Fresh Open Source Software Archive

Member "evolution-mapi-3.46.1/src/libexchangemapi/e-mapi-mail-utils.c" (2 Dec 2022, 55333 Bytes) of package /linux/misc/evolution-mapi-3.46.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "e-mapi-mail-utils.c" see the Fossies "Dox" file reference documentation.

    1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
    2 /*
    3  * This program is free software; you can redistribute it and/or
    4  * modify it under the terms of the GNU Lesser General Public
    5  * License as published by the Free Software Foundation; either
    6  * version 2 of the License, or (at your option) version 3.
    7  *
    8  * This program is distributed in the hope that it will be useful,
    9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   11  * Lesser General Public License for more details.
   12  *
   13  * You should have received a copy of the GNU Lesser General Public
   14  * License along with the program; if not, see <http://www.gnu.org/licenses/>
   15  *
   16  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
   17  *
   18  */
   19 
   20 #include "evolution-mapi-config.h"
   21 
   22 #include <camel/camel.h>
   23 #include <libecal/libecal.h>
   24 
   25 #include "e-mapi-defs.h"
   26 #include "e-mapi-utils.h"
   27 #include "e-mapi-book-utils.h"
   28 #include "e-mapi-cal-utils.h"
   29 #include "e-mapi-mail-utils.h"
   30 
   31 #define STREAM_SIZE 4000
   32 
   33 void
   34 e_mapi_mail_utils_decode_email_address (EMapiConnection *conn,
   35                     struct mapi_SPropValue_array *properties,
   36                     const uint32_t *name_proptags,
   37                     guint name_proptags_len,
   38                     const uint32_t *smtp_proptags,
   39                     guint smtp_proptags_len,
   40                     uint32_t email_type_proptag,
   41                     uint32_t email_proptag,
   42                     gchar **name,
   43                     gchar **email)
   44 {
   45     gint ii;
   46     const gchar *cname = NULL, *cemail = NULL;
   47     const gchar *addr_type, *email_addr;
   48 
   49     g_return_if_fail (conn != NULL);
   50     g_return_if_fail (properties != NULL);
   51     g_return_if_fail (name_proptags_len == 0 || name_proptags != NULL);
   52     g_return_if_fail (smtp_proptags_len == 0 || smtp_proptags != NULL);
   53     g_return_if_fail (name != NULL);
   54     g_return_if_fail (email != NULL);
   55 
   56     *name = NULL;
   57     *email = NULL;
   58 
   59     for (ii = 0; ii < name_proptags_len && !cname; ii++) {
   60         cname = e_mapi_util_find_array_propval (properties, name_proptags[ii]);
   61     }
   62 
   63     addr_type = e_mapi_util_find_array_propval (properties, email_type_proptag);
   64     email_addr = e_mapi_util_find_array_propval (properties, email_proptag);
   65 
   66     if (addr_type && g_ascii_strcasecmp (addr_type, "SMTP") == 0)
   67         cemail = email_addr;
   68 
   69     for (ii = 0; ii < smtp_proptags_len && !cemail; ii++) {
   70         cemail = e_mapi_util_find_array_propval (properties, smtp_proptags[ii]);
   71     }
   72 
   73     if (!cemail && addr_type && g_ascii_strcasecmp (addr_type, "EX") == 0 && email_addr) {
   74         *email = e_mapi_connection_ex_to_smtp (conn, email_addr, name, NULL, NULL);
   75     }
   76 
   77     if (!*email) {
   78         *name = g_strdup (cname);
   79         *email = g_strdup (cemail);
   80     }
   81 }
   82 
   83 void
   84 e_mapi_mail_utils_decode_email_address1 (EMapiConnection *conn,
   85                      struct mapi_SPropValue_array *properties,
   86                      uint32_t name_proptag,
   87                      uint32_t email_proptag,
   88                      uint32_t email_type_proptag,
   89                      gchar **name,
   90                      gchar **email)
   91 {
   92     uint32_t names[1];
   93 
   94     names[0] = name_proptag;
   95 
   96     e_mapi_mail_utils_decode_email_address (conn, properties, names, 1, NULL, 0, email_type_proptag, email_proptag, name, email);
   97 }
   98 
   99 void
  100 e_mapi_mail_utils_decode_recipients (EMapiConnection *conn,
  101                      EMapiRecipient *recipients,
  102                      CamelAddress *to_addr,
  103                      CamelAddress *cc_addr,
  104                      CamelAddress *bcc_addr)
  105 {
  106     const uint32_t name_proptags[] = {
  107         PROP_TAG (PT_UNICODE, 0x6001), /* PidTagNickname for Recipients table */
  108         PidTagNickname,
  109         PidTagDisplayName,
  110         PidTagRecipientDisplayName,
  111         PidTagAddressBookDisplayNamePrintable
  112     };
  113 
  114     const uint32_t email_proptags[] = {
  115         PidTagSmtpAddress
  116     };
  117 
  118     EMapiRecipient *recipient;
  119 
  120     g_return_if_fail (conn != NULL);
  121     g_return_if_fail (to_addr != NULL);
  122     g_return_if_fail (cc_addr != NULL);
  123     g_return_if_fail (bcc_addr != NULL);
  124 
  125     for (recipient = recipients; recipient; recipient = recipient->next) {
  126         const uint32_t *recip_type = e_mapi_util_find_array_propval (&recipient->properties, PidTagRecipientType);
  127         gchar *name = NULL, *email = NULL;
  128         CamelAddress *addr = NULL;
  129 
  130         if (!recip_type)
  131             continue;
  132 
  133         switch (*recip_type) {
  134         case MAPI_TO:
  135             addr = to_addr;
  136             break;
  137         case MAPI_CC:
  138             addr = cc_addr;
  139             break;
  140         case MAPI_BCC:
  141             addr = bcc_addr;
  142             break;
  143         default:
  144             break;
  145         }
  146 
  147         if (!addr)
  148             continue;
  149 
  150         e_mapi_mail_utils_decode_email_address (conn, &recipient->properties,
  151                     name_proptags, G_N_ELEMENTS (name_proptags),
  152                     email_proptags, G_N_ELEMENTS (email_proptags),
  153                     PidTagAddressType, PidTagEmailAddress,
  154                     &name, &email);
  155 
  156         camel_internet_address_add (CAMEL_INTERNET_ADDRESS (addr), name, email ? email : "");
  157 
  158         g_free (name);
  159         g_free (email);
  160     }
  161 }
  162 
  163 static void
  164 build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t proptag)
  165 {
  166     uint64_t str_cb = 0;
  167     const uint8_t *str_lpb = NULL;
  168 
  169     g_return_if_fail (part != NULL);
  170     g_return_if_fail (object != NULL);
  171     g_return_if_fail (proptag == PidTagHtml || proptag == PidTagBody);
  172 
  173     camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
  174 
  175     if (e_mapi_object_get_bin_prop (object, proptag, &str_cb, &str_lpb)) {
  176         const gchar *type = NULL;
  177         gchar *buff = NULL, *in_utf8;
  178         const uint32_t *pcpid = e_mapi_util_find_array_propval (&object->properties, PidTagInternetCodepage);
  179 
  180         if (proptag == PidTagBody) {
  181             type = "text/plain";
  182         } else {
  183             type = "text/html";
  184         }
  185 
  186         if (!e_mapi_util_find_array_proptag (&object->properties, proptag)) {
  187             EMapiStreamedProp *stream = e_mapi_object_get_streamed (object, proptag);
  188             if (stream)
  189                 proptag = stream->proptag;
  190         } else {
  191             proptag = e_mapi_util_find_array_proptag (&object->properties, proptag);
  192         }
  193 
  194         if (pcpid && *pcpid && (proptag & 0xFFFF) != PT_UNICODE) {
  195             uint32_t cpid = *pcpid;
  196 
  197             if (cpid == 20127)
  198                 buff = g_strdup_printf ("%s; charset=\"us-ascii\"", type);
  199             else if (cpid == 20866)
  200                 buff = g_strdup_printf ("%s; charset=\"koi8-r\"", type);
  201             else if (cpid >= 28591 && cpid <= 28599)
  202                 buff = g_strdup_printf ("%s; charset=\"ISO-8859-%d\"", type, cpid % 10);
  203             else if (cpid == 28603)
  204                 buff = g_strdup_printf ("%s; charset=\"ISO-8859-13\"", type);
  205             else if (cpid == 28605)
  206                 buff = g_strdup_printf ("%s; charset=\"ISO-8859-15\"", type);
  207             else if (cpid == 65000)
  208                 buff = g_strdup_printf ("%s; charset=\"UTF-7\"", type);
  209             else if (cpid == 65001)
  210                 buff = g_strdup_printf ("%s; charset=\"UTF-8\"", type);
  211             else
  212                 buff = g_strdup_printf ("%s; charset=\"CP%d\"", type, cpid);
  213             type = buff;
  214         }
  215 
  216         in_utf8 = NULL;
  217 
  218         if (proptag == PidTagHtml) {
  219             if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, str_lpb, str_cb, &in_utf8))
  220                 camel_mime_part_set_content (part, in_utf8, strlen (in_utf8), type);
  221             else
  222                 camel_mime_part_set_content (part, (const gchar *) str_lpb, str_cb, type);
  223             
  224         } else {
  225             if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, str_lpb, str_cb, &in_utf8)) {
  226                 str_lpb = (const uint8_t *) in_utf8;
  227                 str_cb = strlen (in_utf8);
  228             }
  229 
  230             /* cannot set an empty content */
  231             if (!str_cb)
  232                 camel_mime_part_set_content (part, " ", 1, type);
  233             else
  234                 camel_mime_part_set_content (part, (const gchar *) str_lpb, str_cb, type);
  235         }
  236 
  237         g_free (in_utf8);
  238         g_free (buff);
  239     } else
  240         camel_mime_part_set_content (part, " ", 1, "text/plain");
  241 }
  242 
  243 static gboolean
  244 is_apple_attach (EMapiAttachment *attach, guint32 *data_len, guint32 *resource_len)
  245 {
  246     gboolean is_apple = FALSE;
  247     uint64_t enc_cb = 0;
  248     const uint8_t *enc_lpb = NULL;
  249     guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
  250 
  251     if (e_mapi_attachment_get_bin_prop (attach, PidTagAttachEncoding, &enc_cb, &enc_lpb) && enc_cb == G_N_ELEMENTS (apple_enc_magic)) {
  252         gint idx;
  253 
  254         is_apple = TRUE;
  255         for (idx = 0; idx < enc_cb && is_apple; idx++) {
  256             is_apple = apple_enc_magic[idx] == enc_lpb[idx];
  257         }
  258     }
  259 
  260     if (is_apple) {
  261         /* check boundaries too */
  262         uint64_t data_cb = 0;
  263         const uint8_t *data_lpb = NULL;
  264 
  265         is_apple = e_mapi_attachment_get_bin_prop (attach, PidTagAttachDataBinary, &data_cb, &data_lpb) && data_lpb && data_cb > 128;
  266 
  267         if (is_apple) {
  268             const guint8 *bin = data_lpb;
  269 
  270             /* in big-endian format */
  271             *data_len = (bin[83] << 24) | (bin[84] << 16) | (bin[85] << 8) | (bin[86]);
  272             *resource_len = (bin[87] << 24) | (bin[88] << 16) | (bin[89] << 8) | (bin[90]);
  273 
  274             /* +/- mod 128 (but the first 128 is a header length) */
  275             is_apple = 128 + *data_len + *resource_len <= data_cb && bin[1] < 64;
  276         }
  277     }
  278 
  279     return is_apple;
  280 }
  281 
  282 typedef struct {
  283     GHashTable *tzids;
  284     ICalComponent *icomp;
  285 } ForeachTZIDData;
  286 
  287 static void
  288 add_timezones_cb (ICalParameter *param,
  289           gpointer data)
  290 {
  291     ForeachTZIDData *tz_data = data;
  292     const gchar *tzid;
  293     ICalTimezone *zone = NULL;
  294     ICalComponent *vtimezone_comp;
  295 
  296     /* Get the TZID string from the parameter. */
  297     tzid = i_cal_parameter_get_tzid (param);
  298     if (!tzid || g_hash_table_lookup (tz_data->tzids, tzid))
  299         return;
  300 
  301     /* Look for the timezone */
  302     zone = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
  303     if (!zone)
  304         return;
  305 
  306     /* Convert it to a string and add it to the hash. */
  307     vtimezone_comp = i_cal_timezone_get_component (zone);
  308     if (!vtimezone_comp)
  309         return;
  310 
  311     i_cal_component_take_component (tz_data->icomp, i_cal_component_clone (vtimezone_comp));
  312 
  313     g_hash_table_insert (tz_data->tzids, g_strdup (tzid), GINT_TO_POINTER (1));
  314 }
  315 
  316 static gchar *
  317 build_ical_string (EMapiConnection *conn,
  318            EMapiObject *object,
  319            const gchar *msg_class)
  320 {
  321     gchar *ical_string = NULL, *use_uid;
  322     ICalComponentKind kind = I_CAL_NO_COMPONENT;
  323     ICalPropertyMethod method = I_CAL_METHOD_NONE;
  324     const uint64_t *pmid;
  325     ECalComponent *comp;
  326     ICalComponent *icomp;
  327     GSList *detached_components = NULL, *iter;
  328 
  329     g_return_val_if_fail (conn != NULL, NULL);
  330     g_return_val_if_fail (object != NULL, NULL);
  331     g_return_val_if_fail (msg_class != NULL, NULL);
  332 
  333     if (g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_REQUEST) == 0) {
  334         method = I_CAL_METHOD_REQUEST;
  335         kind = I_CAL_VEVENT_COMPONENT;
  336     } else if (g_ascii_strcasecmp (msg_class, IPM_SCHEDULE_MEETING_CANCELED) == 0) {
  337         method = I_CAL_METHOD_CANCEL;
  338         kind = I_CAL_VEVENT_COMPONENT;
  339     } else if (g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_RESP_PREFIX)) {
  340         method = I_CAL_METHOD_REPLY;
  341         kind = I_CAL_VEVENT_COMPONENT;
  342     } else if (g_ascii_strcasecmp (msg_class, IPM_APPOINTMENT) == 0) {
  343         method = I_CAL_METHOD_NONE;
  344         kind = I_CAL_VEVENT_COMPONENT;
  345     } else if (g_ascii_strcasecmp (msg_class, IPM_TASK) == 0) {
  346         method = I_CAL_METHOD_NONE;
  347         kind = I_CAL_VTODO_COMPONENT;
  348     } else if (g_ascii_strcasecmp (msg_class, IPM_STICKYNOTE) == 0) {
  349         method = I_CAL_METHOD_NONE;
  350         kind = I_CAL_VJOURNAL_COMPONENT;
  351     } else {
  352         return NULL;
  353     }
  354 
  355     pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
  356     if (pmid)
  357         use_uid = e_mapi_util_mapi_id_to_string (*pmid);
  358     else
  359         use_uid = e_util_generate_uid ();
  360 
  361     comp = e_mapi_cal_util_object_to_comp (conn, object, kind, method == I_CAL_METHOD_REPLY, use_uid, &detached_components);
  362 
  363     g_free (use_uid);
  364 
  365     if (!comp)
  366         return NULL;
  367 
  368     if (method != I_CAL_METHOD_NONE || detached_components) {
  369         ForeachTZIDData tz_data;
  370         ICalComponent *clone;
  371 
  372         clone = i_cal_component_clone (e_cal_component_get_icalcomponent (comp));
  373 
  374         icomp = e_cal_util_new_top_level ();
  375         if (method != I_CAL_METHOD_NONE)
  376             i_cal_component_set_method (icomp, method);
  377 
  378         tz_data.tzids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
  379         tz_data.icomp = icomp;
  380 
  381         /* Add timezones first */
  382         i_cal_component_foreach_tzid (clone, add_timezones_cb, &tz_data);
  383 
  384         g_hash_table_destroy (tz_data.tzids);
  385 
  386         /* Then the components */
  387         i_cal_component_take_component (icomp, clone);
  388         for (iter = detached_components; iter; iter = g_slist_next (iter)) {
  389             i_cal_component_take_component (icomp,
  390                 i_cal_component_clone (e_cal_component_get_icalcomponent (iter->data)));
  391         }
  392 
  393         ical_string = i_cal_component_as_ical_string (icomp);
  394 
  395         g_object_unref (icomp);
  396     } else {
  397         ical_string = e_cal_component_get_as_string (comp);
  398     }
  399 
  400     g_slist_free_full (detached_components, g_object_unref);
  401     g_object_unref (comp);
  402 
  403     return ical_string;
  404 }
  405 
  406 static void
  407 classify_attachments (EMapiConnection *conn,
  408               EMapiAttachment *attachments,
  409               gboolean can_inline_attachments,
  410               const gchar *msg_class,
  411               GSList **inline_attachments,
  412               GSList **noninline_attachments)
  413 {
  414     EMapiAttachment *attach;
  415     gboolean is_smime = msg_class && strstr (msg_class, ".SMIME.") > msg_class;
  416 
  417     g_return_if_fail (inline_attachments != NULL);
  418     g_return_if_fail (noninline_attachments != NULL);
  419 
  420     for (attach = attachments; attach != NULL; attach = attach->next) {
  421         const gchar *filename, *mime_type, *content_id = NULL;
  422         CamelContentType *content_type;
  423         CamelMimePart *part;
  424         const uint32_t *ui32;
  425         uint64_t data_cb = 0;
  426         const uint8_t *data_lpb = NULL;
  427         gboolean is_apple, is_message;
  428         guint32 apple_data_len = 0, apple_resource_len = 0;
  429 
  430         if (!e_mapi_attachment_get_bin_prop (attach, PidTagAttachDataBinary, &data_cb, &data_lpb) && !attach->embedded_object) {
  431             g_debug ("%s: Skipping attachment without data and without embedded object", G_STRFUNC);
  432             continue;
  433         }
  434 
  435         is_apple = is_apple_attach (attach, &apple_data_len, &apple_resource_len);
  436 
  437         /* Content-Type */
  438         ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMethod);
  439         is_message = ui32 && *ui32 == ATTACH_EMBEDDED_MSG;
  440         if (is_message) {
  441             mime_type = "message/rfc822";
  442         } else {
  443             mime_type = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachMimeTag);
  444             if (!mime_type)
  445                 mime_type = "application/octet-stream";
  446             is_message = g_ascii_strcasecmp (mime_type, "message/rfc822") == 0;
  447         }
  448 
  449         if (is_apple) {
  450             mime_type = "application/applefile";
  451         } else if (strstr (mime_type, "apple") != NULL) {
  452             mime_type = "application/octet-stream";
  453         }
  454 
  455         part = camel_mime_part_new ();
  456 
  457         filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachLongFilename);
  458         if (!filename || !*filename)
  459             filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachFilename);
  460         camel_mime_part_set_filename (part, filename);
  461         camel_content_type_set_param (camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (part)), "name", filename);
  462 
  463         if (is_apple) {
  464             CamelMultipart *mp;
  465             gchar *apple_filename;
  466             uint64_t mac_info_cb = 0;
  467             const uint8_t *mac_info_lpb = NULL;
  468 
  469             mp = camel_multipart_new ();
  470             camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/appledouble");
  471             camel_multipart_set_boundary (mp, NULL);
  472 
  473             camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
  474 
  475             if (e_mapi_attachment_get_bin_prop (attach, PidNameAttachmentMacInfo, &mac_info_cb, &mac_info_lpb) && mac_info_lpb && mac_info_cb > 0) {
  476                 camel_mime_part_set_content (part, (const gchar *) mac_info_lpb, mac_info_cb, mime_type);
  477             } else {
  478                 /* RFC 1740 */
  479                 guint8 header[] = {
  480                     0x00, 0x05, 0x16, 0x07, /* magic */
  481                     0x00, 0x02, 0x00, 0x00, /* version */
  482                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* filler */
  483                     0x00, 0x01, /* number of entries */
  484                     0x00, 0x00, 0x00, 0x02, /* entry ID - resource fork */
  485                     0x00, 0x00, 0x00, 0x26, /* entry offset - 38th byte*/
  486                     0x00, 0x00, 0x00, 0x00  /* entry length */
  487                 };
  488 
  489                 GByteArray *arr = g_byte_array_sized_new (apple_resource_len + G_N_ELEMENTS (header));
  490 
  491                 header[34] = (apple_resource_len >> 24) & 0xFF;
  492                 header[35] = (apple_resource_len >> 16) & 0xFF;
  493                 header[36] = (apple_resource_len >>  8) & 0xFF;
  494                 header[37] = (apple_resource_len      ) & 0xFF;
  495 
  496                 g_byte_array_append (arr, header, G_N_ELEMENTS (header));
  497                 g_byte_array_append (arr, data_lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
  498 
  499                 camel_mime_part_set_content (part, (const gchar *) arr->data, arr->len, mime_type);
  500 
  501                 g_byte_array_free (arr, TRUE);
  502             }
  503 
  504             camel_multipart_add_part (mp, part);
  505             g_object_unref (part);
  506 
  507             part = camel_mime_part_new ();
  508 
  509             apple_filename = g_strndup ((const gchar *) data_lpb + 2, data_lpb[1]);
  510             camel_mime_part_set_filename (part, (apple_filename && *apple_filename) ? apple_filename : filename);
  511             g_free (apple_filename);
  512 
  513             mime_type = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacContentType);
  514             if (!mime_type)
  515                 mime_type = "application/octet-stream";
  516 
  517             camel_mime_part_set_content (part, (const gchar *) data_lpb + 128, apple_data_len, mime_type);
  518             camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
  519             camel_multipart_add_part (mp, part);
  520             g_object_unref (part);
  521 
  522             part = camel_mime_part_new ();
  523             camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (mp));
  524             g_object_unref (mp);
  525         } else if (is_smime) {
  526             CamelMimeParser *parser;
  527             CamelStream *mem;
  528 
  529             mem = camel_stream_mem_new ();
  530             camel_stream_write (mem, (const gchar *) data_lpb, data_cb, NULL, NULL);
  531             g_seekable_seek (G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
  532 
  533             parser = camel_mime_parser_new ();
  534             camel_mime_parser_scan_from (parser, FALSE);
  535             camel_mime_parser_scan_pre_from (parser, FALSE);
  536             camel_mime_parser_init_with_stream (parser, mem, NULL);
  537 
  538             if (camel_mime_parser_step (parser, NULL, NULL) == CAMEL_MIME_PARSER_STATE_HEADER
  539                 && camel_mime_parser_content_type (parser) != NULL) {
  540                 g_object_unref (part);
  541                 part = camel_mime_part_new ();
  542 
  543                 camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (part), camel_mime_parser_content_type (parser));
  544                 camel_mime_part_construct_content_from_parser (part, parser, NULL, NULL);
  545             } else {
  546                 is_smime = FALSE;
  547             }
  548 
  549             g_object_unref (parser);
  550             g_object_unref (mem);
  551         } 
  552 
  553         if (!is_smime && !is_apple) {
  554             if (ui32 && *ui32 == ATTACH_EMBEDDED_MSG && attach->embedded_object) {
  555                 const gchar *embedded_msg_class = e_mapi_util_find_array_propval (&attach->embedded_object->properties, PidTagMessageClass);
  556                 gboolean fallback = FALSE;
  557 
  558                 if (embedded_msg_class &&
  559                     (g_ascii_strcasecmp (embedded_msg_class, IPM_CONTACT) == 0 ||
  560                      g_ascii_strcasecmp (embedded_msg_class, IPM_DISTLIST) == 0)) {
  561                     EContact *contact = e_mapi_book_utils_contact_from_object (conn, attach->embedded_object, NULL);
  562 
  563                     if (contact) {
  564                         gchar *str;
  565 
  566                         if (!e_contact_get_const (contact, E_CONTACT_UID))
  567                             e_contact_set (contact, E_CONTACT_UID, "");
  568 
  569                         str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
  570                         if (str) {
  571                             camel_mime_part_set_content (part, str, strlen (str), "text/x-vcard");
  572 
  573                             g_free (str);
  574                         } else {
  575                             fallback = TRUE;
  576                         }
  577 
  578                         g_object_unref (contact);
  579                     } else {
  580                         fallback = TRUE;
  581                     }
  582                 } else if (embedded_msg_class &&
  583                     (g_ascii_strcasecmp (embedded_msg_class, IPM_APPOINTMENT) == 0 ||
  584                      g_ascii_strcasecmp (embedded_msg_class, IPM_TASK) == 0 ||
  585                      g_ascii_strcasecmp (embedded_msg_class, IPM_STICKYNOTE) == 0)) {
  586                     gchar *str = build_ical_string (conn, attach->embedded_object, embedded_msg_class);
  587 
  588                     if (str) {
  589                         camel_mime_part_set_content (part, str, strlen (str), "text/calendar");
  590 
  591                         g_free (str);
  592                     } else {
  593                         fallback = TRUE;
  594                     }
  595                 } else {
  596                     fallback = TRUE;
  597                 }
  598 
  599                 if (fallback) {
  600                     CamelMimeMessage *embedded_msg;
  601 
  602                     embedded_msg = e_mapi_mail_utils_object_to_message (conn, attach->embedded_object);
  603                     if (embedded_msg) {
  604                         CamelStream *mem;
  605                         GByteArray *data;
  606 
  607                         data = g_byte_array_new ();
  608 
  609                         mem = camel_stream_mem_new ();
  610                         camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), data);
  611                         camel_data_wrapper_write_to_stream_sync (
  612                             CAMEL_DATA_WRAPPER (embedded_msg), mem, NULL, NULL);
  613 
  614                         g_object_unref (mem);
  615                         g_object_unref (embedded_msg);
  616 
  617                         camel_mime_part_set_content (part, (const gchar *) data->data, data->len, mime_type);
  618 
  619                         g_byte_array_free (data, TRUE);
  620                     } else {
  621                         camel_mime_part_set_content (part, (const gchar *) data_lpb, data_cb, mime_type);
  622                     }
  623                 }
  624             } else {
  625                 camel_mime_part_set_content (part, (const gchar *) data_lpb, data_cb, mime_type);
  626             }
  627 
  628             content_type = camel_mime_part_get_content_type (part);
  629             if (content_type && camel_content_type_is (content_type, "text", "*"))
  630                 camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
  631             else if (!is_message)
  632                 camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
  633         }
  634 
  635         /* Content-Disposition */
  636         ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagRenderingPosition);
  637         if (ui32 && *ui32 != 0xFFFFFFFF)
  638             camel_mime_part_set_disposition (part, "attachment; inline");
  639         else
  640             camel_mime_part_set_disposition (part, "attachment");
  641 
  642         /* Content-ID */
  643         content_id = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachContentId);
  644         if (content_id)
  645             camel_mime_part_set_content_id (part, content_id);
  646 
  647         if (content_id && !is_apple && !is_smime && can_inline_attachments) {
  648             *inline_attachments = g_slist_append (*inline_attachments, part);
  649         } else
  650             *noninline_attachments = g_slist_append (*noninline_attachments, part);
  651     }
  652 }
  653 
  654 static void
  655 add_multipart_attachments (CamelMultipart *multipart, GSList *attachments)
  656 {
  657     CamelMimePart *part;
  658     while (attachments) {
  659         part = attachments->data;
  660         camel_multipart_add_part (multipart, part);
  661         attachments = attachments->next;
  662     }
  663 }
  664 
  665 static CamelMultipart *
  666 build_multipart_related (EMapiObject *object, GSList *inline_attachments)
  667 {
  668     CamelMimePart *part;
  669     CamelMultipart *m_related = camel_multipart_new ();
  670     camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_related), "multipart/related");
  671     camel_multipart_set_boundary (m_related, NULL);
  672 
  673     if (e_mapi_object_contains_prop (object, PidTagHtml)) {
  674         part = camel_mime_part_new ();
  675         build_body_part_content (part, object, PidTagHtml);
  676         camel_multipart_add_part (m_related, part);
  677         g_object_unref (part);
  678     } else if (e_mapi_object_contains_prop (object, PidTagBody)) {
  679         part = camel_mime_part_new ();
  680         build_body_part_content (part, object, PidTagBody);
  681         camel_multipart_add_part (m_related, part);
  682         g_object_unref (part);
  683     }
  684 
  685     add_multipart_attachments (m_related, inline_attachments);
  686 
  687     return m_related;
  688 }
  689 
  690 static CamelMultipart *
  691 build_multipart_alternative (EMapiObject *object, GSList *inline_attachments)
  692 {
  693     CamelMimePart *part;
  694     CamelMultipart *m_alternative;
  695 
  696     m_alternative = camel_multipart_new ();
  697     camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_alternative), "multipart/alternative");
  698     camel_multipart_set_boundary (m_alternative, NULL);
  699 
  700     if (e_mapi_object_contains_prop (object, PidTagBody)) {
  701         part = camel_mime_part_new ();
  702         build_body_part_content (part, object, PidTagBody);
  703         camel_multipart_add_part (m_alternative, part);
  704         g_object_unref (part);
  705     }
  706 
  707     if (e_mapi_object_contains_prop (object, PidTagHtml)) {
  708         part = camel_mime_part_new ();
  709         if (inline_attachments) {
  710             CamelMultipart *m_related;
  711 
  712             m_related = build_multipart_related (object, inline_attachments);
  713             camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (m_related));
  714             g_object_unref (m_related);
  715         } else {
  716             build_body_part_content (part, object, PidTagHtml);
  717         }
  718         camel_multipart_add_part (m_alternative, part);
  719         g_object_unref (part);
  720     }
  721 
  722     return m_alternative;
  723 }
  724 
  725 static CamelMultipart *
  726 build_multipart_mixed (CamelMultipart *content, GSList *attachments)
  727 {
  728     CamelMultipart *m_mixed = camel_multipart_new ();
  729     camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (m_mixed), "multipart/mixed");
  730     camel_multipart_set_boundary (m_mixed, NULL);
  731 
  732     if (content) {
  733         CamelMimePart *part = camel_mime_part_new ();
  734 
  735         camel_medium_set_content (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (content));
  736         camel_multipart_add_part (m_mixed, part);
  737 
  738         g_object_unref (part);
  739         g_object_unref (content);
  740     }
  741 
  742     add_multipart_attachments (m_mixed, attachments);
  743 
  744     return m_mixed;
  745 }
  746 
  747 CamelMimeMessage *
  748 e_mapi_mail_utils_object_to_message (EMapiConnection *conn, /* const */ EMapiObject *object)
  749 {
  750     CamelMimeMessage *msg;
  751     CamelMultipart *multipart_body = NULL;
  752     GSList *inline_attachments, *noninline_attachments;
  753     gboolean build_alternative, build_related, build_calendar;
  754     const gchar *str, *msg_class;
  755     gboolean skip_set_content = FALSE;
  756     gchar *ical_string = NULL;
  757 
  758     g_return_val_if_fail (conn != NULL, NULL);
  759     g_return_val_if_fail (object != NULL, NULL);
  760 
  761     if (e_mapi_debug_is_enabled ()) {
  762         printf ("%s:\n", G_STRFUNC);
  763         e_mapi_debug_dump_object (object, TRUE, 3);
  764     }
  765 
  766     msg = camel_mime_message_new ();
  767 
  768     str = e_mapi_util_find_array_propval (&object->properties, PidTagTransportMessageHeaders);
  769     if (str && *str) {
  770         CamelMimePart *part = camel_mime_part_new ();
  771         CamelStream *stream;
  772         CamelMimeParser *parser;
  773 
  774         stream = camel_stream_mem_new_with_buffer (str, strlen (str));
  775         parser = camel_mime_parser_new ();
  776         camel_mime_parser_init_with_stream (parser, stream, NULL);
  777         camel_mime_parser_scan_from (parser, FALSE);
  778         g_object_unref (stream);
  779 
  780         if (camel_mime_part_construct_from_parser_sync (part, parser, NULL, NULL)) {
  781             const CamelNameValueArray *headers;
  782             CamelMedium *msg_medium = CAMEL_MEDIUM (msg);
  783             guint ii, len;
  784 
  785             headers = camel_medium_get_headers (CAMEL_MEDIUM (part));
  786             len = camel_name_value_array_get_length (headers);
  787 
  788             for (ii = 0; ii < len; ii++) {
  789                 const gchar *header_name = NULL, *header_value = NULL;
  790 
  791                 /* skip all headers describing content of a message,
  792                    because it's overwritten on message decomposition */
  793                 if (!camel_name_value_array_get (headers, ii, &header_name, &header_value) ||
  794                     !header_name ||
  795                     g_ascii_strncasecmp (header_name, "Content", 7) == 0)
  796                     continue;
  797 
  798                 while (header_value && camel_mime_is_lwsp (*header_value))
  799                     header_value++;
  800 
  801                 camel_medium_add_header (msg_medium, header_name, header_value);
  802             }
  803         }
  804 
  805         g_object_unref (parser);
  806         g_object_unref (part);
  807     } else {
  808         CamelInternetAddress *to_addr, *cc_addr, *bcc_addr;
  809         const struct FILETIME *msg_date;
  810         const uint8_t *read_receipt;
  811         const uint32_t *priority;
  812         gchar *name, *email;
  813 
  814         to_addr = camel_internet_address_new ();
  815         cc_addr = camel_internet_address_new ();
  816         bcc_addr = camel_internet_address_new ();
  817 
  818         e_mapi_mail_utils_decode_recipients (conn, object->recipients, (CamelAddress *) to_addr, (CamelAddress *) cc_addr, (CamelAddress *) bcc_addr);
  819 
  820         camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_TO, to_addr);
  821         camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_CC, cc_addr);
  822         camel_mime_message_set_recipients (msg, CAMEL_RECIPIENT_TYPE_BCC, bcc_addr);
  823 
  824         g_object_unref (to_addr);
  825         g_object_unref (cc_addr);
  826         g_object_unref (bcc_addr);
  827 
  828         msg_date = e_mapi_util_find_array_propval (&object->properties, PidTagClientSubmitTime);
  829         if (!msg_date)
  830             msg_date = e_mapi_util_find_array_propval (&object->properties, PidTagMessageDeliveryTime);
  831         if (msg_date)
  832             camel_mime_message_set_date (msg, e_mapi_util_filetime_to_time_t (msg_date), 0);
  833 
  834         str = e_mapi_util_find_array_propval (&object->properties, PidTagSubject);
  835         if (str)
  836             camel_mime_message_set_subject (msg, str);
  837 
  838         name = NULL;
  839         email = NULL;
  840 
  841         e_mapi_mail_utils_decode_email_address1 (conn, &object->properties,
  842             PidTagSentRepresentingName,
  843             PidTagSentRepresentingEmailAddress,
  844             PidTagSentRepresentingAddressType,
  845             &name, &email);
  846 
  847         if (email && *email) {
  848             CamelInternetAddress *addr;
  849 
  850             addr = camel_internet_address_new ();
  851             camel_internet_address_add (addr, name, email);
  852             camel_mime_message_set_from (msg, addr);
  853             g_object_unref (addr);
  854         }
  855         
  856         g_free (name);
  857         g_free (email);
  858 
  859         /* Threading */
  860         str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetMessageId);
  861         if (str)
  862             camel_medium_add_header (CAMEL_MEDIUM (msg), "Message-ID", str);
  863 
  864         str = e_mapi_util_find_array_propval (&object->properties, PidTagInternetReferences);
  865         if (str)
  866             camel_medium_add_header (CAMEL_MEDIUM (msg), "References", str);
  867 
  868         str = e_mapi_util_find_array_propval (&object->properties, PidTagInReplyToId);
  869         if (str)
  870             camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", str);
  871 
  872         priority = e_mapi_util_find_array_propval (&object->properties, PidTagPriority);
  873         if (priority && *priority == 1)
  874             camel_medium_add_header (CAMEL_MEDIUM (msg), "X-Priority", "1");
  875 
  876         /* Read-Receipt handling */
  877         read_receipt = e_mapi_util_find_array_propval (&object->properties, PidTagReadReceiptRequested);
  878         if (read_receipt && *read_receipt) {
  879             if (!camel_medium_get_header (CAMEL_MEDIUM (msg), "Disposition-Notification-To")) {
  880                 name = NULL;
  881                 email = NULL;
  882 
  883                 e_mapi_mail_utils_decode_email_address1 (conn, &object->properties,
  884                     PidTagReadReceiptName,
  885                     PidTagReadReceiptEmailAddress,
  886                     PidTagReadReceiptAddressType,
  887                     &name, &email);
  888 
  889                 if (email && *email) {
  890                     CamelInternetAddress *addr;
  891                     gchar *address;
  892 
  893                     addr = camel_internet_address_new ();
  894                     camel_internet_address_add (addr, name, email);
  895                     address = camel_address_encode (CAMEL_ADDRESS (addr));
  896 
  897                     camel_medium_add_header (CAMEL_MEDIUM (msg), "Disposition-Notification-To", address);
  898 
  899                     g_object_unref (addr);
  900                     g_free (address);
  901                 }
  902 
  903                 g_free (name);
  904                 g_free (email);
  905             }
  906         }
  907     }
  908 
  909     str = e_mapi_util_find_array_propval (&object->properties, PidNameContentClass);
  910     if (str)
  911         camel_medium_add_header (CAMEL_MEDIUM (msg), "Content-class", str);
  912 
  913     inline_attachments = NULL;
  914     noninline_attachments = NULL;
  915     msg_class = e_mapi_util_find_array_propval (&object->properties, PidTagMessageClass);
  916     classify_attachments (conn, object->attachments, e_mapi_object_contains_prop (object, PidTagHtml), msg_class, &inline_attachments, &noninline_attachments);
  917 
  918     build_calendar = msg_class && g_str_has_prefix (msg_class, IPM_SCHEDULE_MEETING_PREFIX);
  919     if (build_calendar) {
  920         ical_string = build_ical_string (conn, object, msg_class);
  921         if (!ical_string)
  922             build_calendar = FALSE;
  923     }
  924 
  925     build_alternative = !build_calendar
  926         && e_mapi_object_contains_prop (object, PidTagHtml)
  927         && e_mapi_object_contains_prop (object, PidTagBody);
  928     build_related = !build_calendar && !build_alternative && inline_attachments
  929         && e_mapi_object_contains_prop (object, PidTagHtml);
  930 
  931     if (!build_alternative && !build_related && inline_attachments) {
  932         noninline_attachments = g_slist_concat (noninline_attachments, inline_attachments);
  933         inline_attachments = NULL;
  934     }
  935 
  936     if (build_calendar) {
  937         g_return_val_if_fail (ical_string != NULL, msg);
  938 
  939         camel_mime_part_set_content (CAMEL_MIME_PART (msg), ical_string, strlen (ical_string), "text/calendar");
  940     } else if (build_alternative) {
  941         multipart_body = build_multipart_alternative (object, inline_attachments);
  942     } else if (build_related) {
  943         multipart_body = build_multipart_related (object, inline_attachments);
  944     } else if (noninline_attachments) {
  945         /* Simple multipart/mixed */
  946         CamelMimePart *part = camel_mime_part_new ();
  947 
  948         multipart_body = camel_multipart_new ();
  949         camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body), "multipart/mixed");
  950         camel_multipart_set_boundary (multipart_body, NULL);
  951         if (e_mapi_object_contains_prop (object, PidTagHtml))
  952             build_body_part_content (part, object, PidTagHtml);
  953         else
  954             build_body_part_content (part, object, PidTagBody);
  955         camel_multipart_add_part (multipart_body, part);
  956         g_object_unref (part);
  957     } else {
  958         /* Flat message */
  959         if (e_mapi_object_contains_prop (object, PidTagHtml))
  960             build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagHtml);
  961         else
  962             build_body_part_content (CAMEL_MIME_PART (msg), object, PidTagBody);
  963     }
  964 
  965     if (noninline_attachments) { /* multipart/mixed */
  966         if (build_alternative || build_related || build_calendar) {
  967             multipart_body = build_multipart_mixed (multipart_body, noninline_attachments);
  968         } else if (g_slist_length (noninline_attachments) == 1 && msg_class && strstr (msg_class, ".SMIME") > msg_class) {
  969             CamelMimePart *part = noninline_attachments->data;
  970 
  971             skip_set_content = TRUE;
  972 
  973             camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
  974 
  975             if (!strstr (msg_class, ".SMIME.")) {
  976                 /* encrypted */
  977                 camel_medium_set_content (CAMEL_MEDIUM (msg), camel_medium_get_content (CAMEL_MEDIUM (part)));
  978                 camel_mime_part_set_encoding (CAMEL_MIME_PART (msg), camel_mime_part_get_encoding (part));
  979             } else {
  980                 /* signed */
  981                 camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (part));
  982             }
  983         } else {
  984             add_multipart_attachments (multipart_body, noninline_attachments);
  985         }
  986     }
  987 
  988     if (!skip_set_content && multipart_body)
  989         camel_medium_set_content (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart_body));
  990 
  991     if (multipart_body)
  992         g_object_unref (multipart_body);
  993     g_slist_free_full (inline_attachments, g_object_unref);
  994     g_slist_free_full (noninline_attachments, g_object_unref);
  995     g_free (ical_string);
  996 
  997     return msg;
  998 }
  999 
 1000 static void
 1001 e_mapi_mail_add_recipients (EMapiObject *object,
 1002                 CamelInternetAddress *addresses,
 1003                 OlMailRecipientType recip_type)
 1004 {
 1005     gint ii;
 1006     const gchar *name = NULL, *email = NULL;
 1007 
 1008     g_return_if_fail (object != NULL);
 1009 
 1010     for (ii = 0; addresses && camel_internet_address_get (addresses, ii, &name, &email); ii++) {
 1011         EMapiRecipient *recipient;
 1012         uint32_t ui32 = 0;
 1013         uint8_t bl;
 1014 
 1015         recipient = e_mapi_recipient_new (object);
 1016         e_mapi_object_add_recipient (object, recipient);
 1017 
 1018         #define set_value(pt,vl) {                              \
 1019             if (!e_mapi_utils_add_property (&recipient->properties, pt, vl, recipient)) {   \
 1020                 g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);       \
 1021                                                     \
 1022                 return;                                 \
 1023             }                                       \
 1024         }
 1025 
 1026         ui32 = recip_type;
 1027         set_value (PidTagRecipientType, &ui32);
 1028 
 1029         if (!name || !*name)
 1030             name = email;
 1031 
 1032         if (name && *name) {
 1033             set_value (PidTagDisplayName, name);
 1034             set_value (PidTagRecipientDisplayName, name);
 1035         }
 1036         if (email && *email) {
 1037             set_value (PidTagAddressType, "SMTP");
 1038             set_value (PidTagEmailAddress, email);
 1039             set_value (PidTagSmtpAddress, email);
 1040         }
 1041 
 1042         ui32 = 0;
 1043         set_value (PidTagSendInternetEncoding, &ui32);
 1044 
 1045         ui32 = DT_MAILUSER;
 1046         set_value (PidTagDisplayType, &ui32);
 1047 
 1048         ui32 = MAPI_MAILUSER;
 1049         set_value (PidTagObjectType, &ui32);
 1050 
 1051         bl = 0;
 1052         set_value (PidTagSendRichInfo, &bl);
 1053 
 1054         #undef set_value
 1055 
 1056         name = NULL;
 1057         email = NULL;
 1058     }
 1059 }
 1060 
 1061 static CamelStream *
 1062 get_content_stream (CamelMimePart *part, GCancellable *cancellable)
 1063 {
 1064     CamelStream *content_stream;
 1065     CamelStream *filter_stream = NULL;
 1066     CamelMimeFilterWindows *windows = NULL;
 1067     CamelDataWrapper *dw;
 1068 
 1069     g_return_val_if_fail (part != NULL, NULL);
 1070 
 1071     dw = camel_medium_get_content (CAMEL_MEDIUM (part));
 1072     g_return_val_if_fail (dw != NULL, NULL);
 1073 
 1074     content_stream = camel_stream_mem_new();
 1075 
 1076     if (camel_mime_part_get_content_type (part)) {
 1077         const gchar *charset = camel_content_type_param (camel_mime_part_get_content_type (part), "charset");
 1078 
 1079         if (charset && *charset && g_ascii_strcasecmp (charset, "utf8") != 0 && g_ascii_strcasecmp (charset, "utf-8") != 0) {
 1080             if (g_ascii_strncasecmp (charset, "iso-8859-", 9) == 0) {
 1081                 CamelStream *null;
 1082 
 1083                 /* Since a few Windows mailers like to claim they sent
 1084                  * out iso-8859-# encoded text when they really sent
 1085                  * out windows-cp125#, do some simple sanity checking
 1086                  * before we move on... */
 1087 
 1088                 null = camel_stream_null_new ();
 1089                 filter_stream = camel_stream_filter_new (null);
 1090                 g_object_unref (null);
 1091 
 1092                 windows = (CamelMimeFilterWindows *)camel_mime_filter_windows_new (charset);
 1093                 camel_stream_filter_add (
 1094                     CAMEL_STREAM_FILTER (filter_stream),
 1095                     CAMEL_MIME_FILTER (windows));
 1096 
 1097                 camel_data_wrapper_decode_to_stream_sync (
 1098                     dw, (CamelStream *)filter_stream, cancellable, NULL);
 1099                 camel_stream_flush ((CamelStream *)filter_stream, cancellable, NULL);
 1100                 g_object_unref (filter_stream);
 1101 
 1102                 charset = camel_mime_filter_windows_real_charset (windows);
 1103             }
 1104 
 1105             if (charset && *charset) {
 1106                 CamelMimeFilter *filter;
 1107 
 1108                 filter_stream = camel_stream_filter_new (content_stream);
 1109 
 1110                 if ((filter = camel_mime_filter_charset_new (charset, "UTF-8"))) {
 1111                     camel_stream_filter_add (
 1112                         CAMEL_STREAM_FILTER (filter_stream),
 1113                         CAMEL_MIME_FILTER (filter));
 1114                     g_object_unref (filter);
 1115                 } else {
 1116                     g_object_unref (filter_stream);
 1117                     filter_stream = NULL;
 1118                 }
 1119             }
 1120         }
 1121     }
 1122 
 1123     if (filter_stream) {
 1124         camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) filter_stream, cancellable, NULL);
 1125         camel_stream_flush (filter_stream, cancellable, NULL);
 1126         g_object_unref (filter_stream);
 1127     } else {
 1128         camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
 1129     }
 1130 
 1131     if (windows)
 1132         g_object_unref (windows);
 1133 
 1134     g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
 1135 
 1136     return content_stream;
 1137 }
 1138 
 1139 static void
 1140 e_mapi_mail_content_stream_to_bin (CamelStream *content_stream,
 1141                    uint64_t *pcb,
 1142                    uint8_t **plpb,
 1143                    TALLOC_CTX *mem_ctx,
 1144                    GCancellable *cancellable)
 1145 {
 1146     guint8 *buf;
 1147     guint32 read_size;
 1148     uint64_t cb;
 1149     uint8_t *lpb;
 1150 
 1151     g_return_if_fail (content_stream != NULL);
 1152     g_return_if_fail (pcb != NULL);
 1153     g_return_if_fail (plpb != NULL);
 1154     g_return_if_fail (mem_ctx != NULL);
 1155 
 1156     buf = g_new0 (guint8 , STREAM_SIZE);
 1157 
 1158     cb = 0;
 1159     lpb = NULL;
 1160 
 1161     g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
 1162     while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
 1163         lpb = talloc_realloc (mem_ctx, lpb, uint8_t, cb + read_size);
 1164         memcpy (lpb + cb, buf, read_size);
 1165         cb += read_size;
 1166     }
 1167 
 1168     g_free (buf);
 1169 
 1170     *pcb = cb;
 1171     *plpb = lpb;
 1172 }
 1173 
 1174 static gboolean
 1175 e_mapi_mail_part_is_attachment (CamelMimePart *part)
 1176 {
 1177     const CamelContentDisposition *content_disposition;
 1178 
 1179     g_return_val_if_fail (CAMEL_IS_MIME_PART (part), FALSE);
 1180 
 1181     content_disposition = camel_mime_part_get_content_disposition (part);
 1182 
 1183     if (!content_disposition)
 1184         return FALSE;
 1185 
 1186     return content_disposition &&
 1187         content_disposition->disposition && (
 1188         g_ascii_strcasecmp (content_disposition->disposition, "attachment") == 0 ||
 1189         g_ascii_strcasecmp (content_disposition->disposition, "inline") == 0);
 1190 }
 1191 
 1192 #define set_attach_value(pt,vl) {                       \
 1193     if (!e_mapi_utils_add_property (&attach->properties, pt, vl, attach)) { \
 1194         g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);   \
 1195         return FALSE;                           \
 1196     }                                   \
 1197 }
 1198 
 1199 static gboolean
 1200 e_mapi_mail_add_attach (EMapiObject *object,
 1201             CamelMimePart *part,
 1202             CamelStream *content_stream,
 1203             GCancellable *cancellable)
 1204 {
 1205     EMapiAttachment *attach;
 1206     CamelContentType *content_type;
 1207     const gchar *content_id;
 1208     const gchar *filename;
 1209     uint64_t data_cb = 0;
 1210     uint8_t *data_lpb = NULL;
 1211     uint32_t ui32;
 1212 
 1213     g_return_val_if_fail (object != NULL, FALSE);
 1214     g_return_val_if_fail (part != NULL, FALSE);
 1215     g_return_val_if_fail (content_stream != NULL, FALSE);
 1216 
 1217     attach = e_mapi_attachment_new (object);
 1218     e_mapi_object_add_attachment (object, attach);
 1219 
 1220     ui32 = ATTACH_BY_VALUE;
 1221     set_attach_value (PidTagAttachMethod, &ui32);
 1222     ui32 = -1;
 1223     set_attach_value (PidTagRenderingPosition, &ui32);
 1224 
 1225     filename = camel_mime_part_get_filename (part);
 1226     if (filename) {
 1227         set_attach_value (PidTagAttachFilename, filename);
 1228         set_attach_value (PidTagAttachLongFilename, filename);
 1229     }
 1230 
 1231     content_id = camel_mime_part_get_content_id (part);
 1232     if (content_id)
 1233         set_attach_value (PidTagAttachContentId, content_id);
 1234 
 1235     content_type  = camel_mime_part_get_content_type (part);
 1236     if (content_type) {
 1237         gchar *ct = camel_content_type_simple (content_type);
 1238         if (ct)
 1239             set_attach_value (PidTagAttachMimeTag, ct);
 1240         g_free (ct);
 1241     }
 1242 
 1243     e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, attach, cancellable);
 1244     e_mapi_attachment_add_streamed (attach, PidTagAttachDataBinary, data_cb, data_lpb);
 1245 
 1246     return TRUE;
 1247 }
 1248 
 1249 static gboolean
 1250 e_mapi_mail_add_body (EMapiObject *object,
 1251               CamelStream *content_stream,
 1252               uint32_t proptag,
 1253               GCancellable *cancellable)
 1254 {
 1255     uint64_t data_cb = 0;
 1256     uint8_t *data_lpb = NULL;
 1257     gchar *str;
 1258 
 1259     e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, object, cancellable);
 1260     str = talloc_strndup (object, (const gchar *) data_lpb, data_cb);
 1261     talloc_free (data_lpb);
 1262 
 1263     if ((proptag & 0xFFFF) == PT_BINARY) {
 1264         data_lpb = (uint8_t *) (str ? str : "");
 1265         data_cb = strlen ((const gchar *) data_lpb) + 1;
 1266         /* include trailing zero .................. ^^^ */
 1267 
 1268         e_mapi_object_add_streamed (object, proptag, data_cb, data_lpb);
 1269 
 1270         return TRUE;
 1271     } else if (str) {
 1272         if (!e_mapi_utils_add_property (&object->properties, proptag, str, object)) {
 1273             talloc_free (str);
 1274             return FALSE;
 1275         }
 1276 
 1277         talloc_free (str);
 1278     } else {
 1279         return e_mapi_utils_add_property (&object->properties, proptag, "", object);
 1280     }
 1281 
 1282     return TRUE;
 1283 }
 1284 
 1285 static gboolean
 1286 e_mapi_mail_do_smime_encrypted (EMapiObject *object,
 1287                 CamelMedium *message,
 1288                 gchar **pmsg_class,
 1289                 gchar **ppid_name_content_type,
 1290                 GCancellable *cancellable)
 1291 {
 1292     EMapiAttachment *attach;
 1293     CamelStream *content_stream;
 1294     CamelDataWrapper *dw;
 1295     CamelContentType *type;
 1296     uint32_t ui32;
 1297     uint64_t data_cb = 0;
 1298     uint8_t *data_lpb = NULL;
 1299     gchar *content_type_str;
 1300 
 1301     g_return_val_if_fail (object != NULL, FALSE);
 1302     g_return_val_if_fail (message != NULL, FALSE);
 1303     g_return_val_if_fail (pmsg_class != NULL, FALSE);
 1304     g_return_val_if_fail (ppid_name_content_type != NULL, FALSE);
 1305 
 1306     g_free (*pmsg_class);
 1307     *pmsg_class = g_strdup ("IPM.Note.SMIME");
 1308 
 1309     type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
 1310     dw = camel_medium_get_content (message);
 1311     content_type_str = camel_content_type_format (type);
 1312 
 1313     g_free (*ppid_name_content_type);
 1314     *ppid_name_content_type = content_type_str; /* will be freed within the caller */
 1315 
 1316     content_stream = camel_stream_mem_new ();
 1317     camel_data_wrapper_decode_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
 1318 
 1319     attach = e_mapi_attachment_new (object);
 1320     e_mapi_object_add_attachment (object, attach);
 1321 
 1322     ui32 = ATTACH_BY_VALUE;
 1323     set_attach_value (PidTagAttachMethod, &ui32);
 1324     ui32 = -1;
 1325     set_attach_value (PidTagRenderingPosition, &ui32);
 1326     set_attach_value (PidTagAttachMimeTag, content_type_str);
 1327     set_attach_value (PidTagAttachFilename, "SMIME.txt");
 1328     set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
 1329     set_attach_value (PidTagDisplayName, "SMIME.txt");
 1330 
 1331     e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, attach, cancellable);
 1332     e_mapi_attachment_add_streamed (attach, PidTagAttachDataBinary, data_cb, data_lpb);
 1333 
 1334     g_object_unref (content_stream);
 1335 
 1336     return TRUE;
 1337 }
 1338 
 1339 static gboolean
 1340 e_mapi_mail_do_smime_signed (EMapiObject *object,
 1341                  CamelMultipart *multipart,
 1342                  gchar **pmsg_class,
 1343                  GCancellable *cancellable)
 1344 {
 1345     EMapiAttachment *attach;
 1346     CamelMimePart *content, *signature;
 1347     CamelStream *content_stream;
 1348     CamelContentType *type;
 1349     CamelDataWrapper *dw;
 1350     uint32_t ui32;
 1351     uint64_t data_cb = 0;
 1352     uint8_t *data_lpb = NULL;
 1353     gchar *content_type_str, *content_type_unfolded;
 1354 
 1355     g_free (*pmsg_class);
 1356     *pmsg_class = g_strdup ("IPM.Note.SMIME.MultipartSigned");
 1357 
 1358     content = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
 1359     signature = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_SIGNATURE);
 1360 
 1361     g_return_val_if_fail (content != NULL, FALSE);
 1362     g_return_val_if_fail (signature != NULL, FALSE);
 1363 
 1364     content_stream = get_content_stream (content, cancellable);
 1365     type = camel_mime_part_get_content_type (content);
 1366 
 1367     if (camel_content_type_is (type, "text", "plain")) {
 1368         e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
 1369     } else if (camel_content_type_is (type, "text", "html")) {
 1370         e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
 1371     } else {
 1372         e_mapi_mail_add_attach (object, content, content_stream, cancellable);
 1373     }
 1374 
 1375     if (content_stream)
 1376         g_object_unref (content_stream);
 1377 
 1378     content_stream = camel_stream_mem_new ();
 1379     dw = CAMEL_DATA_WRAPPER (multipart);
 1380     type = camel_data_wrapper_get_mime_type_field (dw);
 1381     content_type_str = camel_content_type_format (type);
 1382     content_type_unfolded = camel_header_unfold (content_type_str);
 1383 
 1384     #define wstr(str) camel_stream_write (content_stream, str, strlen (str), cancellable, NULL)
 1385     wstr("Content-Type: ");
 1386     wstr(content_type_unfolded);
 1387     wstr("\r\n\r\n");
 1388     #undef wstr
 1389 
 1390     g_free (content_type_str);
 1391     g_free (content_type_unfolded);
 1392 
 1393     camel_data_wrapper_write_to_stream_sync (dw, (CamelStream *) content_stream, cancellable, NULL);
 1394 
 1395     attach = e_mapi_attachment_new (object);
 1396     e_mapi_object_add_attachment (object, attach);
 1397 
 1398     ui32 = ATTACH_BY_VALUE;
 1399     set_attach_value (PidTagAttachMethod, &ui32);
 1400     ui32 = -1;
 1401     set_attach_value (PidTagRenderingPosition, &ui32);
 1402     set_attach_value (PidTagAttachMimeTag, "multipart/signed");
 1403     set_attach_value (PidTagAttachFilename, "SMIME.txt");
 1404     set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
 1405     set_attach_value (PidTagDisplayName, "SMIME.txt");
 1406 
 1407     e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, attach, cancellable);
 1408     e_mapi_attachment_add_streamed (attach, PidTagAttachDataBinary, data_cb, data_lpb);
 1409 
 1410     g_object_unref (content_stream);
 1411 
 1412     return TRUE;
 1413 }
 1414 
 1415 static gboolean
 1416 e_mapi_mail_do_multipart (EMapiObject *object,
 1417               CamelMultipart *mp,
 1418               gboolean *is_first,
 1419               GCancellable *cancellable)
 1420 {
 1421     CamelDataWrapper *dw;
 1422     CamelStream *content_stream;
 1423     CamelContentType *type;
 1424     CamelMimePart *part;
 1425     gboolean parent_is_alternative;
 1426     gint nn, ii;
 1427 
 1428     g_return_val_if_fail (is_first != NULL, FALSE);
 1429 
 1430     type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (mp));
 1431     parent_is_alternative = type && camel_content_type_is (type, "multipart", "alternative");
 1432 
 1433     nn = camel_multipart_get_number (mp);
 1434     for (ii = 0; ii < nn; ii++) {
 1435         /* getting part */
 1436         part = camel_multipart_get_part (mp, ii);
 1437         if (!part)
 1438             continue;
 1439 
 1440         dw = camel_medium_get_content (CAMEL_MEDIUM (part));
 1441         if (CAMEL_IS_MULTIPART (dw)) {
 1442             /* recursive */
 1443             if (!e_mapi_mail_do_multipart (object, CAMEL_MULTIPART (dw), is_first, cancellable))
 1444                 return FALSE;
 1445             continue;
 1446         }
 1447 
 1448         if (CAMEL_IS_MIME_MESSAGE (dw)) {
 1449             CamelMimeMessage *message;
 1450             EMapiObject *embedded = NULL;
 1451             EMapiAttachment *attach;
 1452 
 1453             attach = e_mapi_attachment_new (object);
 1454             message = CAMEL_MIME_MESSAGE (dw);
 1455             if (e_mapi_mail_utils_message_to_object (message, 0, E_MAPI_CREATE_FLAG_NONE, &embedded, attach, cancellable, NULL)) {
 1456                 uint32_t ui32;
 1457                 const gchar *str;
 1458 
 1459                 e_mapi_object_add_attachment (object, attach);
 1460                 attach->embedded_object = embedded;
 1461                 embedded->parent = object;
 1462 
 1463                 ui32 = ATTACH_EMBEDDED_MSG;
 1464                 set_attach_value (PidTagAttachMethod, &ui32);
 1465                 ui32 = 0;
 1466                 set_attach_value (PidTagRenderingPosition, &ui32);
 1467                 set_attach_value (PidTagAttachMimeTag, "message/rfc822");
 1468 
 1469                 str = camel_mime_message_get_subject (message);
 1470                 if (str)
 1471                     set_attach_value (PidTagAttachFilename, str);
 1472                 continue;
 1473             } else {
 1474                 e_mapi_attachment_free (attach);
 1475             }
 1476         }
 1477 
 1478         content_stream = get_content_stream (part, cancellable);
 1479         type = camel_mime_part_get_content_type (part);
 1480 
 1481         if (ii == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
 1482             e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
 1483             *is_first = FALSE;
 1484         } else if ((ii == 0 || parent_is_alternative) &&
 1485                camel_content_type_is (type, "text", "html") &&
 1486                !e_mapi_mail_part_is_attachment (part)) {
 1487             e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
 1488         } else {
 1489             e_mapi_mail_add_attach (object, part, content_stream, cancellable);
 1490         }
 1491 
 1492         if (content_stream)
 1493             g_object_unref (content_stream);
 1494     }
 1495 
 1496     return TRUE;
 1497 }
 1498 
 1499 #undef set_attach_value
 1500 
 1501 gboolean
 1502 e_mapi_mail_utils_message_to_object (struct _CamelMimeMessage *message,
 1503                      guint32 message_camel_flags,
 1504                      EMapiCreateFlags create_flags,
 1505                      EMapiObject **pobject,
 1506                      TALLOC_CTX *mem_ctx,
 1507                      GCancellable *cancellable,
 1508                      GError **perror)
 1509 {
 1510     EMapiObject *object;
 1511     CamelContentType *content_type;
 1512     CamelInternetAddress *addresses;
 1513     const gchar *namep = NULL, *addressp = NULL;
 1514     const gchar *str;
 1515     gchar *msg_class = NULL;
 1516     gchar *pid_name_content_type = NULL;
 1517     gint ii = 0;
 1518     uint32_t ui32;
 1519     uint8_t bl;
 1520 
 1521     g_return_val_if_fail (message != NULL, FALSE);
 1522     g_return_val_if_fail (pobject != NULL, FALSE);
 1523     g_return_val_if_fail (*pobject == NULL, FALSE);
 1524     g_return_val_if_fail (mem_ctx != NULL, FALSE);
 1525 
 1526     content_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message));
 1527     g_return_val_if_fail (content_type != NULL, FALSE);
 1528 
 1529     /* headers */
 1530     if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
 1531         /* though invalid, then possible, to pass in a message without any 'from' */
 1532         CamelInternetAddress *from = camel_mime_message_get_from (message);
 1533         if (!from || !camel_internet_address_get (from, 0, &namep, &addressp))
 1534             namep = NULL;
 1535     }
 1536 
 1537     object = e_mapi_object_new (mem_ctx);
 1538 
 1539     #define set_value(pt,vl) {                          \
 1540         if (!e_mapi_utils_add_property (&object->properties, pt, vl, object)) { \
 1541             e_mapi_object_free (object);                    \
 1542             g_free (msg_class);                     \
 1543             g_free (pid_name_content_type);                 \
 1544                                             \
 1545             g_warning ("%s: Failed to set property 0x%x", G_STRFUNC, pt);   \
 1546                                             \
 1547             return FALSE;                           \
 1548         }                                   \
 1549     }
 1550 
 1551     ui32 = 65001; /* UTF8 - also used with PR_HTML */
 1552     set_value (PidTagInternetCodepage, &ui32);
 1553 
 1554     if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
 1555         if ((message_camel_flags & CAMEL_MESSAGE_ANSWERED) != 0 ||
 1556             (message_camel_flags & CAMEL_MESSAGE_ANSWERED_ALL) != 0) {
 1557             ui32 = 0x105;
 1558             set_value (PidTagIconIndex, &ui32);
 1559         } else if ((message_camel_flags & CAMEL_MESSAGE_FORWARDED) != 0) {
 1560             ui32 = 0x106;
 1561             set_value (PidTagIconIndex, &ui32);
 1562         }
 1563 
 1564         ui32 = 0;
 1565         if (message_camel_flags & CAMEL_MESSAGE_SEEN)
 1566             ui32 |= MSGFLAG_READ;
 1567         if (message_camel_flags & CAMEL_MESSAGE_ATTACHMENTS)
 1568             ui32 |= MSGFLAG_HASATTACH;
 1569     } else {
 1570         ui32 = MSGFLAG_UNSENT;
 1571     }
 1572     set_value (PidTagMessageFlags, &ui32);
 1573 
 1574     bl = 0;
 1575     set_value (PidTagSendRichInfo, &bl);
 1576 
 1577     /* PidTagConversationTopic and PidTagNormalizedSubject, together with PidTagSubjectPrefix
 1578        are computed from PidTagSubject by a server */
 1579     str = camel_mime_message_get_subject (message);
 1580     if (str)
 1581         set_value (PidTagSubject, str);
 1582 
 1583     /* some properties may not be set when submitting a message */
 1584     if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) == 0) {
 1585         time_t msg_time = 0;
 1586         gint msg_time_offset = 0;
 1587         CamelNameValueArray *headers;
 1588 
 1589         if (namep && *namep)
 1590             set_value (PidTagSentRepresentingName, namep);
 1591 
 1592         if (addressp && *addressp) {
 1593             set_value (PidTagSentRepresentingAddressType, "SMTP");
 1594             set_value (PidTagSentRepresentingEmailAddress, addressp);
 1595         }
 1596 
 1597         msg_time = camel_mime_message_get_date (message, &msg_time_offset);
 1598         if (msg_time == CAMEL_MESSAGE_DATE_CURRENT)
 1599             msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
 1600         if (msg_time != 0) {
 1601             struct FILETIME msg_date = { 0 };
 1602 
 1603             e_mapi_util_time_t_to_filetime (msg_time, &msg_date);
 1604 
 1605             set_value (PidTagClientSubmitTime, &msg_date);
 1606         }
 1607 
 1608         msg_time = camel_mime_message_get_date_received (message, &msg_time_offset);
 1609         if (msg_time != 0) {
 1610             struct FILETIME msg_date = { 0 };
 1611 
 1612             e_mapi_util_time_t_to_filetime (msg_time, &msg_date);
 1613 
 1614             set_value (PidTagMessageDeliveryTime, &msg_date);
 1615         }
 1616 
 1617         headers = camel_medium_dup_headers (CAMEL_MEDIUM (message));
 1618         if (headers) {
 1619             GString *hstr = g_string_new ("");
 1620             guint len;
 1621 
 1622             len = camel_name_value_array_get_length (headers);
 1623 
 1624             for (ii = 0; ii < len; ii++) {
 1625                 const gchar *header_name = NULL, *header_value = NULL;
 1626 
 1627                 if (!camel_name_value_array_get (headers, ii, &header_name, &header_value) ||
 1628                     !header_name || !*header_name || g_ascii_strncasecmp (header_name, "X-Evolution", 11) == 0)
 1629                     continue;
 1630 
 1631                 g_string_append_printf (hstr, "%s: %s\n", header_name, header_value ? header_value : "");
 1632             }
 1633 
 1634             camel_name_value_array_free (headers);
 1635 
 1636             if (hstr->len && hstr->str)
 1637                 set_value (PidTagTransportMessageHeaders, hstr->str);
 1638 
 1639             g_string_free (hstr, TRUE);
 1640         }
 1641     }
 1642 
 1643     str = camel_medium_get_header ((CamelMedium *) message, "References");
 1644     if (str)
 1645         set_value (PidTagInternetReferences, str);
 1646 
 1647     str = camel_medium_get_header ((CamelMedium *) message, "In-Reply-To");
 1648     if (str)
 1649         set_value (PidTagInReplyToId, str);
 1650 
 1651     str = camel_medium_get_header ((CamelMedium *) message, "Message-ID");
 1652     if (str)
 1653         set_value (PidTagInternetMessageId, str);
 1654 
 1655     str = camel_medium_get_header ((CamelMedium *) message, "X-Priority");
 1656     if (str && g_str_equal (str, "1")) {
 1657         ui32 = 1;
 1658         set_value (PidTagPriority, &ui32);
 1659     }
 1660 
 1661     str = camel_medium_get_header ((CamelMedium *) message, "Disposition-Notification-To");
 1662     if (str) {
 1663         CamelInternetAddress *addr;
 1664 
 1665         namep = NULL;
 1666         addressp = NULL;
 1667 
 1668         addr = camel_internet_address_new ();
 1669         if (camel_address_decode (CAMEL_ADDRESS (addr), str) != -1 &&
 1670             camel_internet_address_get (addr, 0, &namep, &addressp) &&
 1671             addressp && *addressp) {
 1672             if (namep && *namep)
 1673                 set_value (PidTagReadReceiptName, namep);
 1674 
 1675             set_value (PidTagReadReceiptEmailAddress, addressp);
 1676             set_value (PidTagReadReceiptAddressType, "SMTP");
 1677 
 1678             if ((create_flags & E_MAPI_CREATE_FLAG_SUBMIT) != 0) {
 1679                 bl = 1;
 1680 
 1681                 set_value (PidTagReadReceiptRequested, &bl);
 1682             }
 1683         }
 1684 
 1685         g_object_unref (addr);
 1686     }
 1687 
 1688     addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
 1689     e_mapi_mail_add_recipients (object, addresses, olTo);
 1690 
 1691     addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
 1692     e_mapi_mail_add_recipients (object, addresses, olCC);
 1693 
 1694     addresses = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
 1695     e_mapi_mail_add_recipients (object, addresses, olBCC);
 1696 
 1697     if (camel_content_type_is (content_type, "application", "x-pkcs7-mime") ||
 1698         camel_content_type_is (content_type, "application", "pkcs7-mime")) {
 1699         e_mapi_mail_do_smime_encrypted (object, CAMEL_MEDIUM (message), &msg_class, &pid_name_content_type, cancellable);
 1700     } else {
 1701         CamelDataWrapper *dw = NULL;
 1702         CamelStream *content_stream;
 1703         CamelMultipart *multipart;
 1704 
 1705         /* contents body */
 1706         dw = camel_medium_get_content (CAMEL_MEDIUM (message));
 1707         if (CAMEL_IS_MULTIPART (dw)) {
 1708             gboolean is_first = TRUE;
 1709 
 1710             multipart = CAMEL_MULTIPART (dw);
 1711 
 1712             if (CAMEL_IS_MULTIPART_SIGNED (multipart) && camel_multipart_get_number (multipart) == 2) {
 1713                 e_mapi_mail_do_smime_signed (object, multipart, &msg_class, cancellable);
 1714             } else {
 1715                 e_mapi_mail_do_multipart (object, multipart, &is_first, cancellable);
 1716             }
 1717         } else if (dw) {
 1718             CamelContentType *type;
 1719             CamelMimePart *part = CAMEL_MIME_PART (message);
 1720 
 1721             content_stream = get_content_stream (part, cancellable);
 1722             type = camel_data_wrapper_get_mime_type_field (dw);
 1723 
 1724             if (camel_content_type_is (type, "text", "plain")) {
 1725                 e_mapi_mail_add_body (object, content_stream, PidTagBody, cancellable);
 1726             } else if (camel_content_type_is (type, "text", "html")) {
 1727                 e_mapi_mail_add_body (object, content_stream, PidTagHtml, cancellable);
 1728             } else {
 1729                 e_mapi_mail_add_attach (object, part, content_stream, cancellable);
 1730             }
 1731 
 1732             if (content_stream)
 1733                 g_object_unref (content_stream);
 1734         }
 1735     }
 1736 
 1737     if (msg_class)
 1738         set_value (PidTagMessageClass, msg_class);
 1739 
 1740     if (pid_name_content_type)
 1741         set_value (PidNameContentType, pid_name_content_type);
 1742 
 1743     g_free (msg_class);
 1744     g_free (pid_name_content_type);
 1745 
 1746     *pobject = object;
 1747 
 1748     #undef set_value
 1749 
 1750     if (e_mapi_debug_is_enabled ()) {
 1751         printf ("%s:\n", G_STRFUNC);
 1752         e_mapi_debug_dump_object (object, TRUE, 3);
 1753     }
 1754 
 1755     return TRUE;
 1756 }