multi_mail 0.0.2 → 0.1.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.
Files changed (60) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +10 -0
  3. data/README.md +283 -59
  4. data/Rakefile +38 -19
  5. data/lib/multi_mail/cloudmailin/receiver.rb +3 -13
  6. data/lib/multi_mail/mailgun/message.rb +67 -0
  7. data/lib/multi_mail/mailgun/receiver.rb +20 -13
  8. data/lib/multi_mail/mailgun/sender.rb +79 -2
  9. data/lib/multi_mail/mandrill/message.rb +74 -0
  10. data/lib/multi_mail/mandrill/receiver.rb +36 -16
  11. data/lib/multi_mail/mandrill/sender.rb +77 -2
  12. data/lib/multi_mail/message/base.rb +40 -0
  13. data/lib/multi_mail/postmark/receiver.rb +1 -1
  14. data/lib/multi_mail/postmark/sender.rb +35 -5
  15. data/lib/multi_mail/receiver/base.rb +31 -2
  16. data/lib/multi_mail/receiver.rb +1 -4
  17. data/lib/multi_mail/sender/base.rb +23 -1
  18. data/lib/multi_mail/sendgrid/message.rb +74 -0
  19. data/lib/multi_mail/sendgrid/receiver.rb +72 -23
  20. data/lib/multi_mail/sendgrid/sender.rb +63 -2
  21. data/lib/multi_mail/service.rb +48 -56
  22. data/lib/multi_mail/simple/receiver.rb +4 -4
  23. data/lib/multi_mail/version.rb +1 -1
  24. data/lib/multi_mail.rb +16 -1
  25. data/multi_mail.gemspec +4 -1
  26. data/spec/fixtures/empty.gif +0 -0
  27. data/spec/fixtures/mailgun/raw/invalid.txt +13 -0
  28. data/spec/fixtures/mailgun/raw/missing.txt +13 -0
  29. data/spec/fixtures/mailgun/raw/spam.txt +13 -0
  30. data/spec/fixtures/mailgun/raw/valid.txt +13 -0
  31. data/spec/fixtures/mandrill/invalid.txt +15 -0
  32. data/spec/fixtures/mandrill/missing.txt +14 -0
  33. data/spec/fixtures/mandrill/multiple.txt +15 -0
  34. data/spec/fixtures/mandrill/valid.txt +10 -5
  35. data/spec/fixtures/postmark/valid.txt +13 -13
  36. data/spec/fixtures/sendgrid/encoding.txt +90 -0
  37. data/spec/fixtures/sendgrid/spam.txt +94 -0
  38. data/spec/fixtures/sendgrid/valid.txt +136 -0
  39. data/spec/mailgun/message_spec.rb +251 -0
  40. data/spec/mailgun/receiver_spec.rb +35 -20
  41. data/spec/mailgun/sender_spec.rb +175 -0
  42. data/spec/mandrill/message_spec.rb +305 -0
  43. data/spec/mandrill/receiver_spec.rb +90 -46
  44. data/spec/mandrill/sender_spec.rb +138 -0
  45. data/spec/message/base_spec.rb +81 -0
  46. data/spec/postmark/receiver_spec.rb +4 -4
  47. data/spec/postmark/sender_spec.rb +118 -0
  48. data/spec/receiver/base_spec.rb +16 -9
  49. data/spec/sender/base_spec.rb +24 -10
  50. data/spec/sendgrid/message_spec.rb +265 -0
  51. data/spec/sendgrid/receiver_spec.rb +77 -0
  52. data/spec/sendgrid/sender_spec.rb +140 -0
  53. data/spec/service_spec.rb +18 -1
  54. data/spec/simple/receiver_spec.rb +1 -1
  55. data/spec/spec_helper.rb +46 -4
  56. metadata +226 -143
  57. data/lib/multi_mail/sender.rb +0 -46
  58. data/lib/multi_mail/simple/sender.rb +0 -14
  59. data/spec/sender_spec.rb +0 -13
  60. data/spec/simple/sender_spec.rb +0 -0
