SMTP の仕組み
DNSルックアップから最終配信まで、SMTP トランザクションの完全なウォークスルー。プログラムでメールを送信する場合、これはあなたが必要とするメンタルモデルです。
全体像
SMTP — シンプルメール転送プロトコル — はインターネット全体でメールを移動させるプロトコルです。RFC 5321 で定義されており、1982年以来(元の RFC 821)メール の基盤となっています。数十年の拡張にもかかわらず、コアトランザクションは依然として TCP ポート 25 上の 2 つのサーバー間の短い、同期的なテキスト会話です。
すべてのメール配信は同じシーケンスに従います:
- DNS ルックアップ — 受信者のメールサーバーを検索
- TCP 接続 — ポート 25(またはサブミッション用の 465/587)に接続
- バナーと EHLO — ID と機能を交換
- STARTTLS — 暗号化接続にアップグレード(通常)
- AUTH — サブミット時に認証(ポート 587)
- エンベロープ — MAIL FROM と RCPT TO
- DATA — メッセージヘッダーとボディを送信
- QUIT — 接続を閉じる
ステップ 1: DNS — メールサーバーの検索
SMTP 会話が始まる前に、送信サーバーはメッセージを配信する 場所 を発見する必要があります。受信者のドメインの MX レコードに対して DNS に問い合わせます。
10 mx1.example.com.
20 mx2.example.com.
数字は 優先度 (低いほど優先)です。送信者は最初に mx1.example.com を試します。到達不可能またはエラーが返される場合、送信者は mx2.example.com にフォールバックします。
MX レコードが存在しない場合、送信者はドメインの A または AAAA レコードにフォールバックします — ただしこれは最後の手段です。明示的な Null MX レコード(0 .)が存在する場合、ドメインはメールを受け入れません。完全なアルゴリズムについては DNS とメールルーティング を参照してください。
ステップ 2: TCP 接続とバナー
送信者は MX ホストのポート 25 への TCP 接続を開きます。受信側サーバーは 220 バナー で最初に話しかけます:
220 mx1.example.com ESMTP ready
ステータスコード 220 は「サービス準備完了」を意味します。サーバーが過負荷の場合、421(サービス利用不可)で応答して接続を閉じることがあります。送信者は後で再試行すべきです。
メッセージ サブミッション(ユーザーのメールクライアントがプロバイダーを通じて送信)の場合、接続はポート 25 の代わりにポート 587(RFC 6409)またはポート 465(暗黙の TLS、RFC 8314)に対して行われます。
ステップ 3: EHLO — 機能の通知
送信者は EHLO(拡張 HELO)で自身を導入し、独自のホスト名を提供します。サーバーはサポートされている拡張で応答します:
250-mx1.example.com Hello sender.mailertogo.com
250-SIZE 52428800
250-8BITMIME
250-STARTTLS
250-AUTH PLAIN LOGIN
250-PIPELINING
250-ENHANCEDSTATUSCODES
250 SMTPUTF8
各 250- 行は拡張を通知します。最後の行は 250 (ダッシュではなくスペース)を使用して終了を通知します。主要な拡張:
- SIZE — バイト単位の最大メッセージサイズ
- STARTTLS — サーバーは TLS へのアップグレードをサポート(RFC 3207)
- AUTH — サポートされている認証メカニズム(RFC 4954)
- PIPELINING — 送信者は待たずにコマンドをバッチ処理できる(RFC 2920)
- ENHANCEDSTATUSCODES — 5.1.1 のような拡張ステータスコード(RFC 3463)
- 8BITMIME — 8 ビットコンテンツ転送がサポートされている
- SMTPUTF8 — 国際化されたメールアドレス(RFC 6531)
レガシーの HELO コマンド(「E」なし)は拡張を完全にスキップします。今日では実際にはほとんど使用されていません。
ステップ 4: STARTTLS — 暗号化へのアップグレード
サーバーが STARTTLS を通知した場合、送信者は接続をアップグレードするコマンドを発行します:
220 2.0.0 Ready to start TLS
# TLS ハンドシェイクがここで発生
# 接続は暗号化されています
# 送信者は暗号化されたチャネル上で再度 EHLO を実行する必要があります
EHLO sender.mailertogo.com
250-mx1.example.com Hello sender.mailertogo.com
250-SIZE 52428800
250 ENHANCEDSTATUSCODES
STARTTLS の後、送信者は 必須 EHLO を再度送信する必要があります。サーバーは暗号化された接続上で異なる拡張を通知する場合があります(たとえば、AUTH は通常 TLS が確立された後でのみ通知されます)。
ポート 465 では、TLS は暗黙的です — 接続は最初のバイトから暗号化されており、STARTTLS ステップは不要です。
TLS がなければ、パスワードとメッセージコンテンツを含む SMTP 会話全体がプレーンテキストで送信されます。最新のベストプラクティスは常に TLS を使用することです。強制メカニズムについては MTA-STS と DANE を参照してください。
ステップ 5: AUTH — 認証(サブミッションのみ)
メールクライアントがポート 587 を通じてメッセージを送信する場合、SMTP AUTH(RFC 4954)を使用して認証します:
235 2.7.0 Authentication successful
Base64 文字列は \0username\0password をエンコードします。これが TLS が重要な理由です — なければ、認証情報は平文で移動します。
ポート 25 のサーバー間配信は AUTH を使用しません。代わりに、受信側サーバーは送信者の IP アドレス、SPF レコード、DKIM 署名、およびその他の認証メカニズムに依存してメッセージを検証します。メール認証の説明 を参照してください。
ステップ 6: エンベロープ — MAIL FROM と RCPT TO
エンベロープ はメッセージヘッダーから分離されています。受信側サーバーにメッセージを誰が送信し、誰が受信するかを伝えます:
250 2.1.0 OK
RCPT TO:<bob@example.net>
250 2.1.5 OK
RCPT TO:<carol@example.net>
250 2.1.5 OK
主な詳細:
-
MAIL FROM は リターンパス(エンベロープ送信者またはバウンスアドレスとも呼ばれる)を指定します。ここに DSN(バウンスメッセージ)が送信されます。
From:ヘッダーと異なる場合があります。 - RCPT TO は各受信者を指定します。1 つのメッセージに複数の RCPT TO コマンドを持つことができます。
- オプションの
SIZE=パラメーターにより、サーバーは大きすぎるメッセージを早期に拒否できます。 -
MAIL FROM:<>(空のリターンパス)はバウンスメッセージ自体に使用され、無限バウンスループを防ぎます。
各コマンドは個別の応答を受け取ります。250 は受け入れられたことを意味します。RCPT TO の 550 はメールボックスが存在しないことを意味します。452 はサーバーが一時的にその受信者を受け入れることができないことを意味します。送信者は各応答を個別に処理する必要があります — 一部の受信者は受け入れられ、他の受信者は拒否される場合があります。
ステップ 7: DATA — メッセージの送信
DATA コマンドはメッセージ送信を開始します:
354 Start mail input; end with <CRLF>.<CRLF>
From: Alice <alice@example.com>
To: Bob <bob@example.net>
Subject: Meeting tomorrow
Date: Tue, 11 Mar 2026 10:30:00 -0400
Message-ID: <abc123@example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Hi Bob,
Are we still on for 2pm?
- Alice
.
250 2.0.0 OK: queued as 4F3A21C8
メッセージにはヘッダーとボディの両方が含まれ、空白行で区切られています。メッセージはピリオド(.)のみを含む行で終了します — 「ドットスタッフィング」規則です。メッセージボディ内のピリオドで始まる行は送信中に追加のピリオドが前に付けられ、受信時に削除されます。
DATA の後の 250 応答はメッセージが 配信のために受け入れられた ことを意味します。受信者のメールボックスに 配信された ことを意味しません。受信側サーバーはコンテンツフィルタリング中に拒否するか、後でバウンスを生成する場合があります。
キュー ID(例:4F3A21C8)はデバッグに非常に貴重です。記録してください。
ステップ 8: QUIT
221 2.0.0 Bye
送信者はセッションを閉じます。TCP 接続が切断されます。送信者が同じサーバーに対してさらにメッセージを持っている場合、QUIT の代わりに別の MAIL FROM を発行して接続を再利用できます。
SMTP レスポンスコード
すべての SMTP レスポンスは 3 桁のコードで始まります。最初の桁はカテゴリを示します:
| コード | 意味 | アクション |
|---|---|---|
| 2xx | 成功 | コマンド完了。進める |
| 3xx | 中間 | サーバーはさらにデータを待機中(例:DATA の後) |
| 4xx | 一時的な失敗 | 後で再試行してください。サーバーは後続の試行でメッセージを受け入れる場合があります |
| 5xx | 永続的な失敗 | 再試行しないでください。メッセージは現状のままでは受け入れられません |
一般的なコード:
-
220— サービス準備完了(バナー) -
250— リクエスト済みのアクションが完了 -
354— メッセージ入力開始 -
421— サービス利用不可、接続を閉じます(後で再試行してください) -
450— メールボックス一時的に利用不可(グレイリスティング、レート制限) -
451— ローカルエラーのため、リクエスト済みのアクションが中止 -
452— ストレージ不足 -
550— メールボックスが見つかりません/アクションが実行されません -
551— ユーザーはローカルではありません。転送アドレスを試してください -
552— メッセージサイズが制限を超えています -
553— メールボックス名は許可されていません -
554— トランザクション失敗(ポリシー拒否に使用されることが多い)
ENHANCEDSTATUSCODES を使用する場合、サーバーは 5.1.1(不正な宛先メールボックス)のようなより具体的なコードを追加します。詳細な内訳については メールバウンスの理解 を参照してください。
完全なトランザクション
接続から閉じるまでの全 SMTP セッションが注釈付きで以下の通りです:
220 mx1.example.net ESMTP Postfix
# 2. クライアントが自身を導入
EHLO sender.mailertogo.com
250-mx1.example.net
250-STARTTLS
250-SIZE 26214400
250-PIPELINING
250-ENHANCEDSTATUSCODES
250 8BITMIME
# 3. TLS にアップグレード
STARTTLS
220 2.0.0 Ready to start TLS
# (TLS ハンドシェイク完了)
# 4. 暗号化されたチャネル上で再度導入
EHLO sender.mailertogo.com
250-mx1.example.net
250-SIZE 26214400
250-PIPELINING
250-ENHANCEDSTATUSCODES
250 8BITMIME
# 5. エンベロープ
MAIL FROM:<notifications@app.example.com>
250 2.1.0 OK
RCPT TO:<bob@example.net>
250 2.1.5 OK
# 6. メッセージコンテンツ
DATA
354 End data with <CR><LF>.<CR><LF>
From: App Notifications <notifications@app.example.com>
To: bob@example.net
Subject: Your invoice is ready
Date: Tue, 11 Mar 2026 14:00:00 +0000
Message-ID: <inv-7842@app.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Your March invoice is ready. Log in to view it.
.
250 2.0.0 OK: queued as B9C4E1A3F
# 7. 完了
QUIT
221 2.0.0 Bye
サブミッション vs リレー
SMTP は 2 つの異なる役割を提供します:
- サブミッション(ポート 587 または 465): メールクライアントが新しいメッセージをメールサーバーに送信します。認証が必要です。サーバーが配信の責任を引き受けます。
- リレー(ポート 25): あるメールサーバーが別のメールサーバーにメッセージを配信します。認証なし — 認可は DNS(MX レコード)と送信者検証(SPF、DKIM)から来ます。
オープンリレー — 誰からでも誰にでもメールを受け入れるサーバー — はメール設定の致命的な罪です。スパマーはオープンリレーをすぐに悪用します。すべての最新メールサーバーはリレーを認証ユーザーまたは既知の送信者に制限する必要があります。
何が悪くなる可能性があります
接続が拒否されたかタイムアウト
MX ホストがダウンしているかファイアウォールで保護されています。送信者のキューは指数バックオフで再試行し、優先度の低い MX レコードをサイクルします。再試行期間(通常 4~5 日)の後、メッセージはバウンスします。
グレイリスティング
受信側サーバーは未知の送信者からの最初の試行に対して 450 を返します。正当なサーバーは再試行します。スパマーは通常はしません。メッセージは数分遅延しますが、最終的に配信されます。
RCPT TO で拒否
550 5.1.1 User unknown の応答はメールボックスが存在しないことを意味します。これは硬いバウンスです。リストから即座にアドレスを削除してください。
DATA で拒否
サーバーはエンベロープを受け入れるがコンテンツを拒否する場合があります。一般的な理由: メッセージが大きすぎる、スパムとしてフラグが立てられたコンテンツ、または失敗した認証チェック(SPF/DKIM/DMARC)。応答は終了ピリオドの後に来ます。
受け入れられてからバウンス
サーバーは DATA に対して 250 を返しますが、メールボックスがクォーオーバー、コンテンツフィルタリングが拒否、または内部エラーが発生したため、後に DSN(バウンスメッセージ)を生成します。これは処理するのが最も難しい場合です — MAIL FROM アドレスに送信されるバウンスメッセージを通じてのみ見つけることができます。
TLS 失敗
STARTTLS ネゴシエーションが失敗する場合、ほとんどのサーバーはプレーンテキストにフォールバックします。これはセキュリティリスクです — アクティブな攻撃者は TLS を削除できます。MTA-STS と DANE はこのダウングレードを防止します。
主要なポイント
- SMTP は同期的でテキストベースのプロトコルです。すべてのコマンドはレスポンスコードを取得します。
- エンベロープ(MAIL FROM/RCPT TO)はメッセージヘッダー(From:/To:)から分離されています。異なる場合があります。
- DATA の後の
250は「配信のために受け入れられた」を意味し、「受信トレイに配信された」ではありません。 - 4xx エラーは一時的です — 再試行してください。5xx エラーは永続的です — 再試行しないでください。
- 常に TLS を使用してください。MTA-STS または DANE で強制してください。
- デバッグのためにサーバーレスポンスからキュー ID を記録してください。