尝试使用 MIME 发送 "alternative" 但它也出现在有能力的邮件客户端中
Trying to send "alternative" with MIME but it also shows up in capable mail client
我正在尝试发送漂亮的 MIME 电子邮件,其中 html 将尽可能显示,如果不可能,它应该有一个文本回退。
也就是说,当html包含图片时,"alternative"部分应该显示"img ... should be here"。
问题是我在 gmail 中看到了一切,还有替代方案。
我的 MIME 消息有问题吗?
内容如下:
Content-Type: multipart/mixed; boundary="===============9061258228856181354=="
MIME-Version: 1.0
From: me@gmail.com <me@gmail.com>
To: me@gmail.com
--===============9061258228856181354==
Content-Type: multipart/alternative; boundary="===============2889524977048828163=="
MIME-Version: 1.0
--===============2889524977048828163==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
img 1043833786270341319 should be here
--===============2889524977048828163==--
--===============9061258228856181354==
Content-Type: image/jpeg; name="sky.jpg"
MIME-Version: 1.0
Content-ID: <1043833786270341319>
Content-Transfer-Encoding: base64
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK
CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU
FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAEbAakDASIA
AhEBAxEB/8QAHQAAAgIDAQEBAAAAAAAAAAAAAgQBAwUGBwAICf/EADoQAAEEAQMDAwIFAgYBBAMB
--===============9061258228856181354==
Content-Type: multipart/related; boundary="===============7011550496984103126=="
MIME-Version: 1.0
--===============7011550496984103126==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
<div><h1>bla</h1></div><img src="cid:1043833786270341319" title="1043833786270341319"/>
--===============7011550496984103126==--
--===============9061258228856181354==--
注意:图片代码被剪掉了,所以它不是很大的代码。同样,简单的目标是为非 html 读者显示后备,它应该有与 html 消息不同的消息。一个有能力的邮件程序不应该显示替代消息,对吗?
基本上,您的邮件排列不正确。有几种方法可以安排 MIME 消息中的各个部分,使它们对邮件代理有意义。让我们从简单的开始到复杂的选项:
最简单的是带有几个附件的文本。例如,你想把你的简历发给某人,于是你写了几句介绍并附上一份或多份文件(cover letter, CV):
mime───multipart/mixed─┬─text
├─attachment1
└─attachment2
Multipart/mixed 表示电子邮件代理将按顺序显示各个部分 - 一个接一个。
- 如果附件的内容配置是
inline
,并且电子邮件代理能够显示给定的附件类型,那么它将显示在邮件本身的内部 - 在其末尾。
- 如果附件的内容配置是
attachment
,它们通常会显示为某种图标或用于保存附件的链接。
如果你想发送一个漂亮的HTML消息,习惯上包括明文版本和HTML版本。这样即使在不支持 HTML 的电子邮件 reader 中,收件人也可以阅读它。您需要使用 multipart/alternative:
mime───multipart/mixed─┬─multipart/alternative─┬─text/plain
│ └─text/html
├─attachment1
└─attachment2
所以,同样,消息内容包括三个部分,正文和两个附件。但是正文本身是一个multipart/alternative
,它包含明文版本和HTML版本。请记住将纯文本放在第一位,然后是 HTML,因为惯例是邮件代理选择它知道如何显示的最后一个备选方案。
附件将在正文之后连续显示,就像之前一样,因为它们是主级别的下一部分,即 multipart/mixed
。
现在让我们看一下没有 "attachments" 的邮件,但它确实有应该嵌入在 HTML 中的图像。在这种情况下,邮件代理需要知道附件不仅仅是发送到要下载的 reader 的文件,而且应该与 HTML 相关联地显示它们。所以正确的 mime 类型是 multipart/related
,以表明这些部分是相关的。在这种情况下,您还需要为它们提供适当的内容 ID,并在 HTML 中使用这些内容 ID。这不是 MIME 标准的一部分,但现在 HTML 邮件通常是这样处理的。
就 MIME 而言,这样的消息将如下所示:
mime───multipart/alternative─┬─text/plain
└─multipart/related─┬─text/html
├─embedded image 1
└─embedded image 2
这次我们没有附件,所以我们可以把multipart/alternative作为我们的顶级内容。和以前一样,它首先有明文备选方案,但第二个备选方案本身就是 MimeMultipart("related")
.
里面有 HTML 部分和两张图片。 HTML 及其图像必须始终是同一 multipart/related 对象的一部分。
现在,如果您想要将您的文档附加到这样一封邮件,其中包含 HTML 和 图片怎么办?那么你会使用这样的东西:
mime───multipart/mixed─┬─multipart/alternative─┬─text/plain
│ └─multipart/related─┬─text/html
│ ├─embedded image 1
│ └─embedded image 2
├─attachment1
└─attachment2
因此您的顶级对象是 multipart/mixed,允许您将附件连续添加到邮件中。消息 "body"(multipart/mixed
的第一部分)是 multipart/alternative
的复杂结构,其中嵌入了 multipart/related
。然后是其他附件。
总结:
- 一封
multipart/mixed
邮件的第一部分应该是您可读的邮件,其余部分是附件。 所有部分将由 reader 的邮件代理显示。
- 一条
multipart/alternative
消息给出了相同内容的不同显示选项,从最常见的分母到最罕见的显示类型排序(例如纯文本→HTML→富文本→专有格式)和收件人的邮件程序选择它知道如何显示的最后一个。 您只看到其中一个选项。
multipart/related
消息通常用于将 HTML 正文与其内联消息组合在一起。第一部分是 HTML,其他部分具有 HTML 用于其 <img src="..." />
标签的内容 ID。
现在让我们看看您自己的层次结构,它基于 边界 字符串。您的最外层是一个 multipart/mixed
,边界 ===============9061258228856181354==
。如果您查找此边框出现的所有位置,您会看到此 multipart/alternative
.
分为三个部分
第一部分是:
Content-Type: multipart/alternative; boundary="===============2889524977048828163=="
MIME-Version: 1.0
--===============2889524977048828163==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
img 1043833786270341319 should be here
--===============2889524977048828163==--
这部分是multipart/alternative
,但它只有一个替代部分 - 其内容类型是text/plain。
第二部分是:
Content-Type: image/jpeg; name="sky.jpg"
MIME-Version: 1.0
Content-ID: <1043833786270341319>
Content-Transfer-Encoding: base64
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK
CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU
FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAEbAakDASIA
AhEBAxEB/8QAHQAAAgIDAQEBAAAAAAAAAAAAAgQBAwUGBwAICf/EADoQAAEEAQMDAwIFAgYBBAMB
所以这是一张图片。
第三部分是:
Content-Type: multipart/related; boundary="===============7011550496984103126=="
MIME-Version: 1.0
--===============7011550496984103126==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
<div><h1>bla</h1></div><img src="cid:1043833786270341319" title="1043833786270341319"/>
--===============7011550496984103126==--
嗯,这是 multipart/related
。但它只有一部分 - text/html
消息。图片不是其中的一部分。
因此,与其使用以下层次结构,不如使用以下层次结构来满足您的描述(纯文本和 html 替代方案,html 部分具有嵌入图像)
mime───multipart/alternative─┬─text/plain
└─multipart/related─┬─text/html
└─embedded image
你有这个错误的层次结构:
mime───multipart/mixed─┬─multipart/alternative───text/plain
├─image
└─multipart/related───text/html
因为所有的部分都在一个multipart/mixed
中,所以是顺序显示的,不是交替显示的。因为 text/plain
和 multipart/related
不是同一 multipart/alternative
的一部分,邮件代理不知道它们是彼此的替代项。它看不到 text/plain
的其他选择,multipart/alternative
.
只有一个部分
因为 multipart/related
部分不包含图像,所以会有邮件代理无法将图像正确放入 HTML 中。此外,正因为如此,该图像可能会连续显示或作为附件显示 - 它是独立的,与其他任何东西都不相关。
因此,您必须重新排列您的消息以符合正确的层次结构,以便备选方案能够正常工作,并使图像与 HTML.
正确相关
我正在尝试发送漂亮的 MIME 电子邮件,其中 html 将尽可能显示,如果不可能,它应该有一个文本回退。
也就是说,当html包含图片时,"alternative"部分应该显示"img ... should be here"。
问题是我在 gmail 中看到了一切,还有替代方案。
我的 MIME 消息有问题吗?
内容如下:
Content-Type: multipart/mixed; boundary="===============9061258228856181354=="
MIME-Version: 1.0
From: me@gmail.com <me@gmail.com>
To: me@gmail.com
--===============9061258228856181354==
Content-Type: multipart/alternative; boundary="===============2889524977048828163=="
MIME-Version: 1.0
--===============2889524977048828163==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
img 1043833786270341319 should be here
--===============2889524977048828163==--
--===============9061258228856181354==
Content-Type: image/jpeg; name="sky.jpg"
MIME-Version: 1.0
Content-ID: <1043833786270341319>
Content-Transfer-Encoding: base64
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK
CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU
FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAEbAakDASIA
AhEBAxEB/8QAHQAAAgIDAQEBAAAAAAAAAAAAAgQBAwUGBwAICf/EADoQAAEEAQMDAwIFAgYBBAMB
--===============9061258228856181354==
Content-Type: multipart/related; boundary="===============7011550496984103126=="
MIME-Version: 1.0
--===============7011550496984103126==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
<div><h1>bla</h1></div><img src="cid:1043833786270341319" title="1043833786270341319"/>
--===============7011550496984103126==--
--===============9061258228856181354==--
注意:图片代码被剪掉了,所以它不是很大的代码。同样,简单的目标是为非 html 读者显示后备,它应该有与 html 消息不同的消息。一个有能力的邮件程序不应该显示替代消息,对吗?
基本上,您的邮件排列不正确。有几种方法可以安排 MIME 消息中的各个部分,使它们对邮件代理有意义。让我们从简单的开始到复杂的选项:
最简单的是带有几个附件的文本。例如,你想把你的简历发给某人,于是你写了几句介绍并附上一份或多份文件(cover letter, CV):
mime───multipart/mixed─┬─text ├─attachment1 └─attachment2
Multipart/mixed 表示电子邮件代理将按顺序显示各个部分 - 一个接一个。
- 如果附件的内容配置是
inline
,并且电子邮件代理能够显示给定的附件类型,那么它将显示在邮件本身的内部 - 在其末尾。 - 如果附件的内容配置是
attachment
,它们通常会显示为某种图标或用于保存附件的链接。
如果你想发送一个漂亮的HTML消息,习惯上包括明文版本和HTML版本。这样即使在不支持 HTML 的电子邮件 reader 中,收件人也可以阅读它。您需要使用 multipart/alternative:
mime───multipart/mixed─┬─multipart/alternative─┬─text/plain │ └─text/html ├─attachment1 └─attachment2
所以,同样,消息内容包括三个部分,正文和两个附件。但是正文本身是一个multipart/alternative
,它包含明文版本和HTML版本。请记住将纯文本放在第一位,然后是 HTML,因为惯例是邮件代理选择它知道如何显示的最后一个备选方案。
附件将在正文之后连续显示,就像之前一样,因为它们是主级别的下一部分,即 multipart/mixed
。
现在让我们看一下没有 "attachments" 的邮件,但它确实有应该嵌入在 HTML 中的图像。在这种情况下,邮件代理需要知道附件不仅仅是发送到要下载的 reader 的文件,而且应该与 HTML 相关联地显示它们。所以正确的 mime 类型是 multipart/related
,以表明这些部分是相关的。在这种情况下,您还需要为它们提供适当的内容 ID,并在 HTML 中使用这些内容 ID。这不是 MIME 标准的一部分,但现在 HTML 邮件通常是这样处理的。
就 MIME 而言,这样的消息将如下所示:
mime───multipart/alternative─┬─text/plain └─multipart/related─┬─text/html ├─embedded image 1 └─embedded image 2
这次我们没有附件,所以我们可以把multipart/alternative作为我们的顶级内容。和以前一样,它首先有明文备选方案,但第二个备选方案本身就是 MimeMultipart("related")
.
里面有 HTML 部分和两张图片。 HTML 及其图像必须始终是同一 multipart/related 对象的一部分。
现在,如果您想要将您的文档附加到这样一封邮件,其中包含 HTML 和 图片怎么办?那么你会使用这样的东西:
mime───multipart/mixed─┬─multipart/alternative─┬─text/plain │ └─multipart/related─┬─text/html │ ├─embedded image 1 │ └─embedded image 2 ├─attachment1 └─attachment2
因此您的顶级对象是 multipart/mixed,允许您将附件连续添加到邮件中。消息 "body"(multipart/mixed
的第一部分)是 multipart/alternative
的复杂结构,其中嵌入了 multipart/related
。然后是其他附件。
总结:
- 一封
multipart/mixed
邮件的第一部分应该是您可读的邮件,其余部分是附件。 所有部分将由 reader 的邮件代理显示。 - 一条
multipart/alternative
消息给出了相同内容的不同显示选项,从最常见的分母到最罕见的显示类型排序(例如纯文本→HTML→富文本→专有格式)和收件人的邮件程序选择它知道如何显示的最后一个。 您只看到其中一个选项。 multipart/related
消息通常用于将 HTML 正文与其内联消息组合在一起。第一部分是 HTML,其他部分具有 HTML 用于其<img src="..." />
标签的内容 ID。
现在让我们看看您自己的层次结构,它基于 边界 字符串。您的最外层是一个 multipart/mixed
,边界 ===============9061258228856181354==
。如果您查找此边框出现的所有位置,您会看到此 multipart/alternative
.
第一部分是:
Content-Type: multipart/alternative; boundary="===============2889524977048828163=="
MIME-Version: 1.0
--===============2889524977048828163==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
img 1043833786270341319 should be here
--===============2889524977048828163==--
这部分是multipart/alternative
,但它只有一个替代部分 - 其内容类型是text/plain。
第二部分是:
Content-Type: image/jpeg; name="sky.jpg"
MIME-Version: 1.0
Content-ID: <1043833786270341319>
Content-Transfer-Encoding: base64
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK
CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU
FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAEbAakDASIA
AhEBAxEB/8QAHQAAAgIDAQEBAAAAAAAAAAAAAgQBAwUGBwAICf/EADoQAAEEAQMDAwIFAgYBBAMB
所以这是一张图片。
第三部分是:
Content-Type: multipart/related; boundary="===============7011550496984103126=="
MIME-Version: 1.0
--===============7011550496984103126==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
<div><h1>bla</h1></div><img src="cid:1043833786270341319" title="1043833786270341319"/>
--===============7011550496984103126==--
嗯,这是 multipart/related
。但它只有一部分 - text/html
消息。图片不是其中的一部分。
因此,与其使用以下层次结构,不如使用以下层次结构来满足您的描述(纯文本和 html 替代方案,html 部分具有嵌入图像)
mime───multipart/alternative─┬─text/plain └─multipart/related─┬─text/html └─embedded image
你有这个错误的层次结构:
mime───multipart/mixed─┬─multipart/alternative───text/plain ├─image └─multipart/related───text/html
因为所有的部分都在一个multipart/mixed
中,所以是顺序显示的,不是交替显示的。因为 text/plain
和 multipart/related
不是同一 multipart/alternative
的一部分,邮件代理不知道它们是彼此的替代项。它看不到 text/plain
的其他选择,multipart/alternative
.
因为 multipart/related
部分不包含图像,所以会有邮件代理无法将图像正确放入 HTML 中。此外,正因为如此,该图像可能会连续显示或作为附件显示 - 它是独立的,与其他任何东西都不相关。
因此,您必须重新排列您的消息以符合正确的层次结构,以便备选方案能够正常工作,并使图像与 HTML.
正确相关