@@ -0,0 +1,251 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'multi_mail/mailgun/message'
3
+
4
+ describe MultiMail::Message::Mailgun do
5
+ let :message do
6
+ headers = {
7
+ 'X-Autoreply' => true,
8
+ 'X-Precedence' => 'auto_reply',
9
+ 'X-Numeric' => 42,
10
+ 'Delivered-To' => 'Autoresponder',
11
+ }
12
+
13
+ MultiMail::Message::Mailgun.new do
14
+ date Time.at(946702800)
15
+ headers headers
16
+ from %("John Doe" <foo@example.com>)
17
+ to [%("Jane Doe" <bar@example.com>), '<baz@example.com>']
18
+ cc 'cc@example.com'
19
+ bcc 'bcc@example.com'
20
+ reply_to 'noreply@example.com'
21
+ subject 'test'
22
+
23
+ text_part do
24
+ body 'hello'
25
+ end
26
+
27
+ html_part do
28
+ content_type 'text/html; charset=UTF-8'
29
+ body '<p>hello</p>'
30
+ end
31
+
32
+ add_file empty_gif_path
33
+ add_file :filename => 'foo.txt', :content => 'hello world'
34
+ end
35
+ end
36
+
37
+ let :message_without_names do
38
+ MultiMail::Message::Mailgun.new do
39
+ from 'foo@example.com'
40
+ to ['bar@example.com', 'baz@example.com']
41
+ subject 'test'
42
+ body 'hello'
43
+ end
44
+ end
45
+
46
+ let :message_with_known_extension do
47
+ MultiMail::Message::Mailgun.new do
48
+ from 'foo@example.com'
49
+ to 'bar@example.com'
50
+ subject 'test'
51
+ body 'hello'
52
+ add_file :filename => 'xxx.mov', :content => ''
53
+ end
54
+ end
55
+
56
+ let :message_with_unknown_extension do
57
+ MultiMail::Message::Mailgun.new do
58
+ from 'foo@example.com'
59
+ to 'bar@example.com'
60
+ subject 'test'
61
+ body 'hello'
62
+ add_file :filename => 'xxx.xxx', :content => ''
63
+ end
64
+ end
65
+
66
+ let :message_without_extension do
67
+ MultiMail::Message::Mailgun.new do
68
+ from 'foo@example.com'
69
+ to 'bar@example.com'
70
+ subject 'test'
71
+ body 'hello'
72
+ add_file :filename => 'xxx', :content => ''
73
+ end
74
+ end
75
+
76
+ let :message_with_empty_file do
77
+ MultiMail::Message::Mailgun.new do
78
+ from 'foo@example.com'
79
+ to 'bar@example.com'
80
+ subject 'test'
81
+ body 'hello'
82
+ add_file :filename => '', :content => ''
83
+ end
84
+ end
85
+
86
+ let :message_with_empty_headers do
87
+ headers = {
88
+ 'X-Autoreply' => nil,
89
+ }
90
+
91
+ MultiMail::Message::Mailgun.new do
92
+ headers headers
93
+ from 'foo@example.com'
94
+ to 'bar@example.com'
95
+ reply_to nil
96
+ subject 'test'
97
+ body 'hello'
98
+ end
99
+ end
100
+
101
+ let :message_without_html_body do
102
+ MultiMail::Message::Mailgun.new do
103
+ from 'foo@example.com'
104
+ to 'bar@example.com'
105
+ subject 'test'
106
+ body 'hello'
107
+ end
108
+ end
109
+
110
+ let :message_without_text_body do
111
+ MultiMail::Message::Mailgun.new do
112
+ from 'foo@example.com'
113
+ to 'bar@example.com'
114
+ subject 'test'
115
+ body '<p>hello</p>'
116
+ content_type 'text/html; charset=UTF-8'
117
+ end
118
+ end
119
+
120
+ let :empty_message do
121
+ MultiMail::Message::Mailgun.new
122
+ end
123
+
124
+ describe '#mailgun_attachments' do
125
+ it 'should return the attachments' do
126
+ attachments = message.mailgun_attachments
127
+ attachments['inline'][0].content_type.should == 'image/gif; filename=empty.gif'
128
+ attachments['inline'][0].original_filename.should == 'empty.gif'
129
+ attachments['inline'][0].read.should == File.open(empty_gif_path, 'r:binary'){|f| f.read}
130
+ attachments['inline'].size.should == 1
131
+ attachments['attachment'][0].content_type.should == 'text/plain; filename=foo.txt'
132
+ attachments['attachment'][0].original_filename.should == 'foo.txt'
133
+ attachments['attachment'][0].read.should == 'hello world'
134
+ attachments['attachment'].size.should == 1
135
+ end
136
+
137
+ it 'should return an attachment with an known extension' do
138
+ attachments = message_with_known_extension.mailgun_attachments['attachment']
139
+ attachments[0].content_type.should == 'video/quicktime; filename=xxx.mov'
140
+ attachments[0].original_filename.should == 'xxx.mov'
141
+ attachments[0].read.should == ''
142
+ attachments.size.should == 1
143
+ end
144
+
145
+ it 'should return an attachment with an unknown extension' do
146
+ attachments = message_with_unknown_extension.mailgun_attachments['attachment']
147
+ attachments[0].content_type.should == 'text/plain'
148
+ attachments[0].original_filename.should == 'xxx.xxx'
149
+ attachments[0].read.should == ''
150
+ attachments.size.should == 1
151
+ end
152
+
153
+ it 'should return an attachment without an extension' do
154
+ attachments = message_without_extension.mailgun_attachments['attachment']
155
+ attachments[0].content_type.should == 'text/plain'
156
+ attachments[0].original_filename.should == 'xxx'
157
+ attachments[0].read.should == ''
158
+ attachments.size.should == 1
159
+ end
160
+
161
+ it 'should return an empty array if the attachment is blank' do
162
+ message_with_empty_file.mailgun_attachments.should == {}
163
+ end
164
+
165
+ it 'should return an empty array' do
166
+ empty_message.mailgun_attachments.should == {}
167
+ end
168
+ end
169
+
170
+ describe '#mailgun_headers' do
171
+ it 'should return the headers' do
172
+ headers = message.mailgun_headers
173
+ headers['h:Reply-To'].should == ['noreply@example.com']
174
+ headers['h:X-Autoreply'].should == ['true']
175
+ headers['h:X-Precedence'].should == ['auto_reply']
176
+ headers['h:X-Numeric'].should == ['42']
177
+ headers['h:Delivered-To'].should == ['Autoresponder']
178
+
179
+ Time.parse(headers['h:Date'][0]).should be_within(1).of(Time.at(946702800))
180
+ headers['h:Content-Type'][0].should match(%r{\Amultipart/alternative; boundary=--==_mimepart_[0-9a-f_]+\z})
181
+
182
+ headers.size.should == 7
183
+ end
184
+
185
+ it 'should return empty X-* headers' do
186
+ headers = message_with_empty_headers.mailgun_headers
187
+ headers.should == {'h:X-Autoreply' => ['']}
188
+ end
189
+
190
+ it 'should return an empty hash' do
191
+ empty_message.mailgun_headers.should == {}
192
+ end
193
+ end
194
+
195
+ describe '#to_mailgun_hash' do
196
+ it 'should return the message as Mailgun parameters' do
197
+ hash = message.to_mailgun_hash
198
+
199
+ hash[:from].should == [%("John Doe" <foo@example.com>)]
200
+ hash[:to].should == [%("Jane Doe" <bar@example.com>), '<baz@example.com>']
201
+ hash[:cc].should == ['cc@example.com']
202
+ hash[:bcc].should == ['bcc@example.com']
203
+ hash[:subject].should == ['test']
204
+ hash[:text].should == ['hello']
205
+ hash[:html].should == ['<p>hello</p>']
206
+ hash[:'h:Reply-To'].should == ['noreply@example.com']
207
+
208
+ Time.parse(hash[:'h:Date'][0]).should be_within(1).of(Time.at(946702800))
209
+ hash[:'h:Content-Type'][0].should match(%r{\Amultipart/alternative; boundary=--==_mimepart_[0-9a-f_]+\z})
210
+
211
+ hash[:'h:X-Autoreply'].should == ['true']
212
+ hash[:'h:X-Precedence'].should == ['auto_reply']
213
+ hash[:'h:X-Numeric'].should == ['42']
214
+ hash[:'h:Delivered-To'].should == ['Autoresponder']
215
+
216
+ hash[:inline][0].content_type.should == 'image/gif; filename=empty.gif'
217
+ hash[:inline][0].original_filename.should == 'empty.gif'
218
+ hash[:inline][0].read.should == File.open(empty_gif_path, 'r:binary'){|f| f.read}
219
+ hash[:inline].size.should == 1
220
+ hash[:attachment][0].content_type.should == 'text/plain; filename=foo.txt'
221
+ hash[:attachment][0].original_filename.should == 'foo.txt'
222
+ hash[:attachment][0].read.should == 'hello world'
223
+ hash[:attachment].size.should == 1
224
+
225
+ hash.size.should == 16
226
+ end
227
+
228
+ it 'should convert the message without a text body' do
229
+ message_without_text_body.to_mailgun_hash.should == {
230
+ :from => ['foo@example.com'],
231
+ :to => ['bar@example.com'],
232
+ :subject => ['test'],
233
+ :html => ['<p>hello</p>'],
234
+ :'h:Content-Type' => ['text/html; charset=UTF-8'],
235
+ }
236
+ end
237
+
238
+ it 'should convert the message without an HTML body' do
239
+ message_without_html_body.to_mailgun_hash.should == {
240
+ :from => ['foo@example.com'],
241
+ :to => ['bar@example.com'],
242
+ :subject => ['test'],
243
+ :text => ['hello'],
244
+ }
245
+ end
246
+
247
+ it 'should convert an empty message' do
248
+ empty_message.to_mailgun_hash.should == {}
249
+ end
250
+ end
251
+ end
@@ -2,13 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
  require 'multi_mail/mailgun/receiver'
