RFC 2046: MIME パート 2 — メディアタイプ
これが存在する理由
RFC 2045はContent-Typeとトランスファーエンコーディングを導入しましたが、どのコンテンツタイプが存在するか、またそれらがどのように動作するかは定義されていません。RFC 2046は以下を定義することによってその隙間を埋めています:
- トップレベルメディアタイプ(text、image、audio、video、application、multipart、message)。
- 単一のメールが複数のボディパーツをバウンダリデリミタで含むことを可能にするマルチパートメカニズム。
- メールクライアントがパーツを表示する方法を制御する特定のマルチパートサブタイプ(mixed、alternative、digest、parallel)。
これは現代的なメールを可能にするRFCです。これがなければ、すべてのメールは単一のテキストブロックになります。
仕組み
トップレベルメディアタイプ
| タイプ | 説明 | 一般的なサブタイプ |
|---|---|---|
text |
人間が読めるテキスト |
text/plain、text/html、text/calendar
|
image |
画像データ |
image/png、image/jpeg、image/gif、image/svg+xml
|
audio |
オーディオデータ |
audio/mpeg、audio/ogg
|
video |
ビデオデータ |
video/mp4、video/webm
|
application |
バイナリデータまたは構造化形式 |
application/pdf、application/json、application/octet-stream
|
multipart |
1つのメッセージ内の複数のボディパーツ |
multipart/mixed、multipart/alternative、multipart/related
|
message |
カプセル化されたメールメッセージ |
message/rfc822、message/delivery-status
|
マルチパートメカニズム
マルチパートタイプはRFC 2046の中核です。マルチパートメッセージには各パーツを区切るboundaryパラメータが含まれます:
Content-Type: multipart/mixed; boundary="----=_boundary_001" ------ プリアンブル(MIMEクライアントで無視される) ------ ------=_boundary_001 Content-Type: text/plain; charset=utf-8 これが最初のパーツです。 ------=_boundary_001 Content-Type: text/plain; charset=utf-8 これが2番目のパーツです。 ------=_boundary_001-- ^^^ 終了を示す後ろの-- に注意
バウンダリの主要ルール:
- 各パーツの前には
--+ バウンダリ文字列が独立した行にあります。 - 最終バウンダリにもその後に
--が付加されます(例えば、--boundary--)。 - バウンダリ文字列は任意のボディパーツに含まれてはいけません。長いランダム文字列を使用してください。
- 最初のバウンダリの前の内容(プリアンブル)および最終バウンダリの後の内容(エピローグ)はMIME対応クライアントで無視されます。
マルチパートサブタイプ
サブタイプはメールクライアントにパーツをどのように表示するかを伝えます。ここが微妙な点が存在するところです。
multipart/mixed — 順序付きパーツ
最も一般的なマルチパートタイプです。パーツは順序で表示されます。「メッセージボディ + 添付ファイル」に使用されます:
Content-Type: multipart/mixed; boundary="----=_mixed" ------=_mixed Content-Type: text/plain; charset=utf-8 ご要望いただいたレポートをお送りします。 ------=_mixed Content-Type: application/pdf; name="report.pdf" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="report.pdf" JVBERi0xLjQKJeLjz9MK... ------=_mixed--
multipart/alternative — 同じコンテンツ、異なる形式
同じコンテンツの複数バージョンが含まれます。メールクライアントは表示できる最適なものを選択します。パーツは単純から豊か順に並べられます — 最後のパーツが優先されます:
Content-Type: multipart/alternative; boundary="----=_alt" ------=_alt Content-Type: text/plain; charset=utf-8 我々のサービスへようこそ! ------=_alt Content-Type: text/html; charset=utf-8 <h1>我々のサービスへようこそ!</h1> <p>お力になれて光栄です。</p> ------=_alt--
これがすべてのよく形成されたHTMLメールの仕組みです:text/plainフォールバックが最初に来て、text/htmlバージョンが最後に来ます。HTMLをサポートするクライアントはHTMLを表示します。プレーンテキストクライアントはテキストを表示します。
multipart/related — リンクされたパーツ
パーツが相互参照する場合に使用されます。最も一般的なユースケースはインライン画像を含むHTMLメールです。HTMLはContent-ID(cid: URL)で画像を参照します:
Content-Type: multipart/related; boundary="----=_rel" ------=_rel Content-Type: text/html; charset=utf-8 <p>ロゴをご確認ください:</p> <img src="cid:logo@example.com" alt="ロゴ" /> ------=_rel Content-Type: image/png Content-Transfer-Encoding: base64 Content-ID: <logo@example.com> iVBORw0KGgoAAAANSUhEU... ------=_rel--
multipart/digest — メッセージの集合
各パーツのデフォルトコンテンツタイプがtext/plainの代わりにmessage/rfc822となるmixedの変種です。メーリングリストダイジェストで使用されます。現代のメールではめったに見られません。
主要な技術的詳細
マルチパートタイプのネスト
MIMEの真の力はネストから来ます。インライン画像と添付ファイルを含む典型的なマーケティングメールは以下のようになります:
; HTMLメールとインライン画像+添付ファイルの標準的な構造 Content-Type: multipart/mixed ← 外部:ボディ+添付ファイル | |-- multipart/alternative ← ボディ:テキストまたはHTML | |-- text/plain ← プレーンテキストフォールバック | |-- multipart/related ← HTML+インライン画像 | |-- text/html ← HTMLボディ | |-- image/png (cid:logo) ← インライン画像 | |-- application/pdf (attachment) ← ファイル添付
この3段階のネストは事実上すべてのメールライブラリとメールサービスプロバイダーで使用される標準パターンです。
message/rfc822タイプ
メール全体をボディパーツとしてカプセル化します。メッセージを添付として転送する場合とバウンス通知(RFC 3462 multipart/report)で使用されます。カプセル化されたメッセージは独自のヘッダ(From、To、Subject等)とボディを持ちます。
application/octet-streamフォールバック
ファイルのコンテンツタイプが不明な場合、application/octet-streamを使用してください。これはクライアントに汎用バイナリデータとして扱うよう伝え、通常ダウンロードプロンプトをトリガーします。これはMIMEの「これが何であるかわかりません。保存して自分で解決してください」と同等です。
バウンダリ要件
バウンダリ文字列には特定のルールがあります:
- 最大70文字。
- ASCII英数字とカンマで構成されます。制限されたセットの特殊文字:
'()+_,-./:=?とスペース。 - 囲まれたボディパーツに現れてはいけません。
- 実際には、
----=_Part_12345_67890.1234567890のような長いランダム文字列を使用してください。
一般的な間違い
-
テキスト+HTMLに対して
multipart/mixedの代わりにmultipart/alternativeを使用しないこと。テキストとHTMLをmixedコンテナに入れると、クライアントは両方を表示します(またはテキストを表示してHTMLをダウンロードとして提供します)。クライアントが最適な形式を選ぶようにalternativeを使用してください。 -
multipart/alternativeでの間違った部分の順序。最も単純な形式が最初、最も豊かな形式が最後。HTMLをプレーンテキストの前に配置すると、HTMLが利用可能であってもプレーンテキストバージョンを表示するクライアントもあります。 -
multipart/relatedなしのインライン画像。HTMLでcid:URLを参照していても、画像がmultipart/relatedコンテナの代わりにシスターmultipart/mixedパーツにある場合、多くのクライアントは参照を解決しません。 -
Content-ID角括弧がない。Content-IDヘッダ値は角括弧で囲まれている必要があります:
<image001@example.com>。HTMLのcid:参照はそれらを省略します:src="cid:image001@example.com"。 -
バウンダリ衝突。短いまたは予測可能なバウンダリ文字列(
boundaryまたは---のような)を使用すると、ボディコンテンツに現れるリスクがあります。メッセージ構造を破損させます。常にランダムバウンダリを使用してください。 -
最後の
--を忘れる。終了バウンダリは--で終わる必要があります(例えば、--boundary--)。これを忘れるとパーサーがより多くのパーツを待ち、メッセージの改ざんまたは不完全な結果になる可能性があります。
配信性への影響
- 正しいmultipart/alternativeは必須です。スパムフィルターはよく形成されたHTMLメールがtext/plainの代替を含むことを期待しています。これを忘れるとスパムシグナルです。テキスト部分とHTML部分は大体同等のコンテンツを持つべきです — 1行のテキスト部分と50 KBのHTML部分は疑わしく見えます。
-
インライン画像はスパムスコアを増やします。
multipart/relatedが多くのインライン画像に使われると(特にメールがほぼ画像でテキストが少ないとき)、イメージスパムヒューリスティックをトリガーします。マーケティングメールに対してcid:参照よりもhttps://URLでホストされた画像を好みます。 -
添付ファイルタイプが重要です。実行可能な添付ファイル(
.exe、.js、.bat)はほぼすべてのメールプロバイダーでブロックまたは検疫されます。実行可能ファイルを含む.zipファイルさえも標識されます。安全なタイプに留まってください:PDF、一般的な画像形式、オフィスドキュメント。 - 過度に大きいメッセージはバウンスします。多くのプロバイダーは25 MB(一部は10 MB)を超えるメッセージを拒否します。base64エンコーディングは33%のオーバーヘッドを追加することを忘れないでください。20 MBの添付ファイルは~27 MBのメールになります。
- 適切に構造化されたMIMEは正当性を示唆します。正しいネスト、有効なバウンダリ、適切なContent-Type宣言を備えた適切に形成されたMIMEはスパムフィルターにこのメッセージが正当なメールソフトウェアによって生成されたこと、つまりハンドクラフトスパムツールではないことを伝えます。