mailcatcher/lib/mail_catcher.rb

223 lines
5.4 KiB
Ruby
Raw Normal View History

2014-03-17 01:31:05 -04:00
require "open3"
require "optparse"
require "rbconfig"
2010-10-24 20:51:17 -04:00
2014-03-17 01:31:05 -04:00
require "active_support/core_ext"
require "eventmachine"
require "thin"
require "mail_catcher/events"
require "mail_catcher/growl"
require "mail_catcher/mail"
require "mail_catcher/smtp"
require "mail_catcher/web"
require "mail_catcher/version"
2012-07-24 23:12:40 -04:00
module MailCatcher extend self
2014-03-17 01:31:05 -04:00
def which(command)
2012-09-19 03:40:57 -04:00
not windows? and Open3.popen3 'which', 'command' do |stdin, stdout, stderr|
return stdout.read.chomp.presence
end
end
2011-06-09 23:24:08 -04:00
def mac?
2011-10-10 07:28:49 -04:00
RbConfig::CONFIG['host_os'] =~ /darwin/
2011-06-09 23:24:08 -04:00
end
def windows?
2011-10-10 07:28:49 -04:00
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
2011-06-09 23:24:08 -04:00
end
def macruby?
mac? and const_defined? :MACRUBY_VERSION
end
def growlnotify?
which "growlnotify"
2011-06-09 23:24:08 -04:00
end
def growl?
growlnotify?
2011-06-09 23:24:08 -04:00
end
def browse?
windows? or which "open"
end
def browse url
if windows?
system "start", "/b", url
elsif which "open"
system "open", url
end
2011-06-09 23:24:08 -04:00
end
@@defaults = {
:smtp_ip => '127.0.0.1',
:smtp_port => '1025',
:http_ip => '127.0.0.1',
:http_port => '1080',
:verbose => false,
2011-06-09 23:24:08 -04:00
:daemon => !windows?,
:growl => growlnotify?,
:browse => false,
:quit => true,
}
2011-06-01 10:02:04 -04:00
def options
@@options
end
def quittable?
options[:quit]
end
def parse! arguments=ARGV, defaults=@defaults
@@defaults.dup.tap do |options|
OptionParser.new do |parser|
2011-06-09 23:24:08 -04:00
parser.banner = "Usage: mailcatcher [options]"
2012-07-24 23:12:40 -04:00
parser.version = VERSION
2011-05-27 00:39:03 -04:00
2011-06-09 23:24:08 -04:00
parser.on("--ip IP", "Set the ip address of both servers") do |ip|
options[:smtp_ip] = options[:http_ip] = ip
end
2011-06-09 23:24:08 -04:00
parser.on("--smtp-ip IP", "Set the ip address of the smtp server") do |ip|
options[:smtp_ip] = ip
end
2011-06-09 23:24:08 -04:00
parser.on("--smtp-port PORT", Integer, "Set the port of the smtp server") do |port|
options[:smtp_port] = port
end
2011-06-09 23:24:08 -04:00
parser.on("--http-ip IP", "Set the ip address of the http server") do |ip|
options[:http_ip] = ip
end
2011-06-09 23:24:08 -04:00
parser.on("--http-port PORT", Integer, "Set the port address of the http server") do |port|
options[:http_port] = port
end
parser.on("--no-quit", "Don't allow quitting the process") do
options[:quit] = false
end
2011-06-09 23:24:08 -04:00
if mac?
parser.on("--[no-]growl", "Growl to the local machine when a message arrives") do |growl|
if growl and not growlnotify?
puts "You'll need to install growlnotify from the Growl installer."
puts
puts "See: http://growl.info/extras.php#growlnotify"
2013-09-15 22:03:45 -04:00
exit -2
2011-06-09 23:24:08 -04:00
end
options[:growl] = growl
end
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
if browse?
parser.on('-b', '--browse', 'Open web browser') do
options[:browse] = true
end
end
parser.on('-v', '--verbose', 'Be more verbose') do
options[:verbose] = true
end
parser.on('-h', '--help', 'Display this help information') do
puts parser
2013-09-15 22:03:45 -04:00
exit
end
end.parse!
end
end
2011-06-01 10:02:04 -04:00
2011-06-09 23:24:08 -04:00
def run! options=nil
# If we are passed options, fill in the blanks
options &&= options.reverse_merge @@defaults
# Otherwise, parse them from ARGV
options ||= parse!
2011-06-01 10:02:04 -04:00
# Stash them away for later
@@options = options
# If we're running in the foreground sync the output.
unless options[:daemon]
$stdout.sync = $stderr.sync = true
end
puts "Starting MailCatcher"
2014-03-17 01:53:13 -04:00
Thin::Logging.silent = (ENV["MAILCATCHER_ENV"] != "development")
2011-06-01 10:02:04 -04:00
# One EventMachine loop...
EventMachine.run do
2011-06-09 23:24:08 -04:00
# Get our lion on if asked
MailCatcher::Growl.start if options[:growl]
smtp_url = "smtp://#{options[:smtp_ip]}:#{options[:smtp_port]}"
http_url = "http://#{options[:http_ip]}:#{options[:http_port]}"
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_url}"
2011-05-31 13:35:57 -04:00
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
2014-03-17 01:53:13 -04:00
Thin::Server.start(options[:http_ip], options[:http_port], Web)
puts "==> #{http_url}"
end
# Open the web browser before detatching console
if options[:browse]
EventMachine.next_tick do
browse http_url
end
2011-05-31 13:35:57 -04:00
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
if quittable?
puts "*** MailCatcher runs as a daemon by default. Go to the web interface to quit."
else
puts "*** MailCatcher is now running as a daemon that cannot be quit."
end
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-06-09 23:24:08 -04:00
def quit!
2011-05-31 12:49:36 -04:00
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
2011-06-09 23:24:08 -04:00
def rescue_port port
2011-05-31 13:35:57 -04:00
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?"
2013-09-15 22:03:45 -04:00
exit -1
2011-05-31 13:35:57 -04:00
else
raise
end
end
end
2010-10-24 20:51:17 -04:00
end