3
3
 
4
4
  describe MultiMail::Receiver::Mailgun do
5
- describe '#initialize' do
6
- it 'should raise an error if :mailgun_api_key is missing' do
7
- expect{ MultiMail::Receiver.new :provider => :mailgun }.to raise_error(ArgumentError)
8
- expect{ MultiMail::Receiver.new :provider => :mailgun, :mailgun_api_key => nil }.to raise_error(ArgumentError)
9
- end
10
- end
11
-
12
5
  context 'after initialization' do
13
6
  context 'with invalid HTTP POST format' do
14
7
  let :service do
@@ -26,15 +19,36 @@ describe MultiMail::Receiver::Mailgun do
26
19
  end
27
20
  end
28
21
 
22
+ context 'without optional arguments' do
23
+ let :service do
24
+ MultiMail::Receiver.new(:provider => :mailgun)
25
+ end
26
+
27
+ def params(fixture)
28
+ MultiMail::Receiver::Mailgun.parse(response('mailgun/parsed', fixture))
29
+ end
30
+
31
+ describe '#valid?' do
32
+ it 'should return true if the response is valid' do
33
+ service.valid?(params('valid')).should == true
34
+ end
35
+
36
+ it 'should return true if the response is invalid' do
37
+ service.valid?(params('invalid')).should == true
38
+ end
39
+
40
+ it 'should return true if parameters are missing' do
41
+ service.valid?(params('missing')).should == true
42
+ end
43
+ end
44
+ end
45
+
29
46
  [false, true].each do |action_dispatch|
