Support multipart/related reading
authorAndre Heinecke <aheinecke@intevation.de>
Wed, 30 Nov 2016 16:17:14 +0000 (17:17 +0100)
committerAndre Heinecke <aheinecke@intevation.de>
Wed, 30 Nov 2016 16:17:14 +0000 (17:17 +0100)
* src/attachment.cpp (Attachment::set_content_id)
(Attachment::get_content_id): New.
* src/mail.cpp (get_attachment): Return last attachment on -1 pos
(fixup_last_attachment): New. Set content id.
(add_attachments): Call fixup.
* src/oomhelp.h (PR_ATTACH_CONTENT_ID_DASL): New.
* src/mimedataprovider.cpp (t2body): Parse content-id.
(MimeDataProvider::create_attachment): Set content-id.

--
This magically hides the attachment from the attachment list
and Outlook shows images in the body.

src/attachment.cpp
src/attachment.h
src/mail.cpp
src/mimedataprovider.cpp
src/oomhelp.h

index fc528c7..d5961cf 100644 (file)
@@ -56,3 +56,15 @@ Attachment::get_data()
 {
   return m_data;
 }
+
+void
+Attachment::set_content_id(const char *cid)
+{
+  m_cid = cid;
+}
+
+std::string
+Attachment::get_content_id() const
+{
+  return m_cid;
+}
index 47c536e..de75935 100644 (file)
@@ -38,6 +38,10 @@ public:
 
   void set_attach_type(attachtype_t type);
 
+  /* Content id */
+  void set_content_id (const char *cid);
+  std::string get_content_id() const;
+
   /* get the underlying data structure */
   GpgME::Data& get_data();
 
@@ -45,6 +49,7 @@ private:
   GpgME::Data m_data;
   std::string m_utf8DisplayName;
   attachtype_t m_type;
+  std::string m_cid;
 };
 
 #endif // ATTACHMENT_H
index 55800fc..950acd3 100644 (file)
@@ -238,8 +238,16 @@ get_attachment (LPDISPATCH mailitem, int pos)
       return NULL;
     }
 
-  const auto item_str = std::string("Item(") + std::to_string(pos) + ")";
+  std::string item_str;
   int count = get_oom_int (attachments, "Count");
+  if (pos > 0)
+    {
+      item_str = std::string("Item(") + std::to_string(pos) + ")";
+    }
+  else
+    {
+      item_str = std::string("Item(") + std::to_string(count) + ")";
+    }
   if (count < 1)
     {
       log_debug ("%s:%s: Invalid attachment count: %i.",
@@ -417,6 +425,33 @@ copy_attachment_to_file (std::shared_ptr<Attachment> att, HANDLE hFile)
   return 0;
 }
 
+/** Sets some meta data on the last attachment atted. The meta
+  data is taken from the attachment object. */
+static int
+fixup_last_attachment (LPDISPATCH mail, std::shared_ptr<Attachment> attachment)
+{
+  /* Currently we only set content id */
+  if (attachment->get_content_id ().empty())
+    {
+      log_debug ("%s:%s: Content id not found.",
+                 SRCNAME, __func__);
+      return 0;
+    }
+
+  LPDISPATCH attach = get_attachment (mail, -1);
+  if (!attach)
+    {
+      log_error ("%s:%s: No attachment.",
+                 SRCNAME, __func__);
+      return 1;
+    }
+  int ret = put_pa_string (attach,
+                           PR_ATTACH_CONTENT_ID_DASL,
+                           attachment->get_content_id ().c_str());
+  gpgol_release (attach);
+  return ret;
+}
+
 /** Helper to update the attachments of a mail object in oom.
   does not modify the underlying mapi structure. */
 static int
@@ -456,6 +491,8 @@ add_attachments(LPDISPATCH mail,
         }
       xfree (wchar_file);
       xfree (wchar_name);
+
+      err = fixup_last_attachment (mail, att);
     }
   return err;
 }
index bb74bc1..f0273cf 100644 (file)
@@ -50,6 +50,7 @@ struct mimestruct_item_s
   unsigned int level;   /* Level in the hierarchy of that part.  0
                            indicates the outer body.  */
   char *filename;       /* Malloced filename or NULL.  */
+  char *cid;            /* Malloced content id or NULL. */
   char *charset;        /* Malloced charset or NULL.  */
   char content_type[1]; /* String with the content type. */
 };
@@ -174,6 +175,7 @@ t2body (MimeDataProvider *provider, rfc822parse_t msg)
   int is_text = 0;
   int is_text_attachment = 0;
   char *filename = NULL;
+  char *cid = NULL;
   char *charset = NULL;
 
   /* Figure out the encoding.  */
@@ -254,6 +256,14 @@ t2body (MimeDataProvider *provider, rfc822parse_t msg)
         filename = rfc2047_parse (s);
     }
 
+  /* Parse a Content Id header */
+  p = rfc822parse_get_field (msg, "Content-Id", -1, &off);
+  if (p)
+    {
+       cid = xstrdup (p+off);
+       xfree (p);
+    }
+
   /* Update our idea of the entire MIME structure.  */
   {
     mimestruct_item_t ms;
@@ -266,6 +276,7 @@ t2body (MimeDataProvider *provider, rfc822parse_t msg)
     strcpy (stpcpy (stpcpy (ms->content_type, ctmain), "/"), ctsub);
     ms->level = ctx->nesting_level;
     ms->filename = filename;
+    ms->cid = cid;
     filename = NULL;
     ms->charset = charset;
     charset = NULL;
@@ -515,6 +526,7 @@ MimeDataProvider::~MimeDataProvider()
       mimestruct_item_t tmp = m_mime_ctx->mimestruct->next;
       xfree (m_mime_ctx->mimestruct->filename);
       xfree (m_mime_ctx->mimestruct->charset);
+      xfree (m_mime_ctx->mimestruct->cid);
       xfree (m_mime_ctx->mimestruct);
       m_mime_ctx->mimestruct = tmp;
     }
@@ -876,6 +888,10 @@ MimeDataProvider::create_attachment()
           attach->set_display_name (m_mime_ctx->mimestruct_cur->filename);
         }
     }
+  if (m_mime_ctx->mimestruct_cur && m_mime_ctx->mimestruct_cur->cid)
+    {
+      attach->set_content_id (m_mime_ctx->mimestruct_cur->cid);
+    }
   m_attachments.push_back (attach);
 
   return attach;
index 1c6aa94..3914f5e 100644 (file)
@@ -100,6 +100,8 @@ DEFINE_OLEGUID(IID_IOleWindow,                0x00000114, 0, 0);
   "http://schemas.microsoft.com/mapi/proptag/0x7FFE000B"
 #define PR_ATTACH_MIME_TAG_DASL \
   "http://schemas.microsoft.com/mapi/proptag/0x370E001F"
+#define PR_ATTACH_CONTENT_ID_DASL \
+  "http://schemas.microsoft.com/mapi/proptag/0x3712001F"
 #ifdef __cplusplus
 extern "C" {
 #if 0