「SMTPによるメール送信の仕組み」ではメールを送信するためのプロトコル(SMTP)の話をしましたが、 そこではDATAコマンドで送信するメールの形式については言及しませんでした。 今回は、メールの形式について説明します。
7ビット
基本的にSMTPは7ビットのプロトコルです。 それでやり取りされるメールも7ビットのコードを使用します。 この7ビットであることが、様々な制約を生みメールの形式を複雑にしています。
ヘッダと本文
メールは大きくヘッダと本文に分けられます。
ヘッダは、ヘッダ名と値の対になっておりコロン:
で区切られます。
Date: Fri, 29 Sep 2017 14:32:15 +0900
SMTPの1行は1000オクテット(≒バイト)なので、無制限に長くすることはできません。 そのために複数行で表現できるようになっています。 実際には1000オクテットまで伸ばさずに78オクテット程度までで改行します。 複数行のヘッダは、2行目以降は行頭に空白文字を入れることになっています。 (空白文字は、いくつ入れてもかまいません。)
Content-Type: multipart/mixed;
boundary="94eb2c076a6af4de10055a4bf6e4"
このような形で必要な情報を並べて記述します。
Date: Fri, 29 Sep 2017 14:32:15 +0900
Mime-Version: 1.0
Content-Type: multipart/mixed;
boundary="94eb2c076a6af4de10055a4bf6e4"
Subject: This is a sample.
From: Mr.From <from@example.com>
To: Who <who@example.com>
ヘッダの最後に改行だけの空行を入れ、それが本文との区切りになります。
Date: Fri, 29 Sep 2017 14:32:15 +0900
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Subject: This is a sample.
From: Mr.From <from@example.com>
To: Who <who@example.com>
ここからが本文
MIMEエンコード
前にメールの形式は7ビットだと述べましたが、ヘッダにはもう1つ制約があります。
ヘッダは表示可能な文字しか使えません。
7ビットでもコントロールコードは使えないのです。
この制約は英語圏の人々には何の影響もありませんが、日本語では大きな問題となります。
日本語でメールをやり取りする場合、7ビットで表現できるISO-2022-JP文字コード(通称JISコード)が長らく使われてきました。
メール本文はISO-2022-JPで記述できますが、ヘッダには記述できないのです。
ISO-2022-JPは英数字と日本語を切り替えるときにコントロールコードであるESC (1B)を使います。
そのために、Subject(件名)に日本語を使うことができません。
はい、そこの人。使っているよ、と思いましたね。
Subjectに日本語を使うことはできます。
そのためにMIMEエンコードと呼ばれる形式で記述します。
Subject: =?ISO-2022-JP?B?GyRCN29MPiRHJDkhIxsoQg==?=
MIMEエンコードは=?
に始まり?=
に終わります。
途中?
で3つのフィールドに分かれます。
1つ目は、文字コード名を表します。
この例ではISO-2022-JP
です。
2つ目は、エンコード方法です。
この例ではB
(Base64)です。
この他にQ
(Quoted Printable)があります。
3つ目がヘッダの情報です。
この例のGyRCN29MPiRHJDkhIxsoQg==
をBase64でデコードするとISO-2022-JPで「件名です。」になります。
MIME形式
MIMEエンコードのヘッダについて述べましたが、このMIMEとはMultipurpose Internet Mail Exceptionの略で「多目的インターネットメール拡張」と訳されます。
MIMEエンコードのヘッダも、この拡張の一部です。
MIMEを使用するにはメールヘッダに宣言が必要です。
MIME-Version: 1.0
この1.0
はMIMEのバージョンですが1.0しかありません。
MIMEを使うと、本文がどんな形式で記述されているかを明示することができます。
Content-Type: text/plain; charset=UTF-8
この例ではUTF-8コードで本文が記述されています。 UTF-8は8ビットのコードですから、そのままSMTPで送ることができません。 このためにBase64やQuoted Printableで7ビットにエンコードする必要があります。 どのようにエンコードしたかもヘッダに記述します。
Content-Transfer-Encoding: base64
このようにして、1つのメールが完成します。
Date: Fri, 29 Sep 2017 14:32:15 +0900
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
Subject: =?UTF-8?B?44KC44GQ44KC44GQ?=
From: =?UTF-8?B?44GP44KN44KE44GO?= <black@example.com>
To: =?UTF-8?B?44GX44KN44KE44GO?= <white@example.com>
44GV44Gj44GN44Gu44GK5omL57SZ44CB44GU55So5LqL44Gq44GB44Gr77yf
文字コード
多くの場合に日本語のメールにはISO-2022-JPの文字コードが使われています。
この文字コードは7ビットなのでSMTPに乗せやすいのですが、古いので使用できる文字に制限があります。
機種依存文字と呼ばれる記号①や半角カナ、絵文字👍などは扱えません。
またSMTPに乗せやすいと言っても、Subject(件名)などのヘッダにそのまま記述できません。
ヘッダに記述するためにはMIMEが必要です。
みなさん普段は意識せずにSubjectやFrom、Toに日本語を使っているのではないでしょうか?
それはメーラーがMIME形式にして送受信しています。
今時MIMEに対応していないメーラーなんてありません。
OSはユニコードに対応していてUTF-8を扱えない環境もありません。
そこで、日本語のメールはUTF-8にすることを推奨します。
UTF-8にするとISO-2022-JPでは扱えなかった機種依存文字と呼ばれる記号①や半角カナ、絵文字👍などを扱えます。
また、ISO-2022-JPでは英数字と日本語しか扱えませんが、UTF-8では多言語で表現できます。
こんにちは😊
Hello😊
สวัสดี😊
Customer Mail CloudのEmail Sending APIでは標準でUTF-8のメールを送信します。 (ISO-2022-JP も指定できます。)
HTMLメール
先の例のContent-Typeはtext/plain
でした。
これは通常の文字だけのメールです。
表現力が欲しい場合にはHTMLで記述します。
この場合のContent-Typeはtext/html
になります。
HTMLメールは、文字だけの文面と併用することが多くあります。
このために代替可能なマルチパート形式で両方を記述します。
Content-Type: multipart/alternative; boundary="3fieoiur3omcqiw"
--3fieoiur3omcqiw
Content-Type: text/plain
平文の文面
--3fieoiur3omcqiw
Content-Type: text/html
<html><body>
HTMLの文面
</body></html>
--3fieoiur3omcqiw--
代替可能なマルチパート形式は、Content-Typeがmultipart/alternative
になります。
その後に各パートの区切り文字を指定します。
この例では3fieoiur3omcqiw
です。
各パートは、この区切り文字の前に--
を追加して区切ります。
最後は更に後ろにも--
を追加します。
添付ファイル
添付ファイルもマルチパート形式で表現します。
ただし、HTMLメールと異なりパート間で代替の関係では無いのでContent-Typeはmultipart/mixed
になります。
添付ファイルは通常Base64でエンコードします。
Content-Type: multipart/mixed; boundary="3fieoiur3omcqiw"
--3fieoiur3omcqiw
Content-Type: text/plain
平文の文面
--3fieoiur3omcqiw
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-disposition: attachment; filename="attached.data"
ThisIsABase64EncodedData
--3fieoiur3omcqiw--
HTML+添付ファイル
HTMLメールも添付ファイルもマルチパート形式を使用しました。
それでは、HTMLメールに添付ファイルを付けるとどうなるのでしょうか?
Content-Typeが異なるので、そのまま並べることはできません。
ダメな形式
Content-Type: multipart/unknown; boundary="3fieoiur3omcqiw"
--3fieoiur3omcqiw
Content-Type: text/plain
平文の文面
--3fieoiur3omcqiw
Content-Type: text/html
<html><body>
HTMLの文面
</body></html>
--3fieoiur3omcqiw
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-disposition: attachment; filename="attached.data"
ThisIsABase64EncodedData
--3fieoiur3omcqiw--
それでは、どのようにするかと言うとマルチパートを重ねます。
まず、multipart/mixed
で文面と添付ファイルの形にします。
その文面のパートをmultipart/alternative
にして平文とHTMLを共存させます。
正しい形式
Content-Type: multipart/mixed; boundary="3fieoiur3omcqiw"
--3fieoiur3omcqiw
Content-Type: multipart/alternative; boundary="5uifoesjfoewjof"
--5uifoesjfoewjof
Content-Type: text/plain
平文の文面
--5uifoesjfoewjof
Content-Type: text/html
<html><body>
HTMLの文面
</body></html>
--5uifoesjfoewjof--
--3fieoiur3omcqiw
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-disposition: attachment; filename="attached.data"
ThisIsABase64EncodedData
--3fieoiur3omcqiw--
今回は「SMTPによるメール送信の仕組み」で別の機会にと言ったメール本文のフォーマットの話をお送りしました。
Customer Mail CloudのEmail Sending APIでは、このように入り組んだ構造のメールをAPI 1回で送信することができます。 ぜひ活用をご検討ください。