Ruby SMTP Server - Save To Database
Join the DZone community and get the full member experience.Join For Free
This was something I've searched for in the past but have yet to find. It's a super simple server and I'm sure there's a few bugs left in it, but the idea is simple and in my opinion, necessary. It's easy to send email from websites, but receiving it still seems dubious. 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.
require 'gserver' require 'rubygems' require 'active_record' require 'yaml' dbconfig = YAML::load_file(File.dirname(__FILE__) + '/config/database.yml') ActiveRecord::Base.establish_connection(dbconfig['development']) class Email < ActiveRecord::Base end class SMTPServer < GServer def serve(io) @data_mode = false @email_message = "" puts "Connected" io.print "220 hello\r\n" loop do if IO.select([io], nil, nil, 0.1) data = io.readpartial(4096) puts ">>" + data @email_message << data ok, op = process_line(data) break unless ok puts "<<" + op io.print op end break if io.closed? end db_insert(@email_message) io.print "221 bye\r\n" io.close end def process_line(line) if (@data_mode) && (line.chomp =~ /^\.$/) @data_mode = false return true, "220 OK\r\n" elsif @data_mode return true, "" elsif (line =~ /^(HELO|EHLO)/) return true, "220 and..?\r\n" elsif (line =~ /^QUIT/) return false, "bye\r\n" elsif (line =~ /^MAIL FROM\:/) return true, "220 OK\r\n" elsif (line =~ /^RCPT TO\:/) return true, "220 OK\r\n" elsif (line =~ /^DATA/) @data_mode = true return true, "354 Enter message, ending with \".\" on a line by itself\r\n" else return true, "500 ERROR\r\n" end end def db_insert(email) mail_from = (/^MAIL FROM\:<(.+)>.*$/).match(email) rcpt_to = (/^RCPT TO\:<(.+)>.*$/).match(email) subject = (/^Subject\: (.+)$/).match(email) Email.create(:mail_from => mail_from, :rcpt_to => rcpt_to, :subject => subject, :email => email) end end a = SMTPServer.new(25) a.start a.join