email.headerregistry: 自定義標頭物件

原始碼: Lib/email/headerregistry.py


3.6 版本新增: [1]

標頭由 str 的自定義子類表示。用於表示給定標頭的特定類由建立標頭時生效的 header_factorypolicy 確定。本節記錄了 email 包為處理符合 RFC 5322 的電子郵件訊息而實現的特定 header_factory,它不僅為各種標頭型別提供了自定義標頭物件,還為應用程式提供了擴充套件機制來新增其自己的自定義標頭型別。

當使用任何從 EmailPolicy 派生的 policy 物件時,所有標頭都由 HeaderRegistry 生成,並且以 BaseHeader 作為它們的最後一個基類。每個標頭類都有一個附加的基類,該基類由標頭的型別確定。例如,許多標頭都有 UnstructuredHeader 類作為它們的另一個基類。標頭的專門化第二個類由標頭的名稱確定,使用儲存在 HeaderRegistry 中的查詢表。所有這些都為典型的應用程式程式透明地管理,但提供了介面來修改預設行為,供更復雜的應用程式使用。

以下各節首先記錄標頭基類及其屬性,然後是修改 HeaderRegistry 行為的 API,最後是用於表示從結構化標頭解析的資料的支援類。

class email.headerregistry.BaseHeader(name, value)

namevalueheader_factory 呼叫傳遞給 BaseHeader。任何標頭物件的字串值都是完全解碼為 unicode 的 value

此基類定義以下只讀屬性

name

標頭的名稱(欄位中 ‘:’ 之前的部分)。這正是為 nameheader_factory 呼叫中傳遞的值;也就是說,保留了大小寫。

defects

HeaderDefect 例項的元組,報告在解析期間發現的任何 RFC 合規性問題。email 包嘗試完全檢測合規性問題。有關可能報告的缺陷型別,請參閱 errors 模組。

max_count

此型別標頭可以具有相同 name 的最大數量。None 值表示無限制。此屬性的 BaseHeader 值為 None;預期專門化的標頭類將根據需要覆蓋此值。

BaseHeader 還提供了以下方法,該方法由 email 庫程式碼呼叫,通常不應由應用程式程式呼叫

fold(*, policy)

返回一個字串,其中包含 linesep 字元,以便根據 policy 正確摺疊標頭。 cte_type8bit 將被視為 7bit,因為標頭可能不包含任意二進位制資料。如果 utf8False,則非 ASCII 資料將進行 RFC 2047 編碼。

BaseHeader 本身不能用於建立標頭物件。它定義了每個專門的標頭為生成標頭物件而與之協作的協議。具體來說,BaseHeader 要求專門化的類提供一個名為 parseclassmethod()。此方法按如下方式呼叫

parse(string, kwds)

kwds 是一個字典,其中包含一個預初始化的鍵 defectsdefects 是一個空列表。parse 方法應將檢測到的任何缺陷附加到此列表。返回時,kwds 字典必須包含至少鍵 decodeddefects 的值。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 解析器會根據 RFC 2047 中非結構化文字的規則,將這些編碼詞轉換為 Unicode。解析器使用啟發式方法嘗試解碼某些不符合規範的編碼詞。在這種情況下會註冊缺陷,以及在編碼詞或非編碼文字中存在無效字元等問題的缺陷。

此頭部型別不提供其他屬性。

class email.headerregistry.DateHeader

RFC 5322 為電子郵件頭部中的日期指定了非常具體的格式。DateHeader 解析器可以識別該日期格式,並識別有時在“實際應用中”發現的許多變體形式。

此頭部型別提供以下附加屬性

datetime

如果頭部值可以被識別為某種形式的有效日期,則此屬性將包含一個 datetime 例項,表示該日期。如果輸入日期的時區指定為 -0000(表示它在 UTC 中,但不包含有關源時區的任何資訊),則 datetime 將是一個樸素的 datetime。如果找到特定的時區偏移量(包括 +0000),則 datetime 將包含一個感知時區的 datetime,它使用 datetime.timezone 來記錄時區偏移量。

頭部的 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_nameNone

addresses

一個 Address 物件的元組,用於編碼頭部值中的所有單獨地址。如果頭部值包含任何組,則組中的各個地址將包含在列表中,該列表位於該組在值中出現的位置(也就是說,地址列表被“扁平化”為一維列表)。

頭部的 decoded 值將所有編碼詞解碼為 Unicode。idna 編碼的域名也被解碼為 Unicode。decoded 值由 拼接 groups 屬性的元素的 str 值和 ', ' 來設定。

任何組合中的 AddressGroup 物件的列表可用於設定地址頭部的值。display_nameNoneGroup 物件將被解釋為單個地址,這允許透過使用從源頭部的 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

inlineattachment 是常用的唯二有效值。

class email.headerregistry.ContentTransferEncoding

處理 Content-Transfer-Encoding 標頭。

cte

有效值為 7bit8bitbase64quoted-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_mapTrue(預設值)時,標頭名稱到類的標準對映將在初始化期間複製到登錄檔中。 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 而不是 usernamedomain,在這種情況下,將從 addr_spec 解析 usernamedomainaddr_spec 必須是正確 RFC 引用的字串;如果不是,Address 將引發錯誤。允許使用 Unicode 字元,並且在序列化時將正確編碼。但是,根據 RFC,Unicode 允許在地址的使用者名稱部分中使用。

display_name

地址的顯示名稱部分(如果有),刪除所有引號。如果地址沒有顯示名稱,則此屬性將為空字串。

username

地址的 username 部分,刪除所有引號。

domain

地址的 domain 部分。

addr_spec

地址的 username@domain 部分,正確引用以用作裸地址(如上所示的第二種形式)。此屬性是不可變的。

__str__()

物件的 str 值是根據 RFC 5322 規則引用的地址,但沒有任何非 ASCII 字元的內容傳輸編碼。

為了支援 SMTP (RFC 5321),Address 處理一種特殊情況:如果 usernamedomain 都是空字串(或 None),則 Address 的字串值為 <>

class email.headerregistry.Group(display_name=None, addresses=None)

用於表示地址組的類。地址組的一般形式為

display_name: [address-list];

為了方便處理由組和單個地址混合組成的地址列表,Group 也可以透過將 display_name 設定為 None 並提供單個地址列表作為 addresses 來表示不屬於組的單個地址。

display_name

組的 display_name。如果為 Noneaddresses 中恰好有一個 Address,則 Group 表示不屬於組的單個地址。

addresses

一個可能為空的 Address 物件元組,表示組中的地址。

__str__()

Groupstr 值根據 RFC 5322 進行格式化,但不進行任何非 ASCII 字元的內容傳輸編碼。如果 display_name 為 none 且 addresses 列表中有一個 Address,則 str 值將與該單個 Addressstr 值相同。

腳註