【问题标题】:What are the "parts" in a multipart email?多部分电子邮件中的“部分”是什么?
【发布时间】:2018-07-11 18:56:16
【问题描述】:

一点上下文...

前段时间,我用 Python 写了一个处理电子邮件的程序,经常遇到的一件事就是知道电子邮件是否是“多部分”的。

经过一番研究,我知道这与包含 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?或者哪一个是附件?还是只是身体?

【问题讨论】:

  • Multipart 是一种在单个主体内(可能)编码多个数据元素的方式。这可能意味着文本正文中有附件或其他项目,但这不是必需的。您也可以只对多部分消息中的单个消息正文进行编码。
  • if part.get('Content-Disposition') is None: 不正确。这只是告诉您这部分没有明确的处置;所以你必须推断出一个隐含的处置,这取决于零件的类型。 text/* 通常是隐式内联的,而大多数其他类型是隐式附加的。
  • get_text() 同样幼稚。如果您想决定将什么显示为“消息”,您希望避免使用显式 Content-Disposition: attachment 或嵌入例如退回邮件。如果有multipart/alternative(实际上也可能标记为multipart/mixed 或multipart/related),则消息正文可能有多种渲染,您可以选择适合您的用例的一种。跨度>
  • 这个问题是基于一个不准确的心智模型。设计者有一个不同的模型:一条消息(或一个部分)可能有几个部分,可能是替代品('multipart/alternative')、串行等。0-n 个部分中的每一个都必须有一个类型,例如HTML、JPEG、文本、Wordstar 文档、音频/mp3 或许多其他。每个部分都可以指定为内联或附件,如果未指定,则接收者可以猜测。这种模型为发件人提供了很大的灵活性……这对 IMO 来说很好,因为现实世界的发件人无论如何都不是很自律,并且会违反制定的任何规则。
  • @arnt “猜测”不正确;为每种类型定义了默认配置。

标签: python python-3.x email imap


【解决方案1】:

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

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

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

如果您想惊叹于 MIME 的运行之美,请查看“MIME 折磨测试”。找到它有点棘手,因为this random item on github 绝对不是我的意思。这是创建 IMAP 的工程师 Mark Crispin 的原件:

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

【讨论】:

【解决方案2】:

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

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

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

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

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

【讨论】:

  • Python 3.6+ 有一个改进的 email 库,其中包含一个方法 get_body,它试图为您猜测“主体部分”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-11
  • 2018-05-16
  • 2019-05-06
  • 2017-03-19
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多