email.message: 表示一封電子郵件信息?
源代碼: Lib/email/message.py
3.6 新版功能: 1
位于 email 包的中心的類就是 EmailMessage 類。這個類導入自 email.message 模塊。它是 email 對象模型的基類。EmailMessage 為設置和查詢頭字段內容、訪問信息體的內容、以及創(chuàng)建和修改結構化信息提供了核心功能。
一份電子郵件信息由*頭*和*負載*(又被稱為*內容*)組成。頭遵循 RFC 5322 或者 RFC 6532 風格的字段名和值,字段名和字段值之間由一個冒號隔開。這個冒號既不屬于字段名,也不屬于字段值。信息的負載可能是一段簡單的文字消息,也可能是一個二進制的對象,更可能是由多個擁有各自頭和負載的子信息組成的結構化子信息序列。對于后者類型的負載,信息的 MIME 類型將會被指明為諸如 multipart/* 或 message/rfc822 的類型。
EmailMessage 對象所提供的抽象概念模型是一個頭字段組成的有序字典加一個代表 RFC 5322 標準的信息體的*負載*。負載有可能是一系列子``EmailMessage``對象的列表。你除了可以通過一般的字典方法來訪問頭字段名和值,還可以使用特制方法來訪問頭的特定字段(比如說 MIME 內容類型字段)、操縱負載、生成信息的序列化版本、遞歸遍歷對象樹。
EmailMessage 的類字典接口的字典索引是頭字段名,頭字段名必須是ASCII值。字典值是帶有一些附加方法的字符串。雖然頭字段的存儲和獲取都是保留其原始大小寫的,但是字段名的匹配是大小寫不敏感的。與真正的字典不同,鍵與鍵之間不但存在順序關系,還可以重復。我們提供了額外的方法來處理含有重復鍵的頭。
payload 是多樣的。 對于簡單的消息對象,它是字符串或字節(jié)串對象;對于諸如 multipart/* 和 message/rfc822 消息對象的 MIME 容器文檔,它是一個 EmailMessage 對象列表。
-
class
email.message.EmailMessage(policy=default)? 如果指定了*policy*,消息將由這個*policy*所指定的規(guī)則來更新和序列化信息的表達。如果沒有指定*policy*,其將默認使用
default策略。這個策略遵循電子郵件的RFC標準,除了行終止符號(RFC要求使用``rn``,此策略使用Python標準的``n``行終止符)。請前往policy的文檔獲取更多信息。-
as_string(unixfrom=False, maxheaderlen=None, policy=None)? 以一段字符串的形式返回整個消息對象。 若可選的 unixform 參數(shù)為真,返回的字符串會包含信封頭。 unixform 的默認值是
False。 為了保持與基類Message的兼容性,maxheaderlen 是被接受的,但是其默認值是None。 這個默認值表示行長度由策略的max_line_length屬性所控制。從信息實例所獲取到的策略可以通過 policy 參數(shù)重寫。 這樣可以對該方法所產(chǎn)生的輸出進行略微的控制,因為指定的 policy 會被傳遞到Generator當中。扁平化信息可能會對
EmailMessage做出修改。這是因為為了完成向字符串的轉換,一些內容需要使用默認值填入(舉個例子,MIME 邊界字段可能會被生成或被修改)。請注意,這個方法是為了便利而提供,不一定是適合你的應用程序的最理想的序列化信息的方法。這在你處理多封信息的時候尤甚。如果你需要使用更加靈活的API來序列化信息,請參見
email.generator.Generator。同時請注意,當utf8屬性為``False``的時候(這是默認值),本方法將限制其行為為生成以“7 bit clean”方式序列化的信息。在 3.6 版更改: maxheaderlen*沒有被指定時的默認行為從默認為0修改為默認為策略的*max_line_length。
-
__str__()? 與``as_string(policy=self.policy.clone(utf8=True))``等價。這將讓``str(msg)``產(chǎn)生的字符串包含人類可讀的的序列化信息內容。
在 3.4 版更改: 本方法開始使用``utf8=True``,而非
as_string()的直接替身。使用``utf8=True``會產(chǎn)生類似于 RFC 6531 的信息表達。
-
as_bytes(unixfrom=False, policy=None)? 以字節(jié)串對象的形式返回整個扁平化后的消息。 當可選的 unixfrom 為真值時,返回的字符串會包含信封標頭。 unixfrom 的默認值為
False。 policy 參數(shù)可被用于重載從消息實例獲取的默認 policy。 這可被用來控制該方法所產(chǎn)生的部分格式效果,因為指定的 policy 將被傳遞給BytesGenerator。扁平化信息可能會對
EmailMessage做出修改。這是因為為了完成向字符串的轉換,一些內容需要使用默認值填入(舉個例子,MIME 邊界字段可能會被生成或被修改)。請注意,這個方法是為了便利而提供,不一定是適合你的應用程序的最理想的序列化信息的方法。這在你處理多封信息的時候尤甚。如果你需要使用更加靈活的API來序列化信息,請參見
email.generator.BytesGenerator。
-
__bytes__()? 與
as_bytes()等價。這將讓``bytes(msg)``產(chǎn)生一個包含序列化信息內容的字節(jié)序列對象。
-
is_multipart()? 如果該信息的負載是一個子
EmailMessage對象列表,返回True;否則返回False。在is_multipart()返回True的場合下,負載應當是一個字符串對象(有可能是一個使用了內容傳輸編碼進行編碼的二進制負載)。請注意,is_multipart()返回True不意味著msg.get_content_maintype() == 'multipart'也會返回True。舉個例子,is_multipart在EmailMessage是message/rfc822類型的信息的情況下,其返回值也是True。
-
set_unixfrom(unixfrom)? 將信息的信封頭設置為 unixform ,這應當是一個字符串。(在
mboxMessage中有關于這個頭的一段簡短介紹。)
-
get_unixfrom()? 返回消息的信封頭。如果信封頭從未被設置過,默認返回
None。
以下方法實現(xiàn)了對信息的頭字段進行訪問的類映射接口。請留意,只是類映射接口,這與平常的映射接口(比如說字典映射)有一些語義上的不同。舉個例子,在一個字典當中,鍵之間不可重復,但是信息頭字段是可以重復的。不光如此,在字典當中調用
keys()方法返回的結果,其順序沒有保證;但是在一個EmailMessage對象當中,返回的頭字段永遠以其在原信息當中出現(xiàn)的順序,或以其加入信息的順序為序。任何刪了后又重新加回去的頭字段總是添加在當時列表的末尾。這些語義上的不同是刻意而為之的,是出于在絕大多數(shù)常見使用情景中都方便的初衷下設計的。
還請留意,無論在什么情況下,消息當中的任何信封頭字段都不會包含在映射接口當中。
-
__len__()? 返回頭字段的總數(shù),重復的也計算在內。
-
__contains__(name)? 如果消息對象中有一個名為 name 的字段,其返回值為
True。匹配無視大小寫差異, name 也不包含末尾的的冒號。in操作符的實現(xiàn)中用到了這個方法,比如說:if 'message-id' in myMessage: print('Message-ID:', myMessage['message-id'])
-
__getitem__(name)? 返回頭字段名對應的字段值。 name 不含冒號分隔符。如果字段未找到,返回
None。KeyError異常永不拋出。請注意,如果對應名字的字段找到了多個,具體返回哪個字段值是未定義的。請使用
get_all()方法獲取匹配字段名的所有字段值。使用標準策略(非
compat32)時,返回值是email.headerregistry.BaseHeader的某個子類的一個實例。
-
__setitem__(name, val)? 在信息頭中添加名為 name 值為 val 的字段。這個字段會被添加在已有字段列表的結尾處。
請注意,這個方法 既不會 覆蓋 也不會 刪除任何字段名重名的已有字段。如果你確實想保證新字段是整個信息頭當中唯一擁有 name 字段名的字段,你需要先把舊字段刪除。例如:
del msg['subject'] msg['subject'] = 'Python roolz!'
如果
policy明確要求某些字段是唯一的(至少標準策略就有這么做),對這些字段在已有同名字段的情況下仍然嘗試為字段名賦值會引發(fā)ValueError異常。這是為了一致性而刻意設計出的行為,不過我們隨時可能會突然覺得“還是在這種情況下自動把舊字段刪除比較好吧”而把這個行為改掉,所以不要以為這是特性而依賴這個行為。
-
__delitem__(name)? 刪除信息頭當中字段名匹配 name 的所有字段。如果匹配指定名稱的字段沒有找到,也不會拋出任何異常。
-
keys()? 以列表形式返回消息頭中所有的字段名。
-
values()? 以列表形式返回消息頭中所有的字段值。
-
items()? 以二元元組的列表形式返回消息頭中所有的字段名和字段值。
-
get(name, failobj=None)? 返回對應字段名的字段值。這個方法與
__getitem__()是一樣的,只不過如果對應字段名的字段沒有找到,該方法會返回 failobj 。這個參數(shù)是可選的(默認值為None)。
以下是一些與頭有關的更多有用方法:
-
get_all(name, failobj=None)? 返回字段名為 name 的所有字段值的列表。如果信息內不存在匹配的字段,返回 failobj (其默認值為
None)。
-
add_header(_name, _value, **_params)? 高級頭字段設定。這個方法與
__setitem__()類似,不過你可以使用關鍵字參數(shù)為字段提供附加參數(shù)。 _name 是字段名, _value 是字段 主 值。對于關鍵字參數(shù)字典 _params 的每個鍵值對而言,它的鍵被用作參數(shù)的名字,其中下劃線被替換為短橫杠(畢竟短橫杠不是合法的Python標識符)。一般來講,參數(shù)以
鍵="值"的方式添加,除非值是None。要真的是這樣的話,只有鍵會被添加。如果值含有非ASCII字符,你可以將值寫成
(CHARSET, LANGUAGE, VALUE)形式的三元組,這樣你可以人為控制字符的字符集和語言。CHARSET是一個字符串,它為你的值的編碼命名;LANGUAGE一般可以直接設為None,也可以直接設為空字符串(其他可能取值參見 :rfc`2231` );`VALUE是一個字符串值,其包含非ASCII的碼點。如果你沒有使用三元組,你的字符串又含有非ASCII字符,那么它就會使用 RFC 2231 中,CHARSET為utf-8,LANGUAGE為None的格式編碼。例如:
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。(根據(jù) RFC 2045 所述,信息永遠都有一個默認類型,所以
get_content_type()一定會返回一個值。 RFC 2045 定義信息的默認類型為 text/plain 或 message/rfc822 ,其中后者僅出現(xiàn)在消息頭位于一個 multipart/digest 容器中的場合中。如果消息頭的 Content-Type 字段所指定的類型是無效的, RFC 2045 令其默認類型為 text/plain 。)
-
get_content_maintype()? 返回信息的主要內容類型。準確來說,此方法返回的是
get_content_type()方法所返回的形如 maintype/subtype 的字符串當中的 maintype 部分。
-
get_content_subtype()? 返回信息的子內容類型。準確來說,此方法返回的是
get_content_type()方法所返回的形如 maintype/subtype 的字符串當中的 subtype 部分。
-
get_default_type()? 返回默認的內容類型。絕大多數(shù)的信息,其默認內容類型都是 text/plain 。作為 multipart/digest 容器內子部分的信息除外,它們的默認內容類型是 message/rfc822 。
-
set_default_type(ctype)? 設置默認的內容類型。 盡管并非強制,但是 ctype 仍應當是 text/plain 或 message/rfc822 二者取一。默認內容類型并不存儲在 Content-Type 頭字段當中,所以設置此項的唯一作用就是決定當 Content-Type 頭字段在信息中不存在時,
get_content_type方法的返回值。
-
set_param(param, value, header='Content-Type', requote=True, charset=None, language='', replace=False)? 在 Content-Type 頭字段當中設置一個參數(shù)。如果該參數(shù)已于字段中存在,將其舊值替換為 value 。如果 header 是
Content-Type(默認值),并且該頭字段于信息中尚未存在,則會先添加該字段,將其值設置為 text/plain ,并附加參數(shù)值。可選的 header 可以讓你指定 Content-Type 之外的另一個頭字段。如果值包含非ASCII字符,其字符集和語言可以通過可選參數(shù) charset 和 language 顯式指定??蛇x參數(shù) language 指定 RFC 2231 當中的語言,其默認值是空字符串。 charset 和 language 都應當字符串。默認使用的是
utf8charset ,language 為None。如果 replace 為
False(默認值),該頭字段會被移動到所有頭字段的末尾。如果 replace 為True,字段會被原地更新。于
EmailMessage對象而言, requote 參數(shù)已被棄用。請注意,頭字段已有的參數(shù)值可以通過頭字段的
params屬性來訪問(舉例:msg['Content-Type'].params['charset'])。在 3.4 版更改: 添加了
replace關鍵字。
-
del_param(param, header='content-type', requote=True)? 從 Content-Type 頭字段中完全移去給定的參數(shù)。頭字段會被原地重寫,重寫后的字段不含參數(shù)和值。可選的 header 可以讓你指定 Content-Type 之外的另一個字段。
于
EmailMessage對象而言, requote 參數(shù)已被棄用。
-
get_filename(failobj=None)? 返回信息頭當中 Content-Disposition 字段當中名為
filename的參數(shù)值。如果該字段當中沒有此參數(shù),該方法會退而尋找 Content-Type 字段當中的name參數(shù)值。如果這個也沒有找到,或者這些個字段壓根就不存在,返回 failobj 。返回的字符串永遠按照email.utils.unquote()方法去除引號。
-
get_boundary(failobj=None)? 返回信息頭當中 Content-Type 字段當中名為
boundary的參數(shù)值。如果字段當中沒有此參數(shù),或者這些個字段壓根就不存在,返回 failobj 。返回的字符串永遠按照email.utils.unquote()方法去除引號。
-
set_boundary(boundary)? 將 Content-Type 頭字段的
boundary參數(shù)設置為 boundary 。set_boundary()方法永遠都會在必要的時候為 boundary 添加引號。如果信息對象中沒有 Content-Type 頭字段,拋出HeaderParseError異常。請注意使用這個方法與直接刪除舊的 Content-Type 頭字段然后使用
add_header()方法添加一個帶有新邊界值參數(shù)的 Content-Type 頭字段有細微差距。set_boundary()方法會保留 Content-Type 頭字段在原信息頭當中的位置。
-
get_content_charset(failobj=None)? 返回 Content-Type 頭字段中的
charset參數(shù),強制小寫。如果字段當中沒有此參數(shù),或者這個字段壓根不存在,返回 failobj 。
-
get_charsets(failobj=None)? 返回一個包含了信息內所有字符集名字的列表。如果信息是 multipart 類型的,那么列表當中的每一項都對應其負載的子部分的字符集名字。否則,該列表是一個長度為1的列表。
列表當中的每一項都是一個字符串,其值為對應子部分的 Content-Type 頭字段的
charset參數(shù)值。如果該子部分沒有此頭字段,或者沒有此參數(shù),或者其主要 MIME 類型并非 text ,那么列表中的那一項即為 failobj 。
-
is_attachment()? 如果信息頭當中存在一個名為 Content-Disposition 的字段,且該字段的值為
attachment(大小寫無關),返回True。否則,返回False。在 3.4.2 版更改: 為了與
is_multipart()方法一致,is_attachment 現(xiàn)在是一個方法,不再是屬性了。
-
get_content_disposition()? 如果信息的 Content-Disposition 頭字段存在,返回其字段值;否則返回
None。返回的值均為小寫,不包含參數(shù)。如果信息遵循 RFC 2183 標準,則返回值只可能在 inline 、 attachment 和None之間選擇。3.5 新版功能.
下列方法與信息內容(負載)之訪問與操控有關。
-
walk()? walk()方法是一個多功能生成器。它可以被用來以深度優(yōu)先順序遍歷信息對象樹的所有部分和子部分。一般而言,walk()會被用作for循環(huán)的迭代器,每一次迭代都返回其下一個子部分。以下例子會打印出一封具有多部分結構之信息的每個部分的 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除錯幫助函數(shù)可以幫助我們在下面這個例子當中看清楚這一點:>>> 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 必須是一個字符串序列,其內容從
related、html和plain這三者組成的集合中選取。這個序列代表著返回的部分的內容類型之偏好。在
get_body方法被調用的對象上尋找匹配的候選者。如果
related未包括在 preferencelist 中,可考慮將所遇到的任意相關的根部分(或根部分的子部分)在該(子)部分與一個首選項相匹配時作為候選項。當遇到一個
multipart/related時,將檢查start形參并且如果找到了一個匹配 Content-ID 的部分,在查找候選匹配時只考慮它。 在其他情況下則只考慮multipart/related的第一個(默認的根)部分。如果一個部分具有 Content-Disposition 標頭,則當標頭值為
inline時將只考慮將該部分作為候選匹配。如果沒有任何候選部分匹配 preferencelist 中的任何首選項,則返回
None。注: (1) 對于大多數(shù)應用來說有意義的 preferencelist 組合僅有
('plain',),('html', 'plain')以及默認的('related', 'html', 'plain')。 (2) 由于匹配是從調用get_body的對象開始的,因此在multipart/related上調用get_body將返回對象本身,除非 preferencelist 具有非默認值。 (3) 未指定 Content-Type 或者 Content-Type 標頭無效的消息(或消息部分)將被當作具有text/plain類型來處理,這有時可能導致get_body返回非預期的結果。
-
iter_attachments()? 返回包含所有不是候選 "body" 部分的消息的直接子部分的迭代器。 也就是說,跳過首次出現(xiàn)的每個
text/plain,text/html,multipart/related或multipart/alternative(除非通過 Content-Disposition: attachment 將它們顯式地標記為附件),并返回所有的其余部分。 當直接應用于multipart/related時,將返回包含除根部分之外所有相關部分的迭代器(即由start形參所指向的部分,或者當沒有start形參或start形參不能匹配任何部分的 Content-ID 時則為第一部分)。 當直接應用于multipart/alternative或非multipart時,將返回一個空迭代器。
-
get_content(*args, content_manager=None, **kw)? 調用 content_manager 的
get_content()方法,將自身作為消息對象傳入,并將其他參數(shù)或關鍵字作為額外參數(shù)傳入。 如果未指定 content_manager,則會使用當前policy所指定的content_manager。
-
set_content(*args, content_manager=None, **kw)? 調用 content_manager 的
set_content()方法,將自身作為消息傳入,并將其他參數(shù)或關鍵字作為額外參數(shù)傳入。 如果未指定 content_manager,則會使用當前policy所指定的content_manager。
將非
multipart消息轉換為multipart/related消息,將任何現(xiàn)有的 Content- 標頭和載荷移入multipart的(新加)首部分。 如果指定了 boundary,會用它作為 multipart 中的分界字符串,否則會在必要時自動創(chuàng)建分界(例如當消息被序列化時)。
-
make_alternative(boundary=None)? 將非
multipart或multipart/related轉換為multipart/alternative,將任何現(xiàn)有的 Content- 標頭和載荷移入multipart的(新加)首部分。 如果指定了 boundary,會用它作為 multipart 中的分界字符串,否則會在必要時自動創(chuàng)建分界(例如當消息被序列化時)。
-
make_mixed(boundary=None)? 將非
multipart,multipart/related或multipart-alternative轉換為multipart/mixed,將任何現(xiàn)有的 Content- 標頭和載荷移入multipart的(新加)首部分。 如果指定了 boundary,會用它作為 multipart 中的分界字符串,否則會在必要時自動創(chuàng)建分界(例如當消息被序列化時)。
如果消息為
multipart/related,則創(chuàng)建一個新的消息對象,將所有參數(shù)傳給其set_content()方法,并將其attach()到multipart。 如果消息為非multipart,則先調用make_related()然后再繼續(xù)上述步驟。 如果消息為任何其他類型的multipart,則會引發(fā)TypeError。 如果未指定 content_manager,則使用當前policy所指定的content_manager。 如果添加的部分沒有 Content-Disposition 標頭,則會添加一個值為inline的標頭。
-
add_alternative(*args, content_manager=None, **kw)? 如果消息為
multipart/alternative,則創(chuàng)建一個新的消息對象,將所有參數(shù)傳給其set_content()方法,并將其attach()到multipart。 如果消息為非multipart或multipart/related,則先調用make_alternative()然后再繼續(xù)上述步驟。 如果消息為任何其他類型的multipart,則會引發(fā)TypeError。 如果未指定 content_manager,則會使用當前policy所指定的content_manager。
-
add_attachment(*args, content_manager=None, **kw)? 如果消息為
multipart/mixed,則創(chuàng)建一個新的消息對象,將所有參數(shù)傳給其set_content()方法,并將其attach()到multipart。 如果消息為非multipart,multipart/related或multipart/alternative,則先調用make_mixed()然后再繼續(xù)上述步驟。 如果未指定 content_manager,則使用當前policy所指定的content_manager。 如果添加的部分沒有 Content-Disposition 標頭,則會添加一個值為attachment的標頭。 此方法對于顯式附件 (Content-Disposition: attachment) 和inline附件 (Content-Disposition: inline) 均可使用,只須向content_manager傳入適當?shù)倪x項即可。
-
clear()? 移除所有載荷和所有標頭。
-
clear_content()? 移除載荷以及所有
Content-標頭,其他標頭不加改變并且保持其原有順序。
EmailMessage對象具有下列實例屬性:-
preamble? MIME 文檔格式在標頭之后的空白行以及第一個多部分的分界字符串之間允許添加一些文本, 通常,此文本在支持 MIME 的郵件閱讀器中永遠不可見,因為它處在標準 MIME 防護范圍之外。 但是,當查看消息的原始文本,或當在不支持 MIME 的閱讀器中查看消息時,此文本會變得可見。
preamble 屬性包含 MIME 文檔開頭部分的這些處于保護范圍之外的文本。 當
Parser在標頭之后及第一個分界字符串之前發(fā)現(xiàn)一些文本時,它會將這些文本賦值給消息的 preamble 屬性。 當Generator寫出 MIME 消息的純文本表示形式時,如果它發(fā)現(xiàn)消息具有 preamble 屬性,它將在標頭及第一個分界之間區(qū)域寫出這些文本。 請參閱email.parser和email.generator了解更多細節(jié)。請注意如果消息對象沒有前導文本,則 preamble 屬性將為
None。
-
epilogue? epilogue 屬性的作用方式與 preamble 相同,區(qū)別在于它包含在最后一個分界及消息結尾之間出現(xiàn)的文本。 與
preamble類似,如果沒有附加文本,則此屬性將為None。
-
defects? defects 屬性包含在解析消息時發(fā)現(xiàn)的所有問題的列表。 請參閱
email.errors了解可能的解析缺陷的詳細描述。
-
-
class
email.message.MIMEPart(policy=default)? 這個類代表 MIME 消息的子部分。 它與
EmailMessage相似,不同之處在于當set_content()被調用時不會添加 MIME-Version 標頭,因為子部分不需要有它們自己的 MIME-Version 標頭。
備注
- 1
原先在3.4版本中以 provisional module 添加。過時的文檔被移動至 email.message.Message: 使用 compat32 API 來表示電子郵件消息 。
