email.message.Message: compat32 API を使用した電子メールメッセージの表現

Message クラスは EmailMessage クラスによく似ていますが、後者で追加されたメソッドはなく、一部の他のメソッドでもデフォルトの動作が少し異なります。 ここでは、EmailMessage クラスでもサポートされているものの、従来のコードを扱う場合以外には推奨されないメソッドも説明します。

それ以外の点では、両クラスの設計思想と構造は同じです。

このドキュメントは、Message のデフォルトのポリシーである Compat32 での動作を説明します。 別のポリシーを使う場合は、代わりに EmailMessage クラスを使ってください。

電子メールメッセージは ヘッダー と ペイロード からなります。 ヘッダーの名前と値は RFC 5322 の形式に従い、フィールド名と値をコロンで区切る必要があります。 コロンはフィールド名にも値にも含まれません。 ペイロードには、単純なテキストメッセージ、バイナリオブジェクト、または各々が独自のヘッダーとペイロードを持つサブメッセージを構造化して並べたものを使えます。 最後の形式のペイロードは、メッセージの MIME 型が multipart/* や message/rfc822 などの場合に使われます。

Message オブジェクトは概念的にはヘッダーの順序付き辞書であり、ヘッダーの特定の情報やペイロードへのアクセス、メッセージの直列化、オブジェクトツリーの再帰的な巡回のためのメソッドが追加されています。 同名のヘッダーを複数持てますが、それらへのアクセスには専用のメソッドが必要です。

Message は辞書に似たインターフェースを持ち、ASCII 値でなければならないヘッダー名をキーとします。 辞書の値は文字列で、ASCII 文字だけを含むことを想定しています。 非 ASCII 入力には特別な処理がありますが、常に正しい結果になるとは限りません。 ヘッダーの格納時と取得時には大文字・小文字が保持されますが、フィールド名の照合では区別されません。 Unix-From ヘッダーまたは From_ ヘッダーとも呼ばれるエンベロープヘッダーを一つ持つこともできます。 ペイロード は、単純なメッセージオブジェクトでは文字列またはバイト列であり、MIME コンテナ文書 (multipart/* や message/rfc822 など) では Message オブジェクトのリストです。

Message クラスのメソッドは以下のとおりです:

class email.message.Message(policy=compat32)

policy を指定した場合 (policy のクラスのインスタンスでなければなりません)、その規則に従ってメッセージの表現を更新し、直列化します。 policy を指定しない場合、Python 3.2 版の email パッケージとの後方互換性を維持する compat32 ポリシーを使います。 詳しくは policy のドキュメントを参照してください。

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

as_string(unixfrom=False, maxheaderlen=0, policy=None)

メッセージ全体をフラット化した文字列を返します。 オプションの unixfrom が真の場合、戻り値にはエンベロープヘッダーが含まれます。 unixfrom のデフォルトは False です。 後方互換性のため maxheaderlen のデフォルトは 0 なので、別の値を使うには明示的に指定する必要があります (このメソッドはポリシーの max_line_length を無視します)。 policy 引数で、メッセージインスタンスから取得するデフォルトのポリシーを上書きできます。 指定した policy は Generator に渡されるため、メソッドが生成する書式の一部を制御できます。

もし、文字列への変換を完全に行うためにデフォルト値を埋める必要がある場合、メッセージのフラット化は Message の変更を引き起こす可能性があります (例えば、MIME の境界が生成される、変更される等)。

このメソッドは便利な補助機能として提供されており、常に希望どおりの書式になるとは限りません。 例えば、デフォルトでは Unix mbox 形式に必要な、From で始まる行の書き換えを行いません。 より柔軟に制御するには、Generator のインスタンスを作成し、その flatten() メソッドを直接使ってください。 例えば次のようにします。

from io import StringIO
from email.generator import Generator
fp = StringIO()
g = Generator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

メッセージオブジェクトに RFC の規定どおりにエンコードされていないバイナリデータが含まれる場合、そのデータは Unicode の「不明な文字」を示すコードポイントに置き換えられます。 (as_bytes() と BytesGenerator も参照してください。)

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

__str__()

as_string() と同じです。 str(msg) で、書式化されたメッセージを含む文字列を生成できるようにします。

as_bytes(unixfrom=False, policy=None)

メッセージ全体をフラット化した bytes オブジェクトを返します。 オプションの unixfrom が真の場合、戻り値にはエンベロープヘッダーが含まれます。 unixfrom のデフォルトは False です。 policy 引数で、メッセージインスタンスから取得するデフォルトのポリシーを上書きできます。 指定した policy は BytesGenerator に渡されるため、メソッドが生成する書式の一部を制御できます。

もし、文字列への変換を完全に行うためにデフォルト値を埋める必要がある場合、メッセージのフラット化は Message の変更を引き起こす可能性があります (例えば、MIME の境界が生成される、変更される等)。

このメソッドは便利な補助機能として提供されており、常に希望どおりの書式になるとは限りません。 例えば、デフォルトでは Unix mbox 形式に必要な、From で始まる行の書き換えを行いません。 より柔軟に制御するには、BytesGenerator のインスタンスを作成し、その flatten() メソッドを直接使ってください。 例えば次のようにします。

from io import BytesIO
from email.generator import BytesGenerator
fp = BytesIO()
g = BytesGenerator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

Added in version 3.4.

__bytes__()

as_bytes() と同じです。 bytes(msg) で、書式化されたメッセージを含む bytes オブジェクトを生成できるようにします。

Added in version 3.4.

is_multipart()

メッセージのペイロードがサブメッセージの Message オブジェクトのリストなら True を、それ以外なら False を返します。 is_multipart() が False を返す場合、ペイロードは文字列オブジェクトのはずです (CTE でエンコードされたバイナリのペイロードの場合もあります)。 is_multipart() が True を返しても、msg.get_content_maintype() == 'multipart' が True を返すとは限りません。 例えば、Message の型が message/rfc822 の場合も is_multipart() は True を返します。

set_unixfrom(unixfrom)

メッセージのエンベロープヘッダを unixfrom に設定します。これは文字列でなければなりません。

get_unixfrom()

メッセージのエンベロープヘッダを返します。エンベロープヘッダが設定されていない場合は None が返されます。

attach(payload)

与えられた payload を現在のペイロードに追加します。この時点でのペイロードは None か、あるいは Message オブジェクトのリストである必要があります。このメソッドの実行後、ペイロードは必ず Message オブジェクトのリストになります。ペイロードにスカラーオブジェクト (文字列など) を格納したい場合は、かわりに set_payload() を使ってください。

これは従来の API のメソッドです。 EmailMessage クラスでは、set_content() と関連する make および add メソッドがこの機能を置き換えています。

get_payload(i=None, decode=False)

現在のペイロードへの参照を返します。これは is_multipart() が True の場合 Message オブジェクトのリストになり、 is_multipart() が False の場合は文字列になります。ペイロードがリストの場合、リストを変更することはそのメッセージのペイロードを変更することになります。

オプション引数の i がある場合、 is_multipart() が True ならば get_payload() はペイロード中で 0 から数えて i 番目の要素を返します。 i が 0 より小さい場合、あるいはペイロードの個数以上の場合は IndexError が発生します。ペイロードが文字列 (つまり is_multipart() が False) にもかかわらず i が与えられたときは TypeError が発生します。

オプションの decode は、Content-Transfer-Encoding ヘッダーに従ってペイロードをデコードするかどうかを指定するフラグです。 True で、メッセージがマルチパートでない場合、このヘッダーの値が quoted-printable または base64 ならペイロードをデコードします。 別のエンコーディングを使っている場合や Content-Transfer-Encoding ヘッダーがない場合は、ペイロードをデコードせずそのまま返します。 いずれの場合も戻り値はバイナリデータです。 メッセージがマルチパートで decode が True の場合は None を返します。 base64 のペイロードにパディングの欠落や base64 の文字集合にない文字がある場合は、それぞれ InvalidBase64PaddingDefect または InvalidBase64CharactersDefect がメッセージの欠陥を記録するプロパティに追加されます。

decode が False (デフォルト) の場合、Content-Transfer-Encoding をデコードせず、本体を文字列として返します。 ただし、Content-Transfer-Encoding が 8bit の場合は、Content-Type ヘッダーで指定された charset と replace エラーハンドラーを使って、元のバイト列のデコードを試みます。 charset が指定されていない場合、または email パッケージが認識できない場合は、デフォルトの ASCII 文字セットで本体をデコードします。

これは従来の API のメソッドです。 EmailMessage クラスでは、get_content() と iter_parts() がこの機能を置き換えています。

set_payload(payload, charset=None)

メッセージオブジェクトのペイロード全体を payload に設定します。 ペイロードが満たすべき条件を維持する責任は呼び出し側にあります。 省略可能な charset はメッセージのデフォルトの文字セットを設定します。 詳しくは set_charset() を参照してください。

これは従来の API のメソッドです。 EmailMessage クラスでは、set_content() がこの機能を置き換えています。

set_charset(charset)

ペイロードの文字セットを charset に変更します。これは Charset インスタンス (email.charset 参照)、文字セット名を表す文字列、あるいは None のいずれかです。文字列を指定した場合は Charset インスタンスに変換されます。 charset が None の場合、 charset 引数は Content-Type ヘッダから除去されます (それ以外にメッセージは変更されません)。これら以外のものを文字セットとして指定した場合、 TypeError を送出します。

MIME-Version ヘッダが存在しなければ、追加されます。 Content-Type ヘッダが存在しなければ、 text/plain を値として追加されます。 Content-Type が存在していてもいなくても、 charset パラメタは charset.output_charset に設定されます。 charset.input_charset と charset.output_charset が異なるなら、ペイロードは output_charset に再エンコードされます。 Content-Transfer-Encoding ヘッダが存在しなければ、ペイロードは、必要なら指定された Charset を使って transfer エンコードされ、適切な値のヘッダが追加されます。 Content-Transfer-Encoding ヘッダがすでに存在すれば、ペイロードはすでにその Content-Transfer-Encoding によって正しくエンコードされたものと見なされ、変形されません。

これは従来の API のメソッドです。 EmailMessage クラスでは、email.message.EmailMessage.set_content() メソッドの charset 引数がこの機能を置き換えています。

get_charset()

そのメッセージ中のペイロードの Charset インスタンスを返します。

これは従来の API のメソッドです。 EmailMessage クラスでは常に None を返します。

以下のメソッドは、メッセージの RFC 2822 ヘッダにアクセスするためのマップ (辞書) 形式のインタフェイスを実装したものです。これらのメソッドと、通常のマップ (辞書) 型はまったく同じ意味をもつわけではないことに注意してください。たとえば辞書型では、同じキーが複数あることは許されていませんが、ここでは同じメッセージヘッダが複数ある場合があります。また、辞書型では keys() で返されるキーの順序は保証されていませんが、 Message オブジェクト内のヘッダはつねに元のメッセージ中に現れた順序、あるいはそのあとに追加された順序で返されます。削除され、その後ふたたび追加されたヘッダはリストの一番最後に現れます。

こういった意味のちがいは意図的なもので、最大の利便性をもつようにつくられています。

注意: どんな場合も、メッセージ中のエンベロープヘッダはこのマップ形式のインタフェイスには含まれません。

バイト列から生成されたモデルでは、RFC に反して非 ASCII バイトを含むヘッダー値をこのインターフェースから取得すると、文字セットが unknown-8bit の Header オブジェクトとして返されます。

__len__()

複製されたものもふくめてヘッダ数の合計を返します。

__contains__(name)

メッセージオブジェクトが name という名前のフィールドを持っていれば True を返します。この検査では名前の大文字小文字は区別されません。name は最後にコロンをふくんでいてはいけません。このメソッドは以下のように in 演算子で使われます:

if 'message-id' in myMessage:
   print('Message-ID:', myMessage['message-id'])
__getitem__(name)

指定された名前のヘッダフィールドの値を返します。 name は最後にコロンをふくんでいてはいけません。そのヘッダがない場合は None が返され、 KeyError 例外は発生しません。

注意: 指定された名前のフィールドがメッセージのヘッダに2回以上現れている場合、どちらの値が返されるかは未定義です。ヘッダに存在するフィールドの値をすべて取り出したい場合は get_all() メソッドを使ってください。

__setitem__(name, val)

メッセージヘッダに name という名前の val という値をもつフィールドをあらたに追加します。このフィールドは現在メッセージに存在するフィールドのいちばん後に追加されます。

注意: このメソッドでは、すでに同一の名前で存在するフィールドは上書き されません。もしメッセージが名前 name をもつフィールドをひとつしか持たないようにしたければ、最初にそれを除去してください。たとえば:

del msg['subject']
msg['subject'] = 'Python roolz!'
__delitem__(name)

メッセージのヘッダから、name という名前をもつフィールドをすべて除去します。たとえこの名前をもつヘッダが存在していなくても例外は発生しません。

keys()

メッセージ中にあるすべてのヘッダのフィールド名のリストを返します。

values()

メッセージ中にあるすべてのフィールドの値のリストを返します。

items()

メッセージ中にあるすべてのヘッダのフィールド名とその値を 2-タプルのリストとして返します。

get(name, failobj=None)

指定した名前のヘッダーフィールドの値を返します。 __getitem__() と同じですが、ヘッダーがない場合にオプションの failobj (デフォルトは None) を返す点が異なります。

さらに、役に立つメソッドをいくつか紹介します:

get_all(name, failobj=None)

name の名前をもつフィールドのすべての値からなるリストを返します。該当する名前のヘッダがメッセージ中に含まれていない場合は failobj (デフォルトでは None) が返されます。

add_header(_name, _value, **_params)

拡張ヘッダ設定。 このメソッドは __setitem__() と似ていますが、追加のヘッダ・パラメータをキーワード引数で指定できるところが違っています。 _name に追加するヘッダフィールドを、 _value にそのヘッダの 主たる 値を渡します。

キーワード引数辞書 _params の各項目ごとに、そのキーがパラメータ名として扱われ、キー名にふくまれるアンダースコアはハイフンに置換されます (アンダースコアは、Python 識別子としてハイフンを使えないための代替です)。ふつう、パラメータの値が None 以外のときは、 key="value" の形で追加されます。パラメータの値が None のときはキーのみが追加されます。値が非 ASCII 文字を含むなら、それは (CHARSET, LANGUAGE, VALUE) の形式の 3 タプルにすることが出来ます。ここで CHARSET はその値をエンコードするのに使われる文字セットを指示する文字列で、 LANGUAGE は通常 None か空文字列にでき (これら以外で指定出来るものについては RFC 2231 を参照してください)、 VALUE は非 ASCII コードポイントを含む文字列値です。この 3 タプルではなく非 ASCII 文字を含む値が渡された場合は、 CHARSET に utf-8 、 LANGUAGE に None を使って RFC 2231 形式に自動的にエンコードされます。

以下はこの使用例です:

msg.add_header('Content-Disposition', 'attachment', filename='bud.gif')

こうするとヘッダには以下のように追加されます

Content-Disposition: attachment; filename="bud.gif"

非 ASCII 文字を使った例:

msg.add_header('Content-Disposition', 'attachment',
               filename=('iso-8859-1', '', 'Fußballer.ppt'))

は、以下のようになります

Content-Disposition: attachment; filename*="iso-8859-1''Fu%DFballer.ppt"
replace_header(_name, _value)

ヘッダの置換。 _name と一致するヘッダで最初に見つかったものを置き換えます。このときヘッダの順序とフィールド名の大文字小文字は保存されます。一致するヘッダがない場合、 KeyError が発生します。

get_content_type()

そのメッセージの content-type を返します。返された文字列は強制的に小文字で maintype/subtype の形式に変換されます。メッセージ中に Content-Type ヘッダがない場合、デフォルトの content-type は get_default_type() が返す値によって与えられます。 RFC 2045 によればメッセージはつねにデフォルトの content-type をもっているので、 get_content_type() はつねになんらかの値を返すはずです。

RFC 2045 はメッセージのデフォルト content-type を、それが multipart/digest コンテナに現れているとき以外は text/plain に規定しています。あるメッセージが multipart/digest コンテナ中にある場合、その content-type は message/rfc822 になります。もし Content-Type ヘッダが適切でない content-type 書式だった場合、 RFC 2045 はそれのデフォルトを text/plain として扱うよう定めています。

get_content_maintype()

そのメッセージの主 content-type を返します。これは get_content_type() によって返される文字列の maintype 部分です。

get_content_subtype()

そのメッセージの副 content-type (sub content-type、subtype) を返します。これは get_content_type() によって返される文字列の subtype 部分です。

get_default_type()

デフォルトの content-type を返します。ほどんどのメッセージではデフォルトの content-type は text/plain ですが、メッセージが multipart/digest コンテナに含まれているときだけ例外的に message/rfc822 になります。

set_default_type(ctype)

デフォルトの content-type を設定します。 ctype は text/plain あるいは message/rfc822 である必要がありますが、強制ではありません。デフォルトの content-type はヘッダの Content-Type には格納されません。

get_params(failobj=None, header='content-type', unquote=True)

メッセージの Content-Type パラメータをリストとして返します。返されるリストはキー/値の組からなる2要素タプルが連なったものであり、これらは '=' 記号で分離されています。 '=' の左側はキーになり、右側は値になります。パラメータ中に '=' がなかった場合、値の部分は空文字列になり、そうでなければその値は get_param() で説明されている形式になります。また、オプション引数 unquote が True (デフォルト) である場合、この値は unquote されます。

オプション引数 failobj は、 Content-Type ヘッダが存在しなかった場合に返すオブジェクトです。オプション引数 header には Content-Type のかわりに検索すべきヘッダを指定します。

これは従来の API のメソッドです。 EmailMessage クラスでは、ヘッダーへのアクセス用メソッドが返す個々のヘッダーオブジェクトの params プロパティがこの機能を置き換えています。

get_param(param, failobj=None, header='content-type', unquote=True)

Content-Type ヘッダーのパラメータ param の値を文字列で返します。 メッセージに Content-Type ヘッダーがない場合、または指定されたパラメータがない場合は failobj (デフォルトは None) を返します。

オプション引数 header が与えられた場合、 Content-Type のかわりにそのヘッダが使用されます。

パラメータのキー比較は常に大文字小文字を区別しません。 返り値は文字列か 3 要素のタプルで、タプルになるのはパラメータが RFC 2231 エンコードされている場合です。 3 要素タプルの場合、各要素の値は (CHARSET, LANGUAGE, VALUE) の形式になっています。 CHARSET と LANGUAGE は None になることがあり、その場合 VALUE は us-ascii 文字セットでエンコードされているとみなさなければならないので注意してください。 普段は LANGUAGE を無視できます。

この関数を使うアプリケーションが、パラメータが RFC 2231 形式でエンコードされているかどうかを気にしないのであれば、 email.utils.collapse_rfc2231_value() に get_param() の返り値を渡して呼び出すことで、このパラメータをひとつにまとめることができます。この値がタプルならばこの関数は適切にデコードされた Unicode 文字列を返し、そうでない場合は unquote された元の文字列を返します。たとえば:

rawparam = msg.get_param('foo')
param = email.utils.collapse_rfc2231_value(rawparam)

いずれの場合もパラメータの値は (文字列であれ3要素タプルの VALUE 項目であれ) つねに unquote されます。ただし、unquote が False に指定されている場合は unquote されません。

これは従来の API のメソッドです。 EmailMessage クラスでは、ヘッダーへのアクセス用メソッドが返す個々のヘッダーオブジェクトの params プロパティがこの機能を置き換えています。

set_param(param, value, header='Content-Type', requote=True, charset=None, language='', replace=False)

Content-Type ヘッダ中のパラメータを設定します。指定されたパラメータがヘッダ中にすでに存在する場合、その値は value に置き換えられます。 Content-Type ヘッダがまだこのメッセージ中に存在していない場合、 RFC 2045 にしたがいこの値には text/plain が設定され、新しいパラメータ値が末尾に追加されます。

オプションの header は、Content-Type の代わりに使うヘッダーを指定します。 オプションの requote が False でない限り、すべてのパラメータは必要に応じて引用符で囲まれます (requote のデフォルトは True です)。

オプション引数 charset が与えられると、そのパラメータは RFC 2231 に従ってエンコードされます。オプション引数 language は RFC 2231 の言語を指定しますが、デフォルトではこれは空文字列となります。 charset と language はどちらも文字列である必要があります。

replace が False (デフォルト) の場合、ヘッダーはヘッダー一覧の末尾に移動します。 replace が True の場合は、元の位置で更新されます。

バージョン 3.4 で変更: replace キーワードが追加されました。

del_param(param, header='content-type', requote=True)

指定されたパラメータを Content-Type ヘッダ中から完全にとりのぞきます。ヘッダはそのパラメータと値がない状態に書き換えられます。 requote が False でない限り (デフォルトでは True です)、すべての値は必要に応じて quote されます。オプション変数 header が与えられた場合、 Content-Type のかわりにそのヘッダが使用されます。

set_type(type, header='Content-Type', requote=True)

Content-Type ヘッダの maintype と subtype を設定します。 type は maintype/subtype という形の文字列でなければなりません。それ以外の場合は ValueError が発生します。

このメソッドは Content-Type ヘッダを置き換えますが、すべてのパラメータはそのままにします。 requote が False の場合、これはすでに存在するヘッダを quote せず放置しますが、そうでない場合は自動的に quote します (デフォルト動作)。

オプション変数 header が与えられた場合、 Content-Type のかわりにそのヘッダが使用されます。 Content-Type ヘッダが設定される場合には、 MIME-Version ヘッダも同時に付加されます。

これは従来の API のメソッドです。 EmailMessage クラスでは、make_ と add_ メソッドがこの機能を置き換えています。

get_filename(failobj=None)

そのメッセージ中の Content-Disposition ヘッダにある、 filename パラメータの値を返します。目的のヘッダに filename パラメータがない場合には Content-Type ヘッダにある name パラメータを探します。それも無い場合またはヘッダが無い場合には failobj が返されます。返される文字列はつねに email.utils.unquote() によって unquote されます。

get_boundary(failobj=None)

そのメッセージ中の Content-Type ヘッダにある、 boundary パラメータの値を返します。目的のヘッダが欠けていたり、 boundary パラメータがない場合には failobj が返されます。返される文字列はつねに email.utils.unquote() によって unquote されます。

set_boundary(boundary)

メッセージ中の Content-Type ヘッダにある、 boundary パラメータに値を設定します。 set_boundary() は必要に応じて boundary を quote します。そのメッセージが Content-Type ヘッダを含んでいない場合、 HeaderParseError が発生します。

注意: このメソッドを使うのは、古い Content-Type ヘッダを削除して新しい boundary をもったヘッダを add_header() で足すのとは少し違います。 set_boundary() は一連のヘッダ中での Content-Type ヘッダの位置を保つからです。 しかし、これは元の Content-Type ヘッダ中に存在していた継続行は 保持しません 。

get_content_charset(failobj=None)

そのメッセージ中の Content-Type ヘッダにある、 charset パラメータの値を返します。 値はすべて小文字に変換されます。 メッセージ中に Content-Type がなかったり、このヘッダ中に charset パラメータがない場合には failobj が返されます。

注意: これは get_charset() メソッドとは異なります。こちらのほうは文字列のかわりに、そのメッセージボディのデフォルトエンコーディングの Charset インスタンスを返します。

get_charsets(failobj=None)

メッセージ中に含まれる文字セットの名前をすべてリストにして返します。そのメッセージが multipart である場合、返されるリストの各要素がそれぞれの subpart のペイロードに対応します。それ以外の場合、これは長さ 1 のリストを返します。

リスト中の各要素は文字列であり、これは対応する subpart 中のそれぞれの Content-Type ヘッダにある charset の値です。しかし、その subpart が Content-Type をもってないか、 charset がないか、あるいは MIME maintype が text でないいずれかの場合には、リストの要素として failobj が返されます。

get_content_disposition()

メッセージに Content-Disposition ヘッダーがあれば、パラメータを除いた値を小文字で返し、なければ None を返します。 メッセージが RFC 2183 に準拠していれば、戻り値は inline、attachment、None のいずれかです。

Added in version 3.5.

walk()

walk() メソッドは多目的のジェネレータで、これはあるメッセージオブジェクトツリー中のすべての part および subpart をわたり歩くのに使えます。順序は深さ優先です。おそらく典型的な用法は、 walk() を for ループ中でのイテレータとして使うことでしょう。ループを一回まわるごとに、次の subpart が返されるのです。

以下の例は、 multipart メッセージのすべての part において、その MIME タイプを表示していくものです。 :

>>> for part in msg.walk():
...     print(part.get_content_type())
multipart/report
text/plain
message/delivery-status
text/plain
text/plain
message/rfc822
text/plain

walk() は、is_multipart() が True を返すパートのサブパートを反復処理します。 msg.get_content_maintype() == 'multipart' が False を返す場合も同様です。 デバッグ用の補助関数 _structure() を使うと、この例でその様子を確認できます。

>>> for part in msg.walk():
...     print(part.get_content_maintype() == 'multipart',
...           part.is_multipart())
True True
False False
False True
False False
False False
False True
False False
>>> _structure(msg)
multipart/report
    text/plain
    message/delivery-status
        text/plain
        text/plain
    message/rfc822
        text/plain

ここでは message パートは multipart ではありませんが、サブパートを含んでいます。 is_multipart() は True を返し、walk() はサブパートの中へ進みます。

Message オブジェクトはオプションとして 2つのインスタンス属性をとることができます。これはある MIME メッセージからプレーンテキストを生成するのに使うことができます。

preamble

MIME ドキュメントの形式では、ヘッダ直後にくる空行と最初の multipart 境界をあらわす文字列のあいだにいくらかのテキスト (訳注: preamble, 序文) を埋めこむことを許しています。このテキストは標準的な MIME の範疇からはみ出しているので、MIME 形式を認識するメールソフトからこれらは通常まったく見えません。しかしメッセージのテキストを生で見る場合、あるいはメッセージを MIME 対応していないメールソフトで見る場合、このテキストは目に見えることになります。

preamble 属性は MIME ドキュメントに加えるこの最初の MIME 範囲外テキストを含んでいます。 Parser があるテキストをヘッダ以降に発見したが、それはまだ最初の MIME 境界文字列が現れる前だった場合、パーザはそのテキストをメッセージの preamble 属性に格納します。 Generator がある MIME メッセージからプレーンテキスト形式を生成するときメッセージが preamble 属性を持つことが発見されれば、これはそのテキストをヘッダと最初の MIME 境界の間に挿入します。詳細は email.parser および email.generator を参照してください。

注意: そのメッセージに preamble がない場合、preamble 属性には None が格納されます。

epilogue

epilogue 属性はメッセージの最後の MIME 境界文字列からメッセージ末尾までのテキストを含むもので、それ以外は preamble 属性と同じです。

Generator でファイル終端に改行を出力するため、 epilogue に空文字列を設定する必要はなくなりました。

defects

defects 属性はメッセージを解析する途中で検出されたすべての問題点 (defect、障害) のリストを保持しています。解析中に発見されうる障害についてのより詳細な説明は email.errors を参照してください。