【メール入門 第2回】SMTPのやり取り ― コマンドと応答・リプライコード・再送キュー・バウンス

メールサーバー
スポンサーリンク
スポンサーリンク

「送ったメールが『554 5.7.1』で返ってきました。何が悪いんでしょう?」
「数時間遅れてメールが届いたんですけど、どこで止まっていたんですか?」

メールのトラブルでは、エラーの数字や遅延の理由を聞かれることがよくあります。実は、これらはSMTPの会話の仕組みを知っていれば、かなりの部分が読み解けます。

第1回では、メールが届くまでの全体像と登場人物を見ました。第2回では、サーバー同士が実際にどんな会話(コマンドと応答)でメールを渡しているかを見ていきます。エラーコードの読み方、再送の仕組み、バウンスまで押さえましょう。


SMTPとは ― コマンドと応答の対話

SMTP(Simple Mail Transfer Protocol)は、メールを次のサーバーへ渡すためのプロトコルです。

1982年のRFC 821から2008年のRFC 5321までのSMTPの歩みと、クライアントがコマンド、サーバーが3桁の数字で答えるテキストの対話であることと、送信・中継・受信の区間ごとに受け渡し、区間2のRCPT TOで550で拒否されることがあることを示す図
  • 1982年のRFC 821に始まり、2001年のRFC 2821、2008年のRFC 5321と改訂されてきた
  • 1995年にEHLOで機能を足せるESMTPの仕組みが加わり、暗号化や認証などの拡張が積み重なって今の形になった
  • RFC 5321の後継(rfc5321bis)は、2026年9月時点でRFCとしての発行待ち

SMTPの特徴は、人が読めるテキストの対話である点です。接続した側(クライアント)がコマンドを1行ずつ送り、受けた側(サーバー)が3桁の数字で始まる応答を返します。

また、SMTPは1区間ごとの受け渡しで、受け取ったサーバーが責任を引き継いで次へ送ります。そのため「どの区間の、どのコマンドで失敗したか」を特定できます。会話がテキストなので、ログから当時のやり取りを再現できるのも利点です。


セッションの流れ

SMTPの会話(セッション)は、次の順に進みます。

SMTPクライアントがTCPで接続して220の挨拶を受け、EHLOで名乗り、STARTTLSの後にEHLOをやり直し、MAIL FROM・RCPT TO・DATAで1通を送って250 queued asを受け取り、QUITで閉じる流れを示す図
  1. クライアントがサーバーの25番などにTCPで接続すると、サーバーはまず220の挨拶を返す
  2. クライアントはEHLOで自分の名前を名乗り、サーバーは対応している拡張機能の一覧を返す
  3. 暗号化する場合は、ここでSTARTTLSを送ってTLSに切り替え、EHLOからやり直す(第4回)
  4. MAIL FROMで差出人(エンベロープFrom)を、RCPT TOで宛先を1件ずつ伝える。宛先ごとに成否が返るため、一部だけ拒否されることもある
  5. DATAを送ると、サーバーは354で本文を待つ。クライアントはヘッダーと本文を送り、ピリオドだけの行で終わりを示す
  6. サーバーが250を返した時点で、メールの責任はサーバーに移る
  7. 同じ接続で次のメールを送ることもでき、最後はQUITと221で閉じる

エラーの応答がどの行で返ったかで、止まった段階が分かります。


やり取りの実例

実際の会話は、こんな感じです(Postfixの公式の例をもとに作成。C:はクライアント、S:はサーバー)。

S: 220 mx1.example.com ESMTP Postfix
C: EHLO mail.example.jp
S: 250-mx1.example.com  …(拡張の一覧は後述。最後の行は「250 CHUNKING」)
C: MAIL FROM:<taro@example.jp>
S: 250 2.1.0 Ok
C: RCPT TO:<hanako@example.com>
S: 250 2.1.5 Ok
C: RCPT TO:<nobody@example.com>
S: 550 5.1.1 <nobody@example.com>: Recipient address rejected: User unknown in local recipient table
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: …(ヘッダー・空行・本文。第3回)
C: .
S: 250 2.0.0 Ok: queued as 763402AAE6
C: QUIT
S: 221 2.0.0 Bye
  • nobodyだけが550で拒否され、hanakoには届きます。宛先ごとに成否が決まる
  • queued asの後ろは受信側のキューID。相手の管理者にこのIDと時刻を伝えると、先の配送を追ってもらえる(第8回)

自分でSMTPを話して確かめる方法は、第9回で扱います。他社のサーバーで無断に試さないでください。


主なコマンド

