Skip to main content

19.1.2. email.parser:解析电子邮件

源代码: Lib/email/parser.py


消息对象结构可以通过以下两种方式之一创建:可以通过创建 EmailMessage 对象,使用字典接口添加标头,使用 set_content() 和相关方法添加有效内容,从而从整个布料创建消息对象结构,也可以通过创建解析所述电子邮件消息的串行化表示。

email 包提供了一个标准解析器,可以理解大多数电子邮件文档结构,包括MIME文档。您可以向解析器传递一个字节,字符串或文件对象,解析器将返回对象结构的根 EmailMessage 实例。对于简单的非MIME消息,此根对象的有效内容可能是包含消息文本的字符串。对于MIME消息,根对象将从其 is_multipart() 方法返回 True,并且子部分可以通过有效载荷操作方法(例如 get_body()iter_parts()walk())来访问。

实际上有两个解析器接口可供使用,Parser API和增量 FeedParser API。如果在内存中具有消息的整个文本,或者整个消息存在于文件系统上的文件中,那么 Parser API是最有用的。 FeedParser 更适用于从流中读取消息,这可能会阻止等待更多输入(例如从套接字读取电子邮件)。 FeedParser 可以逐次使用和解析消息,并且只有在关闭解析器时才返回根对象。

注意,解析器可以以有限的方式扩展,当然你可以从头开始实现自己的解析器。连接 email 包捆绑解析器和 EmailMessage 类的所有逻辑都体现在 policy 类中,因此自定义解析器可以通过实现适当的 policy 方法的定制版本以任何方式创建消息对象树。

19.1.2.1. FeedParser API

email.feedparser 模块导入的 BytesFeedParser 提供了有利于对电子邮件消息进行增量解析的API,例如当从可以阻塞的源(诸如套接字)读取电子邮件消息的文本时,这是必要的。 BytesFeedParser 当然可以用于解析完全包含在 bytes-like object,字符串或文件中的电子邮件消息,但是 BytesParser API对于这样的使用情况可能更方便。两个解析器API的语义和结果是相同的。

BytesFeedParser 的API很简单;你创建一个实例,喂它一堆字节,直到没有更多的东西喂它,然后关闭解析器检索根消息对象。 BytesFeedParser 在解析符合标准的消息时非常精确,并且非常好地解析不符合要求的消息,提供有关消息被视为损坏的信息。它将填充消息对象的 defects 属性,其中包含在消息中找到的任何问题的列表。有关可以找到的缺陷列表,请参见 email.errors 模块。

这里是 BytesFeedParser 的API:

class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)

创建 BytesFeedParser 实例。可选 _factory 是无参数可调用;如果没有指定使用来自 policymessage_factory。当需要新的消息对象时调用 _factory

如果指定了 policy,则使用它指定的规则来更新消息的表示。如果未设置 policy,请使用 compat32 策略,它保持与Python 3.2版本的电子邮件包的向后兼容性,并提供 Message 作为默认工厂。所有其他策略提供 EmailMessage 作为默认 _factory。有关 policy 控制什么的更多信息,请参阅 policy 文档。

注:应始终指定policy关键字;在Python的未来版本中,默认值将更改为 email.policy.default

3.2 新版功能.

在 3.3 版更改: 添加了 policy 关键字。

在 3.6 版更改: _factory 默认为策略 message_factory

feed(data)

向解析器提供一些更多的数据。 data 应为包含一行或多行的 bytes-like object。线可以是部分的,并且解析器将这些部分线适当地拼接在一起。这些行可以具有三个公共行结尾中的任何一个:回车,换行或回车和换行(甚至可以混合)。

close()

完成对所有先前馈送的数据的解析,并返回根消息对象。未定义如果在调用此方法后调用 feed(),会发生什么。

class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)

BytesFeedParser 一样工作,除了 feed() 方法的输入必须是字符串。这是有限的实用程序,因为这样的消息的有效的唯一方法是它只包含ASCII文本,或者,如果 utf8True,没有二进制附件。

在 3.3 版更改: 添加了 policy 关键字。

19.1.2.2. 解析器API

email.parser 模块导入的 BytesParser 类提供了一个API,当消息的完整内容在 bytes-like object 或文件中可用时,可用于解析消息。 email.parser 模块还提供用于解析字符串的 Parser 和仅头解析器 BytesHeaderParserHeaderParser,如果您只对消息的头部感兴趣,可以使用它们。在这些情况下,BytesHeaderParserHeaderParser 可以快得多,因为它们不会尝试解析邮件正文,而是将有效负载设置为原始主体。

class email.parser.BytesParser(_class=None, *, policy=policy.compat32)

创建 BytesParser 实例。 _classpolicy 参数具有与 BytesFeedParser_factorypolicy 参数相同的含义和语义。

注:应始终指定policy关键字;在Python的未来版本中,默认值将更改为 email.policy.default

