Skip to main content

19.1.11. email.header:国际化标头

源代码: Lib/email/header.py


此模块是旧版(Compat32)电子邮件API的一部分。在当前的API中,头部的编码和解码由 EmailMessage 类的类似字典的API透明地处理。除了在遗留代码中使用之外,此模块在需要完全控制编码头时使用的字符集的应用程序中非常有用。

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

RFC 2822 是描述电子邮件的格式的基本标准。它源于早期的 RFC 822 标准,该标准在大多数电子邮件仅由ASCII字符组成时广泛使用。 RFC 2822 是一个规定,假设电子邮件只包含7位ASCII字符。

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

如果要在电子邮件头中包含非ASCII字符,例如在 SubjectTo 字段中,应该使用 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'

注意这里我们如何想要 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 可以是 bytesstr 的实例,但是请参阅 append() 文档中的语义。

可选的 charset 有两个目的:它与 append() 方法的 charset 参数含义相同。它还为省略 charset 参数的所有后续 append() 调用设置默认字符集。如果构造函数中没有提供 charset (默认值),则 us-ascii 字符集既用作 s 的初始字符集,又用作后续 append() 调用的默认值。

最大线路长度可以通过 maxlinelen 明确指定。为了将第一行拆分为较短的值(以考虑不包括在 s 中的字段报头,例如 Subject)传递 header_name 中的字段的名称。默认的 maxlinelen 是76,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 可以是 bytesstr 的实例。如果它是 bytes 的实例,则 charset 是该字节串的编码,并且如果该字符串不能用该字符集解码,则将产生 UnicodeError

如果 sstr 的实例,则 charset 是指定字符串中字符的字符集的提示。

在任一种情况下,当使用 RFC 2047 规则生成符合 RFC 2822 标头时,将使用字符集的输出编解码器对字符串进行编码。如果无法使用输出编解码器对字符串进行编码,则会引发UnicodeError。

如果 s 是字节字符串,则可选 errors 作为errors参数传递给decode调用。

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

将消息头编码为符合RFC的格式,可能包装长行并以base64或quoted-printable编码封装非ASCII部分。

可选的 splitchars 是一个包含字符的字符串,应该在正常头部包装期间通过分割算法给予额外的权重。这是非常粗糙的支持 RFC 2822 的’较高级别的句法断裂’:分割点之前的splitchar是首选在分线期间,字符首选的顺序,它们在字符串中出现。空格和制表符可以包括在字符串中,以指示当其他分割字符未出现在正在分割的行中时,是否应该将偏好提供给另一个作为分割点。 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 实例不等式。

email.header 模块还提供以下方便的功能。

email.header.decode_header(header)

解码邮件标头值,而不转换字符集。标头值在 header 中。

此函数返回包含头的每个解码部分的 (decoded_string, charset) 对的列表。 charset 是头的非编码部分的 None,否则是包含编码字符串中指定的字符集名称的小写字符串。

这里有一个例子:

>>> from email.header import decode_header
>>> decode_header('=?iso-8859-1?q?p=F6stal?=')
[(b'p\xf6stal', 'iso-8859-1')]
email.header.make_header(decoded_seq, maxlinelen=None, header_name=None, continuation_ws=' ')

从由 decode_header() 返回的一对序列创建 Header 实例。

decode_header() 取一个标题值字符串并返回一个格式为 (decoded_string, charset) 的序列,其中 charset 是字符集的名称。

此函数采用这些序列对中的一个并返回 Header 实例。可选的 maxlinelenheader_namecontinuation_wsHeader 构造函数中一样。