email.parser: 電子メールメッセージの解析

ソースコード: Lib/email/parser.py


メッセージオブジェクトの構造を作成する方法は 2 つあります。 EmailMessage オブジェクトを作成し、辞書インターフェイスでヘッダを追加し、set_content() や関連メソッドでペイロードを追加して一から組み立てる方法と、シリアライズされた電子メールメッセージを解析する方法です。

email パッケージには、MIME 文書を含むほとんどの電子メール文書の構造を解釈できる標準のパーザがあります。 パーザにバイト列、文字列、またはファイルオブジェクトを渡すと、オブジェクト構造のルートに当たる EmailMessage インスタンスが返されます。 MIME 形式でない単純なメッセージでは、通常、このルートオブジェクトのペイロードはメッセージのテキストを含む文字列になります。 MIME メッセージではルートオブジェクトの is_multipart() メソッドが True を返し、get_body()、iter_parts()、walk() などのペイロード操作用メソッドで各部分にアクセスできます。

利用できるパーザインターフェイスは、Parser API と逐次解析を行う FeedParser API の 2 つです。 Parser API は、メッセージ全体のテキストがメモリ内にある場合や、メッセージ全体がファイルシステム上のファイルに格納されている場合に適しています。 追加の入力を待ってブロックする可能性があるストリームからメッセージを読む場合 (例えばソケットから電子メールメッセージを読む場合) は、FeedParser の方が適しています。 FeedParser はメッセージを少しずつ取り込んで解析でき、パーザを閉じたときに初めてルートオブジェクトを返します。

パーザは限られた範囲で拡張でき、もちろん独自のパーザを一から実装することもできます。 email パッケージに付属するパーザと EmailMessage クラスを結び付けるロジックはすべて Policy クラスにまとめられています。 そのため独自のパーザは、適切な Policy メソッドを独自に実装することで、必要な方法でメッセージオブジェクトのツリーを作成できます。

FeedParser API

email.feedparser モジュールからインポートする BytesFeedParser は、電子メールメッセージを逐次解析するための API を提供します。 これはソケットなど、ブロックする可能性がある入力元から電子メールメッセージのテキストを読む場合に必要になるものです。 BytesFeedParser はもちろん、全体が bytes-like object、文字列、またはファイルに格納されている電子メールメッセージも解析できますが、その場合は BytesParser API の方が便利かもしれません。 この 2 つのパーザ API の意味と解析結果は同じです。

BytesFeedParser API は簡単です。 まずインスタンスをつくり、それに bytes を (渡す bytes がなくなるまで) 流しこみます。 その後パーザを close すると根っこ (root) のメッセージオブジェクトが返されます。 標準に従ったメッセージを解析する場合、 BytesFeedParser は非常に正確であり、標準に従っていないメッセージでもちゃんと動きます。 そのさい、これはメッセージがどのように壊れていると認識されたかについての情報を残します。 これはメッセージオブジェクトの defects 属性にリストとして現れ、メッセージ中に発見された問題が記録されます。 パーザが検出できる障害 (defect) については email.errors モジュールを参照してください。

以下は BytesFeedParser の API です:

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

BytesFeedParser インスタンスを作成します。 オプション引数 _factory は引数を取らない呼び出し可能オブジェクトです。 指定しなければ policy の message_factory を使います。 新しいメッセージオブジェクトが必要になるたびに _factory を呼び出します。

policy を指定した場合、そのルールに従ってメッセージの表現を更新します。 指定しない場合は compat32 ポリシーを使います。 このポリシーは Python 3.2 の email パッケージとの後方互換性を維持し、デフォルトのファクトリとして Message を提供します。 その他のポリシーはすべて、デフォルトの _factory として EmailMessage を提供します。 policy が制御するその他の内容は policy のドキュメントを参照してください。

注意: キーワード引数 policy は 常に指定してください。 将来の Python バージョンでは、デフォルトが email.policy.default に変更されます。

Added in version 3.2.

バージョン 3.3 で変更: キーワード引数 policy が追加されました。

バージョン 3.6 で変更: _factory のデフォルトがポリシーの message_factory になりました。

feed(data)

パーサーにデータを供給します。 data は 1行または複数行からなる bytes-like object を渡します。渡される行は完結していなくてもよく、その場合パーサーは部分的な行を適切につなぎ合わせます。各行は3種類の標準的な行末文字 (復帰 CR、改行 LF、または CR+LF) どれかの組み合わせでよく、これらが混在してもかまいません。

close()

それまでに渡されたすべてのデータの解析を完了し、ルートのメッセージオブジェクトを返します。 このメソッドを呼び出した後で feed() を呼び出した場合の動作は未定義です。

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

Works like BytesFeedParser except that the input to the feed() method must be a string. This is of limited utility, since the only way for such a message to be valid is for it to contain only ASCII text or, if utf8 is True, no binary attachments.

バージョン 3.3 で変更: キーワード引数 policy が追加されました。

Parser API

