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,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(MultiMail::Service) do
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
- contents = File.read(File.expand_path("../fixtures/#{provider}/#{fixture}.txt", __FILE__))
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['content-type']['multipart/form-data']
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(MultiMail::Service) do
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