mailcatcher 0.5.12 → 0.6.0pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +24 -11
- data/bin/catchmail +23 -2
- data/bin/mailcatcher +1 -0
- data/lib/mail_catcher.rb +49 -43
- data/lib/mail_catcher/events.rb +5 -3
- data/lib/mail_catcher/mail.rb +15 -15
- data/lib/mail_catcher/smtp.rb +6 -2
- data/lib/mail_catcher/version.rb +1 -1
- data/lib/mail_catcher/web.rb +14 -141
- data/lib/mail_catcher/web/application.rb +188 -0
- data/lib/mailcatcher.rb +3 -0
- data/public/{images → assets}/logo.png +0 -0
- data/public/{images → assets}/logo_large.png +0 -0
- data/public/assets/mailcatcher.css +1 -0
- data/public/assets/mailcatcher.js +5 -0
- data/views/404.erb +6 -0
- data/views/index.erb +62 -0
- metadata +148 -77
- metadata.gz.sig +0 -0
- data/lib/mail_catcher/growl.rb +0 -16
- data/public/javascripts/application.js +0 -408
- data/public/javascripts/date.js +0 -104
- data/public/javascripts/flexie.min.js +0 -36
- data/public/javascripts/jquery.js +0 -6883
- data/public/javascripts/keymaster.min.js +0 -4
- data/public/javascripts/modernizr.js +0 -3
- data/public/javascripts/xslt-3.2.js +0 -1
- data/public/stylesheets/analysis.xsl +0 -33
- data/public/stylesheets/application.css +0 -375
- data/views/index.haml +0 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20a21ec3f69fd47bbc8c269689998ace77da0c1b
|
4
|
+
data.tar.gz: f55e1936c3fb237909fb0bf1bc1282af1c709175
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 693e35eb5cec71175f37e7c7c57a08a591985a65284c71c4a8684e7c020114f9f7733b522f6df404fca1ba5a922b098836fb7b02497ed25e93ca834b06f3d216
|
7
|
+
data.tar.gz: 8e474863a1a3bd887322bb4b9007aba2c14a44d5a3b783cc3384adc5df7ca1f89d07df069e0ed040a8315d47791568b22fc05fff54dbdcf15633308ea4fed0ba
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -10,13 +10,11 @@ MailCatcher runs a super simple SMTP server which catches any message sent to it
|
|
10
10
|
|
11
11
|
* Catches all mail and stores it for display.
|
12
12
|
* Shows HTML, Plain Text and Source version of messages, as applicable.
|
13
|
-
* Rewrites HTML enabling display of embedded, inline images/etc and open links in a new window.
|
14
|
-
* Can send HTML for analysis by [Fractal][fractal].
|
13
|
+
* Rewrites HTML enabling display of embedded, inline images/etc and open links in a new window.
|
15
14
|
* Lists attachments and allows separate downloading of parts.
|
16
15
|
* Download original email to view in your native mail client(s).
|
17
16
|
* Command line options to override the default SMTP/HTTP IP and port settings.
|
18
17
|
* Mail appears instantly if your browser supports [WebSockets][websockets], otherwise updates every thirty seconds.
|
19
|
-
* Growl notifications when you receive a new message.
|
20
18
|
* Runs as a daemon run in the background.
|
21
19
|
* Sendmail-analogue command, `catchmail`, makes [using mailcatcher from PHP][withphp] a lot easier.
|
22
20
|
* Written super-simply in EventMachine, easy to dig in and change.
|
@@ -29,7 +27,7 @@ MailCatcher runs a super simple SMTP server which catches any message sent to it
|
|
29
27
|
3. Go to http://localhost:1080/
|
30
28
|
4. Send mail through smtp://localhost:1025
|
31
29
|
|
32
|
-
The brave can get the source from [the GitHub repository][mailcatcher-github].
|
30
|
+
Use `mailcatcher --help` to see the command line options. The brave can get the source from [the GitHub repository][mailcatcher-github].
|
33
31
|
|
34
32
|
### Bundler
|
35
33
|
|
@@ -46,7 +44,7 @@ Under RVM your mailcatcher command may only be available under the ruby you inst
|
|
46
44
|
|
47
45
|
### Rails
|
48
46
|
|
49
|
-
To set up your rails app, I recommend adding this to your `
|
47
|
+
To set up your rails app, I recommend adding this to your `environments/development.rb`:
|
50
48
|
|
51
49
|
config.action_mailer.delivery_method = :smtp
|
52
50
|
config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
|
@@ -55,14 +53,31 @@ To set up your rails app, I recommend adding this to your `environment/developme
|
|
55
53
|
|
56
54
|
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:
|
57
55
|
|
58
|
-
sendmail_path = /usr/bin/env catchmail
|
56
|
+
sendmail_path = /usr/bin/env catchmail -f some@from.address
|
59
57
|
|
60
|
-
You can do this in
|
58
|
+
You can do this in your [Apache configuration](http://php.net/manual/en/configuration.changes.php) like so:
|
61
59
|
|
62
|
-
|
60
|
+
php_admin_value sendmail_path "/usr/bin/env catchmail -f some@from.address"
|
63
61
|
|
64
62
|
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`.
|
65
63
|
|
64
|
+
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:
|
65
|
+
|
66
|
+
sendmail_path = /usr/bin/env catchmail --smtp-ip 192.160.0.1 --smtp-port 10025 -f some@from.address
|
67
|
+
|
68
|
+
### Django
|
69
|
+
|
70
|
+
For use in Django, simply add the following configuration to your projects' settings.py
|
71
|
+
|
72
|
+
```python
|
73
|
+
if DEBUG:
|
74
|
+
EMAIL_HOST = '127.0.0.1'
|
75
|
+
EMAIL_HOST_USER = ''
|
76
|
+
EMAIL_HOST_PASSWORD = ''
|
77
|
+
EMAIL_PORT = 1025
|
78
|
+
EMAIL_USE_TLS = False
|
79
|
+
```
|
80
|
+
|
66
81
|
### API
|
67
82
|
|
68
83
|
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`.
|
@@ -75,10 +90,9 @@ A fairly RESTful URL schema means you can download a list of messages in JSON fr
|
|
75
90
|
## TODO
|
76
91
|
|
77
92
|
* Add mail delivery on request, optionally multiple times.
|
78
|
-
* Better Growl support in MacRuby and RubyCocoa with click notifications which takes you to the received message.
|
79
93
|
* An API-compatible nodejs version, for fun and profit (and non-ruby npm users).
|
80
94
|
* Test suite.
|
81
|
-
* Compatibility testing against CampaignMonitor's [design guidelines](http://www.campaignmonitor.com/design-guidelines/) and [CSS support matrix](http://www.campaignmonitor.com/
|
95
|
+
* Compatibility testing against CampaignMonitor's [design guidelines](http://www.campaignmonitor.com/design-guidelines/) and [CSS support matrix](http://www.campaignmonitor.com/css/).
|
82
96
|
* Forward mail to rendering service, maybe CampaignMonitor?
|
83
97
|
* Package as an app? Native interfaces? HotCocoa?
|
84
98
|
|
@@ -101,7 +115,6 @@ Copyright © 2010-2011 Samuel Cochran (sj26@sj26.com). Released under the MIT Li
|
|
101
115
|
For dream catching, try [this](http://goo.gl/kgbh). OR [THIS](http://www.nyanicorn.com), OMG.
|
102
116
|
|
103
117
|
[donate]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=522WUPLRWUSKE
|
104
|
-
[fractal]: http://getfractal.com
|
105
118
|
[license]: https://github.com/sj26/mailcatcher/blob/master/LICENSE
|
106
119
|
[mailcatcher-github]: https://github.com/sj26/mailcatcher
|
107
120
|
[mailcatcher-issues]: https://github.com/sj26/mailcatcher/issues
|
data/bin/catchmail
CHANGED
@@ -13,7 +13,7 @@ options = {:smtp_ip => '127.0.0.1', :smtp_port => 1025}
|
|
13
13
|
|
14
14
|
OptionParser.new do |parser|
|
15
15
|
parser.banner = <<-BANNER.gsub /^ +/, ""
|
16
|
-
Usage: catchmail [options]
|
16
|
+
Usage: catchmail [options] [recipient ...]
|
17
17
|
sendmail-like interface to forward mail to MailCatcher.
|
18
18
|
BANNER
|
19
19
|
|
@@ -33,6 +33,17 @@ OptionParser.new do |parser|
|
|
33
33
|
options[:from] = from
|
34
34
|
end
|
35
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
|
+
|
36
47
|
parser.on('-h', '--help', 'Display this help information') do
|
37
48
|
puts parser
|
38
49
|
exit!
|
@@ -45,6 +56,16 @@ Mail.defaults do
|
|
45
56
|
:port => options[:smtp_port]
|
46
57
|
end
|
47
58
|
|
48
|
-
message = Mail.new
|
59
|
+
message = Mail.new($stdin.read)
|
60
|
+
|
49
61
|
message.return_path = options[:from] if options[:from]
|
62
|
+
|
63
|
+
ARGV.each do |recipient|
|
64
|
+
if message.to.nil?
|
65
|
+
message.to = recipient
|
66
|
+
else
|
67
|
+
message.to << recipient
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
50
71
|
message.deliver
|
data/bin/mailcatcher
CHANGED
data/lib/mail_catcher.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'optparse'
|
5
|
-
require 'rbconfig'
|
6
|
-
require 'thin'
|
1
|
+
require "open3"
|
2
|
+
require "optparse"
|
3
|
+
require "rbconfig"
|
7
4
|
|
8
|
-
require
|
5
|
+
require "active_support/all"
|
6
|
+
require "eventmachine"
|
7
|
+
require "thin"
|
8
|
+
|
9
|
+
require "mail_catcher/events"
|
10
|
+
require "mail_catcher/mail"
|
11
|
+
require "mail_catcher/smtp"
|
12
|
+
require "mail_catcher/web"
|
13
|
+
require "mail_catcher/version"
|
9
14
|
|
10
15
|
module MailCatcher extend self
|
11
|
-
def which
|
16
|
+
def which(command)
|
12
17
|
not windows? and Open3.popen3 'which', 'command' do |stdin, stdout, stderr|
|
13
18
|
return stdout.read.chomp.presence
|
14
19
|
end
|
@@ -26,14 +31,6 @@ module MailCatcher extend self
|
|
26
31
|
mac? and const_defined? :MACRUBY_VERSION
|
27
32
|
end
|
28
33
|
|
29
|
-
def growlnotify?
|
30
|
-
which "growlnotify"
|
31
|
-
end
|
32
|
-
|
33
|
-
def growl?
|
34
|
-
growlnotify?
|
35
|
-
end
|
36
|
-
|
37
34
|
def browse?
|
38
35
|
windows? or which "open"
|
39
36
|
end
|
@@ -46,19 +43,27 @@ module MailCatcher extend self
|
|
46
43
|
end
|
47
44
|
end
|
48
45
|
|
49
|
-
|
46
|
+
@@defaults = {
|
50
47
|
:smtp_ip => '127.0.0.1',
|
51
48
|
:smtp_port => '1025',
|
52
49
|
:http_ip => '127.0.0.1',
|
53
50
|
:http_port => '1080',
|
54
51
|
:verbose => false,
|
55
52
|
:daemon => !windows?,
|
56
|
-
:growl => growlnotify?,
|
57
53
|
:browse => false,
|
54
|
+
:quit => true,
|
58
55
|
}
|
59
56
|
|
57
|
+
def options
|
58
|
+
@@options
|
59
|
+
end
|
60
|
+
|
61
|
+
def quittable?
|
62
|
+
options[:quit]
|
63
|
+
end
|
64
|
+
|
60
65
|
def parse! arguments=ARGV, defaults=@defaults
|
61
|
-
|
66
|
+
@@defaults.dup.tap do |options|
|
62
67
|
OptionParser.new do |parser|
|
63
68
|
parser.banner = "Usage: mailcatcher [options]"
|
64
69
|
parser.version = VERSION
|
@@ -83,16 +88,14 @@ module MailCatcher extend self
|
|
83
88
|
options[:http_port] = port
|
84
89
|
end
|
85
90
|
|
91
|
+
parser.on("--no-quit", "Don't allow quitting the process") do
|
92
|
+
options[:quit] = false
|
93
|
+
end
|
94
|
+
|
86
95
|
if mac?
|
87
|
-
parser.on("--[no-]growl"
|
88
|
-
|
89
|
-
|
90
|
-
puts
|
91
|
-
puts "See: http://growl.info/extras.php#growlnotify"
|
92
|
-
exit!
|
93
|
-
end
|
94
|
-
|
95
|
-
options[:growl] = growl
|
96
|
+
parser.on("--[no-]growl") do |growl|
|
97
|
+
puts "Growl is no longer supported"
|
98
|
+
exit -2
|
96
99
|
end
|
97
100
|
end
|
98
101
|
|
@@ -114,7 +117,7 @@ module MailCatcher extend self
|
|
114
117
|
|
115
118
|
parser.on('-h', '--help', 'Display this help information') do
|
116
119
|
puts parser
|
117
|
-
exit
|
120
|
+
exit
|
118
121
|
end
|
119
122
|
end.parse!
|
120
123
|
end
|
@@ -122,19 +125,24 @@ module MailCatcher extend self
|
|
122
125
|
|
123
126
|
def run! options=nil
|
124
127
|
# If we are passed options, fill in the blanks
|
125
|
-
options &&=
|
128
|
+
options &&= options.reverse_merge @@defaults
|
126
129
|
# Otherwise, parse them from ARGV
|
127
130
|
options ||= parse!
|
128
131
|
|
132
|
+
# Stash them away for later
|
133
|
+
@@options = options
|
134
|
+
|
135
|
+
# If we're running in the foreground sync the output.
|
136
|
+
unless options[:daemon]
|
137
|
+
$stdout.sync = $stderr.sync = true
|
138
|
+
end
|
139
|
+
|
129
140
|
puts "Starting MailCatcher"
|
130
141
|
|
131
|
-
Thin::Logging.silent =
|
142
|
+
Thin::Logging.silent = (ENV["MAILCATCHER_ENV"] != "development")
|
132
143
|
|
133
144
|
# One EventMachine loop...
|
134
145
|
EventMachine.run do
|
135
|
-
# Get our lion on if asked
|
136
|
-
MailCatcher::Growl.start if options[:growl]
|
137
|
-
|
138
146
|
smtp_url = "smtp://#{options[:smtp_ip]}:#{options[:smtp_port]}"
|
139
147
|
http_url = "http://#{options[:http_ip]}:#{options[:http_port]}"
|
140
148
|
|
@@ -147,7 +155,7 @@ module MailCatcher extend self
|
|
147
155
|
# Let Thin set itself up inside our EventMachine loop
|
148
156
|
# (Skinny/WebSockets just works on the inside)
|
149
157
|
rescue_port options[:http_port] do
|
150
|
-
Thin::Server.start
|
158
|
+
Thin::Server.start(options[:http_ip], options[:http_port], Web)
|
151
159
|
puts "==> #{http_url}"
|
152
160
|
end
|
153
161
|
|
@@ -161,7 +169,11 @@ module MailCatcher extend self
|
|
161
169
|
# Daemonize, if we should, but only after the servers have started.
|
162
170
|
if options[:daemon]
|
163
171
|
EventMachine.next_tick do
|
164
|
-
|
172
|
+
if quittable?
|
173
|
+
puts "*** MailCatcher runs as a daemon by default. Go to the web interface to quit."
|
174
|
+
else
|
175
|
+
puts "*** MailCatcher is now running as a daemon that cannot be quit."
|
176
|
+
end
|
165
177
|
Process.daemon
|
166
178
|
end
|
167
179
|
end
|
@@ -182,16 +194,10 @@ protected
|
|
182
194
|
rescue RuntimeError
|
183
195
|
if $!.to_s =~ /\bno acceptor\b/
|
184
196
|
puts "~~> ERROR: Something's using port #{port}. Are you already running MailCatcher?"
|
185
|
-
exit
|
197
|
+
exit -1
|
186
198
|
else
|
187
199
|
raise
|
188
200
|
end
|
189
201
|
end
|
190
202
|
end
|
191
203
|
end
|
192
|
-
|
193
|
-
require 'mail_catcher/events'
|
194
|
-
require 'mail_catcher/growl'
|
195
|
-
require 'mail_catcher/mail'
|
196
|
-
require 'mail_catcher/smtp'
|
197
|
-
require 'mail_catcher/web'
|
data/lib/mail_catcher/events.rb
CHANGED
data/lib/mail_catcher/mail.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "active_support/json"
|
2
|
+
require "eventmachine"
|
3
|
+
require "mail"
|
4
|
+
require "sqlite3"
|
5
5
|
|
6
6
|
module MailCatcher::Mail extend self
|
7
7
|
def db
|
8
8
|
@__db ||= begin
|
9
|
-
SQLite3::Database.new(
|
9
|
+
SQLite3::Database.new(":memory:", :type_translation => true).tap do |db|
|
10
10
|
db.execute(<<-SQL)
|
11
11
|
CREATE TABLE message (
|
12
12
|
id INTEGER PRIMARY KEY ASC,
|
@@ -41,7 +41,7 @@ module MailCatcher::Mail extend self
|
|
41
41
|
@add_message_query ||= db.prepare("INSERT INTO message (sender, recipients, subject, source, type, size, created_at) VALUES (?, ?, ?, ?, ?, ?, datetime('now'))")
|
42
42
|
|
43
43
|
mail = Mail.new(message[:source])
|
44
|
-
@add_message_query.execute(message[:sender], message[:recipients].to_json, mail.subject, message[:source], mail.mime_type ||
|
44
|
+
@add_message_query.execute(message[:sender], message[:recipients].to_json, mail.subject, message[:source], mail.mime_type || "text/plain", message[:source].length)
|
45
45
|
message_id = db.last_insert_row_id
|
46
46
|
parts = mail.all_parts
|
47
47
|
parts = [mail] if parts.empty?
|
@@ -49,7 +49,7 @@ module MailCatcher::Mail extend self
|
|
49
49
|
body = part.body.to_s
|
50
50
|
# Only parts have CIDs, not mail
|
51
51
|
cid = part.cid if part.respond_to? :cid
|
52
|
-
add_message_part(message_id, cid, part.mime_type ||
|
52
|
+
add_message_part(message_id, cid, part.mime_type || "text/plain", part.attachment? ? 1 : 0, part.filename, part.charset, body, body.length)
|
53
53
|
end
|
54
54
|
|
55
55
|
EventMachine.next_tick do
|
@@ -69,7 +69,7 @@ module MailCatcher::Mail extend self
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def messages
|
72
|
-
@messages_query ||= db.prepare "SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at
|
72
|
+
@messages_query ||= db.prepare "SELECT id, sender, recipients, subject, size, created_at FROM message ORDER BY created_at, id ASC"
|
73
73
|
@messages_query.execute.map do |row|
|
74
74
|
Hash[row.fields.zip(row)].tap do |message|
|
75
75
|
message["recipients"] &&= ActiveSupport::JSON.decode message["recipients"]
|
@@ -87,7 +87,7 @@ module MailCatcher::Mail extend self
|
|
87
87
|
|
88
88
|
def message_has_html?(id)
|
89
89
|
@message_has_html_query ||= db.prepare "SELECT 1 FROM message_part WHERE message_id = ? AND is_attachment = 0 AND type IN ('application/xhtml+xml', 'text/html') LIMIT 1"
|
90
|
-
(!!@message_has_html_query.execute(id).next) || [
|
90
|
+
(!!@message_has_html_query.execute(id).next) || ["text/html", "application/xhtml+xml"].include?(message(id)["type"])
|
91
91
|
end
|
92
92
|
|
93
93
|
def message_has_plain?(id)
|
@@ -126,7 +126,7 @@ module MailCatcher::Mail extend self
|
|
126
126
|
part ||= message_part_type(message_id, "application/xhtml+xml")
|
127
127
|
part ||= begin
|
128
128
|
message = message(message_id)
|
129
|
-
message if message.present? and [
|
129
|
+
message if message.present? and ["text/html", "application/xhtml+xml"].include? message["type"]
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -135,7 +135,7 @@ module MailCatcher::Mail extend self
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def message_part_cid(message_id, cid)
|
138
|
-
@message_part_cid_query ||= db.prepare
|
138
|
+
@message_part_cid_query ||= db.prepare "SELECT * FROM message_part WHERE message_id = ?"
|
139
139
|
@message_part_cid_query.execute(message_id).map do |row|
|
140
140
|
Hash[row.fields.zip(row)]
|
141
141
|
end.find do |part|
|
@@ -144,16 +144,16 @@ module MailCatcher::Mail extend self
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def delete!
|
147
|
-
@delete_messages_query ||= db.prepare
|
148
|
-
@delete_message_parts_query ||= db.prepare
|
147
|
+
@delete_messages_query ||= db.prepare "DELETE FROM message"
|
148
|
+
@delete_message_parts_query ||= db.prepare "DELETE FROM message_part"
|
149
149
|
|
150
150
|
@delete_messages_query.execute and
|
151
151
|
@delete_message_parts_query.execute
|
152
152
|
end
|
153
153
|
|
154
154
|
def delete_message!(message_id)
|
155
|
-
@delete_messages_query ||= db.prepare
|
156
|
-
@delete_message_parts_query ||= db.prepare
|
155
|
+
@delete_messages_query ||= db.prepare "DELETE FROM message WHERE id = ?"
|
156
|
+
@delete_message_parts_query ||= db.prepare "DELETE FROM message_part WHERE message_id = ?"
|
157
157
|
@delete_messages_query.execute(message_id) and
|
158
158
|
@delete_message_parts_query.execute(message_id)
|
159
159
|
end
|
data/lib/mail_catcher/smtp.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "eventmachine"
|
2
|
+
|
3
|
+
require "mail_catcher/mail"
|
2
4
|
|
3
5
|
class MailCatcher::Smtp < EventMachine::Protocols::SmtpServer
|
4
6
|
# We override EM's mail from processing to allow multiple mail-from commands
|
@@ -34,7 +36,9 @@ class MailCatcher::Smtp < EventMachine::Protocols::SmtpServer
|
|
34
36
|
|
35
37
|
def receive_data_chunk(lines)
|
36
38
|
current_message[:source] ||= ""
|
37
|
-
|
39
|
+
lines.each do |line|
|
40
|
+
current_message[:source] << line << "\r\n"
|
41
|
+
end
|
38
42
|
true
|
39
43
|
end
|
40
44
|
|
data/lib/mail_catcher/version.rb
CHANGED