email.parser:解析電子郵件訊息

原始碼: Lib/email/parser.py


訊息物件結構可以透過兩種方式建立:可以透過建立一個 EmailMessage 物件,使用字典介面新增標頭,並使用 set_content() 及相關方法新增有效載荷來從頭建立;也可以透過解析電子郵件訊息的序列化表示來建立。

email 包提供了一個標準解析器,可以理解大多數電子郵件文件結構,包括 MIME 文件。你可以向解析器傳遞一個位元組串、字串或檔案物件,解析器將返回物件結構的根 EmailMessage 例項。對於簡單的非 MIME 訊息,此根物件的有效載荷可能是一個包含訊息文字的字串。對於 MIME 訊息,根物件的 is_multipart() 方法將返回 True,並且可以透過有效載荷操作方法(如 get_body()iter_parts()walk())訪問其子部分。

實際上有兩種解析器介面可供使用:Parser API 和增量式的 FeedParser API。Parser API 在你已將訊息的全部文字載入到記憶體中,或者整個訊息存在於檔案系統上的檔案中時最為有用。FeedParser 更適用於從可能因等待更多輸入而阻塞的流中讀取訊息(例如從套接字讀取電子郵件訊息)。FeedParser 可以增量地消費和解析訊息,並且只有在關閉解析器時才返回根物件。

請注意,解析器可以在有限的範圍內進行擴充套件,當然你也可以完全從頭開始實現自己的解析器。所有連線 email 包的內建解析器和 EmailMessage 類的邏輯都體現在 Policy 類中,因此自定義解析器可以透過實現相應 Policy 方法的自定義版本,以其認為必要的任何方式建立訊息物件樹。

FeedParser API

email.feedparser 模組匯入的 BytesFeedParser 提供了一個有助於增量解析電子郵件訊息的 API,例如在從可能阻塞的源(如套接字)讀取電子郵件訊息文字時所必需的。當然,BytesFeedParser 也可以用於解析完全包含在類位元組物件、字串或檔案中的電子郵件訊息,但對於此類用例,BytesParser API 可能更方便。這兩種解析器 API 的語義和結果是相同的。

BytesFeedParser 的 API 很簡單;你建立一個例項,向其輸入位元組資料直到沒有更多資料可輸入,然後關閉解析器以檢索根訊息物件。在解析符合標準的訊息時,BytesFeedParser 非常準確,並且在解析不符合標準的訊息方面也做得很好,會提供有關訊息如何被判定為損壞的資訊。它會將訊息中發現的任何問題列表填充到訊息物件的 defects 屬性中。請參閱 email.errors 模組以獲取它能發現的缺陷列表。

以下是 BytesFeedParser 的 API:

class email.parser.BytesFeedParser(_factory=None, *, policy=policy.compat32)

建立一個 BytesFeedParser 例項。可選的 _factory 是一個無引數的可呼叫物件;如果未指定,則使用 policymessage_factory。每當需要新的訊息物件時,就會呼叫 _factory

如果指定了 policy,則使用它指定的規則來更新訊息的表示。如果未設定 policy,則使用 compat32 策略,該策略保持與 Python 3.2 版本的 email 包的向後相容性,並提供 Message 作為預設工廠。所有其他策略都提供 EmailMessage 作為預設的 _factory。有關 policy 控制的其他內容的更多資訊,請參閱 policy 文件。

注意:應始終指定 policy 關鍵字;在 Python 的未來版本中,預設值將更改為 email.policy.default

在 3.2 版本加入。

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

在 3.6 版本發生變更: _factory 預設為策略的 message_factory

feed(data)

向解析器輸入更多資料。data 應為一個包含一行或多行文字的類位元組物件。這些行可以是部分的,解析器會正確地將這些部分行拼接起來。這些行可以有三種常見的行尾符:回車、換行或回車加換行(它們甚至可以混合使用)。

close()

完成對所有先前輸入資料的解析,並返回根訊息物件。在此方法被呼叫後,如果再呼叫 feed(),其行為是未定義的。

class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)

工作方式與 BytesFeedParser 類似,但 feed() 方法的輸入必須是字串。這個類的用途有限,因為要使這樣的訊息有效,它要麼只能包含 ASCII 文字,要麼在 utf8True 的情況下,不包含二進位制附件。

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

Parser API

email.parser 模組匯入的 BytesParser 類提供了一個 API,當訊息的全部內容都可在一個類位元組物件或檔案中獲取時,可以用它來解析訊息。email.parser 模組還提供了用於解析字串的 Parser,以及只解析標頭的解析器 BytesHeaderParserHeaderParser,如果你只對訊息的標頭感興趣,可以使用它們。在這些情況下,BytesHeaderParserHeaderParser 可以快得多,因為它們不嘗試解析訊息正文,而是將有效載荷設定為原始正文。

class email.parser.BytesParser(_class=None, *, policy=policy.compat32)

建立一個 BytesParser 例項。_classpolicy 引數的含義和語義與 BytesFeedParser_factorypolicy 引數相同。

注意:應始終指定 policy 關鍵字;在 Python 的未來版本中,預設值將更改為 email.policy.default

在 3.3 版本發生變更: 移除了在 2.4 版本中已棄用的 strict 引數。添加了 policy 關鍵字。

在 3.6 版本發生變更: _class 預設為策略的 message_factory

