# `email.header`: 国际化标头

源代码: Lib/email/header.py

此模块是旧式 (`Compat32`) email API 的一部分。在当前的 API 中标头的编码和解码是由 `EmailMessage` 类的字典型 API 来透明地处理的。 除了在旧有代码中使用，此模块在需要完全控制当编码标头时所使用的字符集时也很有用处。

本节中的其余文本是此模块的原始文档。

RFC 2822 是描述电子邮件消息格式的基础标准。它派生自更早的 RFC 822 标准，该标准在大多数电子邮件仅由 ASCII 字符组成时已被广泛使用。 RFC 2822 所描述的规范假定电子邮件都只包含 7 位 ASCII 字符。

Of course, as email has been deployed worldwide, it has become internationalized, such that language specific character sets can now be used in email messages. The base standard still requires email messages to be transferred using only 7-bit ASCII characters, so a slew of RFCs have been written describing how to encode email containing non-ASCII characters into RFC 2822-compliant format. These RFCs include RFC 2045, RFC 2046, RFC 2047, and RFC 2231. The `email` package supports these standards in its `email.header` and `email.charset` modules.

If you want to include non-ASCII characters in your email headers, say in the Subject or To fields, you should use the `Header` class and assign the field in the `Message` object to an instance of `Header` instead of using a string for the header value. Import the `Header` class from the `email.header` module. For example:

    >>> from email.message import Message
    >>> from email.header import Header
    >>> msg = Message()
    >>> h = Header('p\xf6stal', 'iso-8859-1')
    >>> msg['Subject'] = h
    >>> msg.as_string()
    'Subject: =?iso-8859-1?q?p=F6stal?=\n\n'

是否注意到这里我们是如何希望 Subject 字段包含非 ASCII 字符的？我们通过创建一个 `Header` 实例并传入字节串编码所用的字符集来做到这一点。当后续的 `Message` 实例被展平时，Subject 字段会正确地按 RFC 2047 来编码。可感知 MIME 的电子邮件阅读器将会使用嵌入的 ISO-8859-1 字符来显示此标头。

以下是 `Header` 类描述：

