Created
December 14, 2012 18:35
-
-
Save yaplik/4287550 to your computer and use it in GitHub Desktop.
Example SMTP Server for PV249
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
source :rubygems | |
gem "eventmachine" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Example SMTP Server in Ruby for course FI:PV249 | |
# | |
# @author Jiri Zapletal <[email protected]> | |
# @license BSD | |
require 'bundler/setup' | |
Bundler.require(:default) | |
module SmtpProtocol | |
include EventMachine::Protocols::LineText2 | |
def post_init | |
reset_state | |
send_line("220 mail.example.net SMTP Ruby Server") | |
end | |
def reset_state | |
@mail = nil | |
@rcpt = [] | |
@data = "" | |
end | |
def send_line(data) | |
puts "[S] " + data | |
send_data(data + "\r\n") | |
end | |
def receive_line(line) | |
puts "[C] " + line | |
case | |
when m = /^HELO (.*)$/i.match(line) | |
send_line "250 Hello" | |
when m = /^EHLO (.*)$/i.match(line) | |
send_line "250-mail.example.net" | |
send_line "250-STARTTLS" | |
send_line "250 DSN" | |
when m = /^STARTTLS$/i.match(line) | |
send_line "220 2.0.0 Ready to start TLS" | |
start_tls | |
when m = /^MAIL FROM:(.*)$/i.match(line) | |
if @from != nil then | |
send_line "503 5.5.1 Error: nested MAIL command" | |
return | |
end | |
@from = m[1] | |
send_line "250 2.1.0 Ok" | |
when m = /^RCPT TO:(.*)/i.match(line) | |
if @from == nil then | |
send_line "503 5.5.1 Error: need MAIL command" | |
return | |
end | |
@rcpt << m[1] | |
send_line "250 2.1.5 Ok" | |
when m = /^RSET$/i.match(line) | |
reset_state | |
send_line "250 2.0.0 Ok" | |
when m = /^DATA$/i.match(line) | |
if @rcpt.count == 0 then | |
send_line "503 5.5.1 Error: need RCPT command" | |
return | |
end | |
send_line "354 End data with <CR><LF>.<CR><LF>" | |
set_text_mode | |
when m = /^QUIT$/i.match(line) | |
send_line "221 Bye" | |
close_connection_after_writing | |
else | |
puts "[error]", line | |
send_line "502 5.5.2 Error: command not recognized" | |
end | |
end | |
def receive_binary_data(data) | |
print "data", data.inspect | |
if /\r\n\.\r\n$/.match(data) then | |
@data += data[0..-5] | |
id = receive_mail(@from, @rcpt, @data) | |
send_line "250 2.0.0 Ok: queued as #{id}" | |
reset_state | |
set_line_mode | |
else | |
@data += data | |
end | |
end | |
def unbind | |
puts "[C Disconnected]" | |
end | |
def receive_mail(from, to, data) | |
puts "Email from #{from} to #{to.join(",")}" | |
return "123456" | |
end | |
end | |
EventMachine.run do | |
Signal.trap("INT") { EventMachine.stop } | |
Signal.trap("TERM") { EventMachine.stop } | |
EventMachine.start_server("0.0.0.0", 8025, SmtpProtocol) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment