email.headerregistry
: 自定义报头对象¶
源代码: Lib/email/headerregistry.py
版本 3.6 中新增: [1]
报头由 str
的自定义子类表示。用于表示给定报头的特定类由 header_factory
决定,该工厂在创建报头时生效的 policy
中定义。本节介绍电子邮件包为处理 RFC 5322 兼容电子邮件消息而实现的特定 header_factory
,它不仅为各种报头类型提供自定义报头对象,还提供了一种扩展机制,允许应用程序添加自己的自定义报头类型。
当使用从 EmailPolicy
派生的任何策略对象时,所有报头都由 HeaderRegistry
生成,并且以 BaseHeader
作为它们的最后一个基类。每个报头类都有一个额外的基类,该基类由报头的类型决定。例如,许多报头以 UnstructuredHeader
类作为它们的另一个基类。报头的专用第二个类由报头的名称决定,使用存储在 HeaderRegistry
中的查找表。所有这些对于典型的应用程序程序都是透明管理的,但提供了用于修改默认行为的接口,供更复杂的应用程序使用。
以下各节首先介绍报头基类及其属性,然后介绍修改 HeaderRegistry
行为的 API,最后介绍用于表示从结构化报头解析的数据的支持类。
- class email.headerregistry.BaseHeader(name, value)¶
name 和 value 从
header_factory
调用传递给BaseHeader
。任何报头对象的字符串值都是完全解码为 Unicode 的 value。此基类定义了以下只读属性
- name¶
报头的名称(字段中冒号之前的部分)。这与在
header_factory
调用中为 name 传递的值完全相同;也就是说,大小写保持不变。
- defects¶
一个包含
HeaderDefect
实例的元组,报告在解析过程中发现的任何 RFC 兼容性问题。电子邮件包尽力全面检测兼容性问题。有关可能报告的缺陷类型的讨论,请参见errors
模块。
- max_count¶
具有相同
name
的此类型报头的最大数量。值为None
表示无限制。此属性的BaseHeader
值为None
;预计专用报头类将根据需要覆盖此值。
BaseHeader
还提供了以下方法,该方法由电子邮件库代码调用,通常不应该由应用程序程序调用- fold(*, policy)¶
返回一个字符串,其中包含
linesep
字符,这些字符是根据 policy 正确折叠报头所需的。cte_type
为8bit
将被视为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
)的剩余内容传递给BaseHeader
的init
方法。
- class email.headerregistry.UnstructuredHeader¶
“非结构化”头是 RFC 5322 中默认类型的头。任何没有指定语法的头都被视为非结构化的。非结构化头的典型示例是 Subject 头。
在 RFC 5322 中,非结构化头是 ASCII 字符集中的任意文本运行。但是,RFC 2047 具有 RFC 5322 兼容机制,用于将非 ASCII 文本编码为头值内的 ASCII 字符。当包含编码词的值传递给构造函数时,
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
的时区。更有用的是使用localtime()
函数,该函数来自utils
模块msg['Date'] = utils.localtime()
此示例将日期头设置为当前时间和日期,使用当前时区偏移量。
- class email.headerregistry.AddressHeader¶
地址头是最复杂的结构化头类型之一。
AddressHeader
类为任何地址头提供了一个通用接口。此头类型提供以下附加属性
- groups¶
一个
Group
对象元组,用于编码头值中找到的地址和组。不在组中的地址在此列表中表示为单个地址Groups
,其display_name
为None
。
- addresses¶
一个
Address
对象元组,用于编码头值中的所有单个地址。如果头值包含任何组,则来自组的单个地址将包含在组在值中出现的位置的列表中(也就是说,地址列表被“扁平化”为一维列表)。
头的
decoded
值将具有所有解码为 Unicode 的编码词。idna
编码的域名也被解码为 Unicode。decoded
值是通过使用', '
连接groups
属性的元素的str
值来设置的。地址头可以使用任何组合的
Address
和Group
对象来设置其值。Group
对象的display_name
为None
将被解释为单个地址,这允许使用从源地址头的groups
属性获得的列表来完整地复制地址列表。
- 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¶
一个
ParameterizedMIMEHeader
类,用于处理 Content-Type 头。- content_type¶
内容类型字符串,格式为
maintype/subtype
。
- maintype¶
- subtype¶
- class email.headerregistry.ContentDispositionHeader¶
一个
ParameterizedMIMEHeader
类,用于处理 Content-Disposition 头。- content_disposition¶
inline
和attachment
是唯一常用的有效值。
- class email.headerregistry.ContentTransferEncoding¶
处理 Content-Transfer-Encoding 头。
- 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__
列表中的最后一个类。默认映射为
- subject:
UniqueUnstructuredHeader
- date:
UniqueDateHeader
- resent-date:
DateHeader
- orig-date:
UniqueDateHeader
- sender:
UniqueSingleAddressHeader
- resent-sender:
SingleAddressHeader
- to:
UniqueAddressHeader
- resent-to:
AddressHeader
- cc:
UniqueAddressHeader
- resent-cc:
AddressHeader
- bcc:
UniqueAddressHeader
- resent-bcc:
AddressHeader
- from:
UniqueAddressHeader
- resent-from:
AddressHeader
- reply-to:
UniqueAddressHeader
- mime-version:
MIMEVersionHeader
- content-type:
ContentTypeHeader
- content-disposition:
ContentDispositionHeader
- content-transfer-encoding:
ContentTransferEncodingHeader
- message-id:
MessageIDHeader
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。- display_name¶
地址的显示名称部分(如果有),已删除所有引号。如果地址没有显示名称,则此属性将为空字符串。
- username¶
地址的
username
部分,已删除所有引号。
- domain¶
地址的
domain
部分。
- addr_spec¶
地址的
username@domain
部分,已正确引用以用作裸地址(上面显示的第二种形式)。此属性不可变。
为了支持 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
表示不在组中的单个地址。
脚注