連載
» 2001年05月02日 00時00分 UPDATE

インターネット・プロトコル詳説(5):SMTP(Simple Mail Transfer Protocol)〜前編

[梁瀬介次,@IT]

シンプルで複雑なプロトコル「SMTP」

1971年 BBN(Bolt Beranek and Newman, Inc)のRay Tomlinsonが最初のメールシステムを開発
1979年 Eric AllmanがBSD Unixの1コマンドとして、sendmailを開発。オープンソースプロジェクト
による保守/開発がスタート。Allmanは1997年にSendmail Inc,. を設立している
1982年 Jonathan B. PostelによりSMTPが策定される。RFC821(後にSTD10)として公開。
ARPAネットにおける標準メールプロトコルとなる
1994年 J. KlensinほかによるESMTP仕様の公開
表1 SMTPの歴史年表

 SMTPは、一般にインターネットメールの送信プロトコルとして知られている。メーラからメールサーバへメールを送信する際に使用するのがSMTPだ。名前どおり、本連載で扱うプロトコルでも1、2位を争うシンプルなプロトコルであると同時に、最も複雑な動作を強いられるプロトコルでもあるのだ。

RFC821
(STD10)
SIMPLE MAIL TRANSFER PROTOCOL
RFC1869 SMTP Service Extensions
RFC1652 SMTP Service Extension for 8bit-MIMEtransport
RFC1870 SMTP Service Extension for Message Size Declaration
RFC1891 SMTP Service Extension for Delivery Status NotificationsDSN
(Delivary Status Notification:配送通知)オプション
RFC1985 SMTP Service Extension for Remote Message Queue Starting
ETRNコマンドについての定義
RFC2197 Command Pipelining
RFC2554 SMTP Service Extension for Authentication
SMTP-AUTH
RFC2034 SMTP Service Extension for Returning Enhanced Error Codes
拡張リプライコード
表2 SMTP関連の標準仕様

 シンプルかつ複雑とはどういう意味なのか? その答えはSMTPと切っても切れない「メール・ルーティング」というメールサーバにおける隠れた機能にある。

メール・ルーティングにおけるSMTP

 メーラからメールを出す際に、メールサーバへSMTPを用いてメールを送信することは分かってもらえるだろう。では、その後メールはどのようにして相手に届くのか。そこにも何らかの仕組みが存在しているはずだ。そうした仕組みを「メール・ルーティング」と呼ぶ。下の図を見てほしい。

図1 メール・ルーティングにおける配信と転送処理 図1 メール・ルーティングにおける配信と転送処理

 これは、メーラとメールサーバを含めた、メール・ルーティングの構造図だ。実はメールサーバというのは、通常幾つかの機能から成り立っている。大きく分けると「メール配信(Delivery)」機能と「メール転送(Transfer)」機能だ。

 メール配信機能とは、サーバのローカルでユーザーのメールボックスへ間違いなくメールを届ける機能のことだ。通常、メールサーバには、登録されているユーザーのメールを保存しておく、ユーザーごとのメールボックスがある。メールサーバは、自分にどういう名前のユーザーが登録されているか、そのユーザーがどのメールボックスを使用しているかを管理し、あて先メールアドレスから判別して、間違いなく配達する必要がある。これが配信だ。この配信機能は、メールサーバ・アプリケーション固有の機能で、アプリケーションにより動作が異なる。例えばsendmailなどでは、UNIXのユーザー登録の仕組みを利用してメールボックスも管理している。Microsoft Exchange ServerやLotus Notes/Dominoなどでは、別のユーザー管理の仕組み(Active Directory/Domino Directory/LDAPなどのディレクトリ機能)を利用することになる。

 もし、メールに示されたあて先がメールサーバ・アプリケーション自身の管理するユーザーでない場合、そのメールをほかのメールサーバへと送信する必要がある。これが転送だ。単にメール・ルーティングといった場合には、この転送だけを指す場合もある。そしてこの転送で、ほかのメールサーバとの通信に使用されるのがSMTPである。

 また細かく見れば、メール転送は送信機能と受信機能にも分かれる。あるいは、送受信メールを一時的に保管し、実際の転送に備えるキューイングと呼ばれる機能を持つこともある(このための領域を「メールキュー」と呼ぶ)。メールサーバによっては、これらの機能がまったく別々のプログラムによって実装されていたり、同一のプログラムですべて処理していることもある。メーラはこれらの機能を利用させてもらっているというわけだ。つまり、メールの転送依頼が終了すると、その後のメールのルーティングの責任はメールサーバに移行する。これを「配送責任(Responsibilities)」と呼ぶ。

 こうしたメール配信や転送機能を受け持つプログラムを総称して「MTA(Mail Tranfer Agent)」と呼ぶ。メールサーバといわれるものは、このMTAとして定義されている機能を実装したサーバのことだ。厳密には、相手サーバに接続するためのクライアント機能も持つ、複合的なプログラムまたは一連のプログラム群だ。sendmailqmailがこれに該当する。

 逆にこうした機能はいっさい持たず、MTAに依存してユーザーのフロントエンドとしてメールの作成や表示に専念するプログラムをMUA(Mail User Agent)と呼ぶ。いわゆるメーラがこれに該当する。

 古くには、MTAとMUAはもともとは1つのプログラムだった。最も初期のころのメールプログラムでは、同じマシン内のユーザーにのみ送受信を行うような代物だったのだ。SMTPというプロトコルの出現は、メールプログラムに遠く離れたユーザーにもメールを送受信できるという力を与えた代わりに、先に述べたような転送のためのさまざまな機能を必要とした。結果、プログラムは膨大なものとなり、MTAとMUAという2階層に分離するのが最も効率的な運用となったのである。