class email.header.Header(s=None, charset=None, maxlinelen=None, header_name=None, continuation_ws=' ', errors='strict')

  创建符合 MIME 要求的标头，其中可包含不同字符集的字符串。

  可选的 s 是初始标头值。 如果为 `None` (默认值)，则表示初始标头值未设置。 你可以在稍后使用 `append()` 方法调用向标头添加新值。 s 可以是 `bytes` 或 `str` 的实例，注意参阅 `append()` 文档了解相关语义。

  可选的 charset 用于两种目的：它的含义与 `append()` 方法的 charset 参数相同。它还会为所有省略了 charset 参数的后续 `append()` 调用设置默认字符集。如果 charset 在构造器中未提供（默认设置），则会将 `us-ascii` 字符集用作 s 的初始字符集以及后续 `append()` 调用的默认字符集。

  通过 maxlinelen 可以显式地指定行长度的最大值。要将第一行拆分为更短的值（以适应未被包括在 s 中的字段标头，例如 Subject 等）则将字段名称作为 header_name 传入。默认的 maxlinelen 为 78，而 header_name 的默认值为 `None`，表示不考虑拆分超长标头的第一行。

  可选的 continuation_ws 必须为符合 RFC 2822 的折叠用空白符，通常是空格符或硬制表符。 这个字符将被加缀至连续行的开头。 continuation_ws 默认为一个空格符。

  可选的 errors 会被直接传递给 `append()` 方法。

  append(s, charset=None, errors='strict')

    将字符串 s 添加到 MIME 标头。

    如果给出可选的 charset，它应当是一个 `Charset` 实例 (参见 `email.charset`) 或字符集名称，该参数将被转换为一个 `Charset` 实例。 如果为 `None` (默认值) 则表示会使用构造器中给出的 charset。

    s 可以是 `bytes` 或 `str` 的实例。如果它是 `bytes` 的实例，则 charset 为该字节串的编码格式，如果字节串无法用该字符集来解码则将引发 `UnicodeError`。

    如果 s 是 `str` 的实例，则 charset 是用来指定字符串中字符字符集的提示。

    在这两种情况下，当使用 RFC 2047 规则产生符合 RFC 2822 的标头时，将使用指定字符集的输出编解码器来编码字符串。 如果字符串无法使用该输出编解码器来编码，则将引发 UnicodeError。

    可选的 errors 会在 s 为字节串时被作为 errors 参数传递给 decode 调用。

  encode(splitchars=';, \t', maxlinelen=None, linesep='\n')

    将消息标头编码为符合 RFC 的格式，可能会对过长的行采取折行并将非 ASCII 部分以 base64 或 quoted-printable 编码格式进行封装。

    可选的 splitchars 是一个字符串，其中包含应在正常的标头折行处理期间由拆分算法赋予额外权重的字符。这是对于 RFC 2822 中 '更高层级语法拆分' 的很粗略的支持：在拆分期间会首选在 splitchar 之前的拆分点，字符的优先级是基于它们在字符串中的出现顺序。 字符串中可包含空格和制表符以指明当其他拆分字符未在被拆分行中出现时是否要将某个字符作为优先于另一个字符的首选拆分点。拆分字符不会影响以 RFC 2047 编码的行。

    如果给出 maxlinelen，它将覆盖实例的最大行长度值。

    linesep 指定用来分隔已折叠标头行的字符。它默认为 Python 应用程序代码中最常用的值 (`\n`)，但也可以指定为 `\r\n` 以便产生带有符合 RFC 的行分隔符的标头。

    在 3.2 版本发生变更: 增加了 linesep 参数。

  `Header` 类还提供了一些方法以支持标准运算符和内置函数。

  __str__()

    以字符串形式返回 `Header` 的近似表示，使用不受限制的行长度。所有部分都会使用指定编码格式转换为 unicode 并适当地连接起来。任何带有 `'unknown-8bit'` 字符集的部分都会使用 `'replace'` 错误处理程序解码为 ASCII。

    在 3.2 版本发生变更: 增加对 `'unknown-8bit'` 字符集的处理。

  __eq__(other)

    这个方法允许你对两个 `Header` 实例进行相等比较。

  __ne__(other)

    这个方法允许你对两个 `Header` 实例进行不等比较。

The `email.header` module also provides the following convenient functions.

email.header.decode_header(header)

  在不转换字符集的情况下对消息标头值进行解码。 header 为标头值。

  出于历史原因，此函数可能返回：

  1. 一个由包含标头的每个已解码部件对 `(decoded_bytes, charset)` 组成的列表，其中 decoded_bytes 总是 `bytes` 的实例，而 charset 可能为：

     > - 一个包含指定字符集名称的小写形式字符串。

     > - `None` 表示标头的未编码部件。

  2. 长度为 1 的包含一个 `(string, None)` 对的列表，其中 string 总是一个 `str` 的实例。

  当特定解码错误发生时（例如 base64 解码异常）可能会引发 `email.errors.HeaderParseError`。

  这里有一些示例：

      >>> from email.header import decode_header
      >>> decode_header('=?iso-8859-1?q?p=F6stal?=')
      [(b'p\xf6stal', 'iso-8859-1')]
      >>> decode_header('unencoded_string')
      [('unencoded_string', None)]
      >>> decode_header('bar =?utf-8?B?ZsOzbw==?=')
      [(b'bar ', None), (b'f\xc3\xb3o', 'utf-8')]

  备注

  此函数仅为向下兼容而存在。对于新的代码，我们推荐使用 `email.headerregistry.HeaderRegistry`。

email.header.make_header(decoded_seq, maxlinelen=None, header_name=None, continuation_ws=' ')

  基于 `decode_header()` 所返回的数据对序列创建一个 `Header` 实例。

  `decode_header()` 接受一个标头值字符串并返回格式为 `(decoded_string, charset)` 的数据对序列，其中 charset 是字符集名称。

  这个函数接受这样的数据对序列并返回一个 `Header` 实例。可选的 maxlinelen, header_name 和 continuation_ws 与 `Header` 构造器中的含义相同。

  备注

  此函数仅为向下兼容而存在，而不推荐在新的代码中使用。