email.message:表示電子郵件

原始碼: Lib/email/message.py


3.6 版本新增: [1]

email 包中的核心類是 EmailMessage 類,它從 email.message 模組匯入。它是 email 物件模型的基礎類。EmailMessage 提供了設定和查詢頭部欄位、訪問訊息正文以及建立或修改結構化訊息的核心功能。

電子郵件訊息由 頭部有效負載 (也稱為 內容)組成。頭部是 RFC 5322RFC 6532 樣式的欄位名和值,其中欄位名和值之間用冒號分隔。冒號不是欄位名或欄位值的一部分。有效負載可以是簡單的文字訊息、二進位制物件,也可以是結構化的子訊息序列,每個子訊息都有自己的頭部集和自己的有效負載。後一種型別的有效負載由訊息具有 MIME 型別(如 multipart/*message/rfc822)指示。

EmailMessage 物件提供的概念模型是一個有序的頭部字典,以及表示訊息 RFC 5322 正文的 有效負載,它可能是一個 EmailMessage 子物件列表。除了用於訪問頭部名稱和值的普通字典方法外,還有一些方法用於訪問頭部中的專門資訊(例如 MIME 內容型別)、操作有效負載、生成訊息的序列化版本以及遞迴遍歷物件樹。

EmailMessage 類字典式介面由頭部名稱索引,頭部名稱必須是 ASCII 值。字典的值是帶有附加方法的一些字串。頭部以保留大小寫形式儲存和返回,但欄位名稱匹配不區分大小寫。鍵是有序的,但與真正的字典不同,可以有重複項。還提供了其他方法用於處理具有重複鍵的頭部。

有效負載 可以是字串或位元組物件(對於簡單的訊息物件),也可以是 EmailMessage 物件列表(對於 MIME 容器文件,如 multipart/*message/rfc822 訊息物件)。

class email.message.EmailMessage(policy=default)

如果指定了 policy,則使用它指定的規則來更新和序列化訊息的表示形式。如果未設定 policy,則使用 default 策略,該策略遵循電子郵件 RFC 的規則,但行尾符除外(它使用 Python 標準的 \n 行尾符,而不是 RFC 規定的 \r\n)。有關詳細資訊,請參閱 policy 文件。

as_string(unixfrom=False, maxheaderlen=None, policy=None)

返回整個訊息,將其展平為字串。當可選的 unixfrom 為 true 時,返回的字串中包含信封頭。unixfrom 預設為 False。為了向後相容基本的 Message 類,接受 maxheaderlen,但預設為 None,這意味著預設情況下,行長由策略的 max_line_length 控制。可以使用 policy 引數覆蓋從訊息例項獲得的預設策略。這可以用來控制該方法生成的一些格式,因為指定的 policy 將傳遞給 Generator

如果需要填充預設值以完成到字串的轉換(例如,可以生成或修改 MIME 邊界),則展平訊息可能會觸發對 EmailMessage 的更改。

請注意,提供此方法是為了方便起見,並且可能不是在應用程式中序列化訊息的最有用的方法,尤其是在處理多個訊息時。有關用於序列化訊息的更靈活的 API,請參閱 email.generator.Generator。另請注意,當 utf8False(預設值)時,此方法僅限於生成序列化為 “7 位乾淨” 的訊息。

在 3.6 版本中更改: 當未指定 maxheaderlen 時,預設行為從預設為 0 更改為預設為策略中的 max_line_length 的值。

__str__()

等效於 as_string(policy=self.policy.clone(utf8=True))。允許 str(msg) 生成一個包含以可讀格式序列化訊息的字串。

3.4 版本更改: 該方法已更改為使用 utf8=True,從而生成類似 RFC 6531 的訊息表示形式,而不是作為 as_string() 的直接別名。

as_bytes(unixfrom=False, policy=None)

將整個訊息扁平化為位元組物件並返回。當可選的 unixfrom 為 true 時,信封頭將包含在返回的字串中。unixfrom 預設為 False。可以使用 policy 引數覆蓋從訊息例項獲得的預設策略。這可用於控制該方法生成的一些格式,因為指定的 policy 將傳遞給 BytesGenerator

如果需要填充預設值以完成到字串的轉換(例如,可以生成或修改 MIME 邊界),則展平訊息可能會觸發對 EmailMessage 的更改。

請注意,此方法是為了方便而提供的,可能不是在應用程式中序列化訊息的最有效方法,特別是當您處理多個訊息時。有關序列化訊息的更靈活的 API,請參閱 email.generator.BytesGenerator

__bytes__()

等效於 as_bytes()。允許 bytes(msg) 生成一個包含序列化訊息的位元組物件。

is_multipart()

如果訊息的有效負載是子 EmailMessage 物件的列表,則返回 True,否則返回 False。當 is_multipart() 返回 False 時,有效負載應為字串物件(可能是 CTE 編碼的二進位制有效負載)。請注意,is_multipart() 返回 True 並不一定意味著 “msg.get_content_maintype() == ‘multipart’” 將返回 True。例如,當 EmailMessage 的型別為 message/rfc822 時,is_multipart 將返回 True

set_unixfrom(unixfrom)

將訊息的信封頭設定為 unixfrom,它應該是一個字串。(有關此標頭的簡要說明,請參閱 mboxMessage。)

get_unixfrom()

返回訊息的信封頭。如果從未設定信封頭,則預設為 None

以下方法實現了用於訪問訊息標頭的類似對映的介面。請注意,這些方法與普通對映(即字典)介面之間存在一些語義差異。例如,在字典中,沒有重複的鍵,但是在這裡,可能存在重複的訊息頭。此外,在字典中,keys() 返回的鍵的順序沒有保證,但是在 EmailMessage 物件中,標頭始終以它們在原始訊息中出現的順序返回,或者以它們稍後新增到訊息中的順序返回。任何刪除然後重新新增的標頭始終附加到標頭列表的末尾。

這些語義差異是有意的,並且偏向於在最常見的用例中提供便利。

請注意,在所有情況下,訊息中存在的任何信封頭都不包含在對映介面中。

__len__()

返回標頭的總數,包括重複項。

__contains__(name)

如果訊息物件具有名為 name 的欄位,則返回 True。匹配不區分大小寫,並且 name 不包括尾隨冒號。用於 in 運算子。例如

if 'message-id' in myMessage:
   print('Message-ID:', myMessage['message-id'])
__getitem__(name)

返回命名標頭欄位的值。name 不包括冒號欄位分隔符。如果缺少標頭,則返回 None;永遠不會引發 KeyError

請注意,如果命名欄位在訊息的標頭中出現多次,則返回哪個欄位值是不確定的。使用 get_all() 方法獲取所有名為 name 的現有標頭的值。

使用標準(非 compat32)策略,返回的值是 email.headerregistry.BaseHeader 的子類的例項。

__setitem__(name, val)

向訊息新增一個標頭,欄位名稱為 name,值為 val。該欄位將附加到訊息的現有標頭的末尾。

請注意,這不會覆蓋或刪除任何具有相同名稱的現有標頭。如果要確保新標頭是訊息中唯一具有欄位名稱 name 的標頭,請先刪除該欄位,例如

del msg['subject']
msg['subject'] = 'Python roolz!'

如果 policy 將某些標頭定義為唯一(標準策略也是如此),則當嘗試為已存在的此類標頭賦值時,此方法可能會引發 ValueError。為了保持一致性,此行為是故意的,但是不要依賴它,因為我們可能會選擇將來使此類賦值自動刪除現有標頭。

__delitem__(name)

從訊息的標頭中刪除所有名稱為 name 的欄位。如果標頭中不存在命名欄位,則不會引發異常。

keys()

返回所有訊息的標頭欄位名稱的列表。

values()

返回所有訊息的欄位值的列表。

items()

返回包含所有訊息的欄位標頭和值的 2 元組的列表。

get(name, failobj=None)

返回命名標頭欄位的值。這與 __getitem__() 相同,只是如果缺少命名標頭,則返回可選的 failobj (failobj 預設為 None)。

以下是一些其他有用的與標頭相關的方法

get_all(name, failobj=None)

返回名為 name 的欄位的所有值的列表。如果訊息中沒有此類命名的標頭,則返回 failobj (預設為 None)。

add_header(_name, _value, **_params)

擴充套件標頭設定。此方法類似於 __setitem__(),不同之處在於可以提供額外的標頭引數作為關鍵字引數。_name 是要新增的標頭欄位,_value 是標頭的主要值。

對於關鍵字引數字典 _params 中的每個專案,鍵被視為引數名稱,下劃線轉換為破折號(因為破折號在 Python 識別符號中是非法的)。通常,引數將新增為 key="value",除非值是 None,在這種情況下,只會新增鍵。

如果值包含非 ASCII 字元,可以透過將值指定為 (CHARSET, LANGUAGE, VALUE) 格式的三元組來顯式控制字元集和語言,其中 CHARSET 是一個字串,用於命名用於編碼該值的字元集, LANGUAGE 通常可以設定為 None 或空字串(有關其他可能性,請參見 RFC 2231), VALUE 是包含非 ASCII 程式碼點的字串值。如果未傳遞三元組,並且值包含非 ASCII 字元,則會使用 utf-8CHARSETNoneLANGUAGERFC 2231 格式自動編碼。

這是一個例子

msg.add_header('Content-Disposition', 'attachment', filename='bud.gif')

這將新增一個看起來像這樣的標頭

Content-Disposition: attachment; filename="bud.gif"

一個帶有非 ASCII 字元的擴充套件介面示例

msg.add_header('Content-Disposition', 'attachment',
               filename=('iso-8859-1', '', 'Fußballer.ppt'))
replace_header(_name, _value)

替換標頭。替換訊息中與 _name 匹配的第一個標頭,保留原始標頭的標頭順序和欄位名稱大小寫。如果沒有找到匹配的標頭,則引發 KeyError

get_content_type()

返回訊息的內容型別,強制轉換為小寫形式的 maintype/subtype。如果訊息中沒有 Content-Type 標頭,則返回 get_default_type() 返回的值。如果 Content-Type 標頭無效,則返回 text/plain

(根據 RFC 2045,訊息始終具有預設型別,get_content_type() 將始終返回一個值。RFC 2045 定義訊息的預設型別為 text/plain,除非它出現在 multipart/digest 容器內,在這種情況下它將是 message/rfc822。如果 Content-Type 標頭具有無效的型別規範,則 RFC 2045 要求預設型別為 text/plain。)

get_content_maintype()

返回訊息的主要內容型別。這是 get_content_type() 返回的字串的 maintype 部分。

get_content_subtype()

返回訊息的子內容型別。這是 get_content_type() 返回的字串的 subtype 部分。

get_default_type()

返回預設內容型別。大多數訊息的預設內容型別為 text/plain,但作為 multipart/digest 容器子部分的訊息除外。此類子部分的預設內容型別為 message/rfc822

set_default_type(ctype)

設定預設內容型別。ctype 應該是 text/plainmessage/rfc822,儘管這不是強制的。預設內容型別不儲存在 Content-Type 標頭中,因此它僅在訊息中不存在 Content-Type 標頭時影響 get_content_type 方法的返回值。

set_param(param, value, header='Content-Type', requote=True, charset=None, language='', replace=False)

Content-Type 標頭中設定引數。如果引數已存在於標頭中,則將其值替換為 value。當 headerContent-Type (預設值)並且標頭尚未存在於訊息中時,新增該標頭,將其值設定為 text/plain,並追加新的引數值。可選的 header 指定 Content-Type 的替代標頭。

如果值包含非 ASCII 字元,可以使用可選的 charsetlanguage 引數顯式指定字元集和語言。可選的 language 指定 RFC 2231 語言,預設為空字串。charsetlanguage 都應該是字串。預設情況下,charset 使用 utf8language 使用 None

如果 replaceFalse (預設值),則標頭將移動到標頭列表的末尾。如果 replaceTrue,則將在適當的位置更新標頭。

不建議將 requote 引數與 EmailMessage 物件一起使用。

請注意,可以透過標頭值的 params 屬性訪問標頭的現有引數值(例如,msg['Content-Type'].params['charset'])。

在版本 3.4 中更改: 添加了 replace 關鍵字。

del_param(param, header='content-type', requote=True)

Content-Type 標頭中完全刪除給定的引數。標頭將在適當的位置重寫,不包含引數或其值。可選的 header 指定 Content-Type 的替代標頭。

不建議將 requote 引數與 EmailMessage 物件一起使用。

get_filename(failobj=None)

返回訊息的 Content-Disposition 標頭的 filename 引數的值。如果標頭沒有 filename 引數,則此方法將回退到查詢 Content-Type 標頭上的 name 引數。如果找不到任何一個,或者標頭丟失,則返回 failobj。返回的字串將始終根據 email.utils.unquote() 進行取消引用。

get_boundary(failobj=None)

返回訊息的 Content-Type 標頭的 boundary 引數的值,如果缺少標頭或沒有 boundary 引數,則返回 failobj。返回的字串將始終按照 email.utils.unquote() 進行非引用。

set_boundary(boundary)

Content-Type 標頭的 boundary 引數設定為 boundaryset_boundary() 如果需要,將始終引用 boundary。如果訊息物件沒有 Content-Type 標頭,則會引發 HeaderParseError

請注意,使用此方法與刪除舊的 Content-Type 標頭,並透過 add_header() 新增具有新邊界的新標頭略有不同,因為 set_boundary() 會保留標頭列表中 Content-Type 標頭的順序。

get_content_charset(failobj=None)

返回 Content-Type 標頭的 charset 引數,強制轉換為小寫。 如果沒有 Content-Type 標頭,或者該標頭沒有 charset 引數,則返回 failobj

get_charsets(failobj=None)

返回包含訊息中字元集名稱的列表。 如果訊息是 multipart,則該列表將為有效負載中的每個子部分包含一個元素,否則,它將是一個長度為 1 的列表。

列表中每個專案都將是一個字串,該字串是所表示子部分的 Content-Type 標頭中 charset 引數的值。 如果子部分沒有 Content-Type 標頭、沒有 charset 引數,或者不是 text 主 MIME 型別,則返回列表中的該專案將為 failobj

is_attachment()

如果存在 Content-Disposition 標頭,並且其(不區分大小寫)的值為 attachment,則返回 True,否則返回 False

在 3.4.2 版本中更改: 為了與 is_multipart() 保持一致,is_attachment 現在是一個方法而不是屬性。

get_content_disposition()

如果訊息有 Content-Disposition 標頭,則返回該標頭的(不帶引數)小寫值,否則返回 None。此方法的可能值為 *inline*、*attachment*,如果訊息遵循 RFC 2183,則返回 None

在 3.5 版本中新增。

以下方法與查詢和操作訊息的內容(有效負載)有關。

walk()

walk() 方法是一個通用的生成器,可用於以深度優先遍歷順序迭代訊息物件樹的所有部分和子部分。通常將 walk() 用作 for 迴圈中的迭代器;每次迭代都會返回下一個子部分。

以下是一個示例,該示例列印多部分訊息結構的每個部分的 MIME 型別

>>> for part in msg.walk():
...     print(part.get_content_type())
multipart/report
text/plain
message/delivery-status
text/plain
text/plain
message/rfc822
text/plain

walk 遍歷任何部分(其中 is_multipart() 返回 True)的子部分,即使 msg.get_content_maintype() == 'multipart' 可能返回 False。我們可以在示例中透過使用 _structure 除錯助手函式來看到這一點

>>> from email.iterators import _structure
>>> for part in msg.walk():
...     print(part.get_content_maintype() == 'multipart',
...           part.is_multipart())
True True
False False
False True
False False
False False
False True
False False
>>> _structure(msg)
multipart/report
    text/plain
    message/delivery-status
        text/plain
        text/plain
    message/rfc822
        text/plain

這裡 message 部分不是 multiparts,但它們確實包含子部分。is_multipart() 返回 True,並且 walk 會下降到子部分中。

get_body(preferencelist=('related', 'html', 'plain'))

返回最適合作為訊息“正文”的 MIME 部分。

preferencelist 必須是字串序列,來自集合 relatedhtmlplain,並指示返回的部分的內容型別的首選順序。

開始查詢與呼叫 get_body 方法的物件匹配的候選物件。

如果 preferencelist 中未包含 related,則當(子)部分與首選項匹配時,將遇到的任何相關部分的根部分(或根部分的子部分)視為候選物件。

當遇到 multipart/related 時,請檢查 start 引數,如果找到具有匹配 Content-ID 的部分,則在查詢候選匹配項時僅考慮它。否則,僅考慮 multipart/related 的第一個(預設根)部分。

如果某個部分具有 Content-Disposition 標頭,則僅當該標頭的值為 inline 時才將該部分視為候選匹配項。

如果候選物件均不匹配 preferencelist 中的任何首選項,則返回 None

注意:(1)對於大多數應用程式,真正有意義的 preferencelist 組合只有 ('plain',)('html', 'plain') 和預設的 ('related', 'html', 'plain')。(2) 由於匹配從呼叫 get_body 的物件開始,因此除非 preferencelist 具有非預設值,否則在 multipart/related 上呼叫 get_body 將返回物件本身。(3) 未指定 Content-Type 或其 Content-Type 標頭無效的訊息(或訊息部分)將被視為 text/plain 型別,這偶爾可能導致 get_body 返回意外結果。

iter_attachments()

返回訊息的所有直接子部分的迭代器,這些子部分不是候選“正文”部分。也就是說,跳過 text/plaintext/htmlmultipart/relatedmultipart/alternative 的首次出現(除非它們透過 Content-Disposition: attachment 顯式標記為附件),並返回所有剩餘部分。當直接應用於 multipart/related 時,返回除根部分之外的所有相關部分的迭代器(即:start 引數指向的部分,或者如果沒有 start 引數或 start 引數與任何部分的 Content-ID 不匹配時的第一部分)。當直接應用於 multipart/alternative 或非 multipart 時,返回一個空迭代器。

iter_parts()

返回訊息的所有直接子部分的迭代器,對於非 multipart,該迭代器將為空。(另請參見 walk()。)

get_content(*args, content_manager=None, **kw)

呼叫 content_managerget_content() 方法,將 self 作為訊息物件傳遞,並將任何其他引數或關鍵字作為附加引數傳遞。如果未指定 content_manager,則使用當前 policy 指定的 content_manager

set_content(*args, content_manager=None, **kw)

呼叫 content_managerset_content() 方法,將 self 作為訊息物件傳遞,並將任何其他引數或關鍵字作為附加引數傳遞。如果未指定 content_manager,則使用當前 policy 指定的 content_manager

將非 multipart 訊息轉換為 multipart/related 訊息,將任何現有的 Content- 標頭和有效負載移動到 multipart 的(新的)第一部分。如果指定了 boundary,則將其用作 multipart 中的邊界字串,否則將邊界留到需要時自動建立(例如,當訊息被序列化時)。

make_alternative(boundary=None)

將非 multipartmultipart/related 訊息轉換為 multipart/alternative 訊息,將任何現有的 Content- 標頭和有效負載移動到 multipart 的(新的)第一部分。如果指定了 boundary,則將其用作 multipart 中的邊界字串,否則將邊界留到需要時自動建立(例如,當訊息被序列化時)。

make_mixed(boundary=None)

將非 multipartmultipart/relatedmultipart-alternative 訊息轉換為 multipart/mixed 訊息,將任何現有的 Content- 標頭和有效負載移動到 multipart 的(新的)第一部分。如果指定了 boundary,則將其用作 multipart 中的邊界字串,否則將邊界留到需要時自動建立(例如,當訊息被序列化時)。

如果訊息是 multipart/related,則建立一個新的訊息物件,將其所有引數傳遞給其 set_content() 方法,並將其 attach()multipart。如果訊息是非 multipart,則呼叫 make_related(),然後按上述步驟進行。如果訊息是任何其他型別的 multipart,則引發 TypeError。如果未指定 content_manager,則使用當前 policy 指定的 content_manager。如果新增的部分沒有 Content-Disposition 標頭,則新增一個值為 inline 的標頭。

add_alternative(*args, content_manager=None, **kw)

如果訊息是 multipart/alternative,則建立一個新的訊息物件,將其所有引數傳遞給其 set_content() 方法,並將其 attach()multipart。如果訊息是非 multipartmultipart/related,則呼叫 make_alternative(),然後按上述步驟進行。如果訊息是任何其他型別的 multipart,則引發 TypeError。如果未指定 content_manager,則使用當前 policy 指定的 content_manager

add_attachment(*args, content_manager=None, **kw)

如果訊息是 multipart/mixed,則建立一個新的訊息物件,將其所有引數傳遞給其 set_content() 方法,並將其 attach()multipart。如果訊息是非 multipartmultipart/relatedmultipart/alternative,則呼叫 make_mixed(),然後按上述步驟進行。如果未指定 content_manager,則使用當前 policy 指定的 content_manager。如果新增的部分沒有 Content-Disposition 標頭,則新增一個值為 attachment 的標頭。此方法可用於顯式附件(Content-Disposition: attachment)和 inline 附件(Content-Disposition: inline),透過將適當的選項傳遞給 content_manager

clear()

刪除有效負載和所有標頭。

clear_content()

移除載荷和所有 !Content- 標頭,保持所有其他標頭完整且順序不變。

EmailMessage 物件具有以下例項屬性

preamble

MIME 文件的格式允許在標頭後的空行和第一個多部分邊界字串之間存在一些文字。通常,此文字在支援 MIME 的郵件閱讀器中是不可見的,因為它位於標準 MIME 封裝之外。但是,在檢視郵件的原始文字或在不支援 MIME 的閱讀器中檢視郵件時,此文字可能會變得可見。

preamble 屬性包含 MIME 文件的此引導式額外封裝文字。當 Parser 在標頭之後但在第一個邊界字串之前發現一些文字時,它會將此文字分配給訊息的 preamble 屬性。當 Generator 正在寫出 MIME 訊息的純文字表示形式,並且發現該訊息具有 preamble 屬性時,它會將此文字寫入標頭和第一個邊界之間的區域。有關詳細資訊,請參閱 email.parseremail.generator

請注意,如果訊息物件沒有 preamble,則 preamble 屬性將為 None

epilogue

epilogue 屬性的作用與 preamble 屬性相同,只是它包含出現在最後一個邊界和訊息末尾之間的文字。與 preamble 一樣,如果沒有 epilogue 文字,此屬性將為 None

defects

defects 屬性包含解析此訊息時發現的所有問題的列表。有關可能的解析缺陷的詳細說明,請參閱 email.errors

class email.message.MIMEPart(policy=default)

此類表示 MIME 訊息的子部分。它與 EmailMessage 相同,只是當呼叫 set_content() 時不會新增 MIME-Version 標頭,因為子部分不需要自己的 MIME-Version 標頭。

腳註