RFC 2920 – SMTP パイプライニング
このRFCが存在する理由
標準的なSMTPは厳密なリクエスト・レスポンスプロトコルです。クライアントは1つのコマンドを送信し、サーバーのレスポンスを待ってから次のコマンドを送信します。各ラウンドトリップはレイテンシを追加し、特に高レイテンシなネットワークリンクでは顕著です。50人の受信者がいるメッセージの場合、クライアントはRCPT TOコマンドだけで50回の個別のラウンドトリップを必要とします。
RFC 2920はPIPELINING SMTP拡張機能を定義しており、これにより、クライアントは個別のレスポンスを待たずに複数のコマンドをバッチで送信できます。サーバーはコマンドをバッファリングして順序通りに処理し、すべてのレスポンスをまとめて送り返します。これにより、SMTPセッションの総時間が大幅に短縮されます。
パイプライニングは最も広くサポートされているSMTP拡張機能の1つです。ほぼすべての最新メールサーバーがこれをアドバタイズしており、ほとんどのSMTPクライアントライブラリはデフォルトで使用しています。
動作方法
- クライアントは
EHLOを送信し、サーバーがそのケーパビリティリストでPIPELININGをアドバタイズしていることを確認します。 - クライアントは、パイプライニングが安全なコマンド(通常、
MAIL FROM、1つ以上のRCPT TO、およびDATA)をグループ化します。 - クライアントは、個別のレスポンスを待たずに、これらすべてのコマンドを連続して送信します。
- サーバーは各コマンドを順序通りに処理し、コマンドごとに1つのレスポンスを順序通りに送り返します。
- クライアントはすべてのレスポンスを読み取り、エラー(例えば、受信者が拒否された場合)を処理します。
SMTPの例
パイプライニングなし(エンベロープの場合5ラウンドトリップ):
パイプライニングあり(エンベロープ全体の場合1ラウンドトリップ):
重要な技術詳細
パイプライニングが可能なコマンド
すべてのSMTPコマンドがパイプライニングに安全とは限りません。RFC 2920はコマンドを2つのカテゴリに分類しています:
| パイプライニング可能 | レスポンスを待つ必要がある |
|---|---|
MAIL FROM |
EHLO / HELO
|
RCPT TO |
STARTTLS |
DATA |
AUTH |
RSET |
QUIT |
NOOP |
DATAコンテンツ(ドット詰めされたボディ) |
接続状態を変更するコマンド(EHLO、STARTTLS、AUTH)は同期ポイントです。クライアントはレスポンスを待ってからその他を送信する必要があります。
エラー処理
パイプライニング時、バッチ内の一部のコマンドが成功し、他は失敗することがあります。クライアントは順序通りにレスポンスをコマンドに一致させる必要があります。拒否されたRCPT TOはトランザクション全体を無効にしません。メッセージはアクセプトされた受信者に配信されます。ただし、MAIL FROMが拒否された場合、その後のRCPT TOコマンドも失敗します。
TCPバッファリング上の考慮事項
パイプライニングはTCPのバッファリングに依存しています。クライアントは読み込まずにソケットに複数のコマンドを書き込み、TCPの送信バッファがそれらを保持できることを信頼します。非常に大量のRCPT TOコマンド(数百または数千)の場合、クライアントはTCPバッファを満たしてデッドロックするのを避けるため、グループ単位でパイプライニングする必要がある場合があります。
STARTTLSとの相互作用
STARTTLSを含むEHLOレスポンス後、クライアントはSTARTTLSを他のコマンドとパイプラインしてはいけません。TLSハンドシェイクは接続全体の状態を変更するため、それは厳密な同期ポイントです。TLSが確立され、新しいEHLOが送信された後、パイプライニングを再開できます。
一般的なミス
-
EHLOまたはSTARTTLSを他のコマンドとパイプライニングする。これらは同期ポイントです。これらをパイプラインするとプロトコルエラーが発生します。サーバーのレスポンスがセッション状態を変更し、その後のコマンドがそれに依存するためです。 - すべてのレスポンスを読み込む前にエラーに対応する。5つのコマンドをパイプラインした場合、最初のものがエラーであっても、5つのレスポンスすべてを読む必要があります。レスポンスストリームを放棄するとプロトコル状態が破損します。
-
すべてのサーバーがパイプライニングをサポートしていると仮定する。ほぼ普遍的ですが、パイプライニングは拡張機能です。使用する前に常に
EHLOレスポンスでPIPELININGを確認してください。ない場合は1つずつモードにフォールバックしてください。 -
MAIL FROMが拒否された後のパイプライニング。MAIL FROMが拒否され、既にRCPT TOコマンドをパイプラインした場合、すべてが失敗します。MAIL FROMレスポンスを読んでから受信者をパイプラインするか、カスケード失敗を処理する準備をしてください。 -
パイプラインにDATAコンテンツを送信する。
DATAコマンド自体はパイプライン可能ですが、その後に続くメッセージボディはできません。DATAに対する354レスポンスを待ってからメッセージコンテンツを送信する必要があります。
配信可能性への影響
- 複数受信者メッセージの配信高速化。パイプライニングにより、N受信者のメッセージがN+2ラウンドトリップから約2ラウンドトリップ(エンベロープフェーズ)に削減されます。高レイテンシな接続では、メッセージごとに数秒の節約になります。
- 大量送信のスループット向上。同じ接続を通じて多くのメッセージを送信する場合、パイプライニングにより現在のメッセージのデータ転送と次のメッセージのエンベロープをオーバーラップさせることができ、接続利用を最大化します。
- 接続時間の短縮。短いセッションは接続を保持する時間が短くなります。これはサーバーが接続ごとの時間制限または接続時間に基づくレート制限を強制する場合に重要です。
- 負荷下でのより良い動作。パイプライニングはネットワークラウンドトリップの数を削減し、送信サーバーと受信サーバーの両方の負荷を削減します。これにより、送信インフラストラクチャがより効率的になります。
-
受信者ごとの拒否は依然として機能する。パイプライニングはサーバーが個々の受信者を拒否する能力を低下させません。各
RCPT TOは依然として独自のレスポンスコードを取得するため、バウンス処理は全く同じように機能します。