mailcatcher-jruby 1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db3de1ac2c71a4f2527f8fc89ca04dd393c8e7dd
4
+ data.tar.gz: 1d6b9017bc94386eb14694308f1557e75d388cbe
5
+ SHA512:
6
+ metadata.gz: fd21fcae35b466de0d78d8fac33bfea6509903a8609122b8e3334ee0f018da3c3f5ec90629789f78167b14d5831f90dd1601c33e7e4da5ac4541d6cddb103290
7
+ data.tar.gz: d431ef8c32c497efa82f1604f886eb9ed118125b722841641467d8e953cec27e079117ded31064f65390a153459237e853390ab0c2e11977cb9b1e391e90c691
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010-2011 Samuel Cochran
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # MailCatcher
2
+
3
+ ## JRuby Support
4
+ 1. Configure rails.
5
+ To set up your rails app, I recommend adding this to your `environment/development.rb`:
6
+
7
+ config.action_mailer.delivery_method = :smtp
8
+ config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
9
+
10
+ 2. Start the smpt server at port 1025
11
+ `jruby server.rb`
12
+
13
+ 3. Start Puma rack server to host web pages of emails.
14
+ `puma`
15
+ add `-p 1080` to use port 1080
16
+
17
+ Open [http://127.0.0.1:9292](http://127.0.0.1:9292) to see emails.
18
+
19
+ # Original Document
20
+
21
+
22
+ Catches mail and serves it through a dream.
23
+
24
+ MailCatcher runs a super simple SMTP server which catches any message sent to it to display in a web interface. Run mailcatcher, set your favourite app to deliver to smtp://127.0.0.1:1025 instead of your default SMTP server, then check out http://127.0.0.1:1080 to see the mail that's arrived so far.
25
+
26
+ ![MailCatcher screenshot](http://f.cl.ly/items/3w2T1p0F3g003b2i1F2z/Screen%20shot%202011-06-23%20at%2011.39.03%20PM.png)
27
+
28
+ ## Features
29
+
30
+ * Catches all mail and stores it for display.
31
+ * Shows HTML, Plain Text and Source version of messages, as applicable.
32
+ * Rewrites HTML enabling display of embedded, inline images/etc and open links in a new window. (currently very basic)
33
+ * Can send HTML for analysis by [Fractal][fractal].
34
+ * Lists attachments and allows separate downloading of parts.
35
+ * Download original email to view in your native mail client(s).
36
+ * Command line options to override the default SMTP/HTTP IP and port settings.
37
+ * Mail appears instantly if your browser supports [WebSockets][websockets], otherwise updates every thirty seconds.
38
+ * Growl notifications when you receive a new message.
39
+ * Runs as a daemon run in the background.
40
+ * Sendmail-analogue command, `catchmail`, makes [using mailcatcher from PHP][withphp] a lot easier.
41
+ * Written super-simply in EventMachine, easy to dig in and change.
42
+ * Keyboard navigation between messages
43
+
44
+ ## How
45
+
46
+ 1. `gem install mailcatcher`
47
+ 2. `mailcatcher`
48
+ 3. Go to http://localhost:1080/
49
+ 4. Send mail through smtp://localhost:1025
50
+
51
+ The brave can get the source from [the GitHub repository][mailcatcher-github].
52
+
53
+ ### Bundler
54
+
55
+ Please don't put mailcatcher into your Gemfile. It will conflict with your applications gems at some point.
56
+
57
+ Instead, pop a note in your README stating you use mailcatcher. Simply run `gem install mailcatcher` then `mailcatcher` to get started.
58
+
59
+ ### RVM
60
+
61
+ Under RVM your mailcatcher command may only be available under the ruby you install mailcatcher into. To prevent this, and to prevent gem conflicts, install mailcatcher into a dedicated gemset and create wrapper scripts:
62
+
63
+ rvm default@mailcatcher --create do gem install mailcatcher
64
+ rvm wrapper default@mailcatcher --no-prefix mailcatcher catchmail
65
+
66
+ ### Rails
67
+
68
+ To set up your rails app, I recommend adding this to your `environment/development.rb`:
69
+
70
+ config.action_mailer.delivery_method = :smtp
71
+ config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
72
+
73
+ ### PHP
74
+
75
+ For projects using PHP, or PHP frameworks and application platforms like Drupal, you can set [PHP's mail configuration](http://www.php.net/manual/en/mail.configuration.php) in your [php.ini](http://www.php.net/manual/en/configuration.file.php) to send via MailCatcher with:
76
+
77
+ sendmail_path = /usr/bin/env catchmail -f some@from.address
78
+
79
+ You can do this in an [Apache htaccess file](http://php.net/manual/en/configuration.changes.php) or general configuration like so:
80
+
81
+ php_value sendmail_path "/usr/bin/env catchmail -f some@from.address"
82
+
83
+ If you've installed via RVM this probably won't work unless you've manually added your RVM bin paths to your system environment's PATH. In that case, run `which catchmail` and put that path into the `sendmail_path` directive above instead of `/usr/bin/env catchmail`.
84
+
85
+ If starting `mailcatcher` on alternative SMTP IP and/or port with parameters like `--smtp-ip 192.168.0.1 --smtp-port 10025`, add the same parameters to your `catchmail` command:
86
+
87
+ sendmail_path = /usr/bin/env catchmail --smtp-ip 192.160.0.1 --smtp-port 10025 -f some@from.address
88
+
89
+ ### Django
90
+
91
+ For use in Django, simply add the following configuration to your projects' settings.py
92
+
93
+ ```python
94
+ if DEBUG:
95
+ EMAIL_HOST = '127.0.0.1'
96
+ EMAIL_HOST_USER = ''
97
+ EMAIL_HOST_PASSWORD = ''
98
+ EMAIL_PORT = 1025
99
+ EMAIL_USE_TLS = False
100
+ ```
101
+
102
+ ### API
103
+
104
+ A fairly RESTful URL schema means you can download a list of messages in JSON from `/messages`, each message's metadata with `/messages/:id.json`, and then the pertinent parts with `/messages/:id.html` and `/messages/:id.plain` for the default HTML and plain text version, `/messages/:id/:cid` for individual attachments by CID, or the whole message with `/messages/:id.source`.
105
+
106
+ ## Caveats
107
+
108
+ * Mail processing is fairly basic but easily modified. If something doesn't work for you, fork and fix it or [file an issue][mailcatcher-issues] and let me know. Include the whole message you're having problems with.
109
+ * The interface is very basic and has not been tested on many browsers yet.
110
+
111
+ ## TODO
112
+
113
+ * Add mail delivery on request, optionally multiple times.
114
+ * Better Growl support in MacRuby and RubyCocoa with click notifications which takes you to the received message.
115
+ * An API-compatible nodejs version, for fun and profit (and non-ruby npm users).
116
+ * Test suite.
117
+ * Compatibility testing against CampaignMonitor's [design guidelines](http://www.campaignmonitor.com/design-guidelines/) and [CSS support matrix](http://www.campaignmonitor.com/design-guidelines/).
118
+ * Forward mail to rendering service, maybe CampaignMonitor?
119
+ * Package as an app? Native interfaces? HotCocoa?
120
+
121
+ ## Thanks
122
+
123
+ MailCatcher is just a mishmash of other people's hard work. Thank you so much to the people who have built the wonderful guts on which this project relies.
124
+
125
+ Thanks also to [The Frontier Group][tfg] for giving me the idea, being great guinea pigs and letting me steal pieces of time to keep the project alive.
126
+
127
+ ## Donations
128
+
129
+ I work on MailCatcher mostly in my own spare time. If you've found Mailcatcher useful and would like to help feed me and fund continued development and new features, please [donate via PayPal][donate]. If you'd like a specific feature added to MailCatcher and are willing to pay for it, please [email me](mailto:sj26@sj26.com).
130
+
131
+ ## License
132
+
133
+ Copyright © 2010-2011 Samuel Cochran (sj26@sj26.com). Released under the MIT License, see [LICENSE][license] for details.
134
+
135
+ ## Dreams
136
+
137
+ For dream catching, try [this](http://goo.gl/kgbh). OR [THIS](http://www.nyanicorn.com), OMG.
138
+
139
+ [donate]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=522WUPLRWUSKE
140
+ [fractal]: http://getfractal.com
141
+ [license]: https://github.com/sj26/mailcatcher/blob/master/LICENSE
142
+ [mailcatcher-github]: https://github.com/sj26/mailcatcher
143
+ [mailcatcher-issues]: https://github.com/sj26/mailcatcher/issues
144
+ [tfg]: http://www.thefrontiergroup.com.au
145
+ [websockets]: http://www.whatwg.org/specs/web-socket-protocol/
146
+ [withphp]: http://webschuur.com/publications/blogs/2011-05-29-catchmail_for_drupal_and_other_phpapplications_the_simple_version
data/bin/catchmail ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'mail'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'mail'
8
+ end
9
+
10
+ require 'optparse'
11
+
12
+ options = {:smtp_ip => '127.0.0.1', :smtp_port => 1025}
13
+
14
+ OptionParser.new do |parser|
15
+ parser.banner = <<-BANNER.gsub /^ +/, ""
16
+ Usage: catchmail [options]
17
+ sendmail-like interface to forward mail to MailCatcher.
18
+ BANNER
19
+
20
+ parser.on('--ip IP') do |ip|
21
+ options[:smtp_ip] = ip
22
+ end
23
+
24
+ parser.on('--smtp-ip IP', 'Set the ip address of the smtp server') do |ip|
25
+ options[:smtp_ip] = ip
26
+ end
27
+
28
+ parser.on('--smtp-port PORT', Integer, 'Set the port of the smtp server') do |port|
29
+ options[:smtp_port] = port
30
+ end
31
+
32
+ parser.on('-f FROM', 'Set the sending address') do |from|
33
+ options[:from] = from
34
+ end
35
+
36
+ parser.on('-oi', 'Ignored option -oi') do |ignored|
37
+ end
38
+ parser.on('-t', 'Ignored option -t') do |ignored|
39
+ end
40
+ parser.on('-q', 'Ignored option -q') do |ignored|
41
+ end
42
+
43
+ parser.on('-x', '--no-exit', 'Can\'t exit from the application') do
44
+ options[:no_exit] = true
45
+ end
46
+
47
+ parser.on('-h', '--help', 'Display this help information') do
48
+ puts parser
49
+ exit!
50
+ end
51
+ end.parse!
52
+
53
+ Mail.defaults do
54
+ delivery_method :smtp,
55
+ :address => options[:smtp_ip],
56
+ :port => options[:smtp_port]
57
+ end
58
+
59
+ message = Mail.new ARGF.read
60
+ message.return_path = options[:from] if options[:from]
61
+ message.deliver
data/bin/mailcatcher ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mail_catcher'
4
+ MailCatcher.run!
@@ -0,0 +1,220 @@
1
+ require 'active_support/core_ext'
2
+ require 'eventmachine'
3
+ require 'open3'
4
+ require 'optparse'
5
+ require 'rbconfig'
6
+ #require 'thin'
7
+
8
+ require_relative 'mail_catcher/version'
9
+
10
+ module MailCatcher extend self
11
+ def which command
12
+ not windows? and Open3.popen3 'which', 'command' do |stdin, stdout, stderr|
13
+ return stdout.read.chomp.presence
14
+ end
15
+ end
16
+
17
+ def mac?
18
+ RbConfig::CONFIG['host_os'] =~ /darwin/
19
+ end
20
+
21
+ def windows?
22
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
23
+ end
24
+
25
+ def macruby?
26
+ mac? and const_defined? :MACRUBY_VERSION
27
+ end
28
+
29
+ def growlnotify?
30
+ which "growlnotify"
31
+ end
32
+
33
+ def growl?
34
+ growlnotify?
35
+ end
36
+
37
+ def browse?
38
+ windows? or which "open"
39
+ end
40
+
41
+ def browse url
42
+ if windows?
43
+ system "start", "/b", url
44
+ elsif which "open"
45
+ system "open", url
46
+ end
47
+ end
48
+
49
+ @@defaults = {
50
+ :smtp_ip => '0.0.0.0',
51
+ :smtp_port => '9000',
52
+ :http_ip => '127.0.0.1',
53
+ :http_port => '1080',
54
+ :verbose => false,
55
+ :daemon => false,
56
+ #:daemon => !windows?,
57
+ :growl => growlnotify?,
58
+ :browse => false,
59
+ :quit => true,
60
+ }
61
+
62
+ def options
63
+ @@options rescue @@defaults
64
+ end
65
+
66
+ def quittable?
67
+ options[:quit]
68
+ end
69
+
70
+ def parse! arguments=ARGV, defaults=@defaults
71
+ @@defaults.dup.tap do |options|
72
+ OptionParser.new do |parser|
73
+ parser.banner = "Usage: mailcatcher [options]"
74
+ parser.version = VERSION
75
+
76
+ parser.on("--ip IP", "Set the ip address of both servers") do |ip|
77
+ options[:smtp_ip] = options[:http_ip] = ip
78
+ end
79
+
80
+ parser.on("--smtp-ip IP", "Set the ip address of the smtp server") do |ip|
81
+ options[:smtp_ip] = ip
82
+ end
83
+
84
+ parser.on("--smtp-port PORT", Integer, "Set the port of the smtp server") do |port|
85
+ options[:smtp_port] = port
86
+ end
87
+
88
+ parser.on("--http-ip IP", "Set the ip address of the http server") do |ip|
89
+ options[:http_ip] = ip
90
+ end
91
+
92
+ parser.on("--http-port PORT", Integer, "Set the port address of the http server") do |port|
93
+ options[:http_port] = port
94
+ end
95
+
96
+ parser.on("--no-quit", "Don't allow quitting the process") do
97
+ options[:quit] = false
98
+ end
99
+
100
+ if mac?
101
+ parser.on("--[no-]growl", "Growl to the local machine when a message arrives") do |growl|
102
+ if growl and not growlnotify?
103
+ puts "You'll need to install growlnotify from the Growl installer."
104
+ puts
105
+ puts "See: http://growl.info/extras.php#growlnotify"
106
+ exit -2
107
+ end
108
+
109
+ options[:growl] = growl
110
+ end
111
+ end
112
+
113
+ unless windows?
114
+ parser.on('-f', '--foreground', 'Run in the foreground') do
115
+ options[:daemon] = false
116
+ end
117
+ end
118
+
119
+ if browse?
120
+ parser.on('-b', '--browse', 'Open web browser') do
121
+ options[:browse] = true
122
+ end
123
+ end
124
+
125
+ parser.on('-v', '--verbose', 'Be more verbose') do
126
+ options[:verbose] = true
127
+ end
128
+
129
+ parser.on('-h', '--help', 'Display this help information') do
130
+ puts parser
131
+ exit
132
+ end
133
+ end.parse!
134
+ end
135
+ end
136
+
137
+ def run! options=nil
138
+ # If we are passed options, fill in the blanks
139
+ options &&= options.reverse_merge @@defaults
140
+ # Otherwise, parse them from ARGV
141
+ options ||= parse!
142
+
143
+ # Stash them away for later
144
+ @@options = options
145
+
146
+ puts "Starting MailCatcher"
147
+
148
+ #Thin::Logging.silent = true
149
+
150
+ # One EventMachine loop...
151
+ EventMachine.run do
152
+ # Get our lion on if asked
153
+ MailCatcher::Growl.start if options[:growl]
154
+
155
+ smtp_url = "smtp://#{options[:smtp_ip]}:#{options[:smtp_port]}"
156
+ http_url = "http://#{options[:http_ip]}:#{options[:http_port]}"
157
+
158
+ # Set up an SMTP server to run within EventMachine
159
+ rescue_port options[:smtp_port] do
160
+ EventMachine.start_server options[:smtp_ip], options[:smtp_port], Smtp
161
+ puts "==> #{smtp_url}"
162
+ end
163
+
164
+ # Let Thin set itself up inside our EventMachine loop
165
+ # (Skinny/WebSockets just works on the inside)
166
+ # rescue_port options[:http_port] do
167
+ #Thin::Server.start options[:http_ip], options[:http_port], Web
168
+ # puts "==> #{http_url}"
169
+ # end
170
+
171
+ # Open the web browser before detatching console
172
+ if options[:browse]
173
+ EventMachine.next_tick do
174
+ browse http_url
175
+ end
176
+ end
177
+
178
+ # Daemonize, if we should, but only after the servers have started.
179
+ if options[:daemon]
180
+ EventMachine.next_tick do
181
+ if quittable?
182
+ puts "*** MailCatcher runs as a daemon by default. Go to the web interface to quit."
183
+ else
184
+ puts "*** MailCatcher is now running as a daemon that cannot be quit."
185
+ end
186
+ #Process.daemon
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ def quit!
193
+ EventMachine.next_tick { EventMachine.stop_event_loop }
194
+ end
195
+
196
+ protected
197
+
198
+ def rescue_port port
199
+ begin
200
+ yield
201
+
202
+ # XXX: EventMachine only spits out RuntimeError with a string description
203
+ rescue RuntimeError
204
+ if $!.to_s =~ /\bno acceptor\b/
205
+ puts "~~> ERROR: Something's using port #{port}. Are you already running MailCatcher?"
206
+ exit -1
207
+ else
208
+ raise
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ require_relative 'mail_catcher/events'
215
+ require_relative 'mail_catcher/growl'
216
+ require_relative 'mail_catcher/mail'
217
+ require_relative 'mail_catcher/smtp'
218
+ require_relative 'mail_catcher/web'
219
+
220
+ # MailCatcher.run!