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

可以pass以下两种方式之一创建消息对象结构:可以pass实例化Message对象并passattach()set_payload()调用将它们串在一起而从整体上创建它们,或者可以pass解析电子邮件的纯文本表示来创建它们。

email软件包提供了一个标准解析器,该解析器可以理解大多数电子邮件文档结构,包括 MIME 文档。您可以将字符串或文件对象传递给解析器,解析器将返回给您该对象结构的根Message实例。对于简单的非 MIME 消息,此根对象的有效负载可能是包含消息文本的字符串。对于 MIME 消息,根对象将从其is_multipart()方法返回True,并且可以passget_payload()walk()方法访问子部分。

实际上,有两个解析器接口可供使用:经典Parser API 和增量FeedParser API。如果您将消息的整个文本作为字符串存储在内存中,或者如果整个消息都位于文件系统上的文件中,则经典的Parser API 很好。 FeedParser更适合您从流中读取消息时,该消息可能会阻止 await 更多 Importing(例如,从套接字中读取电子邮件)。 FeedParser可以逐步使用和解析消息,并且仅在关闭解析器[1]时返回根对象。

请注意,可以以有限的方式扩展解析器,当然,您可以完全从头开始实现自己的解析器。 email包的 Binding 解析器和Message类之间没有魔术连接,因此您的自定义解析器可以按需要找到的任何方式创建消息对象树。

18.1.2.1. FeedParser API

2.4 版的新Function。

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

FeedParser的 API 很简单;您创建一个实例,为它提供一堆文本,直到不再需要它为止,然后关闭解析器以检索根消息对象。 FeedParser在解析符合标准的消息时非常准确,并且在解析不符合要求的消息方面做得非常好,提供了有关如何将消息视为损坏的信息。它将使用消息中发现的任何问题的列表填充消息对象的* defects *属性。有关可以找到的缺陷列表,请参见email.errors模块。

这是FeedParser的 API:

  • 类别 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可以更快,因为它不try解析消息正文,而是将有效负载设置为字符串形式的原始内容。 HeaderParserParser类具有相同的 API。

    • class * email.parser. Parser([* _class *])
    • Parser类的构造函数采用可选参数* _class *。它必须是可调用的工厂(例如函数或类),并且在需要创建子消息对象时使用它。默认为Message(请参见email.message)。将不带参数地调用工厂。

可选的* strict *标志将被忽略。

从版本 2.4 开始不推荐使用:由于Parser类是 Python 2.4 新版本FeedParser的向后兼容 API 包装器,因此* all *解析实际上是非严格的。您只需停止将_strict *标志传递给Parser构造函数。

在版本 2.2.2 中进行了更改:添加了* strict *标志。

在版本 2.4 中更改:不建议使用* strict *标志。

其他公共Parser方法是:

  • parse(* fp * [,* headersonly *])
    • 从类似文件的对象* fp *中读取所有数据,解析结果文本,然后返回根消息对象。 * fp *必须同时支持类似文件的对象的readline()read()方法。
  • fp *中包含的文本必须格式化为 RFC 2822样式标题和标题延续行的块,并可以选择在其前面加上信封标题。标题块以数据结尾或空行结尾。Headers 块之后是邮件的正文(其中可能包含 MIME 编码的子部分)。

可选的* headersonly *是一个标志,用于指定是否在读取标题后停止解析。默认值为False,这意味着它将解析文件的全部内容。

在版本 2.2.2 中更改:添加了* headersonly *标志。

  • parsestr(* text * [,* headersonly *])
    • parse()方法类似,不同之处在于它采用字符串对象而不是类似文件的对象。在字符串上调用此方法完全等效于首先在StringIO实例中包装* text *并调用parse()

可选的* headersonly *与parse()方法相同。

在版本 2.2.2 中更改:添加了* headersonly *标志。

由于从字符串或文件对象创建消息对象结构是一种常见的任务,因此为方便起见提供了两个Function。它们在顶级email软件包名称空间中可用。

  • email. message_from_string(* s * [,* _class * [,* strict *]])
    • 从字符串返回消息对象结构。这完全等于Parser().parsestr(s)。可选的* _class strict *与Parser class 构造函数一样解释。

在版本 2.2.2 中进行了更改:添加了* strict *标志。

  • email. message_from_file(* fp * [,* _class * [,* strict *]])
    • 从打开的文件对象返回消息对象结构树。这完全等于Parser().parse(fp)。可选的* _class strict *与Parser class 构造函数一样解释。

在版本 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子 Component 的列表。

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

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

Footnotes

  • [1]
    • 从 Python 2.4 中引入的电子邮件软件包版本 3.0 开始,经典的Parser已根据FeedParser重新实现,因此两个解析器之间的语义和结果相同。