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,該 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 policy,它保持與電子郵件包的 Python 3.2 版本的向後相容性,並提供 Message 作為預設工廠。所有其他 policy 都提供 EmailMessage 作為預設的 _factory。有關 policy 還控制什麼內容的更多資訊,請參見 policy 文件。

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

3.2 版本中新增。

在 3.3 版本中更改:添加了 policy 關鍵字。

在 3.6 版本中更改:_factory 預設為 policy message_factory

feed(data)

向解析器饋送更多資料。data 應該是一個包含一行或多行的位元組類物件。這些行可以是部分的,並且解析器將正確地將這些部分行拼接在一起。這些行可以具有以下三種常見的行結尾:回車符、換行符或回車符和換行符(它們甚至可以混合)。

close()

完成對所有先前饋送的資料的解析,並返回根訊息物件。如果在呼叫此方法後呼叫 feed(),則會發生未定義的情況。

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

其工作方式類似於 BytesFeedParser,區別在於 feed() 方法的輸入必須是字串。它的用途有限,因為只有當訊息僅包含 ASCII 文字,或者當 utf8True 時,不包含二進位制附件,這樣的訊息才是有效的。

在 3.3 版本中更改:添加了 policy 關鍵字。

解析器 API

email.parser 模組匯入的 BytesParser 類提供了一個 API,當訊息的完整內容在 bytes-like 物件或檔案中可用時,可以使用它來解析訊息。 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-like 物件而不是類檔案物件。在 bytes-like 物件上呼叫此方法等效於首先將 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()

可選的 headersonly 引數與 parse() 方法相同。

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 屬性上內部不一致。此類訊息可能具有型別為 multipartContent-Type 標頭,但它們的 is_multipart() 方法可能返回 False。如果使用 FeedParser 解析此類訊息,則它們的 defects 屬性列表中將包含 MultipartInvariantViolationDefect 類的例項。有關詳細資訊,請參閱 email.errors