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) どれかの組み合わせでよく、これらが混在してもかまいません。
- class email.parser.FeedParser(_factory=None, *, policy=policy.compat32)¶
BytesFeedParserと同様に動作しますが、feed()メソッドへの入力は文字列でなければなりません。 このようなメッセージが有効となるのは、ASCII テキストのみを含む場合、またはutf8がTrueでバイナリの添付ファイルを含まない場合に限られるため、用途は限定されます。バージョン 3.3 で変更: キーワード引数 policy が追加されました。
Parser API¶
email.parser モジュールからインポートする BytesParser クラスは、メッセージ全体が bytes-like object やファイルに格納されている場合に解析するための API を提供します。
email.parser モジュールには、文字列を解析する Parser と、メッセージのヘッダだけが必要な場合に使えるヘッダ専用パーザ BytesHeaderParser および HeaderParser もあります。
BytesHeaderParser と HeaderParser はメッセージ本体を解析せず、そのままペイロードに設定するため、このような場合には大幅に高速になることがあります。
- 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)¶
バイナリのファイル類似オブジェクト fp からすべてのデータを読み込み、得られたバイト列を解析してメッセージオブジェクトを返します。 fp は
readline()とread()の両方のメソッドをサポートしなければなりません。fp 内のバイト列は、RFC 5322 (または
utf8がTrueの場合は RFC 6532) 形式のヘッダとヘッダの継続行からなるブロックで始まらなければなりません。 その前にエンベロープヘッダがあってもかまいません。 ヘッダブロックはデータの終端または空行で終わります。 ヘッダブロックの後にはメッセージ本体が続きます (本体には、Content-Transfer-Encoding が8bitの部分を含め、MIME エンコードされた部分が含まれていることがあります)。オプション引数 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()と同様に動作します。
- 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
Falseforis_multipart(), anditer_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
Trueforis_multipart(), anditer_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 returnTrue. The single element yielded byiter_parts()will be a sub-message object.いくつかの標準的でないメッセージは、 multipart の使い方に統一がとれていない場合があります。このようなメッセージは Content-Type ヘッダに multipart を指定しているものの、その
is_multipart()メソッドはFalseを返すことがあります。もしこのようなメッセージがFeedParserによって解析されると、その defects 属性のリスト中にはMultipartInvariantViolationDefectクラスのインスタンスが現れます。詳しい情報についてはemail.errorsを参照してください。