astrotrain 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +8 -0
- data/LICENSE +18 -17
- data/Rakefile +118 -103
- data/astrotrain.gemspec +87 -136
- data/lib/astrotrain.rb +47 -51
- data/lib/astrotrain/attachment.rb +55 -0
- data/lib/astrotrain/message.rb +221 -235
- data/lib/astrotrain/transports/http_post.rb +67 -0
- data/lib/astrotrain/transports/resque.rb +63 -0
- data/test/fixtures/bad_email_format.txt +15 -0
- data/test/fixtures/basic.txt +4 -1
- data/test/fixtures/iso-8859-1.txt +1 -0
- data/test/message_test.rb +146 -457
- data/test/test_helper.rb +20 -42
- data/test/transport_test.rb +98 -100
- metadata +100 -243
- data/.gitignore +0 -26
- data/README +0 -47
- data/VERSION +0 -1
- data/config/sample.rb +0 -12
- data/lib/astrotrain/api.rb +0 -52
- data/lib/astrotrain/logged_mail.rb +0 -48
- data/lib/astrotrain/mapping.rb +0 -162
- data/lib/astrotrain/mapping/http_post.rb +0 -18
- data/lib/astrotrain/mapping/jabber.rb +0 -28
- data/lib/astrotrain/mapping/transport.rb +0 -55
- data/lib/astrotrain/tmail.rb +0 -58
- data/lib/astrotrain/worker.rb +0 -65
- data/lib/vendor/rest-client/README.rdoc +0 -104
- data/lib/vendor/rest-client/Rakefile +0 -84
- data/lib/vendor/rest-client/bin/restclient +0 -65
- data/lib/vendor/rest-client/foo.diff +0 -66
- data/lib/vendor/rest-client/lib/rest_client.rb +0 -188
- data/lib/vendor/rest-client/lib/rest_client/net_http_ext.rb +0 -23
- data/lib/vendor/rest-client/lib/rest_client/payload.rb +0 -185
- data/lib/vendor/rest-client/lib/rest_client/request_errors.rb +0 -75
- data/lib/vendor/rest-client/lib/rest_client/resource.rb +0 -103
- data/lib/vendor/rest-client/rest-client.gemspec +0 -18
- data/lib/vendor/rest-client/spec/base.rb +0 -5
- data/lib/vendor/rest-client/spec/master_shake.jpg +0 -0
- data/lib/vendor/rest-client/spec/payload_spec.rb +0 -71
- data/lib/vendor/rest-client/spec/request_errors_spec.rb +0 -44
- data/lib/vendor/rest-client/spec/resource_spec.rb +0 -52
- data/lib/vendor/rest-client/spec/rest_client_spec.rb +0 -219
- data/test/api_test.rb +0 -32
- data/test/logged_mail_test.rb +0 -67
- data/test/mapping_test.rb +0 -129
@@ -0,0 +1,67 @@
|
|
1
|
+
module Astrotrain
|
2
|
+
module Transports
|
3
|
+
module HttpPost
|
4
|
+
Astrotrain::Transports::MAP.update \
|
5
|
+
:http => self,
|
6
|
+
:https => self
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_writer :connection
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.connection
|
13
|
+
@connection ||= Faraday.default_connection
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Sends the message to the given address.
|
17
|
+
#
|
18
|
+
# message - Astrotrain::Message instance
|
19
|
+
# url - String address of the recipient service
|
20
|
+
# options - Optional Hash:
|
21
|
+
# :recipient - String email of the main recipient
|
22
|
+
# :extra - Hash to be merged with the payload
|
23
|
+
#
|
24
|
+
# Returns a RestClient::Response object for responses between 200..206
|
25
|
+
# Raises RestClient::Exception for any code not between 200..206 or
|
26
|
+
# 301..302
|
27
|
+
def self.deliver(message, url, options = {})
|
28
|
+
recipient = options[:recipient] || message.recipients.first
|
29
|
+
payload = create_hash(message, recipient)
|
30
|
+
if extra = options[:extra]
|
31
|
+
payload.update(extra)
|
32
|
+
end
|
33
|
+
connection.post(url, payload)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# Creates a param hash for RestClient.
|
38
|
+
#
|
39
|
+
# message - Astrotrain::Message instance
|
40
|
+
# recipient - String email of the main recipient.
|
41
|
+
#
|
42
|
+
# Returns a Hash for RestClient.post
|
43
|
+
def self.create_hash(message, recipient)
|
44
|
+
h = {:subject => message.subject, :to => {}, :from => {}, :cc => {},
|
45
|
+
:body => message.body, :emails => message.recipients.join(", "), :html => message.html,
|
46
|
+
:headers => message.headers, :attachments => {}}
|
47
|
+
[:to, :from, :cc].each do |key|
|
48
|
+
message.send(key).each_with_index do |addr, i|
|
49
|
+
h[key][i] = {:name => addr.display_name, :address => addr.address}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
message.attachments.each_with_index do |a, i|
|
53
|
+
h[:attachments][i] = a
|
54
|
+
end
|
55
|
+
[:attachments, :to, :from, :cc].each do |key|
|
56
|
+
h.delete(key) if h[key].empty?
|
57
|
+
end
|
58
|
+
h
|
59
|
+
end
|
60
|
+
|
61
|
+
# kept for backwards compatibility
|
62
|
+
def self.process(url, message, recipient = nil, extra = nil)
|
63
|
+
deliver(message, url, :recipient => recipient, :extra => extra)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'resque'
|
2
|
+
|
3
|
+
module Astrotrain
|
4
|
+
module Transports
|
5
|
+
module Resque
|
6
|
+
# resque://QUEUE/KLASS
|
7
|
+
Astrotrain::Transports::MAP[:resque] = self
|
8
|
+
|
9
|
+
# Public: Sends the message to the given address.
|
10
|
+
#
|
11
|
+
# message - Astrotrain::Message instance
|
12
|
+
# url - String address of the Resque in this form:
|
13
|
+
# "QUEUE/KLASS"
|
14
|
+
# options - Optional Hash:
|
15
|
+
# :recipient - String email of the main recipient
|
16
|
+
# :extra - Hash to be merged with the payload
|
17
|
+
#
|
18
|
+
# Returns a queued Resque::Job instance.
|
19
|
+
def self.deliver(message, url, options = {})
|
20
|
+
recipient = options[:recipient] || message.recipients.first
|
21
|
+
uri = url.is_a?(Addressable::URI) ?
|
22
|
+
url :
|
23
|
+
Addressable::URI.parse(url)
|
24
|
+
path = uri.path.dup
|
25
|
+
path.sub! /^\//, ''
|
26
|
+
queue, *job = path.split("/")
|
27
|
+
if qu = uri.host
|
28
|
+
job.unshift(queue)
|
29
|
+
queue = qu
|
30
|
+
end
|
31
|
+
payload = create_hash(message, recipient)
|
32
|
+
if extra = options[:extra]
|
33
|
+
payload.update(extra)
|
34
|
+
end
|
35
|
+
::Resque::Job.create(queue, job.join("/"), payload)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates a param hash for RestClient.
|
39
|
+
#
|
40
|
+
# message - Astrotrain::Message instance
|
41
|
+
# recipient - String email of the main recipient.
|
42
|
+
#
|
43
|
+
# Returns a Hash for Resque.
|
44
|
+
def self.create_hash(message, recipient)
|
45
|
+
h = {:subject => message.subject, :to => [], :from => [], :cc => [],
|
46
|
+
:body => message.body, :emails => message.recipients.join(", "), :html => message.html,
|
47
|
+
:headers => message.headers}
|
48
|
+
[:to, :from, :cc].each do |key|
|
49
|
+
message.send(key).each_with_index do |addr, i|
|
50
|
+
h[key] << {:name => addr.display_name, :address => addr.address}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
h
|
54
|
+
end
|
55
|
+
|
56
|
+
# kept for backwards compatibility
|
57
|
+
def self.process(url, message, recipient = nil, extra = nil)
|
58
|
+
deliver(message, url, :recipient => recipient, :extra => extra)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Delivered-To: "Processor" <processor@astrotrain.com>
|
2
|
+
Message-ID: <a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com>
|
3
|
+
Date: Thu, 16 Oct 2008 10:14:18 -0700
|
4
|
+
From: Ricky <ricky.bobby@foo.com>, Bobby:bobby@foo.com, reply....@foo.com
|
5
|
+
To: Processor <processor@astrotrain.com>
|
6
|
+
Cc: Fred <fred@example.com>
|
7
|
+
Subject: Fwd: blah blah
|
8
|
+
MIME-Version: 1.0
|
9
|
+
X-Custom: reply
|
10
|
+
Content-Type: text/plain; charset=ISO-8859-1
|
11
|
+
Content-Transfer-Encoding: 7bit
|
12
|
+
Content-Disposition: inline
|
13
|
+
|
14
|
+
---------- Forwarded message ----------
|
15
|
+
blah blah
|
data/test/fixtures/basic.txt
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
Delivered-To: "Processor" <processor@astrotrain.com>
|
2
2
|
Message-ID: <a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com>
|
3
|
+
Received: by 10.231.149.194 with SMTP id u2mr924086ibv.32.1298067999839; Fri, 18 Feb 2011 14:26:39 -0800
|
4
|
+
Received: by 10.231.153.2 with HTTP; Fri, 18 Feb 2011 14:26:39 -0800
|
3
5
|
Date: Thu, 16 Oct 2008 10:14:18 -0700
|
4
6
|
From: Bob <user@example.com>
|
5
7
|
To: Processor <processor@astrotrain.com>
|
8
|
+
Cc: Fred <fred@example.com>
|
6
9
|
Subject: Fwd: blah blah
|
7
10
|
MIME-Version: 1.0
|
8
11
|
X-Custom: reply
|
@@ -11,4 +14,4 @@ Content-Transfer-Encoding: 7bit
|
|
11
14
|
Content-Disposition: inline
|
12
15
|
|
13
16
|
---------- Forwarded message ----------
|
14
|
-
blah blah
|
17
|
+
blah blah
|
@@ -2,6 +2,7 @@ Delivered-To: "Processor" <processor@astrotrain.com>
|
|
2
2
|
Message-ID: <a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com>
|
3
3
|
Date: Thu, 16 Oct 2008 10:14:18 -0700
|
4
4
|
From: =?ISO-8859-1?Q?Matth=E9w?= <user@example.com>
|
5
|
+
Cc: =?ISO-8859-1?Q?Matth=E9w?= <cc@example.com>
|
5
6
|
To: Processor <processor@astrotrain.com>
|
6
7
|
Subject: Fwd: blah blah
|
7
8
|
MIME-Version: 1.0
|
data/test/message_test.rb
CHANGED
@@ -1,492 +1,181 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Astrotrain::MessageTest < Astrotrain::TestCase
|
4
|
-
describe "mapping" do
|
5
|
-
describe "against default domain" do
|
6
|
-
before :all do
|
7
|
-
Astrotrain::Mapping.transaction do
|
8
|
-
Astrotrain::LoggedMail.all.destroy!
|
9
|
-
Astrotrain::Mapping.all.destroy!
|
10
|
-
@mapping = Astrotrain::Mapping.create!(:email_user => 'xyz')
|
11
|
-
@mapping2 = Astrotrain::Mapping.create!(:email_user => 'xyz', :email_domain => 'sample.com')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "without mapping" do
|
16
|
-
before do
|
17
|
-
Astrotrain::LoggedMail.all.destroy!
|
18
|
-
end
|
19
|
-
|
20
|
-
it "doesn't log message" do
|
21
|
-
@msg = Astrotrain::Message.receive(mail(:basic))
|
22
|
-
@log = Astrotrain::LoggedMail.first
|
23
|
-
assert_nil @log
|
24
|
-
end
|
25
|
-
|
26
|
-
it "logs message if Astrotrain::LoggedMail.log_processed" do
|
27
|
-
Astrotrain::LoggedMail.log_processed = true
|
28
|
-
@msg = Astrotrain::Message.receive(mail(:basic))
|
29
|
-
@log = Astrotrain::LoggedMail.first
|
30
|
-
assert @log
|
31
|
-
assert @log.error_message.blank?
|
32
|
-
end
|
33
|
-
|
34
|
-
it "calls pre_mapping callback" do
|
35
|
-
Astrotrain::LoggedMail.log_processed = true
|
36
|
-
callback_msg = nil
|
37
|
-
Astrotrain.callback(:pre_mapping) do |message|
|
38
|
-
callback_msg = message
|
39
|
-
end
|
40
|
-
|
41
|
-
@msg = Astrotrain::Message.receive(mail(:mapped))
|
42
|
-
assert_equal callback_msg, @msg
|
43
|
-
end
|
44
|
-
|
45
|
-
it "it allows pre_mapping callback to cancel processing" do
|
46
|
-
Astrotrain::LoggedMail.log_processed = true
|
47
|
-
Astrotrain.callback(:pre_mapping) do |message|
|
48
|
-
raise Astrotrain::ProcessingCancelled
|
49
|
-
end
|
50
|
-
|
51
|
-
@msg = Astrotrain::Message.receive(mail(:mapped))
|
52
|
-
assert_equal 0, Astrotrain::LoggedMail.count
|
53
|
-
end
|
54
|
-
|
55
|
-
it "calls pre_processing callback" do
|
56
|
-
Astrotrain::LoggedMail.log_processed = true
|
57
|
-
callback_msg, callback_map = nil
|
58
|
-
Astrotrain.callback(:pre_processing) do |message, mapping|
|
59
|
-
callback_msg = message
|
60
|
-
callback_map = mapping
|
61
|
-
end
|
62
|
-
|
63
|
-
@msg = Astrotrain::Message.receive(mail(:mapped))
|
64
|
-
@log = Astrotrain::LoggedMail.first
|
65
|
-
assert_equal callback_msg, @msg
|
66
|
-
assert_equal callback_map, @log.mapping
|
67
|
-
end
|
68
|
-
|
69
|
-
it "it allows pre_processing callback to cancel processing" do
|
70
|
-
Astrotrain::LoggedMail.log_processed = true
|
71
|
-
Astrotrain.callback(:pre_processing) do |message, mapping|
|
72
|
-
raise Astrotrain::ProcessingCancelled
|
73
|
-
end
|
74
|
-
|
75
|
-
@msg = Astrotrain::Message.receive(mail(:mapped))
|
76
|
-
@log = Astrotrain::LoggedMail.first
|
77
|
-
assert_equal "Cancelled.", @log.error_message
|
78
|
-
end
|
79
|
-
|
80
|
-
it "calls post_processing callback" do
|
81
|
-
Astrotrain::LoggedMail.log_processed = true
|
82
|
-
callback_msg, callback_map, callback_log = nil
|
83
|
-
Astrotrain.callback(:post_processing) do |message, mapping, log|
|
84
|
-
callback_msg = message
|
85
|
-
callback_map = mapping
|
86
|
-
callback_log = log
|
87
|
-
end
|
88
|
-
|
89
|
-
@msg = Astrotrain::Message.receive(mail(:mapped))
|
90
|
-
@log = Astrotrain::LoggedMail.first
|
91
|
-
assert_equal callback_msg, @msg
|
92
|
-
assert_equal callback_map, @log.mapping
|
93
|
-
assert_equal callback_log, @log
|
94
|
-
end
|
95
|
-
|
96
|
-
after do
|
97
|
-
Astrotrain::LoggedMail.log_processed = false
|
98
|
-
Astrotrain.clear_callbacks
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe "erroring" do
|
103
|
-
before do
|
104
|
-
Astrotrain::LoggedMail.all.destroy!
|
105
|
-
end
|
106
|
-
|
107
|
-
it "logs message without mappping" do
|
108
|
-
stub(Astrotrain::Mapping).match { raise RuntimeError }
|
109
|
-
@msg = Astrotrain::Message.receive(mail(:basic))
|
110
|
-
@log = Astrotrain::LoggedMail.first
|
111
|
-
assert @log
|
112
|
-
assert_nil @log.delivered_at
|
113
|
-
assert_match /RuntimeError/, @log.error_message
|
114
|
-
assert_nil @log.mapping
|
115
|
-
end
|
116
|
-
|
117
|
-
it "logs message with mappping" do
|
118
|
-
stub(Astrotrain::Mapping).match {@mapping}
|
119
|
-
stub(@mapping).process { raise RuntimeError }
|
120
|
-
@msg = Astrotrain::Message.receive(mail(:basic))
|
121
|
-
@log = Astrotrain::LoggedMail.first
|
122
|
-
assert @log
|
123
|
-
assert_nil @log.delivered_at
|
124
|
-
assert_match /RuntimeError/, @log.error_message
|
125
|
-
assert_equal @mapping, @log.mapping
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
describe "with mapping" do
|
130
|
-
before :all do
|
131
|
-
@msg = Astrotrain::Message.receive(mail(:mapped))
|
132
|
-
@log = Astrotrain::LoggedMail.first
|
133
|
-
end
|
134
|
-
|
135
|
-
it "does not log message" do
|
136
|
-
assert_nil @log
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe "parsing" do
|
143
|
-
before :all do
|
144
|
-
@body = "---------- Forwarded message ----------\nblah blah"
|
145
|
-
end
|
146
|
-
|
147
|
-
describe "basic, with bad content type header" do
|
148
|
-
before :all do
|
149
|
-
@raw = mail(:bad_content_type)
|
150
|
-
@message = Astrotrain::Message.parse(@raw)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "parses body" do
|
154
|
-
expected = "--====boundary====\nContent-Type: text/plain; charset=\"us-ascii\"\n\nThis message is being generated automatically to notify you\nthat PowerMTA has crashed on mtasv.net.\n\nAs the information below is likely to be essential for debugging\nthe problem, please forward this message to <support@port25.com>.\nThank you.\n\n--====boundary====\nContent-Type: text/plain; charset=\"us-ascii\"\n\nYo\n--====boundary====--"
|
155
|
-
assert_equal expected, @message.body
|
156
|
-
end
|
157
|
-
|
158
|
-
it "attempts parsing bad header" do
|
159
|
-
assert_equal "multipart/mixed; boundary=\"====boundary=\"===\"\"", @message.header('content-type')
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
describe "basic, single sender/recipient" do
|
164
|
-
before :all do
|
165
|
-
@raw = mail(:basic)
|
166
|
-
@message = Astrotrain::Message.parse(@raw)
|
167
|
-
end
|
168
|
-
|
169
|
-
it "parses message-id and headers" do
|
170
|
-
assert_equal 'a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com', @message.message_id
|
171
|
-
expected = {'mime-version' => '1.0', 'content-type' => 'text/plain; charset=ISO-8859-1', 'to' => 'Processor <processor@astrotrain.com>',
|
172
|
-
'x-custom' => 'reply', 'content-transfer-encoding' => '7bit', 'content-disposition' => 'inline', 'message-id' => '<a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com>'}
|
173
|
-
assert_equal expected, @message.headers
|
174
|
-
end
|
175
|
-
|
176
|
-
it "#parse parses TMail::Mail object from raw text" do
|
177
|
-
assert_kind_of TMail::Mail, @message.mail
|
178
|
-
end
|
179
|
-
|
180
|
-
it "recognizes Delivered-To and To: headers as recipients" do
|
181
|
-
assert_equal %w(processor@astrotrain.com), @message.recipients
|
182
|
-
end
|
183
|
-
|
184
|
-
it "recognizes From: header as sender" do
|
185
|
-
assert_equal %(Bob <user@example.com>), @message.sender
|
186
|
-
end
|
187
|
-
|
188
|
-
it "recognizes Subject: header" do
|
189
|
-
assert_equal 'Fwd: blah blah', @message.subject
|
190
|
-
end
|
191
|
-
|
192
|
-
it "recognizes message body" do
|
193
|
-
assert_equal @body, @message.body
|
194
|
-
end
|
195
|
-
|
196
|
-
it "retains raw message" do
|
197
|
-
assert_equal @raw, @message.raw
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
describe "iso 8859 1 encoded headers" do
|
202
|
-
before :all do
|
203
|
-
@raw = mail("iso-8859-1")
|
204
|
-
@message = Astrotrain::Message.parse(@raw)
|
205
|
-
end
|
206
|
-
|
207
|
-
it "recognizes From: header with strange encoding" do
|
208
|
-
assert_equal %(Matthéw <user@example.com>), @message.sender
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
describe "gb2312 encoded body" do
|
213
|
-
before :all do
|
214
|
-
@raw = mail("gb2312_encoding")
|
215
|
-
@message = Astrotrain::Message.parse(@raw)
|
216
|
-
end
|
217
|
-
|
218
|
-
it "converts to UTF-8" do
|
219
|
-
assert_equal "Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd: blah China",
|
220
|
-
@message.body
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe "gb2312 encoded body with invalid charset in mime version header" do
|
225
|
-
before :all do
|
226
|
-
@raw = mail("gb2312_encoding_invalid")
|
227
|
-
@message = Astrotrain::Message.parse(@raw)
|
228
|
-
end
|
229
|
-
|
230
|
-
it "converts to UTF-8" do
|
231
|
-
assert_equal "Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd: blah China",
|
232
|
-
@message.body
|
233
|
-
end
|
234
|
-
end
|
1
|
+
# encoding: UTF-8
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
235
3
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
@message = Astrotrain::Message.parse(@raw)
|
240
|
-
end
|
241
|
-
|
242
|
-
it "recognizes From: header with strange encoding" do
|
243
|
-
assert_equal %(isnard naiké <user@example.com>), @message.sender
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
describe "multipart message with name property on Content Type" do
|
248
|
-
before :all do
|
249
|
-
@raw = mail(:multipart)
|
250
|
-
@message = Astrotrain::Message.parse(@raw)
|
251
|
-
end
|
252
|
-
|
253
|
-
it "#parse parses TMail::Mail object from raw text" do
|
254
|
-
assert_kind_of TMail::Mail, @message.mail
|
255
|
-
end
|
256
|
-
|
257
|
-
it "recognizes Delivered-To/To: headers as recipient" do
|
258
|
-
assert_equal %w(foo@example.com), @message.recipients
|
259
|
-
end
|
260
|
-
|
261
|
-
it "recognizes message body" do
|
262
|
-
assert_equal "Testing out rich emails with attachments!\nThis one has a name property on Content-Type.\n[state:hold responsible:rick]\n\n",
|
263
|
-
@message.body
|
264
|
-
end
|
265
|
-
|
266
|
-
it "retrieves attachments" do
|
267
|
-
assert_equal 1, @message.attachments.size
|
268
|
-
end
|
269
|
-
|
270
|
-
it "retrieves attachment filename" do
|
271
|
-
assert_equal 'bandit.jpg', @message.attachments.first.filename
|
272
|
-
end
|
273
|
-
|
274
|
-
it "retrieves attachment content_type" do
|
275
|
-
assert_equal 'image/jpeg', @message.attachments.first.content_type
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
describe "multipart message with filename property on Content Disposition" do
|
280
|
-
before :all do
|
281
|
-
@raw = mail(:multipart2)
|
282
|
-
@message = Astrotrain::Message.parse(@raw)
|
283
|
-
end
|
284
|
-
|
285
|
-
it "#parse parses TMail::Mail object from raw text" do
|
286
|
-
assert_kind_of TMail::Mail, @message.mail
|
287
|
-
end
|
288
|
-
|
289
|
-
it "recognizes Delivered-To/To: headers as recipient" do
|
290
|
-
assert_equal %w(foo@example.com), @message.recipients
|
291
|
-
end
|
292
|
-
|
293
|
-
it "recognizes message body" do
|
294
|
-
assert_equal "Testing out rich emails with attachments!\nThis one has NO name property on Content-Type.\n[state:hold responsible:rick]\n\n",
|
295
|
-
@message.body
|
296
|
-
end
|
297
|
-
|
298
|
-
it "retrieves attachments" do
|
299
|
-
assert_equal 1, @message.attachments.size
|
300
|
-
end
|
301
|
-
|
302
|
-
it "retrieves attachment filename" do
|
303
|
-
assert_equal 'bandit.jpg', @message.attachments.first.filename
|
304
|
-
end
|
305
|
-
|
306
|
-
it "retrieves attachment content_type" do
|
307
|
-
assert_equal 'image/jpeg', @message.attachments.first.content_type
|
308
|
-
end
|
309
|
-
end
|
4
|
+
class MessageParsingTest < Test::Unit::TestCase
|
5
|
+
test "bad content type header" do
|
6
|
+
msg = astrotrain :bad_content_type
|
310
7
|
|
311
|
-
|
312
|
-
|
313
|
-
@raw = mail(:apple_multipart)
|
314
|
-
@message = Astrotrain::Message.parse(@raw)
|
315
|
-
end
|
8
|
+
expected_body = "This message is being generated automatically to notify you\nthat PowerMTA has crashed on mtasv.net.\n\nAs the information below is likely to be essential for debugging\nthe problem, please forward this message to <support@port25.com>.\nThank you.\nYo"
|
9
|
+
expected_header = "multipart/mixed; boundary=\"====boundary====\""
|
316
10
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
it "recognizes To: header as recipient" do
|
322
|
-
assert_equal %w(foo@example.com), @message.recipients
|
323
|
-
end
|
324
|
-
|
325
|
-
it "recognizes message body" do
|
326
|
-
assert_equal "Let's have a test here:\r\n\r\n\r\n\nYum\r\n\r\n\r\nOn Feb 10, 2009, at 3:37 PM, Tender Support wrote:\r\n\r\n> // Add your reply above here\r\n> ==================================================\r\n> From: Tyler Durden\r\n> Subject: Email attachments and file upload\r\n>\r\n> not at the moment ... let me test\r\n>\r\n> View this Discussion online: http://foobar.com\r\n> .\r\n\r\n\r\n\r\n\r\n--Apple-Mail-7-451386929--",
|
327
|
-
@message.body
|
328
|
-
end
|
329
|
-
|
330
|
-
it "retrieves attachments" do
|
331
|
-
assert_equal 1, @message.attachments.size
|
332
|
-
end
|
333
|
-
|
334
|
-
it "retrieves attachment filename" do
|
335
|
-
assert_equal 'logo.gif', @message.attachments.first.filename
|
336
|
-
end
|
337
|
-
|
338
|
-
it "retrieves attachment content_type" do
|
339
|
-
assert_equal 'image/gif', @message.attachments.first.content_type
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
describe "multiple sender/recipients" do
|
344
|
-
before :all do
|
345
|
-
@raw = mail(:multiple)
|
346
|
-
@message = Astrotrain::Message.parse(@raw)
|
347
|
-
end
|
11
|
+
assert_equal expected_body, msg.body
|
12
|
+
assert_equal expected_header, msg.headers['content-type']
|
13
|
+
end
|
348
14
|
|
349
|
-
|
350
|
-
|
351
|
-
|
15
|
+
test "basic email" do
|
16
|
+
body = "---------- Forwarded message ----------\nblah blah"
|
17
|
+
msg = astrotrain :basic
|
352
18
|
|
353
|
-
|
354
|
-
|
355
|
-
|
19
|
+
assert_equal 'a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com', msg.message_id
|
20
|
+
expected = {'mime-version' => '1.0', 'content-type' => 'text/plain; charset=ISO-8859-1', 'date' => "Thu, 16 Oct 2008 10:14:18 -0700",
|
21
|
+
'x-custom' => 'reply', 'content-transfer-encoding' => '7bit', 'content-disposition' => 'inline', 'message-id' => '<a16be7390810161014n52b603e9k1aa6bb803c6735aa@mail.gmail.com>'}
|
22
|
+
assert_equal expected, msg.headers
|
356
23
|
|
357
|
-
|
358
|
-
assert_equal %w(other@example.com processor@astrotrain.com), @message.recipients(%w(to original_to delivered_to))
|
359
|
-
end
|
24
|
+
assert_kind_of Mail::Message, msg.mail
|
360
25
|
|
361
|
-
|
362
|
-
|
363
|
-
|
26
|
+
assert_equal %w(processor@astrotrain.com), msg.recipients
|
27
|
+
assert_equal %(Bob <user@example.com>), msg.sender.join
|
28
|
+
assert_equal %(Bob), msg.sender.first.display_name
|
29
|
+
assert_equal %(user@example.com), msg.sender.first.address
|
30
|
+
assert_equal 'Fwd: blah blah', msg.subject
|
31
|
+
assert_equal body, msg.body
|
32
|
+
end
|
364
33
|
|
365
|
-
|
366
|
-
|
367
|
-
|
34
|
+
test "iso 8859 1 encoded headers" do
|
35
|
+
msg = astrotrain "iso-8859-1"
|
36
|
+
s = Object.const_defined?(:Encoding) ? "Matthéw" : "Matth\351w"
|
37
|
+
assert_equal "user@example.com", msg.sender.first.address
|
38
|
+
assert_equal "cc@example.com", msg.cc.first.address
|
39
|
+
assert_equal s, msg.sender.first.display_name
|
40
|
+
assert_equal s, msg.cc.first.display_name
|
41
|
+
end
|
368
42
|
|
369
|
-
|
370
|
-
|
371
|
-
|
43
|
+
test "gb2312 encoded body" do
|
44
|
+
msg = astrotrain(:gb2312_encoding)
|
45
|
+
# encoding problem?
|
46
|
+
# "Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd: blah China"
|
47
|
+
s = if Object.const_defined?(:Encoding)
|
48
|
+
# ruby 1.9 is our bro
|
49
|
+
"Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd: blah China"
|
50
|
+
else
|
51
|
+
# ruby 1.8 gets messed up crap
|
52
|
+
"Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd\357\274\232 blah China"
|
53
|
+
end
|
54
|
+
assert_equal s, msg.body
|
55
|
+
end
|
372
56
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
57
|
+
test "gb2312 encoded body with invalid charset in mime version header" do
|
58
|
+
msg = astrotrain(:gb2312_encoding_invalid)
|
59
|
+
# encoding problem?
|
60
|
+
# "Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd: blah China"
|
61
|
+
s = "Dear Sirs, \r\nWe are given to understand that you are Manufacturer of plstic Bottles\r\nAdd?? blah China"
|
62
|
+
assert_equal s, msg.body
|
63
|
+
end
|
377
64
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
65
|
+
test "utf-8 encoded headers" do
|
66
|
+
msg = astrotrain('utf-8')
|
67
|
+
assert_equal "isnard naik\303\251", msg.sender.first.display_name
|
68
|
+
assert_equal "user@example.com", msg.sender.first.address
|
69
|
+
end
|
383
70
|
|
384
|
-
|
385
|
-
|
386
|
-
@message.recipients
|
387
|
-
end
|
388
|
-
end
|
71
|
+
test "multipart message with name property on Content Type" do
|
72
|
+
msg = astrotrain(:multipart)
|
389
73
|
|
390
|
-
|
391
|
-
before :all do
|
392
|
-
@raw = mail(:html_multipart)
|
393
|
-
@message = Astrotrain::Message.parse(@raw)
|
394
|
-
end
|
74
|
+
assert_kind_of Mail::Message, msg.mail
|
395
75
|
|
396
|
-
|
397
|
-
|
398
|
-
|
76
|
+
assert_equal %w(foo@example.com), msg.recipients
|
77
|
+
assert_equal "Testing out rich emails with attachments!\nThis one has a name property on Content-Type.\n[state:hold responsible:rick]",
|
78
|
+
msg.body
|
79
|
+
assert_equal 1, msg.attachments.size
|
80
|
+
assert_equal 'bandit.jpg', msg.attachments.first.filename
|
81
|
+
assert_match 'image/jpeg', msg.attachments.first.content_type
|
82
|
+
end
|
399
83
|
|
400
|
-
|
401
|
-
|
402
|
-
end
|
403
|
-
end
|
84
|
+
test "multipart message with filename property on Content Disposition" do
|
85
|
+
msg = astrotrain(:multipart2)
|
404
86
|
|
405
|
-
|
406
|
-
before :all do
|
407
|
-
@raw = mail(:html)
|
408
|
-
@message = Astrotrain::Message.parse(@raw)
|
409
|
-
end
|
87
|
+
assert_kind_of Mail::Message, msg.mail
|
410
88
|
|
411
|
-
|
412
|
-
|
413
|
-
|
89
|
+
assert_equal %w(foo@example.com), msg.recipients
|
90
|
+
assert_equal "Testing out rich emails with attachments!\nThis one has NO name property on Content-Type.\n[state:hold responsible:rick]",
|
91
|
+
msg.body
|
92
|
+
assert_equal 1, msg.attachments.size
|
93
|
+
assert_equal 'bandit.jpg', msg.attachments.first.filename
|
94
|
+
assert_match 'image/jpeg', msg.attachments.first.content_type
|
95
|
+
end
|
414
96
|
|
415
|
-
|
416
|
-
|
417
|
-
end
|
418
|
-
end
|
97
|
+
test "apple multipart message" do
|
98
|
+
msg = astrotrain(:apple_multipart)
|
419
99
|
|
420
|
-
|
421
|
-
before :all do
|
422
|
-
@raw = mail(:custom)
|
423
|
-
@message = Astrotrain::Message.parse(@raw)
|
424
|
-
end
|
100
|
+
assert_kind_of Mail::Message, msg.mail
|
425
101
|
|
426
|
-
|
427
|
-
|
428
|
-
|
102
|
+
assert_equal %w(foo@example.com), msg.recipients
|
103
|
+
assert_equal "Let's have a test here:\nYum\n\n\nOn Feb 10, 2009, at 3:37 PM, Tender Support wrote:\n\n> // Add your reply above here\n> ==================================================\n> From: Tyler Durden\n> Subject: Email attachments and file upload\n>\n> not at the moment ... let me test\n>\n> View this Discussion online: http://foobar.com\n> .",
|
104
|
+
msg.body
|
105
|
+
assert_equal 1, msg.attachments.size
|
106
|
+
assert_equal 'logo.gif', msg.attachments.first.filename
|
107
|
+
assert_match 'image/gif', msg.attachments.first.content_type
|
108
|
+
end
|
429
109
|
|
430
|
-
|
431
|
-
|
432
|
-
|
110
|
+
test "multiple sender/recipients" do
|
111
|
+
body = "---------- Forwarded message ----------\nblah blah"
|
112
|
+
msg = astrotrain(:multiple)
|
113
|
+
|
114
|
+
assert_kind_of Mail::Message, msg.mail
|
115
|
+
assert_equal %w(processor@astrotrain.com other@example.com), msg.recipients
|
116
|
+
assert_equal %w(other@example.com processor@astrotrain.com), msg.recipients(%w(to original_to delivered_to))
|
117
|
+
assert_equal %(user@example.com), msg.sender[0].address
|
118
|
+
assert_equal %(boss@example.com), msg.sender[1].address
|
119
|
+
assert_equal 'Fwd: blah blah', msg.subject
|
120
|
+
assert_equal body, msg.body
|
121
|
+
end
|
433
122
|
|
434
|
-
|
435
|
-
|
436
|
-
end
|
123
|
+
test "recipients in the body" do
|
124
|
+
msg = astrotrain(:multiple_with_body_recipients)
|
437
125
|
|
438
|
-
|
439
|
-
|
440
|
-
|
126
|
+
assert_equal %w(processor@astrotrain.com other@example.com processor+foobar@astrotrain.com processor+blah@astrotrain.com),
|
127
|
+
msg.recipients
|
128
|
+
end
|
441
129
|
|
442
|
-
|
443
|
-
|
444
|
-
end
|
130
|
+
test "with only HTML body in a multipart message" do
|
131
|
+
msg = astrotrain(:html_multipart)
|
445
132
|
|
446
|
-
|
447
|
-
|
448
|
-
|
133
|
+
assert_equal '', msg.body
|
134
|
+
assert_equal "<p>ABC</p>\n------", msg.html
|
135
|
+
end
|
449
136
|
|
450
|
-
|
451
|
-
|
452
|
-
end
|
137
|
+
test "with only HTML body in a multipart message" do
|
138
|
+
msg = astrotrain(:html)
|
453
139
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
end
|
140
|
+
assert_equal '', msg.body
|
141
|
+
assert_equal "<p>ABC</p>", msg.html
|
142
|
+
end
|
458
143
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
144
|
+
test "with X Original To header" do
|
145
|
+
body = "---------- Forwarded message ----------\nblah blah"
|
146
|
+
msg = astrotrain(:custom)
|
147
|
+
|
148
|
+
assert_kind_of Mail::Message, msg.mail
|
149
|
+
assert_equal %w(processor-reply-57@custom.com processor-delivered@astrotrain.com processor@astrotrain.com), msg.recipients
|
150
|
+
assert_equal %w(processor-delivered@astrotrain.com processor-reply-57@custom.com processor@astrotrain.com), msg.recipients(%w(delivered_to original_to to))
|
151
|
+
assert_equal %w(processor@astrotrain.com processor-reply-57@custom.com processor-delivered@astrotrain.com), msg.recipients(%w(to original_to delivered_to))
|
152
|
+
assert_equal 'user@example.com', msg.sender[0].address
|
153
|
+
assert_equal 'boss@example.com', msg.sender[1].address
|
154
|
+
assert_equal 'Fwd: blah blah', msg.subject
|
155
|
+
assert_equal body, msg.body
|
156
|
+
end
|
464
157
|
|
465
|
-
|
466
|
-
|
467
|
-
end
|
468
|
-
end
|
158
|
+
test "with multiple Delivered To headers" do
|
159
|
+
msg = astrotrain(:multiple_delivered_to)
|
469
160
|
|
470
|
-
|
471
|
-
|
472
|
-
end
|
161
|
+
assert_equal %w(processor-reply-57@custom.com processor-delivered@astrotrain.com processor@astrotrain.com), msg.recipients
|
162
|
+
end
|
473
163
|
|
474
|
-
|
475
|
-
|
476
|
-
|
164
|
+
test "parsing invalid email collection" do
|
165
|
+
msg = astrotrain(:bad_email_format)
|
166
|
+
assert_equal 'ricky.bobby@foo.com', msg.from[0].address
|
167
|
+
assert_equal 'bobby@foo.com', msg.from[1].address
|
168
|
+
assert_equal 2, msg.from.size
|
169
|
+
end
|
477
170
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
assert_equal(["undisclosed-recipients: ;"], m.recipients_from_to)
|
482
|
-
assert_equal({:name => "undisclosed-recipients"}, Astrotrain::Message.parse_email_address(m.recipients_from_to.first))
|
483
|
-
end
|
171
|
+
test "parsing undisclosed recipients" do
|
172
|
+
msg = astrotrain(:undisclosed)
|
173
|
+
assert_equal([], msg.recipients_from_to)
|
484
174
|
end
|
485
175
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
end
|
176
|
+
test "saves path of parsed email" do
|
177
|
+
path = mail(:basic)
|
178
|
+
msg = Astrotrain::Message.read(path)
|
179
|
+
assert_equal path, msg.path
|
491
180
|
end
|
492
|
-
end
|
181
|
+
end
|