email.generator: 生成 MIME 文檔?

源代碼: Lib/email/generator.py


最普通的一種任務(wù)是生成由消息對象結構體表示的電子郵件消息的扁平(序列化)版本。 如果你想通過(guò) smtplib.SMTP.sendmail()nntplib 模塊來(lái)發(fā)送你的消息或是將消息打印到控制臺就將需要這樣做。 接受一個(gè)消息對象結構體并生成其序列化表示就是這些生成器類(lèi)的工作。

email.parser 模塊一樣,你并不會(huì )受限于已捆綁生成器的功能;你可以自己從頭寫(xiě)一個(gè)。 不過(guò),已捆綁生成器知道如何以符合標準的方式來(lái)生成大多數電子郵件,應該能夠很好地處理 MIME 和非 MIME 電子郵件消息,并且被設計為面向字節的解析和生成操作是互逆的,它假定兩者都使用同樣的非轉換型 policy。 也就是說(shuō),通過(guò) BytesParser 類(lèi)來(lái)解析序列化字節流然后再使用 BytesGenerator 來(lái)重新生成序列化字節流應當得到與輸入相同的結果 1。 (而另一方面,在由程序所構造的 EmailMessage 上使用生成器可能導致對默認填入的 EmailMessage 對象的改變。。)

可以使用 Generator 類(lèi)將消息扁平化為文本(而非二進(jìn)制數據)的序列化表示形式,但是由于 Unicode 無(wú)法直接表示二進(jìn)制數據,因此消息有必要被轉換為僅包含 ASCII 字符的數據,這將使用標準電子郵件 RFC 內容傳輸編碼格式技術(shù)來(lái)編碼電子郵件消息以便通過(guò)非 “8 比特位兼容”的信道來(lái)傳輸。

為了適應 SMIME 簽名消息的可重現處理過(guò)程,Generator 禁用了針對 multipart/signed 類(lèi)型的消息部分及所有子部分的標頭折疊。

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

返回一個(gè) BytesGenerator 對象,該對象將把提供給 flatten() 方法的任何消息或者提供給 write() 方法的任何經(jīng)過(guò)代理轉義編碼的文本寫(xiě)入到 file-like object outfp。 outfp 必須支持接受二進(jìn)制數據的 write 方法。

如果可選的 mangle_from_True,則會(huì )將一個(gè) > 字符放到恰好以字符串 "From " 打頭,即開(kāi)頭文本為 From 加一個(gè)空格的的行前面。 mangle_from_ 默認為 policymangle_from_ 設置值 (對于 compat32 策略為 True,對于所有其他策略則為 False)。 mangle_from_ 被設計為在當消息以 unix mbox 格式存儲時(shí)使用 (參見(jiàn) mailboxWHY THE CONTENT-LENGTH FORMAT IS BAD)。

如果 maxheaderlen 不為 None,則重新折疊任何長(cháng)于 maxheaderlen 的標頭行,或者如果為 0,則不重新包裝任何標頭。 如果 manheaderlenNone (默認值),則根據 policy 設置包裝標頭和其他消息行。

如果指定了 policy,則使用該策略來(lái)控制消息的生成。 如果 policyNone (默認值),則使用與傳遞給 flattenMessageEmailMessage 對象相關(guān)聯(lián)的策略來(lái)控制消息的生成。 請參閱 email.policy 了解有關(guān) policy 所控制內容的詳情。

3.2 新版功能.

在 3.3 版更改: 添加了 policy 關(guān)鍵字。

在 3.6 版更改: mangle_from_maxheaderlen 形參的默認行為是遵循策略。

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

將將以 msg 為根的消息對象結構體的文本表示形式打印到創(chuàng )建 BytesGenerator 實(shí)例時(shí)指定的輸出文件。

