email.headerregistry: 自定義標(biāo)頭對(duì)象?
源代碼: Lib/email/headerregistry.py
3.6 新版功能: 1
標(biāo)頭是由 str 的自定義子類來表示的。 用于表示給定標(biāo)頭的特定類則由創(chuàng)建標(biāo)頭時(shí)生效的 policy 的 header_factory 確定。 這一節(jié)記錄了 email 包為處理兼容 RFC 5322 的電子郵件消息所實(shí)現(xiàn)的特定 header_factory,它不僅為各種標(biāo)頭類型提供了自定義的標(biāo)頭對(duì)象,還為應(yīng)用程序提供了添加其自定義標(biāo)頭類型的擴(kuò)展機(jī)制。
當(dāng)使用派生自 EmailPolicy 的任何策略對(duì)象時(shí),所有標(biāo)頭都通過 HeaderRegistry 產(chǎn)生并且以 BaseHeader 作為其最后一個(gè)基類。 每個(gè)標(biāo)頭類都有一個(gè)由該標(biāo)頭類型確定的附加基類。 例如,許多標(biāo)頭都以 UnstructuredHeader 類作為其另一個(gè)基類。 一個(gè)標(biāo)頭專用的第二個(gè)類是由標(biāo)頭名稱使用存儲(chǔ)在 HeaderRegistry 中的查找表來確定的。 所有這些都針對(duì)典型應(yīng)用程序進(jìn)行透明的管理,但也為修改默認(rèn)行為提供了接口,以便由更復(fù)雜的應(yīng)用使用。
以下各節(jié)首先記錄了標(biāo)頭基類及其屬性,然后是用于修改 HeaderRegistry 行為的 API,最后是用于表示從結(jié)構(gòu)化標(biāo)頭解析的數(shù)據(jù)的支持類。
-
class
email.headerregistry.BaseHeader(name, value)? name 和 value 會(huì)從
header_factory調(diào)用傳遞給BaseHeader。 任何標(biāo)頭對(duì)象的字符串值都是完成解碼為 unicode 的 value。這個(gè)基類定義了下列只讀屬性:
-
name? 標(biāo)頭的名稱(字段在 ':' 之前的部分)。 這就是 name 的
header_factory調(diào)用所傳遞的值;也就是說會(huì)保持大小寫形式。
-
defects? 一個(gè)包含
HeaderDefect實(shí)例的元組,這些實(shí)例報(bào)告了在解析期間發(fā)現(xiàn)的任何 RFC 合規(guī)性問題。 email 包會(huì)嘗試盡可能地檢測(cè)合規(guī)性問題。 請(qǐng)參閱errors模塊了解可能被報(bào)告的缺陷類型的相關(guān)討論。
-
max_count? 此類型標(biāo)頭可具有相同
name的最大數(shù)量。None值表示無限制。 此屬性的BaseHeader值為None;專用的標(biāo)頭類預(yù)期將根據(jù)需要重載這個(gè)值。
BaseHeader還提供了以下方法,它由 email 庫(kù)代碼調(diào)用,通常不應(yīng)當(dāng)由應(yīng)用程序來調(diào)用。-
fold(*, policy)? 返回一個(gè)字符串,其中包含用來根據(jù) policy 正確地折疊標(biāo)頭的
linesep字符。cte_type為8bit時(shí)將被作為7bit來處理,因?yàn)闃?biāo)頭不能包含任意二進(jìn)制數(shù)據(jù)。 如果utf8為False,則非 ASCII 數(shù)據(jù)將根據(jù) RFC 2047 來編碼。
BaseHeader本身不能被用于創(chuàng)建標(biāo)頭對(duì)象。 它定義了一個(gè)與每個(gè)專用標(biāo)頭相配合的協(xié)議以便生成標(biāo)頭對(duì)象。 具體來說,BaseHeader要求專用類提供一個(gè)名為parse的classmethod()。 此方法的調(diào)用形式如下:parse(string, kwds)
kwds是包含了一個(gè)預(yù)初始化鍵defects的字典。defects是一個(gè)空列表。 parse 方法應(yīng)當(dāng)將任何已檢測(cè)到的缺陷添加到此列表中。 在返回時(shí),kwds字典 必須 至少包含decoded和defects等鍵的值。decoded應(yīng)當(dāng)是標(biāo)頭的字符串值(即完全解碼為 unicode 的標(biāo)頭值)。 parse 方法應(yīng)當(dāng)假定 string 可能包含 content-transfer-encoded 部分,但也應(yīng)當(dāng)正確地處理全部有效的 unicode 字符以便它能解析未經(jīng)編碼的標(biāo)頭值。隨后
BaseHeader的__new__會(huì)創(chuàng)建標(biāo)頭實(shí)例,并調(diào)用其init方法。 專屬類如果想要設(shè)置BaseHeader自身所提供的屬性之外的附加屬性,只需提供一個(gè)init方法。 這樣的init看起來應(yīng)該是這樣:def init(self, *args, **kw): self._myattr = kw.pop('myattr') super().init(*args, **kw)
也就是說,專屬類放入
kwds字典的任何額外內(nèi)容都應(yīng)當(dāng)被移除和處理,并且kw(和args) 的剩余內(nèi)容會(huì)被傳遞給BaseHeaderinit方法。-
-
class
email.headerregistry.UnstructuredHeader? "非結(jié)構(gòu)化" 標(biāo)頭是 RFC 5322 中默認(rèn)的標(biāo)頭類型。 任何沒有指定語法的標(biāo)頭都會(huì)被視為是非結(jié)構(gòu)化的。 非結(jié)構(gòu)化標(biāo)頭的經(jīng)典例子是 Subject 標(biāo)頭。
在 RFC 5322 中,非結(jié)構(gòu)化標(biāo)頭是指一段以 ASCII 字符集表示的任意文本。 但是 RFC 2047 具有一個(gè) RFC 5322 兼容機(jī)制用來將標(biāo)頭值中的非 ASCII 文本編碼為 ASCII 字符。 當(dāng)包含已編碼字的 value 被傳遞給構(gòu)造器時(shí),
UnstructuredHeader解析器會(huì)按照非結(jié)構(gòu)化文本的 RFC 2047 規(guī)則將此類已編碼字轉(zhuǎn)換為 unicode。 解析器會(huì)使用啟發(fā)式機(jī)制來嘗試解碼一些不合規(guī)的已編碼字。 在此種情況下各類缺陷,例如已編碼字或未編碼文本中的無效字符問題等缺陷將會(huì)被注冊(cè)。此標(biāo)頭類型未提供附加屬性。
-
class
email.headerregistry.DateHeader? RFC 5322 為電子郵件標(biāo)頭內(nèi)的日期指定了非常明確的格式。
DateHeader解析器會(huì)識(shí)別該日期格式,并且也能識(shí)別間或出現(xiàn)的一些“不規(guī)范”變種形式。這個(gè)標(biāo)頭類型提供了以下附加屬性。
-
datetime? 如果標(biāo)頭值能被識(shí)別為某一種有效的日期形式,此屬性將包含一個(gè)代表該日期的
datetime實(shí)例。 如果輸入日期的時(shí)區(qū)被指定為-0000(表示為 UTC 但不包含源時(shí)區(qū)的相關(guān)信息),則datetime將為簡(jiǎn)單型datetime。 如果找到了特定的時(shí)區(qū)時(shí)差值 (包括 +0000),則datetime將包含使用datetime.timezone來記錄時(shí)區(qū)時(shí)差時(shí)的感知型datetime。
標(biāo)頭的
decoded值是由按照 RFC 5322 對(duì)datetime進(jìn)行格式化來確定的;也就是說,它會(huì)被設(shè)為:email.utils.format_datetime(self.datetime)
當(dāng)創(chuàng)建
DateHeader時(shí),value 可以為datetime實(shí)例。 例如這意味著以下代碼是有效的并能實(shí)現(xiàn)人們預(yù)期的行為:msg['Date'] = datetime(2011, 7, 15, 21)
因?yàn)檫@是個(gè)簡(jiǎn)單型
datetime它將被解讀為 UTC 時(shí)間戳,并且結(jié)果值的時(shí)區(qū)將為-0000。 使用來自utils模塊的localtime()函數(shù)會(huì)更有用:msg['Date'] = utils.localtime()
這個(gè)例子將日期標(biāo)頭設(shè)為使用當(dāng)前時(shí)區(qū)時(shí)差值的當(dāng)前時(shí)間和日期。
-
-
class
email.headerregistry.AddressHeader? 地址標(biāo)頭是最復(fù)雜的結(jié)構(gòu)化標(biāo)頭類型之一。
AddressHeader類提供了適合任何地址標(biāo)頭的泛用型接口。這個(gè)標(biāo)頭類型提供了以下附加屬性。
-
groups? 編碼了在標(biāo)頭值中找到的地址和分組的
Group對(duì)象的元組。 非分組成員的地址在此列表中表示為display_name為None的單地址Groups。
-
addresses? 編碼了來自標(biāo)頭值的所有單獨(dú)地址的
Address對(duì)象的元組。 如果標(biāo)頭值包含任何分組,則來自分組的單個(gè)地址將包含在該分組出現(xiàn)在值中的點(diǎn)上列出(也就是說,地址列表會(huì)被“展平”為一維列表)。
標(biāo)頭的
decoded值將為所有已編碼字解碼為 unicode 的結(jié)果。idna編碼的域名也將被解碼為 unicode。decoded值是通過對(duì)groups屬性的元素的str值使用', '進(jìn)行join來設(shè)置的。可以使用
Address與Group對(duì)象的任意組合的列表來設(shè)置一個(gè)地址標(biāo)頭的值。display_name為None的Group對(duì)象將被解讀為單獨(dú)地址,這允許一個(gè)地址列表可以附帶通過使用從源標(biāo)頭的groups屬性獲取的列表而保留原分組。-
-
class
email.headerregistry.SingleAddressHeader? AddressHeader的子類,添加了一個(gè)額外的屬性:-
address? 由標(biāo)頭值編碼的單個(gè)地址。 如果標(biāo)頭值實(shí)際上包含一個(gè)以上的地址(這在默認(rèn)
policy下將違反 RFC),則訪問此屬性將導(dǎo)致ValueError。
-
上述類中許多還具有一個(gè) Unique 變體 (例如 UniqueUnstructuredHeader)。 其唯一差別是在 Unique 變體中 max_count 被設(shè)為 1。
-
class
email.headerregistry.MIMEVersionHeader? 實(shí)際上 MIME-Version 標(biāo)頭只有一個(gè)有效的值,即
1.0。 為了將來的擴(kuò)展,這個(gè)標(biāo)頭類還支持其他的有效版本號(hào)。 如果一個(gè)版本號(hào)是 RFC 2045 的有效值,則標(biāo)頭對(duì)象的以下屬性將具有不為None的值:-
version? 字符串形式的版本號(hào)。 任何空格和/或注釋都會(huì)被移除。
-
major? 整數(shù)形式的主版本號(hào)
-
minor? 整數(shù)形式的次版本號(hào)
-
-
class
email.headerregistry.ParameterizedMIMEHeader? MIME 標(biāo)頭都以前綴 'Content-' 打頭。 每個(gè)特定標(biāo)頭都具有特定的值,其描述在該標(biāo)頭的類之中。 有些也可以接受一個(gè)具有通用格式的補(bǔ)充形參形表。 這個(gè)類被用作所有接受形參的 MIME 標(biāo)頭的基類。
-
params? 一個(gè)將形參名映射到形參值的字典。
-
-
class
email.headerregistry.ContentTypeHeader? 處理 Content-Type 標(biāo)頭的
ParameterizedMIMEHeader類。-
content_type? maintype/subtype形式的內(nèi)容類型字符串。
-
maintype?
-
subtype?
-
-
class
email.headerregistry.ContentDispositionHeader? 處理 Content-Disposition 標(biāo)頭的
ParameterizedMIMEHeader類。-
content-disposition inline和attachment是僅有的常用有效值。
-
-
class
email.headerregistry.ContentTransferEncoding? 處理 Content-Transfer-Encoding 標(biāo)頭。
-
class
email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)? 這是由
EmailPolicy在默認(rèn)情況下使用的工廠函數(shù)。HeaderRegistry會(huì)使用 base_class 和從它所保存的注冊(cè)表中獲取的專用類來構(gòu)建用于動(dòng)態(tài)地創(chuàng)建標(biāo)頭實(shí)例的類。 當(dāng)給定的標(biāo)頭名稱未在注冊(cè)表中出現(xiàn)時(shí),則會(huì)使用由 default_class 所指定的類作為專用類。 當(dāng) use_default_map 為True(默認(rèn)值) 時(shí),則會(huì)在初始化期間把將標(biāo)頭名稱與類的標(biāo)準(zhǔn)映射拷貝到注冊(cè)表中。 base_class 始終會(huì)是所生成類的__bases__列表中的最后一個(gè)類。默認(rèn)的映射有:
- subject
UniqueUnstructuredHeader
- date
UniqueDateHeader
- resent-date
DateHeader
- orig-date
UniqueDateHeader
- sender
UniqueSingleAddressHeader
- resent-sender
SingleAddressHeader
- 到
UniqueAddressHeader
- resent-to
AddressHeader
- cc
UniqueAddressHeader
- resent-cc
AddressHeader
- 從
UniqueAddressHeader
- resent-from
AddressHeader
- reply-to
UniqueAddressHeader
HeaderRegistry具有下列方法:-
map_to_type(self, name, cls)? name 是要映射的標(biāo)頭名稱。 它將在注冊(cè)表中被轉(zhuǎn)換為小寫形式。 cls 是要與 base_class 一起被用來創(chuàng)建用于實(shí)例化與 name 相匹配的標(biāo)頭的類的專用類。
-
__getitem__(name)? 構(gòu)造并返回一個(gè)類來處理 name 標(biāo)頭的創(chuàng)建。
-
__call__(name, value)? 從注冊(cè)表獲得與 name 相關(guān)聯(lián)的專用標(biāo)頭 (如果 name 未在注冊(cè)表中出現(xiàn)則使用 default_class) 并將其與 base_class 相組合以產(chǎn)生類,調(diào)用被構(gòu)造類的構(gòu)造器,傳入相同的參數(shù)列表,并最終返回由此創(chuàng)建的類實(shí)例。
以下的類是用于表示從結(jié)構(gòu)化標(biāo)頭解析的數(shù)據(jù)的類,并且通常會(huì)由應(yīng)用程序使用以構(gòu)造結(jié)構(gòu)化的值并賦給特定的標(biāo)頭。
-
class
email.headerregistry.Address(display_name='', username='', domain='', addr_spec=None)? 用于表示電子郵件地址的類。 地址的一般形式為:
[display_name] <username@domain>
或者:
username@domain
其中每個(gè)部分都必須符合在 RFC 5322 中闡述的特定語法規(guī)則。
為了方便起見可以指定 addr_spec 來替代 username 和 domain,在此情況下 username 和 domain 將從 addr_spec 中解析。 addr_spec 應(yīng)當(dāng)是一個(gè)正確地引用了 RFC 的字符串;如果它不是
Address則將引發(fā)錯(cuò)誤。 Unicode 字符也允許使用并將在序列化時(shí)被正確地編碼。 但是,根據(jù) RFC,地址的 username 部分 不允許 有 unicode。-
display_name? 地址的顯示名稱部分(如果有的話)并去除所有引用項(xiàng)。 如果地址沒有顯示名稱,則此屬性將為空字符串。
-
username? 地址的
username部分,去除所有引用項(xiàng)。
-
domain? 地址的
domain部分。
-
addr_spec? 地址的
username@domain部分,經(jīng)過正確引用處理以作為純地址使用(上面顯示的第二種形式)。 此屬性不可變。
-
__str__()? 對(duì)象的
str值是根據(jù) RFC 5322 規(guī)則進(jìn)行引用處理的地址,但不帶任何非 ASCII 字符的 Content Transfer Encoding。
為了支持 SMTP (RFC 5321),
Address會(huì)處理一種特殊情況:如果username和domain均為空字符串 (或?yàn)?None),則Address的字符串值為<>。-
-
class
email.headerregistry.Group(display_name=None, addresses=None)? 用于表示地址組的類。 地址組的一般形式為:
display_name: [address-list];
作為處理由組和單個(gè)地址混合構(gòu)成的列表的便捷方式,
Group也可以通過將 display_name 設(shè)為None以用來表示不是某個(gè)組的一部分的單個(gè)地址并提供單個(gè)地址的列表作為 addresses。-
display_name? 組的
display_name。 如果其為None并且恰好有一個(gè)Address在addresses中,則Group表示一個(gè)不在某個(gè)組中的單獨(dú)地址。
-
備注
