From: Minero Aoki Date: 2000-07-25T18:12:30+09:00 Subject: [ruby-list:24012] Re: SMTP server (mail filter proxy) あおきです。 In mail "[ruby-list:24009] SMTP server (mail filter proxy)" Hideto ISHIBASHI wrote: > こんにちは。石橋"rubyholic"秀仁です。 > > いまメールフィルタを作ろうとしています。 > 情報・御意見をお願いします。 > Ruby の MTA があれば、一番かんたんですよね。 この前ちょこっと書いたのがあるんで、よければ使ってください。 ただし 7 月中は一切の改善要求に応えられませんのであしからず。 ------------------------------------------------------------------- あおきみねろう # # smtpd.rb # require 'socket' class SMTPd def initialize( port ) @port = port end def execute if $DEBUG then waitcall end fork do Process.setsid fork do $stdin.close $stdout.close $stderr.close waitcall end exit! end exit! end private def waitcall s = TCPServer.open( @port ) trap( 'SIGINT' ) { exit! } trap( 'SIGHUP' ) { exit! } trap( 'SIGTERM' ) { exit! } while true do @sock = s.accept begin session ensure @sock.close end end end def session from = nil to = {} @rbuf = '' writeline "220 #{Socket.gethostname} ESMTP" while true do case resp = readline when /\A(?:helo|ehlo)/i writeline '250 ok' when /\Amail from:<(\S+)>/i from = $1 to.clear writeline '250 ok' when /\Arcpt to:<(\S+)>/i unless from then writeline '508 MAIL first' next end to[$1] = true writeline '250 ok' when /\Adata/i unless from then writeline '508 MAIL first' next end if to.empty? then writeline '508 RCPT first' next end writeline '354 go ahead' recvmail from, to writeline '250 ok' from = nil to.clear when /\Aquit/i writeline "221 #{Socket.gethostname}" to = from = nil @rbuf = '' break else writeline '502 unimplemented' end end end def recvmail( from, to ) tmp = nil # とりあえずはファイルに書いてるだけ File.open( 'tmp', 'w' ) do |f| f.puts "smtp from=#{from}" to.each_key do |i| f.puts "smtp to=#{i}" end f.puts # 本体 while true do tmp = readline tmp.sub! /\A\../, '.' break if tmp == '.' f.write tmp, "\r\n" end end end def writeline( msg ) @sock.write msg + "\r\n" @sock.flush end def readline until m = /\r\n/.match( @rbuf ) do # p @rbuf @rbuf << @sock.sysread( 1024 ) if @rbuf.size > 1024 * 3 then writeline '508 line too long' @rbuf.clear end end # p @rbuf @rbuf = m.post_match m.pre_match end end if $0 == __FILE__ then $DEBUG = true puts 'debug mode. try "telnet localhost 12525" from other terminal' smtp = SMTPd.new( 12525 ) smtp.execute end