email.header: 国际化标头

源代码: Lib/email/header.py


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

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

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

当然,随着电子邮件在全球部署,它已经变得国际化了,例如电子邮件消息中现在可以使用特定语言的专属字符集。 这个基础标准仍然要求电子邮件消息只使用 7 位 ASCII 字符来进行传输,为此编写了大量 RFC 来描述如何将包含非 ASCII 字符的电子邮件编码为符合 RFC 2822 的格式。 这些 RFC 包括 RFC 2045, RFC 2046, RFC 2047 和 RFC 2231。 email 包在其 email.header 和 email.charset 模块中支持了这些标准。

如果你想在你的电子邮件标头中包括非 ASCII 字符,比如说是在 Subject 或 To 字段中,你应当使用 Header 类并将 Message 对象中的字段赋值为 Header 的实例而不是使用字符串作为字段值。 请从 email.header 模块导入 Header 类。 例如:

>>> 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'

Notice here how we wanted the Subject field to contain a non-ASCII character? We did this by creating a Header instance and passing in the character set to use when encoding it. When the subsequent Message instance was flattened, the Subject field was properly RFC 2047 encoded. MIME-aware mail readers would show this header using the embedded ISO-8859-1 character.

以下是 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() 调用的默认字符集。

通过 maximum line length can be specified explicitly via 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__()

Returns an approximation of the Header as a string, using an unlimited line length. All pieces are decoded using the specified encoding and joined together appropriately. Any pieces with a charset of 'unknown-8bit' are decoded as ASCII using the 'replace' error handler.

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

__eq__(other)

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

__ne__(other)

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

email.header 模块还提供了下列便捷函数。

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 构造器中的含义相同。

备注

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