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 方法的自定义版本来创建消息对象树,无论它发现哪种方式有必要。

FeedParser API

email.feedparser 模块导入的 BytesFeedParser 提供了一个 API,该 API 有利于增量解析电子邮件,例如在从可能阻塞的源(例如套接字)读取电子邮件文本时需要这样做。BytesFeedParser 当然可以用来解析完全包含在 类字节对象、字符串或文件中的电子邮件,但 BytesParser API 可能对这些用例更方便。两个解析器 API 的语义和结果是相同的。

BytesFeedParser 的 API 很简单;创建一个实例,向其中输入一批字节,直到没有更多字节可以输入,然后关闭解析器以检索根消息对象。 BytesFeedParser 在解析符合标准的消息时非常准确,并且在解析不符合标准的消息时也能很好地工作,提供有关消息如何被判定为损坏的信息。它将填充消息对象的 defects 属性,其中包含它在消息中发现的任何问题的列表。有关它可以找到的缺陷列表,请参阅 email.errors 模块。

以下是 BytesFeedParser 的 API

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

创建一个 BytesFeedParser 实例。可选的 _factory 是一个无参数的可调用对象;如果没有指定,则使用 policy 中的 message_factory。每当需要新的消息对象时,调用 _factory

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

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

在版本 3.2 中添加。

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

在版本 3.6 中更改: _factory 的默认值变为策略 message_factory

feed(data)

向解析器提供更多数据。data 应为 类字节对象,其中包含一行或多行。这些行可以是不完整的,解析器将正确地拼接这些不完整行。这些行可以具有三种常见的行尾之一:回车、换行或回车和换行(甚至可以混合使用)。

close()

完成先前提供的所有数据的解析并返回根消息对象。如果在调用此方法后调用 feed(),则会发生什么情况是不确定的。

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

BytesFeedParser 的工作方式类似,不同之处在于 feed() 方法的输入必须是字符串。这用处有限,因为此类消息有效的唯一方法是仅包含 ASCII 文本,或者如果 utf8True,则不包含二进制附件。

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

解析器 API

email.parser 模块导入的 BytesParser 类提供了一个 API,当消息的完整内容在 类似字节的对象 或文件中可用时,可用于解析消息。 email.parser 模块还提供 Parser 来解析字符串,以及仅限标头的解析器 BytesHeaderParserHeaderParser,如果您仅对消息的标头感兴趣,可以使用这些解析器。 BytesHeaderParserHeaderParser 在这些情况下速度会快很多,因为它们不会尝试解析消息正文,而是将有效负载设置为原始正文。

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

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

注意:始终应指定策略关键字;在未来版本的 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(或者,如果 utf8True,则为 RFC 6532)样式的标头和标头续行,前面可以有一个信封标头。标头块由数据的末尾或空行终止。标头块后面是消息正文(可能包含 MIME 编码的子部分,包括 Content-Transfer-Encoding8bit 的子部分)。

可选的 headersonly 是一个标志,用于指定是否在读取标头后停止分析。默认值为 False,表示它将分析文件的全部内容。

parsebytes(bytes, headersonly=False)

parse() 方法类似,但它采用 类似字节的对象,而不是类似文件的对象。对 类似字节的对象 调用此方法等同于首先将 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() 方法类似,但它采用字符串对象而不是类文件对象。对字符串调用此方法等效于首先将 text 封装在 StringIO 实例中,然后调用 parse()

可选的 headersonlyparse() 方法相同。

email.parser.HeaderParser(_class=, *, 策略=策略.compat32)

Parser 完全相同,但仅头默认为 True

由于从字符串或文件对象创建消息对象结构是一项常见的任务,因此提供了四个函数作为一种便利。它们可在顶层 email 包名称空间中使用。

email.message_from_bytes(s, _class=, *, 策略=策略.compat32)

类字节对象 返回消息对象结构。这等效于 BytesParser().parsebytes(s)。可选的_class策略的解释与 BytesParser 类构造函数相同。

在版本 3.2 中添加。

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

email.message_from_binary_file(fp, _class=, *, 策略=策略.compat32)

从打开的二进制 文件对象 返回消息对象结构树。这等效于 BytesParser().parse(fp)_class策略的解释与 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)

从一个打开的 文件对象 返回一个消息对象结构树。这等同于 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)  

其他说明

以下是对解析语义的一些说明

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

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

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

  • 某些不符合标准的消息在其 multipart 方面可能在内部不一致。此类消息可能具有类型为 multipartContent-Type 头,但它们的 is_multipart() 方法可能返回 False。如果使用 FeedParser 解析此类消息,它们将在其 defects 属性列表中具有 MultipartInvariantViolationDefect 类的实例。有关详细信息,请参见 email.errors