Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multipart/mixed email attachments not showing up, but only in Windows 10 Mail

Having a weird problem with emails I am sending out via Python email / smtplib.

I am attempting to compose an email with:

  • Alternatives of plain-text and HTML message bodies
  • An image embedded inline in the HTML body
  • A separate non-inline attachment

The MIME structure is setup like this:

multipart/mixed
    multipart/alternative
        text/plain
        multipart/related
            text/html
            image/png - inline
    application/pdf - attachment

This seems to work fine on every mail client I've tested {BlueMail on Android, iOS mail client, Roundcube} except for the Windows 10 mail client. For some reason, the Windows 10 built-in mail client seems to show the inline image just fine, but shows no trace of the other attachment.

The limited information I have been able to find on the internet points to this being a bug with the Windows 10 mail client, but I have personally received other emails in this client with both inline and attached attachments, which are displayed just fine - so there obviously is some sort of workaround / alternative message structure that works.

My question is thus: How can I format this message differently so that it will show up properly in all relevant mail clients?

I am composing the email like this, in Python:

message = MIMEMultipart("mixed")
message["From"] = ...
.
.
.
bodyText = "..."
bodyHTML = "..."
mailFrom = "..."
targetEmail = "..."
imageContent = ...

messageBody = MIMEMultipart("alternative")
messageBody.attach(MIMEText(bodyText, "plain"))

messageBodyHTML = MIMEMultipart("related")
messageBodyHTML.attach(MIMEText(bodyHTML, "html"))
messageImage = MIMEImage(imageContent)
messageImage.add_header("Content-Disposition", 'inline; filename="..."')
messageImage.add_header("Content-ID", "<id used in html body>")
messageBodyHTML.attach(messageImage)

messageBody.attach(messageBodyHTML)

message.attach(messageBody)


attachment = MIMEApplication(fileContent, Name=fileName)
attachment.add_header("Content-Disposition", 'attachment; filename="..."')
message.attach(attachment)


self.smtplibSession.sendmail(mailSource, targetEmail, message.as_string())

Update: Here's the message data from Windows 10 mail (as output via the "save" feature - there's no way to view the original message raw data that I can find...)

MIME-Version: 1.0
Date: Thu, 30 May 2019 17:45:28 +0200
From: xxxxx <xxxxx>
Subject: xxxxx
Thread-Topic: xxxxx
To: "xxxxx" <xxxxx>
Content-Type: multipart/related;
    boundary="_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_"

--_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"

<center><img src=3D"cid:embedded-image" alt=...

--_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_
Content-Type: image/png; name="embedded-image.png"
Content-ID: <embedded-image>
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="embedded-image.png"

iVBORw0KGgoAAAAN...

--_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_--

I'm not sure if this is a result of saving the email from the app, or this is what the app is actually storing, but it seems that the Windows 10 Mail app is cutting out everything outside the multipart/related stanza - that is, it's only taking the chosen alternative and not storing anything else.

For comparison, I've found and exported an email that displayed properly, with an image, html, and attachment, but the format seems to be a lot simpler - that email consisted only of a multipart/mixed layer with text/html and an application/pdf attachment. That email used an external image referenced in the HTML, instead of embedding it in the message - I would like to avoid hosting the images in each email externally.

like image 536
Eli Avatar asked May 30 '19 13:05

Eli


People also ask

How do I view attachments in Windows Mail?

In your message pane, an email message with an attachment has a paperclip symbol next to it. Select a message with an attachment, then double-click the file shown in the message itself. The attachment will open automatically using the appropriate program on your computer. You can then view, edit, or print the document.

Why is PDF not showing in email?

If the Email to PDF toolbar is not showing up in Outlook, most likely the PDF add-in is listed under Inactive Application Add-ins or Disabled Application Add-ins sections. You will have to re-enable the add-in and restart Outlook.

What is multipart mixed content type?

A multipart/mixed MIME message is composed of a mix of different data types. Each body part is delineated by a boundary. The boundary parameter is a text string used to delineate one part of the message body from another. All boundaries start with two hyphens (--).

What is a multipart mail?

multipart/report is a message type that contains data formatted for a mail server to read. It is split between a text/plain (or some other content/type easily readable) and a message/delivery-status, which contains the data formatted for the mail server to read.


1 Answers

Unlike you, there was no problem with the attachment file, instead I've had problems in displaying inline images (Windows 10 Mail 16005.11629.20174.0).

Unfortunately, handling non-standard approaches in MIME messages correctly is a feature that is expected to have good email clients. Apparently Windows 10 Mail is not as "good" yet.

The structure I recommend you to use is:

multipart/mixed
├─── multipart/related
│   ├─── multipart/alternative
│   │   ├─── text/plain
│   │   └─── text/html
│   └─── image/png - inline image
└─── application/pdf - attachment

I've had no problems with this structure in the following clients.

  • Windows 10 Mail
  • Gmail Web & Android
  • Outlook Web & Android & Windows Desktop
  • Blue Mail Android
  • Roundcube Web
  • MailEnable Web

So, give the following code a try to see if it works for you.

message = MIMEMultipart("mixed")
message["From"] = ...
.
.
.
bodyText = "..."
bodyHTML = "..."
mailFrom = "..."
targetEmail = "..."
imageContent = ...
fileContent = ...

relatedBody = MIMEMultipart("related")

messageBody = MIMEMultipart("alternative")
messageBody.attach(MIMEText(bodyText, "plain"))
messageBody.attach(MIMEText(bodyHTML, "html"))

relatedBody.attach(messageBody)

messageImage = MIMEImage(imageContent)
messageImage.add_header("Content-Disposition", 'inline; filename="..."')
messageImage.add_header("Content-ID", "<id used in html body>")

relatedBody.attach(messageImage)

message.attach(relatedBody)

attachment = MIMEApplication(fileContent)
attachment.add_header("Content-Disposition", 'attachment; filename="..."')

message.attach(attachment)
like image 135
Kul-Tigin Avatar answered Oct 07 '22 23:10

Kul-Tigin