email.generator:生成 MIME 文件

原始碼: Lib/email/generator.py


最常見的任務之一是生成由訊息物件結構所表示的電子郵件訊息的扁平化(序列化)版本。如果你想要透過 smtplib.SMTP.sendmail() 傳送訊息,或者在控制檯上列印訊息,就需要這樣做。將一個訊息物件結構並生成其序列化表示形式正是生成器類的工作。

email.parser 模組一樣,你不僅限於使用捆綁的生成器;你也可以自己從頭編寫一個。但是,捆綁的生成器知道如何以符合標準的方式生成大多數電子郵件,應能很好地處理 MIME 和非 MIME 電子郵件訊息,並且其設計使得面向位元組的解析和生成操作是互逆的,前提是兩者使用相同的非轉換 policy。也就是說,透過 BytesParser 類解析序列化的位元組流,然後使用 BytesGenerator 重新生成序列化的位元組流,應能產生與輸入完全相同的輸出 [1]。(另一方面,在透過程式構建的 EmailMessage 上使用生成器,可能會因為填充預設值而導致 EmailMessage 物件發生改變。)

可使用 Generator 類將訊息扁平化為文字(而非二進位制)的序列化表示,但由於 Unicode 無法直接表示二進位制資料,訊息必須轉換為只包含 ASCII 字元的內容,這透過使用標準的電子郵件 RFC 內容傳輸編碼技術,來為那些“非 8 位純淨”的通道傳輸電子郵件進行編碼。

為了支援對 SMIME 簽名的訊息進行可重現的處理,Generator 對於型別為 multipart/signed 的訊息部分及其所有子部分,會停用標頭摺疊。

class email.generator.BytesGenerator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

返回一個 BytesGenerator 物件,該物件會將提供給 flatten() 方法的任何訊息,或提供給 write() 方法的任何經過 surrogateescape 編碼的文字,寫入到 檔案類物件 *outfp* 中。 *outfp* 必須支援一個接受二進位制資料的 write 方法。

如果可選引數 *mangle_from_* 為 True,則在正文中任何以確切字串 "From "(即 From 後跟一個空格)開頭的行前面加上一個 > 字元。*mangle_from_* 預設為 *policy* 的 mangle_from_ 設定值(對於 compat32 策略,該值為 True,對於所有其他策略則為 False)。 *mangle_from_* 旨在用於訊息以 Unix mbox 格式儲存的情況(參見 mailboxWHY THE CONTENT-LENGTH FORMAT IS BAD)。

如果 *maxheaderlen* 不為 None,則重新摺疊任何長度超過 *maxheaderlen* 的標頭行;如果為 0,則不重新換行任何標頭。如果 *maxheaderlen* 為 None(預設值),則根據 *policy* 設定來換行標頭和其他訊息行。

如果指定了 *policy*,則使用該策略來控制訊息生成。如果 *policy* 為 None(預設值),則使用傳遞給 flattenMessageEmailMessage 物件關聯的策略來控制訊息生成。有關 *policy* 控制內容的詳細資訊,請參閱 email.policy

在 3.2 版本加入。

在 3.3 版本發生變更: 添加了 *policy* 關鍵字。

在 3.6 版本發生變更: *mangle_from_* 和 *maxheaderlen* 引數的預設行為將遵循策略。

flatten(msg, unixfrom=False, linesep=None)

將以 *msg* 為根的訊息物件結構的文字表示列印到建立 BytesGenerator 例項時指定的輸出檔案。

如果 policy 選項 cte_type8bit (預設值),則將原始已解析訊息中未被修改的任何標頭複製到輸出中,並保留高位設定的位元組與原始訊息一致,同時保留任何正文部分的非 ASCII Content-Transfer-Encoding。如果 cte_type7bit,則根據需要使用與 ASCII 相容的 Content-Transfer-Encoding 轉換高位設定的位元組。也就是說,將具有非 ASCII Content-Transfer-EncodingContent-Transfer-Encoding: 8bit)的部分轉換為與 ASCII 相容的 Content-Transfer-Encoding,並使用 MIME unknown-8bit 字元集對標頭中不符合 RFC 的非 ASCII 位元組進行編碼,從而使其符合 RFC 標準。

如果 *unixfrom* 為 True,則在根訊息物件的第一個 RFC 5322 標頭之前列印 Unix 郵箱格式使用的信封頭分隔符(見 mailbox)。如果根物件沒有信封頭,則建立一個標準的信封頭。預設值為 False。請注意,對於子部分,從不列印信封頭。

如果 *linesep* 不為 None,則將其用作扁平化訊息所有行之間的分隔符。如果 *linesep* 為 None(預設值),則使用 *policy* 中指定的值。

clone(fp)

返回此 BytesGenerator 例項的一個獨立克隆,其選項設定完全相同,並將 *fp* 作為新的 *outfp*。

write(s)

使用 ASCII 編解碼器和 surrogateescape 錯誤處理程式對 *s* 進行編碼,並將其傳遞給傳入 BytesGenerator 建構函式的 *outfp* 的 *write* 方法。

為了方便起見,EmailMessage 提供了 as_bytes()bytes(aMessage) (也即 __bytes__()) 方法,這簡化了訊息物件的序列化二進位制表示的生成。更多詳情請參閱 email.message

