multi_mail 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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