Ruby SMTP Server - Save to Database
I've simply used Peter's(http://snippets.dzone.com/user/peter) ultra simplistic SMTP server and routed the email to a database table called "Emails" via ActiveRecord. It's running GServer so it should be able to handle a decent load. Like I mentioned earlier, it's probably still got some bugs, but it's a decent start.
1 2 require 'gserver' 3 require 'rubygems' 4 require 'active_record' 5 require 'yaml' 6 7 dbconfig = YAML::load_file(File.dirname(__FILE__) + '/config/database.yml') 8 ActiveRecord::Base.establish_connection(dbconfig['development']) 9 10 class Email < ActiveRecord::Base 11 end 12 13 class SMTPServer < GServer 14 def serve(io) 15 @data_mode = false 16 @email_message = "" 17 puts "Connected" 18 io.print "220 hello\r\n" 19 loop do 20 if IO.select([io], nil, nil, 0.1) 21 data = io.readpartial(4096) 22 puts ">>" + data 23 @email_message << data 24 ok, op = process_line(data) 25 break unless ok 26 puts "<<" + op 27 io.print op 28 end 29 break if io.closed? 30 end 31 db_insert(@email_message) 32 io.print "221 bye\r\n" 33 io.close 34 end 35 36 def process_line(line) 37 if (@data_mode) && (line.chomp =~ /^\.$/) 38 @data_mode = false 39 return true, "220 OK\r\n" 40 elsif @data_mode 41 return true, "" 42 elsif (line =~ /^(HELO|EHLO)/) 43 return true, "220 and..?\r\n" 44 elsif (line =~ /^QUIT/) 45 return false, "bye\r\n" 46 elsif (line =~ /^MAIL FROM\:/) 47 return true, "220 OK\r\n" 48 elsif (line =~ /^RCPT TO\:/) 49 return true, "220 OK\r\n" 50 elsif (line =~ /^DATA/) 51 @data_mode = true 52 return true, "354 Enter message, ending with \".\" on a line by itself\r\n" 53 else 54 return true, "500 ERROR\r\n" 55 end 56 end 57 58 def db_insert(email) 59 mail_from = (/^MAIL FROM\:<(.+)>.*$/).match(email)[1] 60 rcpt_to = (/^RCPT TO\:<(.+)>.*$/).match(email)[1] 61 subject = (/^Subject\: (.+)$/).match(email)[1] 62 Email.create(:mail_from => mail_from, :rcpt_to => rcpt_to, :subject => subject, :email => email) 63 end 64 65 end 66 67 a = SMTPServer.new(25) 68 a.start 69 a.join