【问题标题】:Multipart/mixed email attachments not showing up, but only in Windows 10 Mail多部分/混合电子邮件附件未显示,但仅在 Windows 10 邮件中显示
【发布时间】:2019-10-16 04:22:51
【问题描述】:

我通过 Python email / smtplib 发送的电子邮件有一个奇怪的问题。

我正在尝试撰写一封电子邮件:

  • 纯文本和 HTML 邮件正文的替代方案
  • 内嵌在 HTML 正文中的图像
  • 单独的非内联附件

MIME 结构是这样设置的:

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

这似乎在我为 Windows 10 邮件客户端测试过 {BlueMail on Android, iOS mail client, Roundcube} except 的每个邮件客户端上都可以正常工作。出于某种原因,Windows 10 内置邮件客户端似乎可以很好地显示内联图像,但没有显示其他附件的痕迹。

我在 Internet 上找到的有限信息表明这是 Windows 10 邮件客户端的一个错误,但我个人在此客户端中收到了其他电子邮件,其中包含内联附件和附加附件,显示效果很好- 所以显然有某种解决方法/替代消息结构有效。

因此,我的问题是:我怎样才能以不同的方式格式化这条消息,以便它能够正确显示在所有相关的邮件客户端中?

我正在用 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())

更新:这是来自 Windows 10 邮件的消息数据(通过“保存”功能输出 - 无法查看我能找到的原始消息原始数据...)

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_--

我不确定这是从应用程序保存电子邮件的结果,还是应用程序实际存储的内容,但似乎 Windows 10 邮件应用程序正在删除 multipart/related 节之外的所有内容- 也就是说,它只接受选择的alternative,而不存储任何其他内容。

为了比较,我找到并导出了一封显示正确的电子邮件,其中包含图像、html 和附件,但格式似乎要简单得多 - 该电子邮件仅包含 multipart/mixed 层和 @987654329 @ 和 application/pdf 附件。该电子邮件使用 HTML 中引用的外部图像,而不是将其嵌入到邮件中 - 我想避免在外部托管每封电子邮件中的图像。

【问题讨论】:

    标签: python email mime multipart smtplib


    【解决方案1】:

    与您不同的是,附件文件没有问题,而是我在显示内联图像时遇到了问题 (Windows 10 Mail 16005.11629.20174.0)。

    不幸的是,正确处理 MIME 消息中的非标准方法是一个期望拥有良好电子邮件客户端的功能。显然 Windows 10 Mail 还没有那么“好”。

    我推荐你使用的结构是:

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

    我在以下客户端中对这种结构没有任何问题。

    • Windows 10 邮件
    • Gmail 网页版和安卓版
    • Outlook Web & Android & Windows 桌面
    • 蓝色邮件安卓
    • 圆立方网络
    • MailEnable 网络

    所以,试试下面的代码,看看它是否适合你。

    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)
    

    【讨论】:

      猜你喜欢
      • 2016-01-03
      • 2019-05-02
      • 1970-01-01
      • 2023-02-01
      • 2013-10-30
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多