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 字符,比如在 主题收件人 字段中,你应该使用 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'

注意这里我们如何希望 主题 字段包含一个非 ASCII 字符?我们通过创建一个 Header 实例并传入字节字符串编码的字符集来实现这一点。当后续的 Message 实例被展平时,主题 字段被正确地 RFC 2047 编码。支持 MIME 的邮件阅读器将使用嵌入的 ISO-8859-1 字符显示此标头。

以下是 Header 类描述

电子邮件。标题。标题(s=, 字符集=, maxlinelen=, 标题名称=, 续行 ws=' ', 错误='严格')

创建一个 MIME 兼容标题,其中可以包含不同字符集的字符串。

可选 s 是初始标题值。如果 (默认值),则不会设置初始标题值。您稍后可以使用 append() 方法附加到标题。s 可以是 bytesstr 的实例,但请参阅 append() 文档了解语义。

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

可以通过 maxlinelen 显式指定最大行长度。要将第一行拆分为较短的值(以考虑未包含在 s 中的字段标题,例如 主题),请在 header_name 中传递字段的名称。默认 maxlinelen 为 78,header_name 的默认值为 ,这意味着它不会考虑长、拆分标题的第一行。

可选 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 2822 兼容头 RFC 2047 规则时,将使用字符集的输出编解码器对字符串进行编码。如果无法使用输出编解码器对字符串进行编码,则会引发 UnicodeError。

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

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

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

可选的 splitchars 是一个包含字符的字符串,这些字符在正常标题换行期间应该被拆分算法赋予额外的权重。这是对 RFC 2822 的“更高层次的语法中断”的非常粗略的支持:在拆分行期间,优先考虑带有分隔符的前缀拆分点,字符的优先级按照它们在字符串中出现的顺序。当其他分隔符未出现在要拆分的行中时,字符串中可以包含空格和制表符,以指示是否应该优先考虑一个作为拆分点。分隔符不会影响 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) 对列表,其中包含头部的每个解码部分。对于头部的非编码部分,charsetNone;否则,为包含编码字符串中指定字符集名称的小写字符串。

以下是一个示例

>>> 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 构造函数中的相同。