2012-07-24 23:47:01 -04:00
|
|
|
require 'active_support/core_ext'
|
2010-10-24 20:51:17 -04:00
|
|
|
require 'eventmachine'
|
2012-07-24 23:47:01 -04:00
|
|
|
require 'open3'
|
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'
|
|
|
|
|
2012-07-24 23:12:40 -04:00
|
|
|
require 'mail_catcher/version'
|
|
|
|
|
2012-07-25 00:00:31 -04:00
|
|
|
module MailCatcher extend self
|
2012-04-06 02:16:15 -04:00
|
|
|
def which command
|
2012-09-19 03:40:57 -04:00
|
|
|
not windows? and Open3.popen3 'which', 'command' do |stdin, stdout, stderr|
|
2012-06-19 04:25:19 -04:00
|
|
|
return stdout.read.chomp.presence
|
|
|
|
end
|
2012-04-06 02:16:15 -04:00
|
|
|
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?
|
2012-04-06 02:16:15 -04:00
|
|
|
which "growlnotify"
|
2011-06-09 23:24:08 -04:00
|
|
|
end
|
|
|
|
|
2012-04-06 02:16:15 -04:00
|
|
|
def growl?
|
|
|
|
growlnotify?
|
2011-06-09 23:24:08 -04:00
|
|
|
end
|
|
|
|
|
2012-04-06 02:16:15 -04:00
|
|
|
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
|
|
|
|
|
2013-09-15 21:42:14 -04:00
|
|
|
@@defaults = {
|
2011-05-27 00:19:04 -04:00
|
|
|
: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?,
|
2012-04-06 02:16:15 -04:00
|
|
|
:browse => false,
|
2013-11-17 18:59:11 -05:00
|
|
|
:quit => true,
|
2011-05-27 00:19:04 -04:00
|
|
|
}
|
2011-06-01 10:02:04 -04:00
|
|
|
|
2013-09-15 21:42:14 -04:00
|
|
|
def options
|
|
|
|
@@options
|
|
|
|
end
|
|
|
|
|
2013-11-17 18:59:11 -05:00
|
|
|
def quittable?
|
|
|
|
options[:quit]
|
|
|
|
end
|
|
|
|
|
2012-07-25 00:00:31 -04:00
|
|
|
def parse! arguments=ARGV, defaults=@defaults
|
2013-09-15 21:42:14 -04:00
|
|
|
@@defaults.dup.tap do |options|
|
2011-05-27 00:19:04 -04:00
|
|
|
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|
|
2011-05-27 00:23:46 -04:00
|
|
|
options[:smtp_ip] = options[:http_ip] = ip
|
|
|
|
end
|
2011-05-27 00:19:04 -04:00
|
|
|
|
2011-06-09 23:24:08 -04:00
|
|
|
parser.on("--smtp-ip IP", "Set the ip address of the smtp server") do |ip|
|
2011-05-27 00:19:04 -04:00
|
|
|
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|
|
2011-05-27 00:19:04 -04:00
|
|
|
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|
|
2011-05-27 00:19:04 -04:00
|
|
|
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|
|
2011-05-27 00:19:04 -04:00
|
|
|
options[:http_port] = port
|
|
|
|
end
|
|
|
|
|
2013-11-17 18:59:11 -05:00
|
|
|
parser.on("--no-quit", "Don't allow quitting the process") do
|
|
|
|
options[:quit] = false
|
2013-05-13 07:27:06 -04:00
|
|
|
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
|
|
|
|
|
2012-04-06 02:16:15 -04:00
|
|
|
if browse?
|
|
|
|
parser.on('-b', '--browse', 'Open web browser') do
|
|
|
|
options[:browse] = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-05-27 00:19:04 -04:00
|
|
|
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
|
2011-05-27 00:19:04 -04:00
|
|
|
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
|
2011-05-27 00:19:04 -04:00
|
|
|
# If we are passed options, fill in the blanks
|
2013-09-15 21:42:14 -04:00
|
|
|
options &&= options.reverse_merge @@defaults
|
2011-05-27 00:19:04 -04:00
|
|
|
# Otherwise, parse them from ARGV
|
|
|
|
options ||= parse!
|
2011-06-01 10:02:04 -04:00
|
|
|
|
2013-09-15 21:42:14 -04:00
|
|
|
# Stash them away for later
|
|
|
|
@@options = options
|
2010-10-25 11:32:56 -04:00
|
|
|
|
2014-02-12 07:45:39 -05:00
|
|
|
# If we're running in the foreground sync the output.
|
|
|
|
unless options[:daemon]
|
|
|
|
$stdout.sync = $stderr.sync = true
|
|
|
|
end
|
|
|
|
|
2013-09-15 21:42:14 -04:00
|
|
|
puts "Starting MailCatcher"
|
2013-05-13 07:27:06 -04:00
|
|
|
|
2010-10-24 20:51:17 -04:00
|
|
|
Thin::Logging.silent = true
|
2011-06-01 10:02:04 -04:00
|
|
|
|
2011-05-30 03:37:13 -04:00
|
|
|
# One EventMachine loop...
|
2010-10-27 15:12:26 -04:00
|
|
|
EventMachine.run do
|
2011-06-09 23:24:08 -04:00
|
|
|
# Get our lion on if asked
|
|
|
|
MailCatcher::Growl.start if options[:growl]
|
|
|
|
|
2012-04-06 02:16:15 -04:00
|
|
|
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
|
|
|
|
2011-05-30 03:37:13 -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
|
2012-04-06 02:16:15 -04:00
|
|
|
puts "==> #{smtp_url}"
|
2011-05-31 13:35:57 -04:00
|
|
|
end
|
2011-06-01 10:02:04 -04:00
|
|
|
|
2011-05-30 03:37:13 -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
|
2012-04-06 02:16:15 -04:00
|
|
|
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
|
|
|
|
2011-05-30 03:37:13 -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
|
2013-11-17 18:59:11 -05:00
|
|
|
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
|
2012-07-24 23:47:01 -04:00
|
|
|
|
|
|
|
require 'mail_catcher/events'
|
|
|
|
require 'mail_catcher/growl'
|
|
|
|
require 'mail_catcher/mail'
|
|
|
|
require 'mail_catcher/smtp'
|
|
|
|
require 'mail_catcher/web'
|