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

ソースコード: Lib/email/message.py


Added in version 3.6: [1]

email パッケージの中心となるクラスは、email.message モジュールからインポートする EmailMessage です。 これは email のオブジェクトモデルの基底クラスです。 EmailMessage は、ヘッダーフィールドの設定と参照、メッセージ本体へのアクセス、構造化されたメッセージの作成や変更に関する中核の機能を提供します。

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

EmailMessage オブジェクトは概念的には、ヘッダーの順序付き辞書と、RFC 5322 のメッセージ本体を表す ペイロード を組み合わせたものです。 ペイロードはサブメッセージの EmailMessage オブジェクトのリストになることもあります。 ヘッダーの名前と値にアクセスする通常の辞書メソッドに加え、MIME コンテントタイプなどのヘッダーの特定の情報へのアクセス、ペイロードの操作、メッセージの直列化、オブジェクトツリーの再帰的な巡回のためのメソッドがあります。

EmailMessage の辞書に似たインターフェースは、ASCII 値でなければならないヘッダー名をキーとします。 辞書の値は、追加のメソッドを持つ文字列です。 ヘッダーの格納時と取得時には大文字・小文字が保持されますが、フィールド名の照合では区別されません。 キーには順序がありますが、通常の辞書と異なり重複できます。 キーが重複するヘッダーを扱うための追加のメソッドも用意されています。