由於字串無法表示二進位制資料,Generator 類必須將其扁平化的任何訊息中的所有二進位制資料轉換為 ASCII 相容格式,方法是將其轉換為 ASCII 相容的 Content-Transfer-Encoding。用電子郵件 RFC 的術語來說,可以認為 Generator 是序列化到一個“非 8 位純淨”的 I/O 流。換句話說,大多數應用程式會希望使用 BytesGenerator,而不是 Generator

class email.generator.Generator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

返回一個 Generator 物件,該物件會將提供給 flatten() 方法的任何訊息,或提供給 write() 方法的任何文字,寫入到 檔案類物件 *outfp* 中。 *outfp* 必須支援一個接受字串資料的 write 方法。

如果可選引數 *mangle_from_* 為 True,則在正文中任何以確切字串 "From "(即 From 後跟一個空格)開頭的行前面加上一個 > 字元。*mangle_from_* 預設為 *policy* 的 mangle_from_ 設定值(對於 compat32 策略,該值為 True,對於所有其他策略則為 False)。 *mangle_from_* 旨在用於訊息以 Unix mbox 格式儲存的情況(參見 mailboxWHY THE CONTENT-LENGTH FORMAT IS BAD)。

如果 *maxheaderlen* 不為 None,則重新摺疊任何長度超過 *maxheaderlen* 的標頭行;如果為 0,則不重新換行任何標頭。如果 *maxheaderlen* 為 None(預設值),則根據 *policy* 設定來換行標頭和其他訊息行。

如果指定了 *policy*,則使用該策略來控制訊息生成。如果 *policy* 為 None(預設值),則使用傳遞給 flattenMessageEmailMessage 物件關聯的策略來控制訊息生成。有關 *policy* 控制內容的詳細資訊,請參閱 email.policy

在 3.3 版本發生變更: 添加了 *policy* 關鍵字。

在 3.6 版本發生變更: *mangle_from_* 和 *maxheaderlen* 引數的預設行為將遵循策略。

flatten(msg, unixfrom=False, linesep=None)

將以 *msg* 為根的訊息物件結構的文字表示列印到建立 Generator 例項時指定的輸出檔案。

如果 policy 選項 cte_type8bit,則生成訊息時會如同該選項被設定為 7bit 一樣處理。(這是必需的,因為字串無法表示非 ASCII 位元組。)根據需要使用與 ASCII 相容的 Content-Transfer-Encoding 轉換高位設定的位元組。也就是說,將具有非 ASCII Content-Transfer-EncodingContent-Transfer-Encoding: 8bit)的部分轉換為與 ASCII 相容的 Content-Transfer-Encoding,並使用 MIME unknown-8bit 字元集對標頭中不符合 RFC 的非 ASCII 位元組進行編碼,從而使其符合 RFC 標準。

如果 *unixfrom* 為 True,則在根訊息物件的第一個 RFC 5322 標頭之前列印 Unix 郵箱格式使用的信封頭分隔符(見 mailbox)。如果根物件沒有信封頭,則建立一個標準的信封頭。預設值為 False。請注意,對於子部分,從不列印信封頭。

如果 *linesep* 不為 None,則將其用作扁平化訊息所有行之間的分隔符。如果 *linesep* 為 None(預設值),則使用 *policy* 中指定的值。

在 3.2 版本發生變更: 增加了對重新編碼 8bit 訊息正文的支援,以及 *linesep* 引數。

clone(fp)

返回此 Generator 例項的一個獨立克隆,其選項完全相同,並將 *fp* 作為新的 *outfp*。

write(s)

將 *s* 寫入到傳遞給 Generator 建構函式的 *outfp* 的 *write* 方法。這為 Generator 例項提供了足夠的檔案類 API,使其可以在 print() 函式中使用。

為了方便起見,EmailMessage 提供了 as_string()str(aMessage) (也即 __str__()) 方法,這簡化了訊息物件的格式化字串表示的生成。更多詳情請參閱 email.message

email.generator 模組還提供了一個派生類 DecodedGenerator,它類似於 Generator 基類,不同之處在於非 text 部分不會被序列化,而是在輸出流中用一個根據部分資訊填充的模板派生出的字串來表示。

class email.generator.DecodedGenerator(outfp, mangle_from_=None, maxheaderlen=None, fmt=None, *, policy=None)

行為與 Generator 類似,不同之處在於,對於傳遞給 Generator.flatten() 的訊息的任何子部分,如果子部分的主型別是 text,則列印該子部分的解碼後的有效負載;如果主型別不是 text,則不列印它,而是使用該部分的資訊填充字串 *fmt*,並列印填充後的結果字串。

要填充 *fmt*,執行 fmt % part_info,其中 part_info 是一個由以下鍵和值組成的字典:

  • type – 非 text 部分的完整 MIME 型別

  • maintype – 非 text 部分的主 MIME 型別

  • subtype – 非 text 部分的子 MIME 型別

  • filename – 非 text 部分的檔名

  • description – 與非 text 部分關聯的描述

  • encoding – 非 text 部分的內容傳輸編碼

如果 *fmt* 為 None,則使用以下預設的 *fmt*

“[Non-text (%(type)s) part of message omitted, filename %(filename)s]”

可選的 *_mangle_from_* 和 *maxheaderlen* 與 Generator 基類中的相同。

腳註