30
47
  let :action_dispatch do
31
48
  action_dispatch
32
49
  end
33
50
 
34
- # @todo Write my own Postbin to have a URL ending with "mime" in order
35
- # to get fixtures to test the raw MIME HTTP POST format; all existing
36
- # OS code for bins suck. Simple Rack app with in-memory storage?
37
- ['parsed', '', nil].each do |http_post_format|
51
+ ['parsed', 'raw', '', nil].each do |http_post_format|
38
52
  context "with #{http_post_format.inspect} format and #{action_dispatch ? 'ActionDispatch' : 'Rack'}" do
39
53
  let :http_post_format do
40
54
  http_post_format
@@ -85,16 +99,16 @@ describe MultiMail::Receiver::Mailgun do
85
99
  # Body
86
100
  message.multipart?.should == true
87
101
  message.parts.size.should == 4
88
- message.parts[0].content_type.should == 'text/plain'
89
- message.parts[1].content_type.should == 'text/html; charset=UTF-8'
90
- message.parts[0].body.decoded.should == "bold text\n\n\n\nsome more bold text\n\n\n\nsome italic text\n\n> multiline\n> quoted\n> text\n\n\n--\nSignature block"
91
- message.parts[1].body.decoded.should == %(<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><b>bold text</b><div><br></div><div></div></body></html><html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><head></head><br><div></div><div><br></div><div><b>some more bold text</b></div><div><b><br></b></div><div><b></b></div></body></html><html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><b></b></div><div><b><span class="Apple-style-span" style="font-weight: normal; "><br></span></b></div><div><b><span class="Apple-style-span" style="font-weight: normal; "><i>some italic text</i></span></b></div><div><b><span class="Apple-style-span" style="font-weight: normal; "><br></span></b></div><div><blockquote type="cite">multiline</blockquote><blockquote type="cite">quoted</blockquote><blockquote type="cite">text</blockquote></div><div><br></div><div>--</div><div>Signature block</div></body></html>)
102
+ text_part = message.parts.find{|part| part.content_type == 'text/plain'}
103
+ html_part = message.parts.find{|part| part.content_type == 'text/html; charset=UTF-8'}
104
+ text_part.body.decoded.should == "bold text\n\n\n\nsome more bold text\n\n\n\nsome italic text\n\n> multiline\n> quoted\n> text\n\n\n--\nSignature block"
105
+ html_part.body.decoded.should == %(<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><b>bold text</b><div><br></div><div></div></body></html><html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><head></head><br><div></div><div><br></div><div><b>some more bold text</b></div><div><b><br></b></div><div><b></b></div></body></html><html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><b></b></div><div><b><span class="Apple-style-span" style="font-weight: normal; "><br></span></b></div><div><b><span class="Apple-style-span" style="font-weight: normal; "><i>some italic text</i></span></b></div><div><b><span class="Apple-style-span" style="font-weight: normal; "><br></span></b></div><div><blockquote type="cite">multiline</blockquote><blockquote type="cite">quoted</blockquote><blockquote type="cite">text</blockquote></div><div><br></div><div>--</div><div>Signature block</div></body></html>)
92
106
 