ペイロード は、単純なメッセージオブジェクトでは文字列または bytes オブジェクトです。 multipart/* や message/rfc822 などの MIME コンテナ文書では、EmailMessage オブジェクトのリストです。

class email.message.EmailMessage(policy=default)

policy が指定されていれば、その規則に従ってメッセージの表現を更新し、直列化します。 指定されていなければ default ポリシーを使います。 このポリシーは電子メールの RFC の規則に従いますが、行末だけは RFC が要求する \r\n の代わりに Python 標準の \n を使います。 詳しくは policy のドキュメントを参照してください。[2]

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

メッセージ全体をフラット化した文字列を返します。 オプションの unixfrom が真の場合、戻り値にはエンベロープヘッダーが含まれます。 unixfrom のデフォルトは False です。 基底クラス Message との後方互換性のため maxheaderlen を受け取りますが、デフォルトは None です。 したがって、デフォルトではポリシーの max_line_length が行長を制御します。 policy 引数で、メッセージインスタンスから取得するデフォルトのポリシーを上書きできます。 指定した policy は Generator に渡されるため、メソッドが生成する書式の一部を制御できます。

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

このメソッドは便利な補助機能として提供されており、特に複数のメッセージを扱う場合には、アプリケーションに最適な直列化方法とは限りません。 より柔軟な直列化 API については email.generator.Generator を参照してください。 また、utf8 が False (デフォルト) の場合、このメソッドが生成できるのは 7 ビットだけを使う形式に直列化されたメッセージに限られます。

バージョン 3.6 で変更: maxheaderlen を指定しない場合のデフォルトの動作が、値 0 を使う動作から、ポリシーの max_line_length の値を使う動作に変わりました。

__str__()

as_string(policy=self.policy.clone(utf8=True)) と同じです。 str(msg) で、読みやすい形式に直列化されたメッセージを含む文字列を生成できるようにします。

バージョン 3.4 で変更: as_string() の単なる別名ではなく、utf8=True を使って RFC 6531 に似たメッセージ表現を生成するように変わりました。

as_bytes(unixfrom=False, policy=None)

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

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

このメソッドは便利な補助機能として提供されており、特に複数のメッセージを扱う場合には、アプリケーションに最適な直列化方法とは限りません。 より柔軟な直列化 API については email.generator.BytesGenerator を参照してください。

__bytes__()

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

is_multipart()

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

set_unixfrom(unixfrom)

メッセージのエンベロープヘッダーを unixfrom に設定します。 unixfrom は文字列でなければなりません。 (このヘッダーの簡単な説明は mboxMessage を参照してください。)

get_unixfrom()

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

The following methods implement the mapping-like interface for accessing the message's headers. Note that there are some semantic differences between these methods and a normal mapping (i.e. dictionary) interface. For example, in a dictionary there are no duplicate keys, but here there may be duplicate message headers. Also, in dictionaries there is no guaranteed order to the keys returned by keys(), but in an EmailMessage object, headers are always returned in the order they appeared in the original message, or in which they were added to the message later. Any header deleted and then re-added is always appended to the end of the header list.

このような意味の違いは意図的なもので、一般的な用途で便利になるように設計されています。

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

__len__()

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

__contains__(name)

メッセージオブジェクトに name という名前のフィールドがあれば True を返します。 照合では大文字・小文字を区別せず、name に末尾のコロンは含めません。 in 演算子で使われます。 例えば次のようにします。

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

指定した名前のヘッダーフィールドの値を返します。 name にフィールド区切りのコロンは含めません。 ヘッダーがなければ None を返し、KeyError は送出しません。

指定した名前のフィールドがメッセージのヘッダーに複数ある場合、どの値を返すかは未定義です。 name という名前の既存のヘッダーの値をすべて取得するには、get_all() を使ってください。

標準の (compat32 以外の) ポリシーでは、戻り値は email.headerregistry.BaseHeader のサブクラスのインスタンスです。

__setitem__(name, val)

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

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

del msg['subject']
msg['subject'] = 'Python roolz!'

標準のポリシーのように、ポリシー が特定のヘッダーを一つしか許さないと定めている場合、そのヘッダーがすでにある状態で値を代入しようとすると、このメソッドは ValueError を送出することがあります。 一貫性を保つための意図的な動作ですが、将来はこのような代入で既存のヘッダーを自動的に削除するよう変更する可能性があるため、この動作に依存しないでください。

__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 の識別子ではハイフンを使えないためです)。 通常は 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'))
replace_header(_name, _value)

ヘッダーを置き換えます。 _name に一致する最初のヘッダーを、元のヘッダーの順序とフィールド名の大文字・小文字を保ったまま置き換えます。 一致するヘッダーがなければ KeyError を送出します。

get_content_type()

メッセージのコンテントタイプを、小文字の maintype/subtype 形式で返します。 メッセージに Content-Type ヘッダーがない場合は、get_default_type() の戻り値を返します。 Content-Type ヘッダーが不正な場合は text/plain を返します。

(RFC 2045 によると、メッセージは常にデフォルトの型を持つため、get_content_type() は常に値を返します。 RFC 2045 はデフォルトの型を text/plain と定めていますが、multipart/digest コンテナ内では message/rfc822 と定めています。 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)

デフォルトのコンテントタイプを設定します。 強制はされませんが、ctype は text/plain または message/rfc822 にしてください。 デフォルトのコンテントタイプは Content-Type ヘッダーには格納されないため、メッセージに Content-Type ヘッダーがない場合の get_content_type() の戻り値にだけ影響します。

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

Content-Type ヘッダーにパラメータを設定します。 パラメータがすでにあれば、その値を value に置き換えます。 header が Content-Type (デフォルト) で、そのヘッダーがメッセージにまだない場合、値を text/plain としてヘッダーを追加し、新しいパラメータ値を付け加えます。 オプションの header は、Content-Type の代わりに使うヘッダーを指定します。

If the value contains non-ASCII characters, the charset and language may be explicitly specified using the optional charset and language parameters. Optional language specifies the RFC 2231 language, defaulting to the empty string. Both charset and language should be strings. The default is to use the utf8 charset and None for the language.

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

EmailMessage オブジェクトでの requote 引数の使用は非推奨です。

ヘッダーの既存のパラメータ値には、ヘッダー値の params 属性からアクセスできます (例えば msg['Content-Type'].params['charset'])。

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

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

指定されたパラメータを Content-Type ヘッダ中から完全にとりのぞきます。ヘッダはそのパラメータと値がない状態に書き換えられます。オプション変数 header が与えられた場合、 Content-Type のかわりにそのヘッダが使用されます。

EmailMessage オブジェクトでの requote 引数の使用は非推奨です。

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

set_boundary() は、ヘッダー一覧内の Content-Type ヘッダーの順序を保持します。 そのため、古い Content-Type ヘッダーを削除し、add_header() で新しい境界を持つヘッダーを追加する方法とは少し異なります。

get_content_charset(failobj=None)

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

get_charsets(failobj=None)

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

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

is_attachment()

Content-Disposition ヘッダが存在し、その (大文字小文字を区別しない) 値が attachment の場合、 True を返します。 それ以外の場合は False を返します。

バージョン 3.4.2 で変更: is_multipart() との一貫性のために、is_attachment が属性からメソッドになりました。

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() を使うと、この例でその様子を確認できます。

>>> from email.iterators import _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() はサブパートの中へ進みます。

get_body(preferencelist=('related', 'html', 'plain'))

メッセージの "本体" の最有力候補となる MIME 部を返します。

preferencelist は related、html、plain の中から選んだ文字列のシーケンスでなければならず、返されるパートのコンテントタイプの優先順位を示します。

get_body() を呼び出したオブジェクトから、一致する候補の検索を始めます。

preferencelist に related が含まれていない場合、見つかった related パートのルートパート (またはそのサブパート) が優先候補のいずれかに一致すれば、候補として扱います。

multipart/related を見つけると start パラメータを調べ、Content-ID が一致するパートがあれば、それだけを一致候補の検索対象とします。 なければ、multipart/related の最初のパート (デフォルトのルート) だけを対象とします。

パートに Content-Disposition ヘッダーがある場合、その値が inline のときだけ一致候補とします。

どの候補も preferencelist のいずれの優先候補にも一致しなければ、None を返します。

注意: (1) ほとんどのアプリケーションで意味のある preferencelist の組み合わせは、('plain',)、('html', 'plain')、デフォルトの ('related', 'html', 'plain') だけです。 (2) 一致の検索は get_body() を呼び出したオブジェクトから始まるため、multipart/related に対する get_body() は、preferencelist がデフォルト以外の値でない限り、そのオブジェクト自身を返します。 (3) Content-Type が指定されていないメッセージ (またはパート) や、Content-Type ヘッダーが不正なものは、text/plain とみなされます。 そのため、get_body() が予想外の結果を返すことがあります。

iter_attachments()

メッセージの直下のサブパートのうち、「本体」の候補でないものすべてを反復処理するイテレーターを返します。 つまり、text/plain、text/html、multipart/related、multipart/alternative のそれぞれ最初のパートを除き、残りのパートをすべて返します。 ただし、Content-Disposition: attachment で明示的に添付ファイルとされているパートは除きません。 multipart/related に直接適用した場合、ルートパート以外の関連パートすべてを反復処理するイテレーターを返します。 ルートパートは start パラメータが指すパートで、start がない場合や、どのパートの Content-ID にも一致しない場合は最初のパートです。 multipart/alternative または multipart 以外に直接適用すると、空のイテレーターを返します。

iter_parts()

メッセージの直下のサブパートすべてを反復処理するイテレーターを返します。 multipart でなければ空になります。 (walk() も参照してください。)

get_content(*args, content_manager=None, **kw)

content_manager の get_content() を呼び出します。 メッセージオブジェクトとして self を渡し、他の引数やキーワード引数も追加の引数としてそのまま渡します。 content_manager が指定されていなければ、現在の policy で指定された content_manager を使います。

set_content(*args, content_manager=None, **kw)

content_manager の set_content() を呼び出します。 メッセージオブジェクトとして self を渡し、他の引数やキーワード引数も追加の引数としてそのまま渡します。 content_manager が指定されていなければ、現在の policy で指定された content_manager を使います。

multipart でないメッセージを multipart/related に変換し、既存の Content- ヘッダーとペイロードを、multipart の新しい最初のパートに移します。 boundary が指定されていれば、マルチパートの境界文字列として使います。 指定されていなければ、直列化時など、必要になったときに自動的に生成されるようにします。

make_alternative(boundary=None)

multipart でないメッセージ、または multipart/related を multipart/alternative に変換し、既存の Content- ヘッダーとペイロードを、multipart の新しい最初のパートに移します。 boundary が指定されていれば、マルチパートの境界文字列として使います。 指定されていなければ、直列化時など、必要になったときに自動的に生成されるようにします。

make_mixed(boundary=None)

Convert a non-multipart, a multipart/related, or a multipart/alternative into a multipart/mixed, moving any existing Content- headers and payload into a (new) first part of the multipart. If boundary is specified, use it as the boundary string in the multipart, otherwise leave the boundary to be automatically created when it is needed (for example, when the message is serialized).

メッセージが multipart/related の場合、新しいメッセージオブジェクトを作成し、すべての引数をその set_content() に渡して、attach() で multipart に追加します。 メッセージが multipart でなければ、make_related() を呼び出してから同じ処理を行います。 他の型の multipart の場合は TypeError を送出します。 content_manager が指定されていなければ、現在の policy で指定された content_manager を使います。 追加したパートに Content-Disposition ヘッダーがなければ、値を inline として追加します。

add_alternative(*args, content_manager=None, **kw)

メッセージが multipart/alternative の場合、新しいメッセージオブジェクトを作成し、すべての引数をその set_content() に渡して、attach() で multipart に追加します。 メッセージが multipart でない場合、または multipart/related の場合は、make_alternative() を呼び出してから同じ処理を行います。 他の型の multipart の場合は TypeError を送出します。 content_manager が指定されていなければ、現在の policy で指定された content_manager を使います。

add_attachment(*args, content_manager=None, **kw)

メッセージが multipart/mixed の場合、新しいメッセージオブジェクトを作成し、すべての引数をその set_content() に渡して、attach() で multipart に追加します。 メッセージが multipart でない場合、または multipart/related や multipart/alternative の場合は、make_mixed() を呼び出してから同じ処理を行います。 content_manager が指定されていなければ、現在の policy で指定された content_manager を使います。 追加したパートに Content-Disposition ヘッダーがなければ、値を attachment として追加します。 content_manager に適切なオプションを渡すことで、明示的な添付ファイル (Content-Disposition: attachment) にも、inline の添付ファイル (Content-Disposition: inline) にも使えます。

clear()

ペイロードとヘッダの全てを削除します。

clear_content()

ペイロードとすべての !Content- ヘッダーを削除し、他のヘッダーは内容も順序もそのまま残します。

EmailMessage オブジェクトは次のようなインスタンス属性を持ちます:

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 属性は preamble 属性と同様に働きますが、最後の境界からメッセージの末尾までのテキストを含む点が異なります。 preamble と同様に、末尾のテキストがなければ None になります。

defects

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

class email.message.MIMEPart(policy=default)

このクラスは MIME メッセージのサブパートを表します。 EmailMessage と同じですが、サブパートには独自の MIME-Version ヘッダーが不要なため、set_content() を呼び出しても MIME-Version ヘッダーが追加されない点が異なります。

脚注