メールアドレスとルーティング

 では、MTAがどのようにメール・ルーティングを行うのかを見てみよう。この送信処理は、次の段階に分けられる。

(1)MUAからMTAへメール送信を依頼

(2)あて先メールアドレスから送信先MTAを決定する

(3-a)送信先MTAが自身であった場合には、「配信」処理を行う → 送信終了

(3-b)送信先MTAへSMTP接続を行い、送信

(4)送信先MTAが「配信」処理を行う → 送信終了


 MUAから送信を依頼されたメールは、MTAによって「配信」か「転送」かが判別される。判別の根拠となるのが、メールアドレスだ。メールアドレスは一般に次のような書式をとっている。

ユーザー名@メールサーバ名またはドメイン名

 右辺が自分自身を指していれば、自身で管理しているユーザーへメールを配信すればよいし、違うなら該当するMTAへと転送する必要がある。端的に説明すると、左辺が配信に、右辺が転送にかかわっていると思ってもよい。

 ここで、メールサーバ名(FQDN*1)とドメイン名はまったく別物だということに注意してほしい。本来、メールアドレスは右辺にメールサーバ名を有する書式が一般的だった。歴史的経緯によるものだが、ある特定サーバに存在するユーザーは完全にユニーク性を保持できるため、あいまいさはない。この場合は、単にこのメールサーバに接続し、メールを転送すればよい。

 ただし、メールサーバ名は比較的長くなる傾向があるとともに、組織内で管理しているサーバ名やサブドメイン名を外部に漏らしてしまう傾向にある。また、何より「不格好」だという印象が強いと考えられた。そこで、DNSドメイン名を右辺に定義できる仕組みが考案された。DNS MXレコードを使用する方法で、RFC974(STD14)に定義されている。

 本稿では、DNSについて詳しく述べないが、DNSではドメインにおいてMX(Mail eXchange)と呼ばれる種類のレコードで複数のMTAが関連付けられるとともに、各MTAへの「距離*2」が示される。そのドメインあてのメールが転送される場合には、この距離が最も小さく近いMTAがそのドメインの「代表MTA」として、送信元MTAによって選択される決まりになっている。

図2 送信先MTAの決定 図2 送信先MTAの決定

 例えば、上記の例のようなMXレコードでは、最初のMTAが代表MTAとなる。また、距離がまったく同じMXレコードが登録されていることもある。この場合距離は同じなので、どのMTAを選択してもよい。送信元MTAの実装次第だが、ランダムや順番に選択されれば、一種の負荷分散として機能することになる。また、選択されたMTAに何らかの原因で接続できない場合には、次に距離が短いMTAが選択される。つまり、簡易なフェイルオーバーとして機能させることもできる。

 MTAにおけるメール・ルーティングにはもう1つ、複数メールの転送という複雑な動作も伴う。例えば、あて先やCc(カーボンコピー先)として複数のアドレスが指定されていた場合だ。メールのデータから、あて先やCc、Bcc(ブラインド・カーボンコピー)を解析し、上記のようなロジックから転送すべきMTAをすべて洗い出さなければならない。そして、それぞれの転送先ごとにメールを転送するわけだ。

 そのほか、MTAとして動作するためには、送信時に接続に失敗した際の遅延送信や、受信時のためにキューイングを管理して多数のリクエストがあった場合の処理の効率化を図ったり、ユーザー管理を行うためのディレクトリへのアクセス機能なども必要となる。SMTP自身は非常にシンプルなプロトコルでしかない。だが、その役割の実現のためには、こうした複雑な仕組みの実装が必要となるのだ。

*1FQDN:Fully Qualified Domain Name

「完全修飾ドメイン名」などとも訳される。メールサーバ名にDNSドメイン名を完全に付加したDNS上での正式名

例: server1.sub-domain.exsample.com など

DNS上ではユニーク性が保証される


*2この“距離”はよく優先度として紹介されていることもあるが、実際には距離として理解した方が分かりやすい(ただし、原文のRFCでは単なる比較値でしかないとしているが)。例えばあるドメインのエントリに別ドメインのMTAを登録することもできる。あるドメインから、ほかのドメインのMTAへの距離をそれぞれ示すことで、無駄なルーティングをなくすためだが、これはインターネット上のサーバ同士がまだ電話回線などで接続されていたころの名残だ。バス型などと呼ばれる複数の物理ネットワークから成るネットワーク構造では、複数のサーバを経由する可能性があるため、有効な方法である。この複数サーバを経由する方法は「バケツリレー」とも呼ばれ、一時期は非常にポピュラーな方法だった。メッシュ型がほぼ確立された現在では廃れてしまっている