93
107
  # Attachments
94
- message.attachments[0].filename.should == 'foo.txt'
95
- message.attachments[0].read.should == "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
96
- message.attachments[1].filename.should == 'bar.txt'
97
- message.attachments[1].read.should == "Nam accumsan euismod eros et rhoncus.\n"
108
+ attachment0 = message.attachments.find{|attachment| attachment.filename == 'foo.txt'}
109
+ attachment1 = message.attachments.find{|attachment| attachment.filename == 'bar.txt'}
110
+ attachment0.read.should == "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
111
+ attachment1.read.should == "Nam accumsan euismod eros et rhoncus.\n"
98
112
 
99
113
  # Extra Mailgun parameters
100
114
  # @note Due to a Mailgun bug, `stripped-text` contains "some italic
@@ -114,8 +128,9 @@ describe MultiMail::Receiver::Mailgun do
114
128
 
115
129
  describe '#spam?' do
116
130
  it 'should return true if the response is spam' do
131
+ # The raw MIME HTTP POST format doesn't perform spam filtering.
117
132
  message = service.transform(params('spam'))[0]
118
- service.spam?(message).should == true
133
+ service.spam?(message).should == (actual_http_post_format != 'raw')
119
134
  end
120
135
 
121
136
  it 'should return false if the response is ham' do
