email.headerregistry: 自定义标头对象¶
源代码: Lib/email/headerregistry.py
Added in version 3.6: [1]
标头是由 str 的自定义子类来表示的。用于表示给定标头的特定类则由创建标头时生效的 policy 的 header_factory 确定。这一节记录了 email 包为处理兼容 RFC 5322 的电子邮件消息所实现的特定 header_factory,它不仅为各种标头类型提供了自定义的标头对象,还为应用程序提供了添加其自定义标头类型的扩展机制。
当使用派生自 EmailPolicy 的任何策略对象时,所有标头都通过 HeaderRegistry 产生并且以 BaseHeader 作为其最后一个基类。 每个标头类都有一个由该标头类型确定的附加基类。例如,许多标头都以 UnstructuredHeader 类作为其另一个基类。 一个标头专用的第二个类是由标头名称使用存储在 HeaderRegistry 中的查找表来确定的。 所有这些都针对典型应用程序进行透明的管理,但也为修改默认行为提供了接口,以便由更复杂的应用使用。
以下各节首先记录了标头基类及其属性,然后是用于修改 HeaderRegistry 行为的 API,最后是用于表示从结构化标头解析的数据的支持类。
- class email.headerregistry.BaseHeader(name, value)¶
name and value are passed to
BaseHeaderfrom theheader_factorycall. The string value of any header object is the value fully decoded to a string.这个基类定义了下列只读属性:
- name¶
标头的名称(字段在 ':' 之前的部分)。这就是 name 的
header_factory调用所传递的值;也就是说会保持大小写形式。
- defects¶
一个包含
HeaderDefect实例的元组,这些实例报告了在解析期间发现的任何 RFC 合规性问题。 email 包会尝试尽可能地检测合规性问题。请参阅errors模块了解可能被报告的缺陷类型的相关讨论。
- max_count¶
此类型标头可具有相同
name的最大数量。None值表示无限制。此属性的BaseHeader值为None;专用的标头类预期将根据需要覆盖这个值。
BaseHeader还提供了以下方法,它由 email 库代码调用,通常不应当由应用程序来调用。- fold(*, policy)¶
返回一个字符串,其中包含用来根据 policy 正确地折叠标头的
linesep字符。cte_type为8bit时将被作为7bit来处理,因为标头不能包含任意二进制数据。如果utf8为False,则非 ASCII 数据将根据 RFC 2047 来编码。
BaseHeader本身不能被用于创建标头对象。它定义了一个与每个专用标头相配合的协议以便生成标头对象。 具体来说,BaseHeader要求专用类提供一个名为parse的classmethod()。 此方法的调用形式如下:parse(string, kwds)
kwdsis a dictionary containing one pre-initialized key,defects.defectsis an empty list. The parse method should append any detected defects to this list. On return, thekwdsdictionary must contain values for at least the keysdecoded,defectsandparse_tree.decodedshould be the string value for the header (that is, the header value fully decoded to a string).parse_treeis set to the parse tree obtained from parsing the header. The parse method should assume that string may contain content-transfer-encoded parts, but should correctly handle all valid Unicode characters as well so that it can parse un-encoded header values.随后
BaseHeader的__new__会创建标头实例,并调用其init方法。专属类如果想要设置BaseHeader自身所提供的属性之外的附加属性,只需提供一个init方法。这样的init看起来应该是这样:def init(self, /, *args, **kw): self._myattr = kw.pop('myattr') super().init(*args, **kw)
也就是说,专属类放入
kwds字典的任何额外内容都应当被移除和处理,并且kw(和args) 的剩余内容会被传递给BaseHeaderinit方法。
- class email.headerregistry.UnstructuredHeader¶
An "unstructured" header is the default type of header in RFC 5322. Any header that does not have a specified syntax is treated as unstructured. The classic example of an unstructured header is the Subject header.
In RFC 5322, an unstructured header is a run of arbitrary text in the ASCII character set. RFC 2047, however, has an RFC 5322 compatible mechanism for encoding non-ASCII text as ASCII characters within a header value. When a value containing encoded words is passed to the constructor, the
UnstructuredHeaderparser converts such encoded words into a string, following the RFC 2047 rules for unstructured text. The parser uses heuristics to attempt to decode certain non-compliant encoded words. Defects are registered in such cases, as well as defects for issues such as invalid characters within the encoded words or the non-encoded text.此标头类型未提供附加属性。
- 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对象的元组。非分组成员的地址在此列表中表示为display_name为None的单地址Groups。
- addresses¶
编码了来自标头值的所有单独地址的
Address对象的元组。 如果标头值包含任何分组,则来自分组的单个地址将包含在该分组出现在值中的点上列出(也就是说,地址列表会被“展平”为一维列表)。
The
decodedvalue of the header will have all encoded words decoded to a string.idnaencoded domain names are also decoded to a string. Thedecodedvalue is set by joining thestrvalue of the elements of thegroupsattribute with', '.可以使用
Address与Group对象的任意组合的列表来设置一个地址标头的值。display_name为None的Group对象将被解读为单独地址,这允许一个地址列表可以附带通过使用从源标头的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¶
处理 Content-Type 标头的
ParameterizedMIMEHeader类。- content_type¶
maintype/subtype形式的内容类型字符串。
- maintype¶
- subtype¶
- class email.headerregistry.ContentDispositionHeader¶
处理 Content-Disposition 标头的
ParameterizedMIMEHeader类。- content_disposition¶
inline和attachment是仅有的常用有效值。
- class email.headerregistry.ContentTransferEncodingHeader¶
处理 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 中阐述的特定语法规则。
As a convenience addr_spec can be specified instead of username and domain, in which case username and domain will be parsed from the addr_spec. An addr_spec must be a properly RFC quoted string; if it is not
Addresswill raise an error. Unicode characters are allowed and will be property encoded when serialized. However, per the RFCs, Unicode is not allowed in the username portion of the address.- 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并且恰好有一个Address在addresses中,则Group表示一个不在某个组中的单独地址。
脚注