SMTPコマンド

 では、実際のSMTPのプロセスについて見てみることにしよう。

 SMTPも、HTTPなどとよく似たプロトコル構造をしている。まずメールを転送(送信)したい側である転送元MTAから転送先MTAへ接続した後、転送元から「コマンド」と呼ばれる要求文字列が送信される。接続元はこのコマンドに応じて、毎回「レスポンス・メッセージ」を返答する。レスポンスの先頭には3ケタの「リプライコード」が含まれ、このコードによって、成功/不成功が判別できるようになっている。これらもやはり文字列である。

コマンドの書式

コマンド[コマンドごとのオプションキーワードや引数など]

レスポンスの書式

リプライコード[空白]任意のリプライ・メッセージ

 いずれもASCIIコードで示され、文字列の終端はCR(0x0d)+LF(0x0a)である。つまり行のイメージを持っているのもHTTPと同様だ。これら文字列は、MIMEの回でも出てきた7ビットコードである。原則的にSMTPでは7ビットコードしか使用されない。理由はMIMEの回でも述べたとおりだが、通常のSMTPサーバでは8ビットは文字化けを起こしたり(データ欠損)、動作を不安定にする可能性がある。

図3 SMTP通信の例 図3 SMTP通信の例

 上記は実際のSMTP通信例だ。簡単に見えるが、実際にほとんどの場合、以上のような流れだけで通信は完結してしまう。HTTPとは異なり、接続後、複数回のメッセージのやりとりが行われるのが普通だ。また、レスポンスは複数行をとることもあるが、その際、次にも行が続く場合には、リプライコードとリプライ・メッセージの間は空白ではなく、-(ハイフン)を用いる。ただし、できる限りレスポンスは1行に収めることが推奨されている。また、1行の最大文字数は512までにしなければならない。

 最初に、グリーティングと呼ばれる「自己紹介」が行われる。接続先MTAが220リプライコードを用いて自分を名乗ると、接続先MTAはHELOコマンドを用いて、やはり自身を名乗る。次に接続先MTAが250リプライコードを返せば、接続は完了する。これは互いに相手のサーバ名などを確認する作業だ。レスポンス・メッセージでは通常、正常時に250リプライコードを返答することになっているが、コマンドによってはほかのコードが正常終了時に返ることがある。

 次に送信側は、MAIL FROMコマンドとRCPT TOコマンドでメールの送信者とあて先を送信先へ通知する。送信先MTAでは、RCPT TOコマンドで伝えられたアドレスに配信できるかどうかを、通常はこの時点で判断する必要がある。ローカルで受け取るユーザーが存在しているかどうかを調べ、存在していないのであれば、この時点でエラーを返答する。同じMTA上の複数のユーザーにメールを送る場合には、このRCPT TOコマンドは複数回繰り返されることになる。

 次にDATAコマンドを送信し、その後メール・データを送信することを伝える。このメール・データが、前回まで出てきた「インターネットメール・フォーマット」または「MIME」に準拠したメールそのものである。メール・データの最後は必ず.(ピリオド)のみを含んだ行で終結しなくてはならない。こうした行を送信先MTAが検出すると、レスポンス・メッセージを返答する。最後に、QUITコマンドを用いて切断を行う。

 こうした通信内容は、もちろんMUAからの送信依頼時でも何ら変わることはない。そのほかSMTPで用いられるコマンドは別表にまとめたが、SMTP通信ではほとんどの場合、上記コマンドとレスポンスで事足りてしまう。まさに“Simple”メール・プロトコルだ。

メール・メッセージとSMTPの関係

 上記の説明で、ちょっとした疑問がわかなかっただろうか? つまり、メール・メッセージに含まれているToやCc、BccとMAIL FROM、RCPT TOは共有されていないのか、との疑問だ。

 そう、これらは別物として扱われている。SMTPはSMTPであり、SMTP(またはMTA)から見ると、メール・データはヘッダも含めて単に送信するデータでしかない。ヘッダがメール・ルーティングに影響を及ぼすことはまずない(ただし、Received、Date、Message-IDフィールドなど、特定のヘッダにMTAが書き換え、挿入を行うことはある)。ただ、メーラの仕様次第だが、実際にはMAIL FROMやRCPT TOの根拠はもちろん入力されたアドレスからなので、結果的には同じものなのだが。

 また、SMTPから見ると、MAIL FROMとRCPT TOのみが手紙の「表書き」に相当し、ヘッダも含めたメール・メッセージは単に「手紙の中身」になってしまう。このとき、MAIL FROMとRCPT TOを含めて、「エンベロープ(封筒)」と呼ぶことがある。実は、MTAでは多くの場合、MAIL FROMとRCPT TOの表書きも含めてメールボックスなどで管理することになる。ただし、POPなどでメーラに取り込んだ時点でこの表書きは消えてしまうので、利用者が意識することはまずない。

 エンベロープという概念は時折技術書などで登場するので、しっかりその範囲を把握しておこう。



Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。