19.1.6. email.headerregistry:自定义标题对象 — Python 文档
19.1.6. email.headerregistry :自定义标题对象
源代码: :source:`Lib/email/headerregistry.py`
3.6 版新功能: 1
标头由 str 的自定义子类表示。 用于表示给定标头的特定类由创建标头时有效的 policy 的 header_factory 确定。 本节记录了由电子邮件包实现的特定 header_factory
,用于处理 RFC 5322 兼容的电子邮件消息,它不仅为各种标题类型提供自定义标题对象,而且为应用程序提供了一种扩展机制来添加他们自己的自定义标头类型。
当使用派生自 EmailPolicy 的任何策略对象时,所有标头均由 HeaderRegistry 生成,并以 BaseHeader 作为其最后一个基类。 每个头类都有一个附加的基类,该基类由头的类型决定。 例如,许多标头将类 UnstructuredHeader 作为其其他基类。 标题的专用第二类由标题的名称确定,使用存储在 HeaderRegistry 中的查找表。 对于典型的应用程序,所有这些都是透明管理的,但是提供了用于修改默认行为以供更复杂的应用程序使用的接口。
下面的部分首先记录标头基类及其属性,然后是用于修改 HeaderRegistry 行为的 API,最后是用于表示从结构化标头解析的数据的支持类。
- class email.headerregistry.BaseHeader(name, value)
name 和 value 从 header_factory 调用传递给
BaseHeader
。 任何标头对象的字符串值都是完全解码为 unicode 的 值 。该基类定义了以下只读属性:
- name
标题的名称(':' 之前的字段部分)。 这正是在 name 的 header_factory 调用中传递的值; 也就是说,大小写被保留。
- defects
HeaderDefect
实例的元组报告在解析过程中发现的任何 RFC 合规性问题。 电子邮件包试图完整地检测合规性问题。 有关可能报告的缺陷类型的讨论,请参阅 errors 模块。
- max_count
可以具有相同
name
的此类标题的最大数量。None
的值表示无限制。 该属性的BaseHeader
值为None
; 预计专用头类将根据需要覆盖此值。
BaseHeader
还提供了如下方法,由邮件库代码调用,一般不应该被应用程序调用:- fold(*, policy)
根据 policy 正确折叠标头所需,返回包含 linesep 字符的字符串。
8bit
的 cte_type 将被视为7bit
,因为标头可能不包含任意二进制数据。 如果 utf8 是False
,非 ASCII 数据将被 RFC 2047 编码。
BaseHeader
本身不能用于创建头对象。 它定义了一个协议,每个专用标头与之合作以生成标头对象。 具体来说,BaseHeader
要求专门的类提供一个名为parse
的 classmethod()。 该方法调用如下:parse(string, kwds)
kwds
是一个包含一个预初始化键defects
的字典。defects
是一个空列表。 parse 方法应将任何检测到的缺陷附加到此列表中。 返回时,kwds
字典 必须 至少包含键decoded
和defects
的值。decoded
应该是标头的字符串值(即完全解码为 unicode 的标头值)。 parse 方法应该假设 string 可能包含内容传输编码的部分,但也应该正确处理所有有效的 unicode 字符,以便它可以解析未编码的标头值。BaseHeader
的__new__
然后创建头实例,并调用它的init
方法。 如果专用类希望设置除BaseHeader
本身提供的属性之外的其他属性,则只需要提供init
方法。 这样的init
方法应该如下所示:def init(self, *args, **kw): self._myattr = kw.pop('myattr') super().init(*args, **kw)
也就是说,特殊类放入
kwds
字典的任何额外内容都应该被删除和处理,并将kw
(和args
)的剩余内容传递给 [ X188X]init
方法。
- class email.headerregistry.UnstructuredHeader
“非结构化”标头是 RFC 5322 中标头的默认类型。 任何没有指定语法的头都被视为非结构化的。 非结构化标头的经典示例是 Subject 标头。
在 RFC 5322 中,非结构化标题是 ASCII 字符集中的任意文本的运行。 然而,RFC 2047 具有 RFC 5322 兼容机制,用于将非 ASCII 文本编码为标头值中的 ASCII 字符。 当包含编码词的 value 传递给构造函数时,
UnstructuredHeader
解析器将这些编码词转换为 unicode,遵循 RFC 2047 规则对于非结构化文本。 解析器使用试探法来尝试解码某些不合规的编码字。 在这种情况下会记录缺陷,以及编码字或非编码文本中的无效字符等问题的缺陷。此标头类型不提供其他属性。
- class email.headerregistry.DateHeader
RFC 5322 为电子邮件标题中的日期指定了一种非常具体的格式。
DateHeader
解析器识别该日期格式,以及识别有时“在野外”发现的许多变体形式。此标头类型提供以下附加属性:
- datetime
如果标题值可以被识别为一种或另一种形式的有效日期,则该属性将包含表示该日期的 datetime 实例。 如果输入日期的时区指定为
-0000
(表明它是 UTC 但不包含有关源时区的信息),那么 datetime 将是一个朴素的 datetime ]。 如果找到特定的时区偏移量(包括 +0000),则 datetime 将包含使用 datetime.timezone 进行记录的感知datetime
时区偏移量。
头部的
decoded
值根据RFC 5322规则格式化datetime
确定; 也就是说,它被设置为:email.utils.format_datetime(self.datetime)
创建
DateHeader
时,value 可能是 datetime 实例。 这意味着,例如,以下代码是有效的,并且可以执行预期的操作:msg['Date'] = datetime(2011, 7, 15, 21)
因为这是一个简单的
datetime
,它将被解释为 UTC 时间戳,并且结果值的时区为-0000
。 更有用的是使用 utils 模块中的 localtime() 函数:msg['Date'] = utils.localtime()
此示例使用当前时区偏移将日期标头设置为当前时间和日期。
- class email.headerregistry.AddressHeader
地址标头是最复杂的结构化标头类型之一。
AddressHeader
类为任何地址标头提供通用接口。此标头类型提供以下附加属性:
- groups
Group 对象的元组,用于编码在标头值中找到的地址和组。 不属于组的地址在此列表中表示为单地址
Groups
,其 display_name 为None
。
- addresses
Address 对象的元组,对标头值中的所有单个地址进行编码。 如果标头值包含任何组,则该组中的各个地址将包含在该值中出现该组的位置的列表中(即,地址列表被“扁平化”为一维列表)。
标头的
decoded
值将所有编码字解码为 unicode。 idna 编码的域名也被解码为 unicode。decoded
值是通过 join 将groups
属性的元素的 str 值与', '
结合来设置的。可以使用任意组合的 Address 和 Group 对象的列表来设置地址头的值。
display_name
为None
的Group
对象将被解释为单个地址,这允许使用从 获取的列表完整地复制地址列表X189X] 源头的属性。
- class email.headerregistry.SingleAddressHeader
- AddressHeader 的子类,添加了一个附加属性:
- address
- 由标头值编码的单个地址。 如果标头值实际上包含多个地址(这将违反默认 policy 下的 RFC),访问此属性将导致 ValueError。
上述许多类还具有 Unique
变体(例如,UniqueUnstructuredHeader
)。 唯一的区别是在 Unique
变体中,max_count 设置为 1。
- class email.headerregistry.MIMEVersionHeader
MIME-Version 标头实际上只有一个有效值,即
1.0
。 为了将来打样,这个头类支持其他有效的版本号。 如果版本号根据 RFC 2045 具有有效值,则标头对象将具有以下属性的非None
值:- version
作为字符串的版本号,删除了任何空格和/或注释。
- major
作为整数的主要版本号
- minor
次要版本号作为整数
- class email.headerregistry.ParameterizedMIMEHeader
- MIME 标头都以前缀“Content-”开头。 每个特定的标头都有一个特定的值,在该标头的类下描述。 有些还可以采用具有通用格式的补充参数列表。 此类用作所有带参数的 MIME 标头的基础。
- params
- 将参数名称映射到参数值的字典。
- class email.headerregistry.ContentTypeHeader
处理 Content-Type 标头的 ParameterizedMIMEHeader 类。
- content_type
内容类型字符串,格式为
maintype/subtype
。
- maintype
- subtype
- class email.headerregistry.ContentDispositionHeader
- 处理 Content-Disposition 标头的 ParameterizedMIMEHeader 类。
- content-disposition
inline
和attachment
是唯一常用的有效值。
- class email.headerregistry.ContentTransferEncoding
- 处理 Content-Transfer-Encoding 标头。
- cte
- 有效值为
7bit
、8bit
、base64
和quoted-printable
。 有关更多信息,请参阅 RFC 2045。
- class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)
这是 EmailPolicy 默认使用的工厂。
HeaderRegistry
使用 base_class 和从它持有的注册表中检索的专用类来构建用于动态创建头实例的类。 当给定的头名称没有出现在注册表中时,由 default_class 指定的类用作专用类。 当 use_default_map 是True
(默认值)时,标头名称到类的标准映射会在初始化期间复制到注册表中。 base_class 始终是生成的类的__bases__
列表中的最后一个类。默认映射是:
- 主题
唯一非结构化头
- 日期
唯一日期头
- 重发日期
日期头
- 原始日期
唯一日期头
- 发件人
唯一的单一地址头
- 重发者
单地址头
- 到
唯一地址头
- 反感
地址头
- 抄送
唯一地址头
- 复抄抄送
地址头
- 从
唯一地址头
- 怨恨的
地址头
- 回复
唯一地址头
HeaderRegistry
有以下方法:- map_to_type(self, name, cls)
name 是要映射的头的名称。 它将在注册表中转换为小写。 cls 是与 base_class 一起使用的专用类,用于创建用于实例化与 name 匹配的标头的类。
- __getitem__(name)
构造并返回一个类来处理创建 name 标头。
- __call__(name, value)
从注册表中检索与 name 关联的专用标头(如果 name 未出现在注册表中,则使用 default_class)并将其与 base_class 组合] 生成一个类,调用构造类的构造函数,将相同的参数列表传递给它,最后返回由此创建的类实例。
以下类是用于表示从结构化头解析的数据的类,通常,应用程序可以使用这些类来构造结构化值以分配给特定头。
- class email.headerregistry.Address(display_name=, username=, domain=, addr_spec=None)
用于表示电子邮件地址的类。 地址的一般形式是:
[display_name] <username@domain>
或者:
username@domain
其中每个部分都必须符合 RFC 5322 中规定的特定语法规则。
为方便起见,可以指定 addr_spec 代替 username 和 domain,在这种情况下,username 和 domain从 addr_spec 解析。 addr_spec 必须是正确的 RFC 引用字符串; 如果不是
Address
将引发错误。 允许使用 Unicode 字符,并将在序列化时进行属性编码。 但是,根据 RFC,在地址的用户名部分中不允许使用 unicode not。- display_name
地址的显示名称部分(如果有),并删除所有引用。 如果地址没有显示名称,则此属性将为空字符串。
- username
地址的
username
部分,删除了所有引用。
- domain
地址的
domain
部分。
- addr_spec
地址的
username@domain
部分,正确引用以用作裸地址(上面显示的第二种形式)。 这个属性是不可变的。
- __str__()
对象的
str
值是根据 RFC 5322 规则引用的地址,但没有任何非 ASCII 字符的内容传输编码。
为了支持 SMTP (RFC 5321),
Address
处理一种特殊情况:如果username
和domain
都是空字符串(或None
),则Address
的字符串值为<>
。
- class email.headerregistry.Group(display_name=None, addresses=None)
用于表示地址组的类。 地址组的一般形式是:
display_name: [address-list];
为了方便处理由组和单个地址混合组成的地址列表,
Group
也可以通过设置 display_name 来表示不属于组的单个地址到None
并提供单个地址列表作为 addresses。- display_name
组的
display_name
。 如果是None
并且addresses
中正好有一个Address
,那么Group
代表一个不在一个组中的地址。
- addresses
一个可能为空的 Address 对象元组,表示组中的地址。
- __str__()
Group
的str
值根据 RFC 5322 格式化,但没有任何非 ASCII 字符的内容传输编码。 如果display_name
为 none 且addresses
列表中有一个Address
,则str
值将与str
相同那个单Address
。
脚注