如果 policy 選項 cte_type8bit (默認值),則會(huì )將未被修改的原始已解析消息中的任何標頭拷貝到輸出,其中會(huì )重新生成與原始數據相同的高比特位組字節數據,并保留具有它們的任何消息體部分的非 ASCII Content-Transfer-Encoding。 如果 cte_type7bit,則會(huì )根據需要使用兼容 ASCII 的 Content-Transfer-Encoding 來(lái)轉換高比特位組字節數據。 也就是說(shuō),將具有非 ASCII Content-Transfer-Encoding (Content-Transfer-Encoding: 8bit) 的部分轉換為兼容 ASCII 的 Content-Transfer-Encoding,并使用 MIME unknown-8bit 字符集來(lái)編碼標頭中不符合 RFC 的非 ASCII 字節數據,以使其符合 RFC。

如果 unixfromTrue,則會(huì )在根消息對象的第一個(gè) RFC 5322 標頭之前打印 Unix mailbox 格式 (參見(jiàn) mailbox) 所使用的封包標頭分隔符。 如果根對象沒(méi)有封包標頭,則會(huì )創(chuàng )建一個(gè)標準標頭。 默認值為 False。 請注意對于子部分來(lái)說(shuō),不會(huì )打印任何封包標頭。

如果 linesep 不為 None,則會(huì )將其用作扁平化消息的所有行之間的分隔符。 如果 linesepNone (默認值),則使用在 policy 中指定的值。

clone(fp)?

返回此 BytesGenerator 實(shí)例的獨立克隆,具有完全相同的選項設置,而 fp 為新的 outfp。

write(s)?

使用 ASCII 編解碼器和 surrogateescape 錯誤處理程序編碼 s,并將其傳遞給傳入到 BytesGenerator 的構造器的 outfpwrite 方法 。

作為一個(gè)便捷工具,EmailMessage 提供了 as_bytes()bytes(aMessage) (即 __bytes__()) 等方法,它們簡(jiǎn)單地生成一個(gè)消息對象的序列化二進(jìn)制表示形式。 更多細節請參閱 email.message。

因為字符串無(wú)法表示二進(jìn)制數據,Generator 類(lèi)必須將任何消息中扁平化的任何二進(jìn)制數據轉換為兼容 ASCII 的格式,具體將其轉換為兼容 ASCII 的 Content-Transfer_Encoding。 使用電子郵件 RFC 的術(shù)語(yǔ),你可以將其視作 Generator 序列化為不 "支持 8 比特" 的 I/O 流。 換句話(huà)說(shuō),大部分應用程序將需要使用 BytesGenerator,而非 Generator。

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

返回一個(gè) Generator,它將把提供給 flatten() 方法的任何消息,或者提供給 write() 方法的任何文本寫(xiě)入到 file-like object outfp。 outfp 必須支持接受字符串數據的 write 方法。

如果可選的 mangle_from_True,則會(huì )將一個(gè) > 字符放到恰好以字符串 "From " 打頭,即開(kāi)頭文本為 From 加一個(gè)空格的的行前面。 mangle_from_ 默認為 policymangle_from_ 設置值 (對于 compat32 策略為 True,對于所有其他策略則為 False)。 mangle_from_ 被設計為在當消息以 unix mbox 格式存儲時(shí)使用 (參見(jiàn) mailboxWHY THE CONTENT-LENGTH FORMAT IS BAD)。

如果 maxheaderlen 不為 None,則重新折疊任何長(cháng)于 maxheaderlen 的標頭行,或者如果為 0,則不重新包裝任何標頭。 如果 manheaderlenNone (默認值),則根據 policy 設置包裝標頭和其他消息行。

如果指定了 policy,則使用該策略來(lái)控制消息的生成。 如果 policyNone (默認值),則使用與傳遞給 flattenMessageEmailMessage 對象相關(guān)聯(lián)的策略來(lái)控制消息的生成。 請參閱 email.policy 了解有關(guān) policy 所控制內容的詳情。

在 3.3 版更改: 添加了 policy 關(guān)鍵字。

在 3.6 版更改: mangle_from_maxheaderlen 形參的默認行為是遵循策略。

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

將以 msg 為根的消息對象結構體的文本表示形式打印到當 Generator 實(shí)例被創(chuàng )建時(shí)所指定的輸出文件。

