mailcatcher/lib/mail_catcher.rb

129 lines
3.3 KiB
Ruby
Raw Normal View History

2011-05-27 00:19:15 -04:00
require 'active_support/all'
2010-10-24 20:51:17 -04:00
require 'eventmachine'
2011-06-01 20:57:14 -04:00
require 'optparse'
2011-06-01 20:15:50 -04:00
require 'rbconfig'
2010-10-24 20:51:17 -04:00
require 'thin'
2011-06-01 10:02:04 -04:00
def windows?
2011-06-01 20:15:50 -04:00
Config::CONFIG['host_os'] =~ /mswin|mingw/
2011-06-01 10:02:04 -04:00
end
2010-10-24 20:51:17 -04:00
module MailCatcher
2011-05-27 00:19:15 -04:00
extend ActiveSupport::Autoload
2011-06-01 10:02:04 -04:00
2011-05-27 00:19:15 -04:00
autoload :Events
autoload :Mail
autoload :Smtp
autoload :Web
2011-06-01 10:02:04 -04:00
@@defaults = {
:smtp_ip => '127.0.0.1',
:smtp_port => '1025',
:http_ip => '127.0.0.1',
:http_port => '1080',
:verbose => false,
2011-06-01 20:15:50 -04:00
:daemon => (true unless windows?),
}
2011-06-01 10:02:04 -04:00
def self.parse! arguments=ARGV, defaults=@@defaults
@@defaults.dup.tap do |options|
OptionParser.new do |parser|
parser.banner = 'Usage: mailcatcher [options]'
2011-05-27 00:39:03 -04:00
parser.on('--ip IP', 'Set the ip address of both servers') do |ip|
options[:smtp_ip] = options[:http_ip] = ip
end
parser.on('--smtp-ip IP', 'Set the ip address of the smtp server') do |ip|
options[:smtp_ip] = ip
end
parser.on('--smtp-port PORT', Integer, 'Set the port of the smtp server') do |port|
options[:smtp_port] = port
end
parser.on('--http-ip IP', 'Set the ip address of the http server') do |ip|
options[:http_ip] = ip
end
parser.on('--http-port PORT', Integer, 'Set the port address of the http server') do |port|
options[:http_port] = port
end
2011-06-01 10:02:04 -04:00
unless windows?
parser.on('-f', '--foreground', 'Run in the foreground') do
options[:daemon] = false
end
2011-05-27 00:39:03 -04:00
end
parser.on('-v', '--verbose', 'Be more verbose') do
options[:verbose] = true
end
parser.on('-h', '--help', 'Display this help information') do
puts parser
exit!
end
end.parse!
end
end
2011-06-01 10:02:04 -04:00
def self.run! options=nil
# If we are passed options, fill in the blanks
options &&= @@defaults.merge options
# Otherwise, parse them from ARGV
options ||= parse!
2011-06-01 10:02:04 -04:00
puts "Starting MailCatcher"
2010-10-24 20:51:17 -04:00
Thin::Logging.silent = true
2011-06-01 10:02:04 -04:00
# One EventMachine loop...
EventMachine.run do
2011-05-31 13:35:57 -04:00
# TODO: DRY this up
2011-06-01 10:02:04 -04:00
# Set up an SMTP server to run within EventMachine
2011-05-31 13:35:57 -04:00
rescue_port options[:smtp_port] do
EventMachine.start_server options[:smtp_ip], options[:smtp_port], Smtp
puts "==> smtp://#{options[:smtp_ip]}:#{options[:smtp_port]}"
end
2011-06-01 10:02:04 -04:00
# Let Thin set itself up inside our EventMachine loop
# (Skinny/WebSockets just works on the inside)
2011-05-31 13:35:57 -04:00
rescue_port options[:http_port] do
Thin::Server.start options[:http_ip], options[:http_port], Web
puts "==> http://#{options[:http_ip]}:#{options[:http_port]}"
end
2011-06-01 10:02:04 -04:00
# Daemonize, if we should, but only after the servers have started.
2011-05-31 13:35:57 -04:00
if options[:daemon]
EventMachine.next_tick do
2011-05-31 13:36:05 -04:00
puts "*** MailCatcher now runs as a daemon by default. Go to the web interface to quit."
2011-05-31 13:35:57 -04:00
Process.daemon
end
end
2010-10-24 20:51:17 -04:00
end
end
2011-06-01 10:02:04 -04:00
2011-05-31 12:49:36 -04:00
def self.quit!
EventMachine.next_tick { EventMachine.stop_event_loop }
end
2011-05-31 13:35:57 -04:00
2011-06-01 10:02:04 -04:00
protected
2011-05-31 13:35:57 -04:00
def self.rescue_port port
begin
yield
2011-06-01 10:02:04 -04:00
2011-05-31 13:35:57 -04:00
# XXX: EventMachine only spits out RuntimeError with a string description
rescue RuntimeError
if $!.to_s =~ /\bno acceptor\b/
puts "~~> ERROR: Something's using port #{port}. Are you already running MailCatcher?"
exit -1
else
raise
end
end
end
2010-10-24 20:51:17 -04:00
end