@@ -0,0 +1,175 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'multi_mail/mailgun/sender'
3
+
4
+ describe MultiMail::Sender::Mailgun do
5
+ let :message do
6
+ Mail.new do
7
+ date Time.at(946702800)
8
+ from 'foo@example.com'
9
+ to 'bar@example.com'
10
+ subject 'test'
11
+ body 'hello'
12
+ end
13
+ end
14
+
15
+ let :message_without_from do
16
+ Mail.new do
17
+ date Time.at(946702800)
18
+ to 'bar@example.com'
19
+ subject 'test'
20
+ body 'hello'
21
+ end
22
+ end
23
+
24
+ let :message_without_to do
25
+ Mail.new do
26
+ date Time.at(946702800)
27
+ from 'foo@example.com'
28
+ subject 'test'
29
+ body 'hello'
30
+ end
31
+ end
32
+
33
+ let :message_without_subject do
34
+ Mail.new do
35
+ date Time.at(946702800)
36
+ from 'foo@example.com'
37
+ to 'bar@example.com'
38
+ body 'hello'
39
+ end
40
+ end
41
+
42
+ let :message_without_body do
43
+ Mail.new do
44
+ date Time.at(946702800)
45
+ from 'foo@example.com'
46
+ to 'bar@example.com'
47
+ subject 'test'
48
+ end
49
+ end
50
+
51
+ describe '#initialize' do
52
+ it 'should raise an error if :api_key is missing' do
53
+ expect{
54
+ message.delivery_method MultiMail::Sender::Mailgun, :domain => 'xxx'
55
+ message.deliver # request not sent
56
+ }.to raise_error(ArgumentError, "Missing required arguments: api_key")
57
+ end
58
+
59
+ it 'should raise an error if :domain is missing' do
60
+ expect{
61
+ message.delivery_method MultiMail::Sender::Mailgun, :api_key => 'xxx'
62
+ message.deliver # request not sent
63
+ }.to raise_error(ArgumentError, "Missing required arguments: domain")
64
+ end
65
+
66
+ it 'should raise an error if :api_key is nil' do
67
+ expect{
68
+ message.delivery_method MultiMail::Sender::Mailgun, :api_key => nil, :domain => 'xxx'
69
+ message.deliver # request not sent
70
+ }.to raise_error(ArgumentError, "Missing required arguments: api_key")
71
+ end
72
+
73
+ it 'should raise an error if :domain is nil' do
74
+ expect{
75
+ message.delivery_method MultiMail::Sender::Mailgun, :api_key => 'xxx', :domain => nil
76
+ message.deliver # request not sent
77
+ }.to raise_error(ArgumentError, "Missing required arguments: domain")
78
+ end
79
+
80
+ it 'should raise an error if :domain or :api_key are invalid' do
81
+ expect{
82
+ message.delivery_method MultiMail::Sender::Mailgun, :api_key => 'xxx', :domain => 'xxx'
83
+ message.deliver
84
+ }.to raise_error(MultiMail::InvalidAPIKey)
85
+ end
86
+
87
+ it 'should assign custom settings' do
88
+ sender = MultiMail::Sender::Mailgun.new(:api_key => 'xxx', :domain => 'xxx')
89
+
90
+ sender.api_key.should == 'xxx'
91
+ sender.domain.should == 'xxx'
92
+ end
93
+ end
94
+
95
+ describe '#parameters' do
96
+ it 'should allow "yes", "no" and "htmlonly" values' do
97
+ %w(yes no htmlonly).each do |value|
98
+ sender = MultiMail::Sender::Mailgun.new({
99
+ :api_key => 'xxx',
100
+ :domain => 'xxx',
101
+ :track => {
102
+ :clicks => value,
103
+ }
104
+ })
105
+
106
+ sender.parameters.should == {:'o:tracking-clicks' => value}
107
+ end
108
+ end
109
+
110
+ it 'should transform true and false values' do
111
+ sender = MultiMail::Sender::Mailgun.new({
112
+ :api_key => 'xxx',
113
+ :domain => 'xxx',
114
+ :track => {
115
+ :opens => false,
116
+ :clicks => true,
117
+ }
118
+ })
119
+
120
+ sender.parameters.should == {:'o:tracking-opens' => 'no', :'o:tracking-clicks' => 'yes'}
121
+ end
122
+
123
+ it 'should ignore nil values' do
124
+ sender = MultiMail::Sender::Mailgun.new({
125
+ :api_key => 'xxx',
126
+ :domain => 'xxx',
127
+ :track => {
128
+ :clicks => nil,
129
+ }
130
+ })
131
+
132
+ sender.parameters.should == {}
133
+ end
134
+ end
135
+
136
+ describe '#deliver' do
137
+ before :all do
138
+ Mail.defaults do
139
+ delivery_method MultiMail::Sender::Mailgun, :api_key => ENV['MAILGUN_API_KEY'], :domain => 'multimail.mailgun.org', 'o:testmode' => 'yes'
140
+ end
141
+ end
142
+
143
+ it 'should send a message' do
144
+ message.deliver.should == message
145
+ end
146
+ end
147
+
148
+ describe '#deliver!' do
149
+ before :all do
150
+ Mail.defaults do
151
+ delivery_method MultiMail::Sender::Mailgun, :api_key => ENV['MAILGUN_API_KEY'], :domain => 'multimail.mailgun.org', 'o:testmode' => 'yes', :return_response => true
152
+ end
153
+ end
154
+
155
+ it 'should send a message' do
156
+ result = message.deliver!
157
+ result.size.should == 2
158
+
159
+ result['message'].should == 'Queued. Thank you.'
160
+ result['id'].should match(/<\S+@\S+>/)
161
+ end
162
+
163
+ it 'should not send a message without a From header' do
164
+ expect{message_without_from.deliver!}.to raise_error(MultiMail::MissingSender, "'from' parameter is missing")
165
+ end
166
+
167
+ it 'should not send a message without a To header' do
168
+ expect{message_without_to.deliver!}.to raise_error(MultiMail::MissingRecipients, "'to' parameter is missing")
169
+ end
170
+
171
+ it 'should not send a message without a body' do
172
+ expect{message_without_body.deliver!}.to raise_error(MultiMail::MissingBody, "Need at least one of 'text' or 'html' parameters specified")
173
+ end
174
+ end
175
+ end