y-matsui::weblog

電子楽器、音楽、コンピュータ、プログラミング、雑感。面倒くさいオヤジの独り言

SMTPについて

これまでメールサーバーの構築・運用でしか接していなかったSMTPについて、今回のお仕事で、プログラマの視点から眺めることが出来た。今回以前は、プログラムからメールを送信する際には、言語で用意されているメソッドを利用していたため、mailsend(to,from,subject,body)みたいな部分しか分かっていなかったのである(汗)
PHPやLotusScript、BASP21を使ったASPプログラムなど・・。

SMTPコマンドのレベルからメール送信を眺めてみると、非常に面白い仕組みであることが分かる。

例えば、コマンドとしてHELO(接続確認)、MAIL(TO)、RCPT(FROM)、DATA(Subjectと本文)、RSET(処理のクリア)、QUIT(切断)なんていうのがあるので、普通なら
HELO→MAIL→RCPT→DATA→QUITと1通ごとに切断を接続を繰り返すように作りたいところ。
しかし、コネクションを接続する部分で7秒くらい掛かることが判明し、1通あたり最低でも7秒掛かってしまうことに気づく。コネクション完了以降切断までは1秒も掛からないので、これはもったいない。しかもコネクションというのは、ネットワークの混雑などの外部要因に左右されるので、システムとして性能を保証できない。

そこで、telnetコマンドを使って、ひとつずつコマンドを発行しながら応答を見てみると、本文データを書き終わって最後にドットを入れてリターンを押すと、即座にメールが飛んでくるではないか!
つまり、コネクションを切らなくても、メールサーバーはメールをキューイングした上で、そそくさと送信してしまう仕様らしい。
「コネクションしたら、連続でMAIL〜DATAまでの処理をループすれば、コネクションのための長い時間ロスを回避できる」エラーを検出したらまた同じところを繰り返してやれば、信頼性も確保できるだろう。
クラスや外部モジュールを使っている分には、絶対に気づかないことなのだが(何故なら1通づつコネクションを張っては、切断する仕様だろうから)、コマンドレベルで動作が分かるからこそ、高速に処理する方法が分かるということ。
メール関連のプログラムを組んでいる人からすれば当たり前の事実かもしれないが、自分としては大きな発見であった。

結果は、
・1通1通を素直にコネクションして送信した場合で、7秒/通
・1回のコネクションで複数メッセージを送信した場合で、0.3秒/通
なんと20倍の速度差。
こうなると今度はsendmailqmailなどのサーバーアプリの仕組みも気になってくるというもの。
メール転送プログラムが動いているLinuxサーバー上で、ローカル配信のスピードで処理できるプログラムをアタッチできれば、最強のパフォーマンスを得られるはずだからである。
ローカル配信に見せかけて、sendmailにメッセージを挿入しちゃうプログラムを作れば、コネクションの時間が不要になり、ネットワーク転送の時間も不要。
やっぱメールって面白い。