コマンド役割主な応答補足
EHLO/HELO名乗る。EHLO は拡張の一覧も求める250今は EHLO を使う。HELO では拡張が使えない
MAIL FROM:<アドレス>差出人(エンベロープ From)を伝え、1通を始める250、550、553バウンスの返送先になる。<> は空の差出人
RCPT TO:<アドレス>宛先を1件伝える250、450、550宛先の数だけ繰り返す。Cc・Bcc も含む
DATA本文の送信を始める354 → 250ピリオドだけの行で終わる
BDAT 大きさ [LAST]大きさを指定して本文を送る250CHUNKING 拡張(RFC 3030)。DATA の代わり
RSET/NOOP途中の1通を取り消す/何もしない(生存確認)250RSET は接続を保ったままやり直す
QUIT終了する221
STARTTLS/AUTHTLS への切り替え/送信者の認証220/235EHLO の応答にあるときだけ使える(第4回)
VRFY/EXPNアドレスの確認/メーリングリストの展開250、252、550アドレスの収集に悪用されるため無効にすることが多い

VRFY・EXPNに答えると、存在するアドレスを外部から一覧できてしまいます。RFC 5321は無効にしてよいとし、その場合は成否をはぐらかす252を返すよう定めています。Postfixの既定はdisable_vrfy_command = no(VRFYが有効)なので、インターネットに面したサーバーではyesにするのが定番です。


本文の終わり「.」と行の決まり

本文の終わりはCRLF . CRLFで、本文に「.」だけの行があるときは送るとき「..」にして受けたとき「.」に戻すドットスタッフィングと、LF . LFを混ぜて1通の中に偽のメールを仕込み解釈の違う受信サーバーで2通に化けさせるSMTPスマグリングを示す図
  • 本文の終わりは、CRLF(改行)、ピリオド、CRLFの並びで示す
  • 本文にピリオドだけの行があるときは、送る側が行頭のピリオドをもう1つ足して送り、受ける側が1つ取り除く(ドットスタッフィング)
  • SMTPの1行は、CRLFを含めて1000オクテット以内。長い行は折り返すか、MIMEで符号化する(第3回)

この「終わりの印」の解釈の違いを突いたのが、2023年12月に公表されたSMTPスマグリングです。LFだけの改行を混ぜて、1通の中に仕込んだ偽のメールを、受信側に別のメールとして受け取らせ、送信ドメイン認証をすり抜けます。Postfixは3.9から、終わりの印に正しいCRLFを求める設定(smtpd_forbid_bare_newline = normalize)を既定にしました。MTAは更新しておきましょう。


EHLOの応答を読む

C: EHLO mail.example.jp
S: 250-mx1.example.com
S: 250-PIPELINING
S: 250-SIZE 10240000
S: 250-VRFY
S: 250-ETRN
S: 250-STARTTLS
S: 250-ENHANCEDSTATUSCODES
S: 250-8BITMIME
S: 250-DSN
S: 250-SMTPUTF8
S: 250 CHUNKING

(Postfixの既定に近い25番の応答。Postfix 3.11 の実機の応答と同じ並びで、名前と SIZE の値は既定に置き換えたもの)

  • 250-は続きがある、最後の行だけ250 (空白)で終わる
  • 1行目はサーバーの名前、2行目以降が対応している拡張。一覧に無い拡張は使えない。disable_vrfy_command = yes にしたサーバーでは 250-VRFY の行が消える
  • SIZE 10240000は受け付ける最大の大きさ(Postfixの既定のmessage_size_limit、約10MB)。添付はbase64で約1.37倍になるため、実際に送れる添付は約7MB
  • STARTTLSの後にEHLOをやり直すと、一覧が変わる。サブミッションのポートでは、TLSの後にだけAUTHが現れるのが普通で、Postfix 3.11のREQUIRETLSもTLSの後に現れる(第4回)

「10MBの添付が送れない」と言われたら、このSIZEとbase64の増え方を思い出してください。

主なESMTP拡張

目的キーワード規格内容
大きさと上限SIZE・LIMITSRFC 1870・RFC 9422最大の大きさを示し、MAIL FROM で大きさを先に申告できる。LIMITS は1通の宛先数(RCPTMAX)、1接続の通数(MAILMAX)などの上限を知らせる
文字8BITMIME・SMTPUTF8RFC 6152・RFC 65318ビットの本文を送れる。UTF-8 のアドレス・ヘッダーを送れる(第3回)
効率PIPELINING・CHUNKINGRFC 2920・RFC 3030応答を待たずにコマンドをまとめて送る。BDAT で本文を大きさ指定で分けて送る
暗号化STARTTLS・REQUIRETLSRFC 3207・RFC 8689途中から TLS に切り替える。経路のすべてで TLS を求める(第4回)
認証AUTHRFC 4954送信者を認証する(PLAIN・LOGIN・XOAUTH2 など。第4回)
エラーと通知DSN・ENHANCEDSTATUSCODESRFC 3461・RFC 2034配送通知の条件(成功・失敗・遅延)を指定する。x.y.z の拡張ステータスコードを返す

