Ruby で疑似メールサーバを作ってみた
昨日、静岡まで富士山を見に行ってきた suzuki です。雲が晴れるまで、40分くらい待って、写真を撮ってきました。
さて、今回は Ruby で擬似的なメールサーバを紹介してみます。
大量のメール配信の負荷テストと同時にエラーメールの処理テストを行いたい時があり、作ってみたプログラムです。このプログラムは次のようなイメージで使います。

まず、メールサーバからメールを送信し、一定の割合で疑似メールサーバがエラーを返します。すると、そのエラーメールをメールサーバからエラーメール処理サーバへ渡すようなイメージになります。
プログラムは、こちら。
■dummy-smtpd.rb
#!/bin/env ruby
require 'socket'
require 'syslog'
# port number
port = 25
# randmax 100 means => about 1 / 100
randmax = 100
gs = TCPServer.open(port)
addr = gs.addr
addr.shift
syslog = Syslog.open('dummy-smtpd', Syslog::LOG_PID | Syslog::LOG_USER)
syslog.log(Syslog::LOG_INFO, sprintf("server is on %s", addr.join(":")))
while true
Thread.start(gs.accept) do |s|
# greeting
s.write("220 welcome to dummy smtp server\n")
# DATA command flag
dataflg = false
while s.gets
# request data
original_request = $_.chomp
request = original_request.upcase
if dataflg == true
# in DATA stream
if /^\.$/ =~ request
s.write("250 OK\n")
dataflg = false
end
else
# normal request
case request
when 'DATA'
dataflg = true
s.write("354 OK\n")
when /^RCPT TO:/
if rand( randmax ) == 1
syslog.log(Syslog::LOG_INFO, original_request + ' :ERROR')
s.write("550 ERROR\n")
else
syslog.log(Syslog::LOG_INFO, original_request + ' :OK')
s.write("250 OK\n")
end
when 'QUIT'
s.write("221 OK\n")
s.close
else
# ok ok ok !
s.write("250 OK\n")
end
end
end
end
end
使い方はこんな感じです。
■疑似メールサーバ
- 事前に本来の MTA(Postfix / qmail / sendmail など)を停止しておく
- root で dummy-smtpd.rb を起動する
# ruby dummy-smtpd.rb - 動作テスト(太字部分を入力する)
$ telnet localhost 25 Trying 127.0.0.1... Connected to localhost (127.0.0.1). Escape character is '^]'. 220 welcome to dummy smtp server EHLO localhost 250 OK MAIL FROM: <hoge@example.com> 250 OK RCPT TO: <hoge-1@example.com> 250 OK DATA 354 OK To: <hoge-1@example.com> From: <hoge@example.com> Subject: test test . 250 OK QUIT 221 OK
見た感じ、普通の SMTP サーバのようですが、ソースコードを見れば分かる通り、実際には何もしていません。
また、上記の処理中、RCPT TO: のところでランダムに「550 ERROR」が返るようにしています。そのアドレスは、syslog にも記録しています。
大量配信のテスト後、syslog に記録されたエラーアドレスと、実際にエラーメール処理サーバで処理したアドレスを比較するなどして、エラー処理に漏れが無いかどうか、などをチェックしました。
もちろん、疑似メールサーバなど使わずに、Postfix / qmail / Sendmail などの MTA を使っても良いのですが、大量送信時の負荷(特にディスク負荷)がバカになりません。送信側のピークより前に、受信側のピークが来てしまうのです。
このプログラムではメールキューをディスクへ保存していませんので、低スペックなサーバでも比較的負荷に耐えられるようになります。
あまり使う機会は無いかも知れませんが、何かの参考になれば幸いです。


ディスカッション
コメント一覧
まだ、コメントがありません