如果 policy 選項 cte_type8bit,則視同選項被設為 7bit 來(lái)生成消息。 (這是必需的,因為字符串無(wú)法表示非 ASCII 字節數據。) 將使用兼容 ASCII 的 Content-Transfer-Encoding 按需轉換任何具有高比特位組的字節數據。 也就是說(shuō),將具有非 ASCII Content-Transfer-Encoding (Content-Transfer-Encoding: 8bit) 的部分轉換為兼容 ASCII 的 Content-Transfer-Encoding,并使用 MIME unknown-8bit 字符集來(lái)編碼標頭中不符合 RFC 的非 ASCII 字節數據,以使其符合 RFC。

如果 unixfromTrue,則會(huì )在根消息對象的第一個(gè) RFC 5322 標頭之前打印 Unix mailbox 格式 (參見(jiàn) mailbox) 所使用的封包標頭分隔符。 如果根對象沒(méi)有封包標頭,則會(huì )創(chuàng )建一個(gè)標準標頭。 默認值為 False。 請注意對于子部分來(lái)說(shuō),不會(huì )打印任何封包標頭。

如果 linesep 不為 None,則會(huì )將其用作扁平化消息的所有行之間的分隔符。 如果 linesepNone (默認值),則使用在 policy 中指定的值。

在 3.2 版更改: 添加了對重編碼 8bit 消息體的支持,以及 linesep 參數。

clone(fp)?

返回此 Generator 實(shí)例的獨立克隆,具有完全相同的選項設置,而 fp 為新的 outfp。

write(s)?

s 寫(xiě)入到傳給 Generator 的構造器的 outfpwrite 方法。 這足夠為 Generator 實(shí)際提供可用于 print() 函數的文件類(lèi) API。

作為一個(gè)便捷工具,EmailMessage 提供了 as_string()str(aMessage) (即 __str__()) 等方法,它們簡(jiǎn)單地生成一個(gè)消息對象的已格式化字符串表示形式。 更多細節請參閱 email.message。

email.generator 模塊還提供了一個(gè)派生類(lèi) DecodedGenerator,它類(lèi)似于 Generator 基類(lèi),不同之處在于非 text 部分不會(huì )被序列化,而是被表示為 基于模板并填寫(xiě)了有關(guān)該部分的信息的字符串輸出流的形式。

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

行為類(lèi)似于 Generator,不同之處在于對傳給 Generator.flatten() 的消息的任何子部分,如果該子部分的主類(lèi)型為 text,則打印該子部分的已解碼載荷,而如果其主類(lèi)型不為 text,則不直接打印它而是使用來(lái)自該部分的信息填入字符串 fmt 并將填寫(xiě)完成的字符串打印出來(lái)。

要填入 fmt,則執行 fmt % part_info,其中 part_info 是由下列鍵和值組成的字典:

  • type -- 非 text 部分的完整 MIME 類(lèi)型

  • maintype -- 非 text 部分的主 MIME 類(lèi)型

  • subtype -- 非 text 部分的子 MIME 類(lèi)型

  • filename -- 非 text 部分的文件名

  • description -- 與非 text 部分相關(guān)聯(lián)的描述

  • encoding -- 非 text 部分的內容轉換編碼格式

如果 fmtNone,則使用下列默認 fmt:

"[忽略消息的非文本 (%(type)s) 部分,文件名 %(filename)s]"

可選的 _mangle_from_maxheaderlenGenerator 基類(lèi)的相同。

備注

1

此語(yǔ)句假定你使用了正確的 unixfrom 設置,并且沒(méi)有用于自動(dòng)調整的 policy 設置調用(例如 refold_source 必須為 none,這 不是 默認值)。 這也不是 100% 為真,因為如果消息不遵循 RFC 標準則有時(shí)實(shí)際原始文本的信息會(huì )在解析錯誤恢復時(shí)丟失。 它的目標是在可能的情況下修復這些后續邊緣情況。