拡張は、サーバーがEHLOの応答で示し、クライアントが使うかどうかを選びます。たとえば相手に8BITMIMEが無ければ、送信側は本文をbase64などの7ビットに変換してから送ります。なお、LIMITS(2024年2月)は新しい拡張で、対応はまだ限られます(Postfix 3.11のsmtpd(8)が挙げる対応規格には含まれません)。


リプライコードの読み方

ここがトラブル対応でいちばん役に立つところです。

550 5.1.1のような応答がリプライコード・拡張ステータスコード・人向けの文言からなり、2xxは成功、3xxは途中、4xxは一時的な失敗でキューに残して再送、5xxは恒久的な失敗でバウンスになることと、拡張ステータスコードx.y.zの分類を示す図
1桁目意味送信側の動きよく見る例
2xx成功次へ進む220 挨拶、221 切断、250 成功、252 確認はできないが受け付ける
3xx途中(続きを待つ)続きを送る354 本文をどうぞ、334 認証の続き
4xx一時的な失敗キューに残して後で再送421 切断・サービス停止、450・451 一時的な拒否・処理エラー、452 容量不足
5xx恒久的な失敗再送せず、送信者へ返す500・501 構文エラー、530 認証が必要、550 宛先不可・ポリシーで拒否、552 大きすぎる、554 失敗
  • 2桁目は分類(x0z 構文、x1z 情報、x2z 接続、x5z メールシステム。x3z・x4zは未定義)、3桁目はさらに細かい区別
  • 後ろの文言は人間向けで、製品ごとに違う。ソフトは数字だけで判断するため、ログを読むときもまず1桁目を見る
  • RFC 7504で、受け取らないことを示す521(ホスト)・556(ドメイン、Null MX)が加わった
  • 数字の意味は、RFC 5321の4.2節にまとまっている

拡張ステータスコード(x.y.z)

リプライコードの後ろの5.1.1のような番号が、拡張ステータスコード(RFC 3463)です。

2番目(y)分類例
0その他2.0.0 成功
1アドレス5.1.1 宛先不明、5.1.10 Null MX
2メールボックス4.2.2 満杯
3メールシステム5.3.4 大きすぎる
4ネットワーク・経路4.4.1 応答なし、4.4.7 期限切れ
5配送のプロトコル5.5.3 宛先が多すぎる
6内容・形式5.6.x 変換できない等
7セキュリティ・ポリシー5.7.1 拒否、5.7.8 認証失敗、5.7.26 認証検査の失敗
  • 1番目(x)は2 成功、4 一時的、5 恒久的で、リプライコードの1桁目と合わせる
  • 3番目(z)が詳細。番号の登録簿は、RFC 5248に基づいてIANAが管理している
  • よく見る例:550 5.1.1ユーザー不明、554 5.7.1中継やポリシーでの拒否、535 5.7.8認証情報の誤り、550 5.7.26SPF・DKIMなど複数の認証検査に失敗
  • 満杯は本来4.2.2(一時的)だが、552 5.2.2と恒久的に返す実装も多い

Microsoft 365の5.7.515(送信ドメイン認証の要件を満たさない)のように、事業者が独自に細かく分けた番号もあります。登録簿に無い番号は、その事業者のドキュメントで意味を確かめましょう。


4xxと5xx、再送キュー

冒頭の「数時間遅れて届いた」の答えがここです。

送信側再試行の間隔遅延の通知あきらめるまで
RFC 5321 の推奨30分以上実装しだい4〜5日以上
Postfix(既定)5分から倍々に延ばし最大約67分(300〜4000秒)送らない(delay_warning_time = 0h)5日(maximal_queue_lifetime)
Exchange Server(既定)接続の失敗後は10分ごと(Edge Transport は30分)4時間後2日(MessageExpirationTimeOut)
Exchange Online24時間にわたり再試行(記載なし)24時間後に 550 4.4.7 の NDR
  • 4xxを受けた送信側は、キューに残して再試行する。受信側の混雑、グレイリスティング(第7回)、DNSの一時的な失敗などが原因
  • 5xxは再試行しない。MTA同士なら送信側が送信者へバウンスを返し、メールソフトからの送信なら画面にエラーが出る
  • Postfixのsoft_bounce = yesは、5xxを4xx扱いにしてメールを失わないための試験用の設定。戻し忘れると、届かないメールが何日もキューに溜まる

