"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
==============

The "BytesFeedParser", imported from the "email.feedparser" module,
provides an API that is conducive to incremental parsing of email
messages, such as would be necessary when reading the text of an email
message from a source that can block (such as a socket).  The
"BytesFeedParser" can of course be used to parse an email message
fully contained in a *bytes-like object*, string, or file, but the
"BytesParser" API may be more convenient for such use cases.  The
semantics and results of the two parser APIs are identical.

"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 版本的 email 包的后向兼容性，并且使用
   "Message" 作为默认的工厂。其他策略使用 "EmailMessage" 作为默认的
   *_factory*。关于 *policy* 还会控制什么，参见 "policy" 的文档。

   Note: **The policy keyword should always be specified**. The
   default will change to "email.policy.default" in a future version
   of Python.

   Added in version 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 文字，
   或者 "utf8" 被设置为 "True" 且没有二进制格式的附件的时候，才会有效
   。

   在 3.3 版本发生变更: 添加了 *policy* 关键字。


Parser API
==========

"BytesParser" 类自 "email.parser" 模块导入，它提供了当消息的完整内容可
从 *bytes-like object* 或文件中获取时可被用于解析消息的 API。
"email.parser" 模块还提供了 "Parser" 用来解析字符串，以及仅用于标头的
解析器 "BytesHeaderParser" 和 "HeaderParser"，它们可在你只对消息标头感
兴趣时被使用。 "BytesHeaderParser" 和 "HeaderParser" 在这些场合中速度
更快，因为它们不会尝试解析消息体，而是将载荷设为原始消息体。

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

   创建一个 "BytesParser" 实例。 *_class* 和 *policy* 参数在含义和语义
   上与 "BytesFeedParser" 的 *_factory* 和 *policy* 参数一致。

   Note: **The policy keyword should always be specified**. The
   default will change to "email.policy.default" in a future version
   of Python.

   在 3.3 版本发生变更: 移除了在 2.4 版本中被弃用的 *strict* 参数。新
   增了 *policy* 关键字。

   在 3.6 版本发生变更: *_class* 默认为策略 "message_factory"。

   parse(fp, headersonly=False)

      从二进制文件型对象 *fp* 中读取全部数据，解析其字节内容，并返回消
      息对象。 *fp* 必须同时支持 "readline()" 和 "read()" 方法。

      包含在 *fp* 中的字节串必须是一块以 **RFC 5322** (或者如果 "utf8"
      为 "True"，则为 **RFC 6532**) 风格标头和标头延续行进行格式化的消
      息块，并可能附加一个信封标头。标头块或者以数据末尾或者以一个空行
      作为终结。跟在标头块之后的是消息体（它可能包含以 MIME 编码的子部
      分，包括带有 "8bit" 的 *Content-Transfer-Encoding* 的子部分。）

      可选的 *headersonly* 指示了是否应当在读取完消息头后就终止。默认
      值为 "False"，意味着它会解析整个文件的全部内容。

   parsebytes(bytes, headersonly=False)

      与 "parse()" 方法类似，只不过它要求输入为一个 *bytes-like
      object* 而不是类文件对象。对一个 *bytes-like object* 调用此方法
      相当于先将这些字节包装于一个 "BytesIO" 实例中，然后调用
      "parse()" 方法。

      可选的 *headersonly* 与 "parse()" 方法中的 *headersonly* 是一致
      的。

   Added in version 3.2.

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

   除了 *headersonly* 默认为 "True"，其他与 "BytesParser" 类完全一样。

   Added in version 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()" 方法。

      可选的 *headersonly* 与 "parse()" 方法中的 *headersonly* 是一致
      的。

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

   除了 *headersonly* 默认为 "True"，其他与 "Parser" 类完全一样。

考虑到从一个字符串或一个文件对象中创建一个消息对象是非常常见的任务，我
们提供了四个方便的函数。它们于顶层 "email" 包命名空间内可用。

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

   从一个 *bytes-like object* 中返回消息对象。这与
   "BytesParser().parsebytes(s)" 等价。可选的 *_class* 和 *policy* 参
   数与 "BytesParser" 类的构造函数的参数含义一致。

   Added in version 3.2.

   在 3.3 版本发生变更: 移除了 *strict* 参数。添加了 *policy* 关键字。

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

   从打开的二进制 *file object* 中返回消息对象。这与
   "BytesParser().parse(fp)" 等价。 *_class* 和 *policy* 参数与
   "BytesParser" 类的构造函数的参数含义一致。

   Added in version 3.2.

   在 3.3 版本发生变更: 移除了 *strict* 参数。添加了 *policy* 关键字。

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

   从一个字符串中返回消息对象。这与 "Parser().parsestr(s)" 等价。
   *_class* 和 *policy* 参数与 "Parser" 类的构造函数的参数含义一致。

   在 3.3 版本发生变更: 移除了 *strict* 参数。添加了 *policy* 关键字。

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

   从一个打开的 *file object* 中返回消息对象。这与
   "Parser().parse(fp)" 等价。 *_class* 和 *policy* 参数与 "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-status* 和
  *message/rfc822*) 的消息也会被解析为一个负载是长度为 1 的列表的容器
  对象。在它们身上调用 "is_multipart()" 方法会返回 "True"，调用
  "iter_parts()" 所产生的单个元素会是一个子消息对象。

* 一些不遵循标准的消息在其内部关于它是否为 *multipart* 类型前后不一。
  这些消息可能在消息头的 *Content-Type* 字段中写明为 *multipart*，但它
  们的 "is_multipart()" 方法的返回值可能是 "False" 。如果这种消息被
  "FeedParser" 类解析，它们的 *defects* 属性列表当中会有一个
  "MultipartInvariantViolationDefect" 类的实例。关于更多信息，详见
  "email.errors" .
