レンタルサーバーを借りてメールサーバーを構築している方もいると思いますが、メールの送信に使われる代表的なプロトコルが「SMTP(Simple Mail Transfer Protocol)」です。
今回は SMTP プロトコルの「仕組み」や「内部動作」について調べてみました。
SMTPプロトコルの動作
SMTPプロトコルは「TCP/IP」を基に実装された「クライアント」と「サーバー」間で TCP プロトコルを使用してメッセージを交換するプロトコルです。
「TCP」の他には「UDP」プロトコルがあります。
また、「IP」プロトコルと「ICMP」プロトコルは「階層」が異なります。
- OSIモデル 4層(トランスポート層):TCP、UDP
- OSIモデル 3層(ネットワーク層):IP、ICMP
- TCP/IPモデル(トランスポート層):TCP、UDP
- TCP/IPモデル(インターネット層):IP、ICMP
SMTPは要求・応答プロトコルによってメッセージを転送します。
SMTPクライアントは、サーバーにテキストベースのコマンドを送信します。
SMTPサーバー(メールサーバー)はクライアントから送信されたコマンドへの応答としてコマンドが「成功」か「失敗」かコードをリプライします。
「仕組み」や「内部動作」について” width=”431″ height=”509″ />
上記の SMTP クライアントと SMTP サーバーの通信を確認すると分かりますが、相手からリプライが返ってくるまで次のコマンドを発行しません。
つまり「シーケンシャル(sequential、連続的な、逐次的な、一連の)」です。
※逐次的(ちくじてき)とは、一歩一歩進むという意味です。
SMTP リプライコード(応答コード)
更に詳しくいうと、SMTP クライアントから STMP サーバーへ要求(コマンド)を発行しますが、コマンドを投げると SMTP サーバーより「リプライコード」が返ってきます。
クライアントは、リプライコードが返ってくるまで次のコマンドを発行しません。
このようにして「SMTPクライアント」と「SMTPサーバー」は同期を取っています。
応答コードは「成功」か「失敗」かを返しますが、「250」や「450」など3桁の数字で表します。
- 2xx系のリプライコード ← ポジティブ系(成功)
- 4xx系のリプライコード ← ネガディブ系(失敗)
- 5xx系のリプライコード ← ネガティブ系(失敗)
SMTPのコマンド
SMTPのコマンドには大文字・小文字の区別はありません。
「helo」も「HELO」も同じコマンドとして扱われます。
以下、主な SMTP コマンドの解説です。
HELO コマンド
HELO コマンド(HELLOではありません)は、SMTP サーバー(メールサーバー)に対して SMTP クライアントが自分自身を知らせるためのもので「自己紹介」に近いです。
HELO コマンドの後ろにはドメイン名が続きます。
その結果、SMTP サーバーに SMTP クライアントを特定させることができます。
MAIL コマンド
MAIL コマンドで発信元(SMTP クライアント)のメールアドレスを SMTP サーバーに知らせます。
コマンドは「MAIL FROM:xxx@xxx.xx」の形式で記述します。
このメールアドレスはエラーになった場合にエラーメールを返すために使います。
RCTP コマンド
RCTP コマンドはメッセージの宛先のメールアドレスを指定するために使います。
- MAIL コマンド ← エラーメールを返すメールアドレス(通常は SMTP クライアントのメールアドレス)
- RCTP コマンド ← 宛先のメールアドレス(ここにメールを送ります)
コマンドは「RCTP TO: xxx@xxx.xx」の形式で記述します。
また、「MAIL」コマンドと「RCTP」コマンドで指定するメールアドレスが本当のメールアドレスと言っていいのか分かりませんが、
- エンベロープ From ← MAIL コマンドで指定した送信元メールアドレス
- エンベロープ To ← RCTP コマンドで指定した送信先メールアドレス
と呼びます。
■メールの仕組み
上図のメールの仕組みを見ると分かりますが、メールは「エンベロープ」と「メッセージ」に分かれており、「メッセージ」の「To:」と「From:」は自由に書き替えることができます。
「メッセージ」の方の「To フィールド」や「From フィールド」は、自由に書きかえることができますが、こっちは本当の「送信元メールアドレス」「送信先メールアドレス」ではなく、あくまでも「メッセージの一部」としての扱いになります。
郵便に例えると「To フィールド」を見て配達するのではなく「エンベロープ To」のアドレスに配達をするイメージです。
DATA コマンド
DATA コマンドは SMTP クライアントが SMTP サーバーに対してデータ送信可能なことを知らせるためのコマンドです。
SMTP サーバーは、この DATA コマンドを受けてリプライコード「354」を返すと、SMTP クライアントはメッセージを MIME フォーマット化して、メッセージの各行を「復帰改行」コードで区切ります。
復帰改行とは
復帰改行は2つの動作が合わさっています。
- 復帰(CR、キャリッジリターン、Carriage Return) ← カーソルを文頭に戻すこと
- 改行(LF、ラインフィード、Line Feed) ← カーソルを次の行に移動すること
この2つが合わさって「復帰改行(カーソルを文頭に持ってきて、次の行に移動させる)」になります。
Carriage とは「乗り物、車、タイプライターのキャリッジ」という意味です。
タイプライターの「キャリッジ」と言われてもピンとこないと思うので、キャリッジを赤い枠で囲みました。
昔の映画などで見たことがあるかもしれませんが、タイプライターで文字をカタカタと打つと上のキャリッジが右側に移動します。
キャリッジが右側に動き切ったらキャリッジをリターン(元の位置に戻す)します。
これがキャリッジリターン(復帰)です。
ラインフィードとは、タイプライターの動きとしては、紙を1行分送る行為になります。
その結果、キャリッジリターンをしても文字が重なりません。
ラインフィードをしないと、文字の上に文字をタイプすることになります。
この「キャリッジリターン」と「ラインフィード」が合わさって「復帰改行」になりました。
話が少々飛びましたが、DATA コマンドを送信後、SMTP サーバーからリプライコード「354」が返ってきたら SMTP クライアントはメッセージを送ります。
メッセージは、各行を復帰改行(キャリッジリターン&ラインフィード)コードで区切って送ります。
メッセージを終了する場合は「.(ドット)」だけからなる1行を SMTP サーバーに送るとメッセージの終了と判断されます。
QUIT コマンド
QUIT コマンドは「SMTP サーバー」と「SMTP クライアント」間のセッションを終了するためのコマンドです。
SMTP クライアントがメッセージの送信終了のリプライコードを受信後に、QUIT コマンドを SMTP サーバーへ送信します。
SMTP サーバーはこの「QUIT コマンド」を受信後にリプライコードを SMTP クライアントに返して接続を切ります。
SMTP サーバーと SMTP クライアントの通信手順図
上のコマンドを含めた SMTP サーバーと SMTP クライアントの通信手順を図にしました。
参考
RFC821 日本語訳 ← 古い仕様になります。
http://pentan.info/doc/rfc/j821.html
RFC 2821 日本語訳 ← これも古い仕様になります。
http://srgia.com/docs/rfc2821j.html
RFC 5321 日本語訳 ← 新しい仕様です。
http://srgia.com/docs/rfc5321j.html
参考にした本
かなり詳しくプロトコルの動作を解説しています。
C言語でのサンプルプログラム&プログラムの解説があるので内部動作に関しても詳しく勉強できるのでおすすめです。
コメント