18.1.2. email.parser:解析电子邮件消息 — Python 文档
18.1.2. 电子邮件解析器 :解析电子邮件
消息对象结构可以通过以下两种方式之一创建:它们可以通过实例化 Message 对象并通过 attach() 和 set_payload() 将它们串在一起来从整个布料创建 调用,或者它们可以通过解析电子邮件的纯文本表示来创建。
email 包提供了一个标准解析器,可以理解大多数电子邮件文档结构,包括 MIME 文档。 您可以将字符串或文件对象传递给解析器,解析器将返回对象结构的根 Message 实例。 对于简单的非 MIME 消息,此根对象的有效负载可能是包含消息文本的字符串。 对于 MIME 消息,根对象将从其 is_multipart() 方法返回 True
,并且可以通过 get_payload() 和 walk 访问子部分() 方法。
实际上有两个解析器接口可供使用,经典的 Parser API 和增量 FeedParser API。 经典的 Parser API 如果您将整个消息文本作为字符串保存在内存中,或者如果整个消息位于文件系统上的一个文件中,则该 API 很好。 FeedParser 更适合当您从流中读取消息时,该流可能会阻塞等待更多输入(例如 从套接字读取电子邮件)。 FeedParser可以增量消费和解析消息,并且只有在关闭解析器1时才返回根对象。
请注意,解析器可以通过有限的方式进行扩展,当然您可以完全从头开始实现自己的解析器。 email 包的捆绑解析器和 Message 类之间没有神奇的联系,因此您的自定义解析器可以以任何它认为必要的方式创建消息对象树。
18.1.2.1. FeedParser API
2.4 版中的新功能。
从 email.feedparser
模块导入的 FeedParser 提供了一个有助于增量解析电子邮件消息的 API,例如从以下来源读取电子邮件消息的文本时所必需的可以阻止(例如 一个插座)。 FeedParser 当然可用于解析完全包含在字符串或文件中的电子邮件,但经典的 Parser API 可能更方便此类用例。 两个解析器 API 的语义和结果是相同的。
FeedParser 的 API 很简单; 你创建一个实例,给它提供一堆文本,直到没有更多的文本可以提供它,然后关闭解析器以检索根消息对象。 FeedParser 在解析符合标准的消息时非常准确,它在解析不符合标准的消息方面做得非常好,提供有关如何认为消息已损坏的信息。 它将使用在消息中发现的任何问题的列表填充消息对象的 defects 属性。 请参阅 email.errors 模块以获取它可以找到的缺陷列表。
这是 FeedParser 的 API:
- class email.parser.FeedParser([_factory])
创建一个 FeedParser 实例。 可选的 _factory 是一个无参数的可调用对象,每当需要新消息对象时都会调用它。 它默认为 email.message.Message 类。
- feed(data)
向 FeedParser 提供更多数据。 data 应该是包含一行或多行的字符串。 这些行可以是部分行,FeedParser 会将这些部分行正确拼接在一起。 字符串中的行可以有任何常见的三行结尾,回车、换行或回车和换行(它们甚至可以混合)。
- close()
关闭一个 FeedParser 完成对所有先前馈送数据的解析,并返回根消息对象。 如果将更多数据提供给关闭的 FeedParser,会发生什么是不确定的。
18.1.2.2. 解析器类 API
从 email.parser 模块导入的 Parser 类提供了一个 API,当消息的完整内容在字符串或文件中可用时,该 API 可用于解析消息。 email.parser 模块还提供了第二个类,称为 HeaderParser
,如果您只对邮件的标题感兴趣,可以使用它。 HeaderParser
在这些情况下可以快得多,因为它不会尝试解析消息正文,而是将有效负载设置为原始正文作为字符串。 HeaderParser
与 Parser 类具有相同的 API。
- class email.parser.Parser([_class])
Parser 类的构造函数接受一个可选参数 _class。 这必须是可调用的工厂(例如函数或类),并且在需要创建子消息对象时使用。 它默认为 Message(参见 email.message)。 工厂将在没有参数的情况下被调用。
可选的 strict 标志被忽略。
自 2.4 版起已弃用:因为 Parser 类是 Python 2.4 中的新 FeedParser、all 的向后兼容 API 包装器解析实际上是非严格的。 您应该停止将 strict 标志传递给 Parser 构造函数。
在 2.2.2 版更改: 添加了 strict 标志。
2.4 版更改: strict 标志已弃用。
其他公共 Parser 方法是:
- parse(fp[, headersonly])
从类文件对象 fp 读取所有数据,解析结果文本,并返回根消息对象。 fp 必须同时支持文件类对象的 readline() 和 read() 方法。
fp 中包含的文本必须格式化为 RFC 2822 样式标题和标题连续行的块,可选地以信封标题开头。 标题块以数据结尾或空行结束。 头块后面是消息的主体(可能包含 MIME 编码的子部分)。
可选的 headersonly 是一个标志,指定是否在读取标头后停止解析。 默认值为
False
,这意味着它解析文件的全部内容。在 2.2.2 版更改: 添加了 headersonly 标志。
由于从字符串或文件对象创建消息对象结构是一项常见任务,因此提供了两个函数以方便使用。 它们在顶级 email 包命名空间中可用。
- email.message_from_string(s[, _class[, strict]])
从字符串返回消息对象结构。 这完全等同于
Parser().parsestr(s)
。 可选的 _class 和 strict 被解释为 Parser 类构造函数。在 2.2.2 版更改: 添加了 strict 标志。
- email.message_from_file(fp[, _class[, strict]])
从打开的文件对象返回消息对象结构树。 这完全等同于
Parser().parse(fp)
。 可选的 _class 和 strict 被解释为 Parser 类构造函数。在 2.2.2 版更改: 添加了 strict 标志。
下面是一个如何在交互式 Python 提示符下使用它的示例:
>>> import email
>>> msg = email.message_from_string(myString)
18.1.2.3. 补充说明
以下是有关解析语义的一些说明:
- 大多数非 multipart 类型的消息被解析为带有字符串负载的单个消息对象。 这些对象将为 is_multipart() 返回
False
。 他们的 get_payload() 方法将返回一个字符串对象。 - 所有 multipart 类型的消息都将被解析为一个容器消息对象,其中包含其有效负载的子消息对象列表。 外部容器消息将为 is_multipart() 返回
True
,它们的 get_payload() 方法将返回 Message 子部分的列表。 - 大多数内容类型为 message/* 的消息(例如 message/delivery-status 和 message/rfc822) 也将被解析为包含长度为 1 的列表负载的容器对象。 他们的 is_multipart() 方法将返回
True
。 列表有效负载中的单个元素将是一个子消息对象。 - 一些不符合标准的消息在它们的 multipart-edness 方面可能在内部不一致。 此类消息可能具有 multipart 类型的 Content-Type 标头,但它们的 is_multipart() 方法可能返回
False
。 如果使用 FeedParser 解析此类消息,则它们的 defects 属性列表中将具有MultipartInvariantViolationDefect
类的实例。 有关详细信息,请参阅 email.errors。
脚注
- 1
- 从 Python 2.4 中引入的电子邮件包版本 3.0 开始,经典的 Parser 根据 FeedParser 重新实现,因此两个解析器之间的语义和结果是相同的。