19.1.2. email.parser
: 電子メールメッセージのパース¶
ソースコード: Lib/email/parser.py
メッセージオブジェクト構造体の作成には 2 つの方法があります。
一つ目は Message
オブジェクトをインスタンス化し、
attach()
と set_payload()
を呼び出しつなぎあわせることで、一から作る方法です。
二つ目は電子メールメッセージのフラットテクスト表現のパースです。
email
パッケージが提供する標準的なパーザ (解析器) は、MIME 文書を含むほとんどの電子メールの文書構造を解釈できます。
パーザに文字列やファイルオブジェクトを渡せば、パーザはそのオブジェクト構造のルート Message
インスタンスを返します。
簡単な非 MIME メッセージの場合、このルートオブジェクトのペイロードはメッセージのテキストを含む文字列になるでしょう。
MIME メッセージであれば、ルートオブジェクトの is_multipart()
メソッドは True
を返します。
ルート下の要素には get_payload()
や walk()
メソッドによってアクセスすることができます。
実際には 2つのパーザインターフェイスが使用可能です。
古典的な Parser
API と増分的な FeedParser
API です。
メッセージのテキスト全体を文字列としてメモリ上に保持している場合や、メッセージ全体がファイルシステム上のファイルにある場合は
古典的な Parser
API が良いです。
入力待ちによるブロックがありえるようなストリームからメッセージを読んでいる場合 (例えば電子メールメッセージをソケットから読み込んでいる場合) は、FeedParser
の方が適切です。
FeedParser
はメッセージを増分的に受け取ってパースします。
パーザを閉じたときはルートオブジェクトのみを返します [1]。
パーザを拡張できる方法は制限されていることに注意してください。
もちろん、自分でパーザを一から実装することはできます。
email
パッケージのバンドルされたパーザと Message
クラスの間には不思議な関係はありませんから、カスタムパーザはそれが必要とするやりかたでメッセージオブジェクトツリーを作成することができます。
19.1.2.1. FeedParser API¶
email.feedparser
モジュールからインポートされる FeedParser
は email メッセージをインクリメンタルに解析するのに向いた API を提供します。これは email メッセージのテキストを (ソケットなどの) 読み込みがブロックされる可能性のある情報源から入力するときに必要となります。もちろん FeedParser
は文字列またはファイルにすべて格納されている email メッセージを解析するのにも使うことができますが、このような場合には旧式の Parser
API のほうが便利かもしれません。これら 2つのパーザ API の意味論と得られる結果は同一です。
FeedParser
API は簡単です。まずインスタンスをつくり、それにテキストを (それ以上テキストが必要なくなるまで) 流しこみます。その後パーザを close すると根っこ (root) のメッセージオブジェクトが返されます。標準に従ったメッセージを解析する場合、 FeedParser
は非常に正確であり、標準に従っていないメッセージでもちゃんと動きます。そのさい、これはメッセージがどのように壊れていると認識されたかについての情報を残します。これはメッセージオブジェクトの defects 属性にリストとして現れ、メッセージ中に発見された問題が記録されます。パーザが検出できる障害 (defect) については email.errors
モジュールを参照してください。
以下は FeedParser
の API です:
-
class
email.parser.
FeedParser
(_factory=email.message.Message, *, policy=policy.compat32)¶ FeedParser
インスタンスを作成します。オプション引数 _factory には引数なしの callable を指定し、これはつねに新しいメッセージオブジェクトの作成が必要になったときに呼び出されます。デフォルトでは、これはemail.message.Message
クラスになっています。policy が指定された場合 (それは
policy
クラスのインスタンスでなければなりません) メッセージの表現を更新するために、ポリシーが指定するルールを用います。もし policy が設定されていなければ、compat32
ポリシーが使われます。このポリシーは、 Python 3.2 バージョンの email パッケージとの後方互換性を維持します。詳細についてはpolicy
ドキュメンテーションを見てください。バージョン 3.3 で変更: キーワード引数 policy が追加されました。
-
feed
(data)¶ FeedParser
にデータを供給します。 data は 1行または複数行からなる文字列を渡します。渡される行は完結していなくてもよく、その場合FeedParser
は部分的な行を適切につなぎ合わせます。文字列中の各行は標準的な 3種類の行末文字 (復帰 CR、改行 LF、または CR+LF) どれかの組み合わせでよく、これらが混在してもかまいません。
-
close
()¶ FeedParser
を close し、それまでに渡されたすべてのデータの解析を完了させ根っこ (root) のメッセージオブジェクトを返します。FeedParser
を close したあとにさらにデータを feed した場合の挙動は未定義です。
-
-
class
email.parser.
BytesFeedParser
(_factory=email.message.Message)¶ feed()
メソッドへの入力が文字列ではなくバイト列でなければならないことを除いてFeedParser
と同等に動作します。バージョン 3.2 で追加.
19.1.2.2. Parser クラス API¶
email.parser
から import される Parser
クラスはメッセージの内容が文字列やファイルで完全な状態のときに、メッセージのパースに利用できる API を提供しています。 email.parser
モジュールはヘッダのみのパーサも提供しています。それは HeaderParser
や BytesHeaderParser
と呼ばれるパーサで、メッセージのヘッダにのみ興味があるときに利用できます。 HeaderParser
と BytesHeaderParser
はそのような状況でより速く動作します、なぜならそれらはメッセージボディのパースを試みる代わりにボディそのものを文字列としてペイロードに格納するからです。これらは Parser
や BytesParser
クラスと同じ API を持っています。
バージョン 3.3 で追加: BytesHeaderParser クラス。
-
class
email.parser.
Parser
(_class=email.message.Message, *, policy=policy.compat32)¶ Parser
クラスのコンストラクタです。オプション引数 _class をとることができます。これは呼び出し可能なオブジェクト (関数やクラス) でなければならず、メッセージ内コンポーネント (sub-message object) が作成されるときは常にそのファクトリクラスとして使用されます。デフォルトではこれはMessage
になっています (email.message
参照)。このファクトリクラスは引数なしで呼び出されます。policy が指定された場合 (それは
policy
クラスのインスタンスでなければなりません) メッセージの表現を更新するために、ポリシーが指定するルールを用います。もし policy が設定されていなければ、compat32
ポリシーが使われます。このポリシーは、 Python 3.2 バージョンの email パッケージとの後方互換性を維持します。詳細についてはpolicy
ドキュメンテーションを見てください。バージョン 3.3 で変更: 2.4 で非推奨になった strict 引数の削除。キーワード引数 policy の追加。
それ以外の
Parser
メソッドは以下のとおりです:-
parse
(fp, headersonly=False)¶ ファイルなどストリーム形式 (file-like) のオブジェクト fp からすべてのデータを読み込み、得られたテキストを解析して基底 (root) メッセージオブジェクト構造を返します。 fp はストリーム形式のオブジェクトで
readline()
およびread()
両方のメソッドをサポートしている必要があります。fp に格納されているテキスト文字列は、一連の RFC 2822 形式のヘッダおよびヘッダ継続行 (header continuation lines) によって構成されている必要があります。オプションとして、最初にエンペローブヘッダが来ることもできます。ヘッダ部分はデータの終端か、ひとつの空行によって終了したとみなされます。ヘッダ部分に続くデータはメッセージ本体となります (MIME エンコードされた subpart を含んでいるかもしれません)。
オプション引数 headersonly はヘッダを読み終えた後にパースを止めるかを指定するフラグです。デフォルトは
False
で、ファイルの内容全体をパースします。
-
-
class
email.parser.
BytesParser
(_class=email.message.Message, *, policy=policy.compat32)¶ このクラスは
Parser
と入力としてバイト列を扱うことを除いて、全く同じです。_class と strict 引数はParser
のコンストラクタと同様に解釈されます。policy が指定された場合 (それは
policy
クラスのインスタンスでなければなりません) メッセージの表現を更新するために、ポリシーが指定するルールを用います。もし policy が設定されていなければ、compat32
ポリシーが使われます。このポリシーは、 Python 3.2 バージョンの email パッケージとの後方互換性を維持します。詳細についてはpolicy
ドキュメンテーションを見てください。バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。
-
parse
(fp, headersonly=False)¶ バイナリ file-like オブジェクト fp からすべてのデータを読み込み、得られたバイト列を解析してメッセージオブジェクト構造を返します。 fp はストリーム形式のオブジェクトで
readline()
およびread()
両方のメソッドをサポートしている必要があります。fp に格納されているバイト列は、一連の RFC 2822 形式のヘッダおよびヘッダ継続行 (header continuation lines) によって構成されている必要があります。オプションとして、最初にエンペローブヘッダが来ることもできます。ヘッダ部分はデータの終端か、ひとつの空行によって終了したとみなされます。ヘッダ部分に続くデータはメッセージ本体となります (Content-Transfer-Encoding が
8bit
の subpart も含めて、 MIME エンコードされた subpart を持っているかもしれません)。オプション引数 headersonly はヘッダを読み終えた後にパースを止めるかを指定するフラグです。デフォルトは
False
で、ファイルの内容全体をパースします。
-
parsebytes
(text, headersonly=False)¶ parse()
メソッドに似ていますが、 file-like オブジェクトの代わりに bytes-like オブジェクト を引数として取るところが違います。このメソッドを呼び出すことは、 text をBytesIO
インスタンスでラップしてからparse()
を呼び出すのと等価です。オプション引数 headersonly は
parse()
メソッドものものと同様です。
バージョン 3.2 で追加.
-
ファイルや文字列からメッセージオブジェクト構造を作成するのはかなりよくおこなわれる作業なので、便宜上次のような 4つの関数が提供されています。これらは email
パッケージのトップレベルの名前空間で使用できます。
-
email.
message_from_string
(s, _class=email.message.Message, *, policy=policy.compat32)¶ 文字列からメッセージオブジェクト構造を作成して返します。これは
Parser().parsestr(s)
と完全に等価です。 _class および policy はParser
クラスのコンストラクタと同様に解釈されます。バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。
-
email.
message_from_bytes
(s, _class=email.message.Message, *, policy=policy.compat32)¶ bytes-like オブジェクト からメッセージオブジェクト構造を作成して返します。これは
BytesParser().parsebytes(s)
と完全に等価です。オプション引数 _class および strict はParser
クラスのコンストラクタと同様に解釈されます。バージョン 3.2 で追加.
バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。
-
email.
message_from_file
(fp, _class=email.message.Message, *, policy=policy.compat32)¶ オープンされた file object からメッセージオブジェクト構造を作成して返します。これは
Parser().parse(fp)
と完全に等価です。 _class および policy はParser
クラスのコンストラクタと同様に解釈されます。バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。
-
email.
message_from_binary_file
(fp, _class=email.message.Message, *, policy=policy.compat32)¶ オープンされたバイナリ file object からメッセージオブジェクト構造を作成して返します。これは
BytesParser().parse(fp)
と完全に等価です。 _class および policy はParser
クラスのコンストラクタと同様に解釈されます。バージョン 3.2 で追加.
バージョン 3.3 で変更: strict 引数の削除。キーワード引数 policy の追加。
対話的な Python プロンプトでこの関数を使用するとすれば、このようになります:
>>> import email
>>> msg = email.message_from_string(myString)
19.1.2.3. 追加事項¶
以下はテキスト解析の際に適用されるいくつかの規約です:
ほとんどの非 multipart 形式のメッセージは単一の文字列ペイロードをもつ単一のメッセージオブジェクトとして解析されます。このオブジェクトは
is_multipart()
に対してFalse
を返します。このオブジェクトに対するget_payload()
メソッドは文字列オブジェクトを返します。multipart 形式のメッセージはすべてメッセージ内コンポーネント (sub-message object) のリストとして解析されます。外側のコンテナメッセージオブジェクトは
is_multipart()
に対してTrue
を返し、このオブジェクトに対するget_payload()
メソッドはMessage
subpart のリストを返します。message/* の Content-Type をもつほとんどのメッセージ (例: message/delivery-status や message/rfc822 など) もコンテナメッセージオブジェクトとして解析されますが、ペイロードのリストの長さは 1 になります。このオブジェクトは
is_multipart()
メソッドに対してTrue
を返し、リスト内にあるひとつだけの要素がメッセージ内のコンポーネントオブジェクトになります。いくつかの標準的でないメッセージは、 multipart の使い方に統一がとれていない場合があります。このようなメッセージは Content-Type ヘッダに multipart を指定しているものの、その
is_multipart()
メソッドはFalse
を返すことがあります。もしこのようなメッセージがFeedParser
によって解析されると、その defects 属性のリスト中にはMultipartInvariantViolationDefect
クラスのインスタンスが現れます。詳しい情報についてはemail.errors
を参照してください。
脚注
[1] | Python 2.4 から導入された email パッケージバージョン 3.0 では、旧式の |