18.1.2. email.parser
: 電子メールメッセージを解析(パース)する¶
メッセージオブジェクト構造体をつくるには 2つの方法があります。ひとつはまったくのスクラッチから Message
を生成して、これを attach()
と set_payload()
呼び出しを介してつなげていく方法で、もうひとつは電子メールメッセージのフラットなテキスト表現を解析 (parse、パーズ) する方法です。
email
パッケージでは、MIME 文書をふくむ、ほとんどの電子メールの文書構造に対応できる標準的なパーザ (解析器) を提供しています。このパーザに文字列あるいはファイルオブジェクトを渡せば、パーザはそのオブジェクト構造の基底となる (root の) Message
インスタンスを返します。簡単な非MIMEメッセージであれば、この基底オブジェクトのペイロードはたんにメッセージのテキストを格納する文字列になるでしょう。 MIMEメッセージであれば、基底オブジェクトはその is_multipart()
メソッドに対して True
を返します。そして、その各 subpart に get_payload()
メソッドおよび walk()
メソッドを介してアクセスすることができます。
実際には 2つのパーザインターフェイスが使用可能です。ひとつは旧式の Parser
API であり、もうひとつはインクリメンタルな FeedParser
API です。旧式の Parser
API はメッセージ全体のテキストが文字列としてすでにメモリ上にあるか、それがローカルなファイルシステム上に存在しているときには問題ありません。 FeedParser
はメッセージを読み込むときに、そのストリームが入力待ちのためにブロックされるような場合 (ソケットから email メッセージを読み込む時など) に、より有効です。 FeedParser
はインクリメンタルにメッセージを読み込み、解析します。パーザを close したときには根っこ (root) のオブジェクトのみが返されます [1] 。
このパーザは、ある制限された方法で拡張できます。また、もちろん自分でご自分のパーザを完全に無から実装することもできます。 email
パッケージについているパーザと Message
クラスの間に隠された秘密の関係はなにもありませんので、ご自分で実装されたパーザも、それが必要とするやりかたでメッセージオブジェクトツリーを作成することができます。
18.1.2.1. FeedParser API¶
バージョン 2.4 で追加.
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])¶ FeedParser
インスタンスを作成します。オプション引数 _factory には引数なしの callable を指定し、これはつねに新しいメッセージオブジェクトの作成が必要になったときに呼び出されます。デフォルトでは、これはemail.message.Message
クラスになっています。-
feed
(data)¶ FeedParser
にデータを供給します。 data は 1行または複数行からなる文字列を渡します。渡される行は完結していなくてもよく、その場合FeedParser
は部分的な行を適切につなぎ合わせます。文字列中の各行は標準的な 3種類の行末文字 (復帰 CR、改行 LF、または CR+LF) どれかの組み合わせでよく、これらが混在してもかまいません。
-
close
()¶ FeedParser
を close し、それまでに渡されたすべてのデータの解析を完了させ根っこ (root) のメッセージオブジェクトを返します。FeedParser
を close したあとにさらにデータを feed した場合の挙動は未定義です。
-
18.1.2.2. Parser クラス API¶
email.parser
モジュールからインポートされる Parser
クラスは、メッセージを表すテキストが文字列またはファイルの形で完全に使用可能なときメッセージを解析するのに使われる API を提供します。 email.Parser
モジュールはまた、 HeaderParser
と呼ばれる2番目のクラスも提供しています。これはメッセージのヘッダのみを処理したい場合に使うことができ、ずっと高速な処理がおこなえます。なぜならこれはメッセージ本体を解析しようとはしないからです。かわりに、そのペイロードにはメッセージ本体の生の文字列が格納されます。 HeaderParser
クラスは Parser
クラスと同じ API をもっています。
-
class
email.parser.
Parser
([_class])¶ Parser
クラスのコンストラクタです。オプション引数 _class をとることができます。これは呼び出し可能なオブジェクト (関数やクラス) でなければならず、メッセージ内コンポーネント (sub-message object) が作成されるときは常にそのファクトリクラスとして使用されます。デフォルトではこれはMessage
になっています (email.message
参照)。このファクトリクラスは引数なしで呼び出されます。オプション引数 strict は無視されます。
バージョン 2.4 で撤廃:
Parser
は Python 2.4 で新しく導入されたFeedParser
の後方互換性のための API ラッパで、 すべての 解析が事実上 non-strict です。Parser
コンストラクタに strict フラグを渡す必要はありません。バージョン 2.2.2 で変更: strict フラグが追加されました.
バージョン 2.4 で変更: strict フラグは推奨されなくなりました.
それ以外の
Parser
メソッドは以下のとおりです:-
parse
(fp[, headersonly])¶ ファイルなどストリーム形式 (file-like) のオブジェクト fp からすべてのデータを読み込み、得られたテキストを解析して基底 (root) メッセージオブジェクト構造を返します。 fp はストリーム形式のオブジェクトで
readline()
およびread()
両方のメソッドをサポートしている必要があります。fp に格納されているテキスト文字列は、一連の RFC 2822 形式のヘッダおよびヘッダ継続行 (header continuation lines) によって構成されている必要があります。オプションとして、最初にエンペローブヘッダが来ることもできます。ヘッダ部分はデータの終端か、ひとつの空行によって終了したとみなされます。ヘッダ部分に続くデータはメッセージ本体となります (MIME エンコードされた subpart を含んでいるかもしれません)。
オプション引数 headersonly はヘッダを読み終えた後にパースを止めるかを指定するフラグです。デフォルトは
False
で、ファイルの内容全体をパースします。バージョン 2.2.2 で変更: headersonly フラグが追加されました.
-
ファイルや文字列からメッセージオブジェクト構造を作成するのはかなりよくおこなわれる作業なので、便宜上次のような 2つの関数が提供されています。これらは email
パッケージのトップレベルの名前空間で使用できます。
-
email.
message_from_string
(s[, _class[, strict]])¶ 文字列からメッセージオブジェクト構造を作成し返します。これは
Parser().parsestr(s)
とまったく同じです。オプション引数 _class および strict はParser
クラスのコンストラクタと同様に解釈されます。バージョン 2.2.2 で変更: strict フラグが追加されました.
-
email.
message_from_file
(fp[, _class[, strict]])¶ Open されたファイルオブジェクトからメッセージオブジェクト構造を作成し返します。これは
Parser().parse(fp)
とまったく同じです。オプション引数 _class および strict はParser
クラスのコンストラクタと同様に解釈されます。バージョン 2.2.2 で変更: strict フラグが追加されました.
対話的な Python プロンプトでこの関数を使用するとすれば、このようになります:
>>> import email
>>> msg = email.message_from_string(myString)
18.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 では、旧式の Parser は FeedParser によって書き直されました。そのためパーザの意味論と得られる結果は 2 つのパーザで同一のものになります。 |