email.headerregistry
: 自定義標頭物件¶
原始碼: Lib/email/headerregistry.py
在 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 和 value 是透過呼叫
header_factory
傳遞給BaseHeader
的。任何標頭物件的字串值都是完全解碼為 Unicode 的 value。這個基類定義了以下只讀屬性:
- name¶
標頭的名稱(欄位中“:”之前的部分)。這與在
header_factory
呼叫中為 name 傳遞的值完全相同;也就是說,大小寫被保留。
- 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)
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 字元。當一個包含編碼詞的 value 傳遞給建構函式時,
UnstructuredHeader
解析器會根據 RFC 2047 的非結構化文字規則將這些編碼詞轉換為 Unicode。解析器使用啟發式方法嘗試解碼某些不合規的編碼詞。在這種情況下會註冊缺陷,同時也會為編碼詞或未編碼文字中的無效字元等問題註冊缺陷。此標頭型別不提供其他屬性。
- class email.headerregistry.DateHeader¶
RFC 5322 為電子郵件標頭中的日期指定了非常特定的格式。
DateHeader
解析器可以識別該日期格式,以及一些有時在“野外”發現的變體形式。此標頭型別提供了以下附加屬性:
- datetime¶
如果標頭值能被識別為某種形式的有效日期,則此屬性將包含一個表示該日期的
datetime
例項。如果輸入日期的時區指定為-0000
(表示它在 UTC,但不包含有關源時區的資訊),則datetime
將是一個 naivedatetime
。如果找到特定的時區偏移量(包括+0000
),則datetime
將包含一個 awaredatetime
,它使用datetime.timezone
來記錄時區偏移量。
標頭的
decoded
值是透過根據 RFC 5322 規則格式化datetime
來確定的;也就是說,它被設定為:email.utils.format_datetime(self.datetime)
建立
DateHeader
時,value 可以是datetime
例項。這意味著,例如,以下程式碼是有效的並且會按預期工作:msg['Date'] = datetime(2011, 7, 15, 21)
由於這是一個 naive
datetime
,它將被解釋為 UTC 時間戳,並且結果值將具有-0000
的時區。更有用的是使用utils
模組中的localtime()
函式:msg['Date'] = utils.localtime()
此示例將日期標頭設定為當前時間和日期,使用當前時區偏移量。
- class email.headerregistry.AddressHeader¶
地址標頭是最複雜的結構化標頭型別之一。
AddressHeader
類為任何地址標頭提供了通用介面。此標頭型別提供了以下附加屬性:
- groups¶
一個
Group
物件的元組,編碼了在標頭值中找到的地址和組。不屬於組的地址在此列表中表示為單個地址的Group
,其display_name
為None
。
- addresses¶
一個
Address
物件的元組,編碼了標頭值中的所有單個地址。如果標頭值包含任何組,則組中的單個地址將包含在列表中,位置是組在值中出現的位置(也就是說,地址列表被“扁平化”為一維列表)。
標頭的
decoded
值將所有編碼詞解碼為 Unicode。idna
編碼的域名也被解碼為 Unicode。decoded
值透過將groups
屬性元素的str
值用', '
連線起來設定。可以使用
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¶
一個
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
表示一個不在組中的單個地址。
腳註