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.
- data/.gitignore +2 -1
- data/.travis.yml +10 -0
- data/README.md +283 -59
- data/Rakefile +38 -19
- data/lib/multi_mail/cloudmailin/receiver.rb +3 -13
- data/lib/multi_mail/mailgun/message.rb +67 -0
- data/lib/multi_mail/mailgun/receiver.rb +20 -13
- data/lib/multi_mail/mailgun/sender.rb +79 -2
- data/lib/multi_mail/mandrill/message.rb +74 -0
- data/lib/multi_mail/mandrill/receiver.rb +36 -16
- data/lib/multi_mail/mandrill/sender.rb +77 -2
- data/lib/multi_mail/message/base.rb +40 -0
- data/lib/multi_mail/postmark/receiver.rb +1 -1
- data/lib/multi_mail/postmark/sender.rb +35 -5
- data/lib/multi_mail/receiver/base.rb +31 -2
- data/lib/multi_mail/receiver.rb +1 -4
- data/lib/multi_mail/sender/base.rb +23 -1
- data/lib/multi_mail/sendgrid/message.rb +74 -0
- data/lib/multi_mail/sendgrid/receiver.rb +72 -23
- data/lib/multi_mail/sendgrid/sender.rb +63 -2
- data/lib/multi_mail/service.rb +48 -56
- data/lib/multi_mail/simple/receiver.rb +4 -4
- data/lib/multi_mail/version.rb +1 -1
- data/lib/multi_mail.rb +16 -1
- data/multi_mail.gemspec +4 -1
- data/spec/fixtures/empty.gif +0 -0
- data/spec/fixtures/mailgun/raw/invalid.txt +13 -0
- data/spec/fixtures/mailgun/raw/missing.txt +13 -0
- data/spec/fixtures/mailgun/raw/spam.txt +13 -0
- data/spec/fixtures/mailgun/raw/valid.txt +13 -0
- data/spec/fixtures/mandrill/invalid.txt +15 -0
- data/spec/fixtures/mandrill/missing.txt +14 -0
- data/spec/fixtures/mandrill/multiple.txt +15 -0
- data/spec/fixtures/mandrill/valid.txt +10 -5
- data/spec/fixtures/postmark/valid.txt +13 -13
- data/spec/fixtures/sendgrid/encoding.txt +90 -0
- data/spec/fixtures/sendgrid/spam.txt +94 -0
- data/spec/fixtures/sendgrid/valid.txt +136 -0
- data/spec/mailgun/message_spec.rb +251 -0
- data/spec/mailgun/receiver_spec.rb +35 -20
- data/spec/mailgun/sender_spec.rb +175 -0
- data/spec/mandrill/message_spec.rb +305 -0
- data/spec/mandrill/receiver_spec.rb +90 -46
- data/spec/mandrill/sender_spec.rb +138 -0
- data/spec/message/base_spec.rb +81 -0
- data/spec/postmark/receiver_spec.rb +4 -4
- data/spec/postmark/sender_spec.rb +118 -0
- data/spec/receiver/base_spec.rb +16 -9
- data/spec/sender/base_spec.rb +24 -10
- data/spec/sendgrid/message_spec.rb +265 -0
- data/spec/sendgrid/receiver_spec.rb +77 -0
- data/spec/sendgrid/sender_spec.rb +140 -0
- data/spec/service_spec.rb +18 -1
- data/spec/simple/receiver_spec.rb +1 -1
- data/spec/spec_helper.rb +46 -4
- metadata +226 -143
- data/lib/multi_mail/sender.rb +0 -46
- data/lib/multi_mail/simple/sender.rb +0 -14
- data/spec/sender_spec.rb +0 -13
- data/spec/simple/sender_spec.rb +0 -0
@@ -0,0 +1,140 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'multi_mail/sendgrid/sender'
|
3
|
+
|
4
|
+
describe MultiMail::Sender::SendGrid 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_user is missing' do
|
53
|
+
expect{
|
54
|
+
message.delivery_method MultiMail::Sender::SendGrid, :api_key => 'xxx'
|
55
|
+
message.deliver # request not sent
|
56
|
+
}.to raise_error(ArgumentError, "Missing required arguments: api_user")
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should raise an error if :api_key is missing' do
|
60
|
+
expect{
|
61
|
+
message.delivery_method MultiMail::Sender::SendGrid, :api_user => 'xxx'
|
62
|
+
message.deliver # request not sent
|
63
|
+
}.to raise_error(ArgumentError, "Missing required arguments: api_key")
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should raise an error if :api_user is nil' do
|
67
|
+
expect{
|
68
|
+
message.delivery_method MultiMail::Sender::SendGrid, :api_user => nil, :api_key => 'xxx'
|
69
|
+
message.deliver # request not sent
|
70
|
+
}.to raise_error(ArgumentError, "Missing required arguments: api_user")
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should raise an error if :api_key is nil' do
|
74
|
+
expect{
|
75
|
+
message.delivery_method MultiMail::Sender::SendGrid, :api_user => 'xxx', :api_key => nil
|
76
|
+
message.deliver # request not sent
|
77
|
+
}.to raise_error(ArgumentError, "Missing required arguments: api_key")
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should raise an error if :api_user or :api_key are invalid' do
|
81
|
+
expect{
|
82
|
+
message.delivery_method MultiMail::Sender::SendGrid, :api_user => 'xxx', :api_key => 'xxx'
|
83
|
+
message.deliver
|
84
|
+
}.to raise_error(MultiMail::InvalidAPIKey, 'Bad username / password')
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should transform x-smtpapi to JSON if it is not JSON' do
|
88
|
+
sender = MultiMail::Sender::SendGrid.new(:api_user => '', :api_key => '', 'x-smtpapi' => {:foo => 'bar'})
|
89
|
+
sender.settings[:'x-smtpapi'].should == '{"foo":"bar"}'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should not transform x-smtpapi to JSON if it is JSON' do
|
93
|
+
sender = MultiMail::Sender::SendGrid.new(:api_user => '', :api_key => '', 'x-smtpapi' => '{"foo":"bar"}')
|
94
|
+
sender.settings[:'x-smtpapi'].should == '{"foo":"bar"}'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#deliver' do
|
99
|
+
before :all do
|
100
|
+
Mail.defaults do
|
101
|
+
delivery_method MultiMail::Sender::SendGrid, :api_user => ENV['SENDGRID_API_USER'], :api_key => ENV['SENDGRID_API_KEY']
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should send a message' do
|
106
|
+
message.deliver.should == message
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#deliver!' do
|
111
|
+
before :all do
|
112
|
+
Mail.defaults do
|
113
|
+
delivery_method MultiMail::Sender::SendGrid, :api_user => ENV['SENDGRID_API_USER'], :api_key => ENV['SENDGRID_API_KEY'], :return_response => true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should send a message' do
|
118
|
+
result = message.deliver!
|
119
|
+
result.size.should == 1
|
120
|
+
|
121
|
+
result['message'].should == 'success'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should not send a message without a From header' do
|
125
|
+
expect{message_without_from.deliver!}.to raise_error(MultiMail::MissingSender, 'Empty from email address (required)')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should not send a message without a To header' do
|
129
|
+
expect{message_without_to.deliver!}.to raise_error(MultiMail::MissingRecipients, 'Missing destination email')
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should not send a message without a subject' do
|
133
|
+
expect{message_without_subject.deliver!}.to raise_error(MultiMail::MissingSubject, 'Missing subject')
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should not send a message without a body' do
|
137
|
+
expect{message_without_body.deliver!}.to raise_error(MultiMail::MissingBody, 'Missing email body')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/spec/service_spec.rb
CHANGED
@@ -2,9 +2,15 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe MultiMail::Service do
|
4
4
|
let :klass do
|
5
|
-
Class.new
|
5
|
+
Class.new do
|
6
|
+
extend MultiMail::Service
|
7
|
+
|
6
8
|
requires :required_argument1, :required_argument2
|
7
9
|
recognizes :optional_argument1, :optional_argument2
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
self.class.validate_options(options)
|
13
|
+
end
|
8
14
|
end
|
9
15
|
end
|
10
16
|
|
@@ -56,5 +62,16 @@ describe MultiMail::Service do
|
|
56
62
|
})
|
57
63
|
}.to raise_error(ArgumentError, "Unrecognized arguments: bar, foo")
|
58
64
|
end
|
65
|
+
|
66
|
+
it 'should raise not an error if unrecognized arguments are allowed' do
|
67
|
+
expect{
|
68
|
+
klass.validate_options({
|
69
|
+
:required_argument1 => 1,
|
70
|
+
:required_argument2 => 1,
|
71
|
+
:bar => 1,
|
72
|
+
:foo => 1,
|
73
|
+
}, false)
|
74
|
+
}.to_not raise_error(ArgumentError, "Unrecognized arguments: bar, foo")
|
75
|
+
end
|
59
76
|
end
|
60
77
|
end
|
@@ -15,7 +15,7 @@ describe MultiMail::Receiver::Simple do
|
|
15
15
|
|
16
16
|
describe '#transform' do
|
17
17
|
it 'should return a mail message' do
|
18
|
-
message = service.transform(params('valid'))[0]
|
18
|
+
message = service.transform(params('valid')['message'])[0]
|
19
19
|
|
20
20
|
# Headers
|
21
21
|
message.date.should == DateTime.parse('Thu, 27 Dec 2012 15:25:37 -0500')
|
data/spec/spec_helper.rb
CHANGED
@@ -3,13 +3,26 @@ require 'rubygems'
|
|
3
3
|
require 'coveralls'
|
4
4
|
Coveralls.wear!
|
5
5
|
|
6
|
+
require 'digest/sha1'
|
6
7
|
require 'net/http'
|
7
8
|
require 'yaml'
|
8
9
|
|
9
10
|
require 'rspec'
|
10
11
|
require 'rack'
|
12
|
+
require 'vcr'
|
11
13
|
require File.dirname(__FILE__) + '/../lib/multi_mail'
|
12
14
|
|
15
|
+
if RUBY_VERSION >= '1.9'
|
16
|
+
VCR.configure do |c|
|
17
|
+
c.cassette_library_dir = 'spec/cassettes'
|
18
|
+
c.hook_into :faraday
|
19
|
+
|
20
|
+
c.around_http_request do |request| # Ruby 1.9+
|
21
|
+
VCR.use_cassette(Digest::SHA1.hexdigest(request.uri + request.body), &request)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
13
26
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
14
27
|
# in spec/support/ and its subdirectories.
|
15
28
|
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
|
@@ -25,9 +38,13 @@ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
|
|
25
38
|
# :mailgun_api_key: ...
|
26
39
|
# :mandrill_api_key: ...
|
27
40
|
# :postmark_api_key: ...
|
41
|
+
# :sendgrid_username: ...
|
42
|
+
# :sendgrid_password: ...
|
28
43
|
#
|
29
44
|
# For Postmark, you must create a server to get an API key.
|
30
45
|
#
|
46
|
+
# If you see `bad content body` exceptions, run `unix2dos` on the fixtures.
|
47
|
+
#
|
31
48
|
# # Cloudmailin
|
32
49
|
#
|
33
50
|
# Change the HTTP POST format on Cloudmailin and wait a few minutes. Run
|
@@ -61,6 +78,14 @@ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
|
|
61
78
|
# spam.txt Send a subject-less message with message body XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
|
62
79
|
# valid.txt Send a complex multipart message
|
63
80
|
#
|
81
|
+
# # SendGrid
|
82
|
+
#
|
83
|
+
# Run `bundle exec rake sendgrid` to set up SendGrid once SendGrid has
|
84
|
+
# provisioned your account.
|
85
|
+
#
|
86
|
+
# spam.txt Send a subject-less message with message body XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
|
87
|
+
# valid.txt Send a complex multipart message
|
88
|
+
#
|
64
89
|
# @param [String] provider a provider
|
65
90
|
# @param [String] fixture one of "valid", "invalid" or "spam"
|
66
91
|
# @param [Boolean] action_dispatch whether uploaded files should be
|
@@ -68,8 +93,9 @@ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
|
|
68
93
|
# @return [String] the provider's baked response
|
69
94
|
# @see FakeWeb::Responder#baked_response
|
70
95
|
# @see https://github.com/rack/rack/blob/master/test/spec_multipart.rb
|
71
|
-
def response(provider, fixture, action_dispatch = false)
|
72
|
-
|
96
|
+
def response(provider, fixture, action_dispatch = false, encoding = 'UTF-8')
|
97
|
+
path = File.expand_path("../fixtures/#{provider}/#{fixture}.txt", __FILE__)
|
98
|
+
contents = File.open(path, "r:#{encoding}"){|f| f.read}
|
73
99
|
io = StringIO.new(contents)
|
74
100
|
socket = Net::BufferedIO.new(io)
|
75
101
|
response = Net::HTTPResponse.read_new(socket)
|
@@ -79,7 +105,13 @@ def response(provider, fixture, action_dispatch = false)
|
|
79
105
|
body = contents[/(?:\r?\n){2,}(.+)\z/m, 1]
|
80
106
|
|
81
107
|
# It's kind of crazy that no library has an easier way of doing this.
|
82
|
-
if response.header['
|
108
|
+
if response.header['x-mandrill-signature']
|
109
|
+
body = Rack::Request.new(Rack::MockRequest.env_for('/', {
|
110
|
+
'HTTP_X_MANDRILL_SIGNATURE' => response.header['x-mandrill-signature'],
|
111
|
+
:method => 'POST',
|
112
|
+
:input => body,
|
113
|
+
}))
|
114
|
+
elsif response.header['content-type']['multipart/form-data']
|
83
115
|
body = Rack::Multipart.parse_multipart(Rack::MockRequest.env_for('/', {
|
84
116
|
'CONTENT_TYPE' => response.header['content-type'],
|
85
117
|
:input => body,
|
@@ -88,7 +120,7 @@ def response(provider, fixture, action_dispatch = false)
|
|
88
120
|
|
89
121
|
if action_dispatch
|
90
122
|
# ActionDispatch would parse the request into a parameters hash.
|
91
|
-
klass = Class.new
|
123
|
+
klass = Class.new do
|
92
124
|
include MultiMail::Receiver::Base
|
93
125
|
end
|
94
126
|
normalize_encode_params(klass.parse(body))
|
@@ -138,3 +170,13 @@ def normalize_encode_params(params)
|
|
138
170
|
params
|
139
171
|
end
|
140
172
|
end
|
173
|
+
|
174
|
+
# @return [String] the path to the GIF file
|
175
|
+
def empty_gif_path
|
176
|
+
File.expand_path('../fixtures/empty.gif', __FILE__)
|
177
|
+
end
|
178
|
+
|
179
|
+
# @return [String] the content of the GIF file
|
180
|
+
def empty_gif_content
|
181
|
+
File.read(empty_gif_path)
|
182
|
+
end
|