「数時間遅れて届いた」「数日後にエラーが返ってきた」は、この再送の仕組みで説明できます。キューの見方は第8回で扱います。


バウンス(DSN・NDR)とバックスキャッター

受け付けた後に配送できなかったメールは、送信者へエラーのメール(バウンス)として返されます。

正しいバウンスでは受信サーバーが宛先不明を送信者AへMAIL FROM:<>で返すが、迷惑メール業者が差出人を無関係のBと偽って送り、受信サーバーがいったん受け付けてから宛先不明を返すと、Bに大量のエラーメールが届くバックスキャッターになり、RCPT TOの時点で550で断れば起きないことを示す図
  • 規格上はDSN(Delivery Status Notification、配送状況通知)と呼び、形式はRFC 3464が定める。MicrosoftはNDRと呼ぶ
  • 人向けの説明、機械向けの状態、元のメール(またはヘッダー)の3部分からなる
  • 返送先はヘッダーのFromではなく、エンベロープFrom(MAIL FROM)。バウンス自体はMAIL FROM:<>(空の差出人)で送って、ループを防ぐ

問題になるのがバックスキャッターです。差出人を偽った迷惑メールをいったん受け付け、後から「宛先不明」を返すと、偽られた無関係の人に大量のエラーメールが届きます。受け付けてから返すと、自分が迷惑メールの送り手になってしまうのです。

防ぐには、存在しない宛先を受け付けてから返すのではなく、RCPT TOの時点で5xxで拒否します。


小ネタ:同じ554 5.7.1でも原因は別

冒頭の「554 5.7.1で返ってきた」の答えです。実は、同じ番号でも原因はまったく別のことがあります。

例1 554 5.7.1 <user@example.com>: Recipient address rejected: Access denied
例2 554 5.7.1 <user@example.com>: Relay access denied
例3 554 5.7.1 Service unavailable; Client host [203.0.113.25] blocked using zen.spamhaus.org
  • 例1:宛先の制限。受信側の設定(アクセス表など)で、その宛先が受け付けられない
  • 例2:中継の拒否。担当外のドメイン宛てを、許可されていない接続元から中継させようとした。新しく立てた機器の通知メールで最も多い(第8回・第11回)
  • 例3:送信元IPアドレスの評判。接続元がブロックリスト(DNSBL)に載っている(第7回)

原因は、文言まで読まないと分かりません。なお、Postfixの既定(smtpd_relay_restrictionsのdefer_unauth_destination)では中継の拒否は454 4.7.1(一時的)になり、送信側は再送を続けます。554になるのはreject_unauth_destinationを使う設定です。


考えてみよう

  1. 職場のメールサーバーのEHLOの応答には、どんな拡張が並んでいると思いますか。25番と587番で違いはあるでしょうか。
  2. 送信したメールが相手に「450 4.7.1」で断られ続けた場合と、「550 5.1.1」で断られた場合、送信者が受け取る結果とタイミングはどう違いますか。
  3. 自社の受信サーバーは、存在しない宛先のメールをRCPT TOの時点で拒否していますか。いったん受け付けてから返していると、何が起きますか。

ヒント:この記事の「EHLOの応答を読む」、「4xxと5xx、再送キュー」の表、「バックスキャッター」が手がかりです。


まとめ

  • SMTPはコマンドと3桁の応答のテキスト対話。1区間ずつ受け渡す
  • セッションは220→EHLO→MAIL→RCPT→DATA→.→QUIT。RCPT TOは宛先ごとに成否が返る
  • 応答は1桁目で動きが決まる。4xxは再送、5xxはバウンス
  • 拡張ステータスコードx.y.zの2番目で分類が分かる。同じ番号でも文言まで読む
  • 存在しない宛先はRCPT TOで拒否して、バックスキャッターを防ぐ
  • SMTPスマグリング対策のため、MTAは更新しておく

次回は、DATAで送られる「中身」、つまりヘッダーと本文の構造を見ます。


連載「メール入門」全12回

  1. メールが届くまで
  2. SMTPのやり取り(この記事)
  3. メッセージの構造
  4. ポートと暗号化・認証
  5. 送信ドメイン認証 前編
  6. 送信ドメイン認証 後編
  7. 迷惑メール対策と配信
  8. MTAの運用
  9. コマンドで調べる
  10. クラウドと現代のメール
  11. メールのトラブルシュート
  12. メールの設計演習

コメント

タイトルとURLをコピーしました