Skip to content

Commit

Permalink
Add an Async-based SMTP server
Browse files Browse the repository at this point in the history
It's rough, but it works
  • Loading branch information
sj26 committed Dec 3, 2018
1 parent c4e3af9 commit e77365b
Show file tree
Hide file tree
Showing 3 changed files with 449 additions and 17 deletions.
7 changes: 7 additions & 0 deletions examples/utf8mail
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
To: Blah <blah@blah.com>
From: Me <me@sj26.com>
Subject: Emoji mail

The mail gem should fix the encoding of this message.

👌
43 changes: 28 additions & 15 deletions lib/mail_catcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "rbconfig"
require "socket"

require "async"
require "async/reactor"
require "async/io/address"
require "async/io/address_endpoint"
Expand Down Expand Up @@ -31,18 +32,10 @@ def which?(command)
end
end

def mac?
RbConfig::CONFIG["host_os"] =~ /darwin/
end

def windows?
RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
end

def macruby?
mac? and const_defined? :MACRUBY_VERSION
end

def browseable?
windows? or which? "open"
end
Expand Down Expand Up @@ -122,13 +115,6 @@ def parse! arguments=ARGV, defaults=@defaults
options[:quit] = false
end

if mac?
parser.on("--[no-]growl") do |growl|
puts "Growl is no longer supported"
exit -2
end
end

unless windows?
parser.on("-f", "--foreground", "Run in the foreground") do
options[:daemon] = false
Expand Down Expand Up @@ -169,6 +155,10 @@ def run! options=nil

puts "Starting MailCatcher"

if options[:verbose]
Async.logger.level = Logger::DEBUG
end

Async::Reactor.run do |task|
http_address = Async::IO::Address.tcp(options[:http_ip], options[:http_port])
http_endpoint = Async::IO::AddressEndpoint.new(http_address)
Expand All @@ -190,6 +180,27 @@ def run! options=nil
end
end

smtp_address = Async::IO::Address.tcp(options[:smtp_ip], options[:smtp_port])
smtp_endpoint = Async::IO::AddressEndpoint.new(smtp_address)
smtp_socket = rescue_port(options[:smtp_port]) { smtp_endpoint.bind }
puts "==> #{smtp_url}"

smtp_endpoint = MailCatcher::SMTP::URLEndpoint.new(URI.parse(smtp_url), smtp_endpoint)
smtp_server = MailCatcher::SMTP::Server.new(smtp_endpoint) do |envelope|
MailCatcher::Mail.add_message(sender: envelope.sender, recipients: envelope.recipients, source: envelope.content)
end

smtp_task = task.async do |task|
task.annotate "binding to #{smtp_socket.local_address.inspect}"

begin
smtp_socket.listen(Socket::SOMAXCONN)
smtp_socket.accept_each(task: task, &smtp_server.method(:accept))
ensure
smtp_socket.close
end
end

if options[:browse]
browse(http_url)
end
Expand All @@ -204,6 +215,8 @@ def run! options=nil
Process.daemon
end
end
rescue Interrupt
# Cool story
end

def quit!
Expand Down
Loading

0 comments on commit e77365b

Please sign in to comment.