The BytesParser class, imported from the email.parser module, provides an API that can be used to parse a message when the complete contents of the message are available in a bytes-like object or file. The email.parser module also provides Parser for parsing strings, and header-only parsers, BytesHeaderParser and HeaderParser, which can be used if you're only interested in the headers of the message. BytesHeaderParser and HeaderParser can be much faster in these situations, since they do not attempt to parse the message body, instead setting the payload to the raw body.

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

BytesParser インスタンスを作成します。 _class 引数と policy 引数の意味と動作は、BytesFeedParser の _factory 引数と policy 引数と同じです。

注意: キーワード引数 policy は 常に指定してください。 将来の Python バージョンでは、デフォルトが email.policy.default に変更されます。

バージョン 3.3 で変更: 2.4 で非推奨になった strict 引数の削除。キーワード引数 policy の追加。

バージョン 3.6 で変更: _class のデフォルトがポリシーの message_factory になりました。

parse(fp, headersonly=False)

Read all the data from the binary file-like object fp, parse the resulting bytes, and return the message object. fp must support both the readline() and the read() methods.

The bytes contained in fp must be formatted as a block of RFC 5322 (or, if utf8 is True, RFC 6532) style headers and header continuation lines, optionally preceded by an envelope header. The header block is terminated either by the end of the data or by a blank line. Following the header block is the body of the message (which may contain MIME-encoded subparts, including subparts with a Content-Transfer-Encoding of 8bit).

オプション引数 headersonly はヘッダを読み終えた後にパースを止めるかを指定するフラグです。デフォルトは False で、ファイルの内容全体をパースします。

parsebytes(bytes, headersonly=False)

parse() メソッドと似ていますが、ファイル類似オブジェクトではなく bytes-like object を受け取ります。 bytes-like object に対してこのメソッドを呼び出すことは、bytes を BytesIO インスタンスに包んで parse() を呼び出すことと同じです。

オプション引数 headersonly は parse() メソッドと同じです。

Added in version 3.2.

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

headersonly のデフォルトが True である点を除き、BytesParser とまったく同じです。

Added in version 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)

ファイルなどテキストモードのストリーム形式 (file-like) のオブジェクト fp からすべてのデータを読み込み、得られたテキストを解析して基底 (root) メッセージオブジェクト構造を返します。 fp はストリーム形式のオブジェクトで readline() および read() 両方のメソッドをサポートしている必要があります。

テキストモードが必要な点を除き、このメソッドは BytesParser.parse() と同様に動作します。

parsestr(text, headersonly=False)

parse() メソッドに似ていますが、ファイルなどのストリーム形式のかわりに文字列を引数としてとるところが違います。文字列に対してこのメソッドを呼ぶことは、 text を StringIO インスタンスとして作成して parse() を適用するのと同じです。

オプション引数 headersonly は parse() メソッドと同じです。

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

headersonly のデフォルトが True である点を除き、Parser とまったく同じです。

ファイルや文字列からメッセージオブジェクト構造を作成するのはかなりよくおこなわれる作業なので、便宜上次のような 4つの関数が提供されています。これらは email パッケージのトップレベルの名前空間で使用できます。

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

bytes-like オブジェクト からメッセージオブジェクト構造を作成して返します。これは BytesParser().parsebytes(s) と同じです。オプション引数 _class および policy は BytesParser クラスのコンストラクタと同様に解釈されます。

Added in version 3.2.

バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。

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

オープンされたバイナリ file object からメッセージオブジェクト構造を作成して返します。これは BytesParser().parse(fp) と同じです。 _class および policy は BytesParser クラスのコンストラクタと同様に解釈されます。

Added in version 3.2.

バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。

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

文字列からメッセージオブジェクト構造を作成して返します。これは Parser().parsestr(s) と同じです。 _class および policy は Parser クラスのコンストラクタと同様に解釈されます。

バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。

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

オープンされた file object からメッセージオブジェクト構造を作成して返します。これは Parser().parse(fp) と同じです。 _class および policy は Parser クラスのコンストラクタと同様に解釈されます。

バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。

バージョン 3.6 で変更: _class のデフォルトがポリシーの message_factory になりました。

対話的な Python プロンプトで message_from_bytes() を使用するとすれば、このようになります:

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

追記事項

以下はテキスト解析の際に適用されるいくつかの規約です:

  • Most non-multipart type messages are parsed as a single message object with a string payload. These objects will return False for is_multipart(), and iter_parts() will yield an empty list.

  • All multipart type messages will be parsed as a container message object with a list of sub-message objects for their payload. The outer container message will return True for is_multipart(), and iter_parts() will yield a list of subparts.

  • Most messages with a content type of message/* (such as message/delivery-status and message/rfc822) will also be parsed as container object containing a list payload of length 1. Their is_multipart() method will return True. The single element yielded by iter_parts() will be a sub-message object.

  • いくつかの標準的でないメッセージは、 multipart の使い方に統一がとれていない場合があります。このようなメッセージは Content-Type ヘッダに multipart を指定しているものの、その is_multipart() メソッドは False を返すことがあります。もしこのようなメッセージが FeedParser によって解析されると、その defects 属性のリスト中には MultipartInvariantViolationDefect クラスのインスタンスが現れます。詳しい情報については email.errors を参照してください。