parse(fp, headersonly=False)

從二進位制類檔案物件 fp 中讀取所有資料,解析得到的位元組串,並返回訊息物件。fp 必須同時支援 readline()read() 方法。

fp 中包含的位元組必須格式化為一個 RFC 5322(或者,如果 utf8True,則為 RFC 6532)風格的標頭和標頭續行塊,前面可以選擇性地帶有一個信封標頭。標頭塊以資料末尾或一個空行結束。標頭塊之後是訊息的正文(可能包含 MIME 編碼的子部分,包括 Content-Transfer-Encoding8bit 的子部分)。

可選的 headersonly 是一個標誌,指定是否在讀取標頭後停止解析。預設為 False,表示解析檔案的全部內容。

parsebytes(bytes, headersonly=False)

parse() 方法類似,但它接受一個類位元組物件而不是一個類檔案物件。對一個類位元組物件呼叫此方法,等同於先將 bytes 包裝在 BytesIO 例項中,然後呼叫 parse()

可選的 headersonlyparse() 方法中的一樣。

在 3.2 版本加入。

class email.parser.BytesHeaderParser(_class=None, *, policy=policy.compat32)

BytesParser 完全相同,只是 headersonly 預設為 True

在 3.3 版本加入。

class email.parser.Parser(_class=None, *, policy=policy.compat32)

這個類與 BytesParser 並行,但處理字串輸入。

在 3.3 版本發生變更: 移除了 strict 引數。添加了 policy 關鍵字。

在 3.6 版本發生變更: _class 預設為策略的 message_factory

parse(fp, headersonly=False)

從文字模式的類檔案物件 fp 中讀取所有資料,解析得到的文字,並返回根訊息物件。fp 必須同時支援類檔案物件的 readline()read() 方法。

除了文字模式的要求外,此方法的操作方式與 BytesParser.parse() 類似。

parsestr(text, headersonly=False)

parse() 方法類似,但它接受一個字串物件而不是一個類檔案物件。對一個字串呼叫此方法,等同於先將 text 包裝在 StringIO 例項中,然後呼叫 parse()

可選的 headersonlyparse() 方法中的一樣。

class email.parser.HeaderParser(_class=None, *, policy=policy.compat32)

Parser 完全相同,只是 headersonly 預設為 True

由於從字串或檔案物件建立訊息物件結構是一項非常常見的任務,因此提供了四個函式以方便使用。它們在頂級的 email 包名稱空間中可用。

email.message_from_bytes(s, _class=None, *, policy=policy.compat32)

類位元組物件返回一個訊息物件結構。這等同於 BytesParser().parsebytes(s)。可選的 _classpolicy 的解釋與 BytesParser 類的建構函式一樣。

在 3.2 版本加入。

在 3.3 版本發生變更: 移除了 strict 引數。添加了 policy 關鍵字。

email.message_from_binary_file(fp, _class=None, *, policy=policy.compat32)

從一個開啟的二進位制檔案物件返回一個訊息物件結構樹。這等同於 BytesParser().parse(fp)_classpolicy 的解釋與 BytesParser 類的建構函式一樣。

在 3.2 版本加入。

在 3.3 版本發生變更: 移除了 strict 引數。添加了 policy 關鍵字。

email.message_from_string(s, _class=None, *, policy=policy.compat32)

從字串返回一個訊息物件結構。這等同於 Parser().parsestr(s)_classpolicy 的解釋與 Parser 類的建構函式一樣。

在 3.3 版本發生變更: 移除了 strict 引數。添加了 policy 關鍵字。

email.message_from_file(fp, _class=None, *, policy=policy.compat32)

從一個開啟的檔案物件返回一個訊息物件結構樹。這等同於 Parser().parse(fp)_classpolicy 的解釋與 Parser 類的建構函式一樣。

在 3.3 版本發生變更: 移除了 strict 引數。添加了 policy 關鍵字。

在 3.6 版本發生變更: _class 預設為策略的 message_factory

以下是在 Python 互動式提示符下如何使用 message_from_bytes() 的示例:

>>> import email
>>> msg = email.message_from_bytes(myBytes)

附加說明

以下是關於解析語義的一些說明:

  • 大多數非 multipart 型別的訊息被解析為帶有一個字串有效載荷的單個訊息物件。這些物件的 is_multipart() 會返回 False,而 iter_parts() 將產生一個空列表。

  • 所有 multipart 型別的訊息將被解析為一個容器訊息物件,其有效載荷為子訊息物件的列表。外部容器訊息的 is_multipart() 將返回 True,而 iter_parts() 將產生一個子部分列表。

  • 大多數內容型別為 message/* 的訊息(例如 message/delivery-statusmessage/rfc822)也將被解析為包含一個長度為 1 的列表有效載荷的容器物件。它們的 is_multipart() 方法將返回 Trueiter_parts() 產生的單個元素將是一個子訊息物件。

  • 一些不符合標準的訊息可能在其 multipart-edness(多部分性)上內部不一致。此類訊息可能有一個型別為 multipartContent-Type 標頭,但其 is_multipart() 方法可能返回 False。如果此類訊息是使用 FeedParser 解析的,它們的 defects 屬性列表中將包含一個 MultipartInvariantViolationDefect 類的例項。有關詳細資訊,請參閱 email.errors