多部分电子邮件中的 "parts" 是什么?

What are the "parts" in a multipart email?

一些上下文...

前段时间,我写了Python一个处理电子邮件的程序,经常遇到的一件事是知道一封电子邮件是否"multipart"。

经过一番研究,我知道它与包含 HTML 的电子邮件或附件等有关......但我并没有真正理解它。

我对它的使用仅限于 2 次:

1.当我不得不从原始电子邮件中保存附件时

我刚在互联网上找到这个(可能在这里 - 抱歉没有注明作者的姓名,但我似乎再也找不到他了:/)并将其粘贴到我的代码中

def downloadAttachments(emailMsg, pathToSaveFile):
    """
    Save Attachments to pathToSaveFile (Example: pathToSaveFile = "C:\Program Files\")
    """
    att_path_list = []
    for part in emailMsg.walk():
        # multipart are just containers, so we skip them
        if part.get_content_maintype() == 'multipart':
            continue

        # is this part an attachment ?
        if part.get('Content-Disposition') is None:
            continue

        filename = part.get_filename()

        att_path = os.path.join(pathToSaveFile, filename)

        #Check if its already there
        if not os.path.isfile(att_path) :
            # finally write the stuff
            fp = open(att_path, 'wb')
            fp.write(part.get_payload(decode=True))
            fp.close()
        att_path_list.append(att_path)
    return att_path_list

2。当我不得不从原始电子邮件中获取文本时

也是从互联网上的某个人那里粘贴的,但并没有真正理解它是如何工作的。

def get_text(emailMsg):
    """
    Output: body of the email (text content)
    """
    if emailMsg.is_multipart():
        return get_text(emailMsg.get_payload(0))
    else:
        return emailMsg.get_payload(None, True)

我明白的...

如果电子邮件消息是多部分的,那么这些部分可以迭代。

我的问题是

这些究竟是什么部分?例如,您怎么知道 html 是哪一个?或者哪个是附件?或者只是 body?

您要找的答案都在 MIME 标准中,尤其是:

这些标准共同将电子邮件从纯文本、纯英文状态转变为目前的状态,我们可以通过有趣的方式发送 Unicode 便便、带有可爱小猫的专有位图,以及数十种用于不符合标准的软件和软件的方式沿路径的中间盒以微妙和非微妙的方式破坏消息。这些功能的更多详细信息位于:

对于问题中特定于 IMAP 的部分,即如何通过 IMAP 最好地访问这些部分的 MIME 树,请参阅 RFC3501,尤其是有关 BODY 和 [= 的章节11=] 构造。

如果你想惊叹 MIME 的动人之美,就看看“MIME 酷刑测试”吧。找起来有点棘手,因为 this random item on github 绝对不是我的意思。这是来自创建 IMAP 的工程师 Mark Crispin 的原件:

是的,阅读量很大。不幸的是,您确实需要理解 上述所有内容才能正确安全地处理 MIME。请不要跳过这些资源和标准,除非您想创建可憎的东西,例如随机批量邮件程序,它始终将 UTF-8 中的非 ASCII 代码点拆分为几个相邻的 MIME 编码块等。谢谢。

一封电子邮件由一个 MIME 部分或一个 multipart 具有多个 MIME 部分的结构组成。

如果没有multipart结构,消息兼容pre-MIMERFC822消息,Content-type:等headers是可选的(如果你不拼出内容类型和编码,Content-type: text/plain; charset="us-ascii"Content-transfer-encoding: 7bit 是隐含的,但对于人类读者来说它们仍然很好;在 MIME 之前,推断内容的类型和编码更像是一个狂野的西部best-guess情况)。

对于如何准确使用多部分消息,没有严格的层次结构或指南。 MIME 只是定义了一种将多个有效负载收集到单个电子邮件消息中的方法。我认为最初的动机之一是能够在文本中嵌入图片;但是能够将二进制文件附加到文本消息,更一般地说,能够创建具有以任意方式相关的有效负载的结构化消息,这只是应用程序以他们认为合适的方式使用的东西。

一个常见的误解是假设 层次结构分为“主要部分”和“从属”部分。创建这种结构当然是可能的,但绝非普遍如此。事实上,大多数多部分消息只是包含一系列没有任何层次结构的部分。用户的电子邮件客户端通常会选择其中一个“内联”部分作为首选“主要”部分以显示在消息窗格中,但这绝不是标准规定的,或者可能由发送方强制执行。

每个 MIME 部分都有一组 headers,告诉您类型、编码和配置;对于 text/* 类型的部分,默认配置是“内联”(因此通常没有明确说明),而大多数其他部分的默认配置是“附件”。您需要参考相关标准以获得严格的定义,但可能会有所保留,因为许多 real-world 应用程序并不是特别 RFC-conformant.

对于您的具体问题,找到(隐式或显式)内联的最顶层叶部分,并将支持您的用例的部分显示为“主要”部分。如果你想强制 HTML 作为首选格式,你可以这样做;但是许多电子邮件应用程序将此留给用户来决定,并且某些用户肯定会 -- 由于技术需要、身体残疾或个人品味 -- 在可用时更喜欢 plain-text。

不幸的是,消息生产者最近的常见做法是创建一个包含 text/plaintext/html 成员的 multipart/alternative 容器,但随后提供完全无用的 text/plain 部分并将所有实际内容放在 text/html 部分中。在这种情况下,正确的安排是如果您不能在其中放置任何有用的东西,则根本不提供 text/plain 部分(但我猜他们只关心通过一些被误导的垃圾邮件过滤器,而不是实际适应首选项的收件人)。