在 3.3 版更改: 删除了在2.4中已弃用的 strict 参数。添加了 policy 关键字。

在 3.6 版更改: _class 默认为策略 message_factory

parse(fp, headersonly=False)

从二进制文件样对象 fp 读取所有数据,解析生成的字节,并返回消息对象。 fp 必须支持 readline()read() 方法。

包含在 fp 中的字节必须被格式化为 RFC 5322 的块(或者,如果 utf8TrueRFC 6532)样式的头部和头部连续行,可选地前面是包络头部。标题块由数据的结尾或空白行终止。在标题块之后是消息的主体(其可以包含MIME编码的子部分,包括具有 8bitContent-Transfer-Encoding 的子部分。

可选 headersonly 是一个标志,指定在读取头之后是否停止解析。默认值为 False,意味着它将解析文件的整个内容。

parsebytes(bytes, headersonly=False)

类似于 parse() 方法,除了它需要一个 bytes-like object 而不是一个类文件对象。在 bytes-like object 上调用此方法等效于首先将 bytes 包装在 BytesIO 实例中并调用 parse()

可选 headersonlyparse() 方法一样。

3.2 新版功能.

class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)

完全像 BytesParser,除了 headersonly 默认为 True

3.3 新版功能.

class email.parser.Parser(_class=None, *, policy=policy.compat32)

此类与 BytesParser 并行,但处理字符串输入。

在 3.3 版更改: 删除了 strict 参数。添加了 policy 关键字。

在 3.6 版更改: _class 默认为策略 message_factory

parse(fp, headersonly=False)

从文本模式文件对象 fp 读取所有数据,解析生成的文本,并返回根消息对象。 fp 必须同时支持类文件对象上的 readline()read() 方法。

除了文本模式要求,此方法操作像 BytesParser.parse()

parsestr(text, headersonly=False)

类似于 parse() 方法,除了它需要一个字符串对象而不是像文件一样的对象。在字符串上调用此方法等效于首先在 StringIO 实例中封装 text 并调用 parse()

可选 headersonlyparse() 方法一样。

class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)

完全像 Parser,除了 headersonly 默认为 True

由于从字符串或文件对象创建消息对象结构是这样的常见任务,为了方便起见,提供了四个功能。它们在顶级 email 包命名空间中可用。

email.message_from_bytes(s, _class=None, *, policy=policy.compat32)

bytes-like object 返回消息对象结构。这相当于 BytesParser().parsebytes(s)。可选的 _classstrict 被解释为使用 BytesParser 类构造函数。

3.2 新版功能.

在 3.3 版更改: 删除了 strict 参数。添加了 policy 关键字。

message_from_binary_file(fp, _class=None, *,
policy=policy.compat32)

从打开的二进制 file object 返回消息对象结构树。这相当于 BytesParser().parse(fp)_classpolicy 被解释为与 BytesParser 类构造函数一样。

3.2 新版功能.

在 3.3 版更改: 删除了 strict 参数。添加了 policy 关键字。

email.message_from_string(s, _class=None, *, policy=policy.compat32)

从字符串返回消息对象结构。这相当于 Parser().parsestr(s)_classpolicy 被解释为与 Parser 类构造函数一样。

在 3.3 版更改: 删除了 strict 参数。添加了 policy 关键字。

email.message_from_file(fp, _class=None, *, policy=policy.compat32)

从打开的 file object 返回消息对象结构树。这相当于 Parser().parse(fp)_classpolicy 被解释为与 Parser 类构造函数一样。

在 3.3 版更改: 删除了 strict 参数。添加了 policy 关键字。

在 3.6 版更改: _class 默认为策略 message_factory

下面是一个在交互式Python提示符下如何使用 message_from_bytes() 的示例:

>>> import email
>>> msg = email.message_from_bytes(myBytes)  

19.1.2.3. 补充笔记

这里有一些关于解析语义的注释:

  • 大多数非 multipart 类型的消息被解析为具有字符串有效载荷的单个消息对象。这些对象将为 is_multipart() 返回 Falseiter_parts() 将产生一个空列表。

  • 所有 multipart 类型的消息将被解析为一个容器消息对象,其有效载荷的子消息对象列表。外部容器消息将为 is_multipart() 返回 Trueiter_parts() 将生成子部分的列表。

  • 大多数内容类型为 message/* 的消息(例如 message/delivery-statusmessage/rfc822)也将被解析为包含长度为1的列表有效内容的容器对象。他们的 is_multipart() 方法将返回 Trueiter_parts() 生成的单个元素将是一个子消息对象。

  • 一些不符合标准的消息可能在内部不一致关于他们的 multipart -edness。这样的消息可以具有类型 multipartContent-Type 报头,但是它们的 is_multipart() 方法可以返回 False。如果这样的消息被 FeedParser 解析,它们将在其 defects 属性列表中具有 MultipartInvariantViolationDefect 类的实例。有关详细信息,请参阅 email.errors