# 18.1.1. `email.message`: 電子メールメッセージの表現

`Message` クラスは、 `email` パッケージの中心となるクラスです。これは `email` オブジェクトモデルの基底クラスになっています。 `Message` はヘッダフィールドを検索したりメッセージ本体にアクセスするための核となる機能を提供します。

概念的には、(`email.message` モジュールからインポートされる) `Message` オブジェクトには ヘッダ と ペイロード が格納されています。ヘッダは、 RFC 2822 形式のフィールド名およびフィールド値がコロンで区切られたものです。コロンはフィールド名またはフィールド値のどちらにも含まれません。

ヘッダは大文字小文字を区別した形式で保存されますが、ヘッダ名が一致するかどうかの検査は大文字小文字を区別せずにおこなうことができます。 Unix-From ヘッダまたは `From_` ヘッダとして知られるエンベロープヘッダがひとつ存在することもあります。ペイロードは、単純なメッセージオブジェクトの場合は単なる文字列ですが、 MIME コンテナ文書 (multipart/* または message/rfc822 など) の場合は `Message` オブジェクトのリストになっています。

`Message` オブジェクトは、メッセージヘッダにアクセスするためのマップ (辞書) 形式のインタフェイスと、ヘッダおよびペイロードの両方にアクセスするための明示的なインタフェイスを提供します。これにはメッセージオブジェクトツリーからフラットなテキスト文書を生成したり、一般的に使われるヘッダのパラメータにアクセスしたり、またオブジェクトツリーを再帰的にたどったりするための便利なメソッドを含みます。

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

class `email.message.``Message`

  コンストラクタは引数をとりません。

  `as_string`([unixfrom])

    メッセージ全体をフラットな文字列として返します。オプション unixfrom が `True` の場合、返される文字列にはエンベロープヘッダも含まれます。 unixfrom のデフォルトは `False` です。もし、文字列への変換を完全に行うためにデフォルト値を埋める必要がある場合、メッセージのフラット化は `Message` の変更を引き起こす可能性があります (例えば、MIME の境界が生成される、変更される等)。

    このメソッドは手軽に利用する事ができますが、必ずしも期待通りにメッセージをフォーマットするとは限りません。たとえば、これはデフォルトでは `From` で始まる行を変更してしまいます。以下の例のように `Generator` のインスタンスを生成して `flatten()` メソッドを直接呼び出せばより柔軟な処理を行う事ができます。

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

  `__str__`()

    `as_string(unixfrom=True)()` と同じです。

  `is_multipart`()

    メッセージのペイロードが子 `Message` オブジェクトからなるリストであれば `True` を返し、そうでなければ `False` を返します。 `is_multipart()` が `False` を返した場合は、ペイロードは文字列オブジェクトである必要があります。

  `set_unixfrom`(unixfrom)

    メッセージのエンベロープヘッダを unixfrom に設定します。これは文字列である必要があります。

  `get_unixfrom`()

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

  `attach`(payload)

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

  `get_payload`([i[, decode]])

    現在のペイロードへの参照を返します。これは `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` でメッセージが multipart ではない場合、ペイロードはこのヘッダの値が `quoted-printable` または `base64` のときにかぎりデコードされます。これ以外のエンコーディングが使われている場合、 Content-Transfer-Encoding ヘッダがない場合、あるいは曖昧な base64 データが含まれる場合は、ペイロードはそのまま (デコードされずに) 返されます。もしメッセージが multipart で decode フラグが `True` の場合は `None` が返されます。 decode のデフォルト値は `False` です。

  `set_payload`(payload[, charset])

    メッセージ全体のオブジェクトのペイロードを payload に設定します。ペイロードの形式をととのえるのは呼び出し側の責任です。オプションの charset はメッセージのデフォルト文字セットを設定します。詳しくは `set_charset()` を参照してください。

    バージョン 2.2.2 で変更: charset 引数を追加。

  `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 によって正しくエンコードされたものと見なされ、変形されません。

    ここでいうメッセージとは、unicode 文字列か charset.input_charset でエンコードされたペイロードを持つ text/* 形式のものを仮定しています。これは、プレーンテキスト形式を生成する際に charset.output_charset と転送 (transfer) エンコードに、エンコードまたは変換されます。MIME ヘッダ (MIME-Version, Content-Type, Content-Transfer-Encoding) は必要に応じて追加されます。

    バージョン 2.2.2 で追加.

  `get_charset`()

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

    バージョン 2.2.2 で追加.

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

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

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

  `__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 という名前をもつフィールドをすべて除去します。たとえこの名前をもつヘッダが存在していなくても例外は発生しません。

  `has_key`(name)

    メッセージが name という名前をもつヘッダフィールドを持っていれば真を、そうでなければ偽を返します。

  `keys`()

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

  `values`()

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

  `items`()

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

  `get`(name[, failobj])

    指定された名前をもつフィールドの値を返します。これは指定された名前がないときにオプション引数の failobj (デフォルトでは `None`) を返すことをのぞけば、 `__getitem__()` と同じです。

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

  `get_all`(name[, failobj])

    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 コードポイントを含む文字列値です。

    以下はこの使用例です:

        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` が発生します。

    バージョン 2.2.2 で追加.

  `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 として扱うよう定めています。

    バージョン 2.2.2 で追加.

  `get_content_maintype`()

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

    バージョン 2.2.2 で追加.

  `get_content_subtype`()

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

    バージョン 2.2.2 で追加.

  `get_default_type`()

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

    バージョン 2.2.2 で追加.

  `set_default_type`(ctype)

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

    バージョン 2.2.2 で追加.

  `get_params`([failobj[, header[, unquote]]])

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

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

    バージョン 2.2.2 で変更: unquote 引数の追加。

  `get_param`(param[, failobj[, header[, unquote]]])

    メッセージの Content-Type ヘッダ中のパラメータ param を文字列として返します。そのメッセージ中に Content-Type ヘッダが存在しなかった場合、 failobj (デフォルトは `None`) が返されます。

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

    パラメータのキー比較は常に大文字小文字を区別しません。返り値は文字列か 3 要素のタプルで、タプルになるのはパラメータが RFC 2231 エンコードされている場合です。3 要素タプルの場合、各要素の値は `(CHARSET, LANGUAGE, VALUE)` の形式になっています。 `CHARSET` と `LAGUAGE` は `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 されません。

    バージョン 2.2.2 で変更: unquote 引数の追加、3要素タプルが返り値になる可能性あり。

  `set_param`(param, value[, header[, requote[, charset[, language]]]])

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

    オプション引数 header が与えられた場合、 Content-Type のかわりにそのヘッダが使用されます。オプション引数 requote が `False` でない限り、この値は quote されます (デフォルトは `True`)。

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

    バージョン 2.2.2 で追加.

  `del_param`(param[, header[, requote]])

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

    バージョン 2.2.2 で追加.

  `set_type`(type[, header][, requote])

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

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

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

    バージョン 2.2.2 で追加.

  `get_filename`([failobj])

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

  `get_boundary`([failobj])

    そのメッセージ中の 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])

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

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

    バージョン 2.2.2 で追加.

  `get_charsets`([failobj])

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

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

  `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

  バージョン 2.5 で変更: 以前の非推奨メソッド `get_type()` 、 `get_main_type()` 、 `get_subtype()` は削除されました。

  `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 属性と同じです。

    バージョン 2.5 で変更: `Generator` でファイル終端に改行を出力するため、 epilogue に空文字列を設定する必要はなくなりました。

  `defects`

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

    バージョン 2.4 で追加.