mailgun-ruby 1.1.9 → 1.2.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -0
  3. data/.rubocop_todo.yml +0 -0
  4. data/.ruby-env.yml.example +1 -0
  5. data/.travis.yml +6 -5
  6. data/CHANGELOG.md +16 -0
  7. data/Gemfile +1 -1
  8. data/README.md +30 -3
  9. data/docs/Domains.md +3 -0
  10. data/docs/EmailValidation.md +34 -0
  11. data/docs/OptInHandler.md +1 -1
  12. data/docs/Snippets.md +54 -61
  13. data/docs/Subaccounts.md +68 -0
  14. data/docs/Suppressions.md +10 -0
  15. data/docs/Webhooks.md +0 -0
  16. data/docs/railgun/EmailValidation.md +34 -0
  17. data/docs/railgun/Overview.md +11 -0
  18. data/docs/railgun/Parameters.md +83 -0
  19. data/docs/railgun/Templates.md +92 -0
  20. data/lib/mailgun/address.rb +3 -28
  21. data/lib/mailgun/chains.rb +0 -0
  22. data/lib/mailgun/client.rb +55 -9
  23. data/lib/mailgun/domains/domains.rb +20 -2
  24. data/lib/mailgun/events/events.rb +2 -2
  25. data/lib/mailgun/exceptions/exceptions.rb +28 -1
  26. data/lib/mailgun/messages/batch_message.rb +1 -0
  27. data/lib/mailgun/messages/message_builder.rb +56 -8
  28. data/lib/mailgun/response.rb +7 -0
  29. data/lib/mailgun/subaccounts/subaccounts.rb +84 -0
  30. data/lib/mailgun/suppressions.rb +15 -8
  31. data/lib/mailgun/templates/templates.rb +187 -0
  32. data/lib/mailgun/version.rb +1 -1
  33. data/lib/mailgun/webhooks/webhooks.rb +2 -2
  34. data/lib/mailgun-ruby.rb +1 -1
  35. data/lib/mailgun.rb +5 -1
  36. data/lib/railgun/mailer.rb +85 -12
  37. data/lib/railgun/message.rb +2 -1
  38. data/lib/railgun/railtie.rb +3 -2
  39. data/mailgun.gemspec +15 -12
  40. data/spec/integration/bounces_spec.rb +3 -3
  41. data/spec/integration/campaign_spec.rb +0 -0
  42. data/spec/integration/complaints_spec.rb +0 -0
  43. data/spec/integration/domains_spec.rb +8 -0
  44. data/spec/integration/email_validation_spec.rb +10 -2
  45. data/spec/integration/events_spec.rb +1 -1
  46. data/spec/integration/list_members_spec.rb +0 -0
  47. data/spec/integration/list_spec.rb +0 -0
  48. data/spec/integration/mailer_spec.rb +67 -0
  49. data/spec/integration/mailgun_spec.rb +92 -1
  50. data/spec/integration/routes_spec.rb +0 -0
  51. data/spec/integration/stats_spec.rb +0 -0
  52. data/spec/integration/subaccounts_spec.rb +58 -0
  53. data/spec/integration/suppressions_spec.rb +18 -2
  54. data/spec/integration/templates_spec.rb +135 -0
  55. data/spec/integration/unsubscribes_spec.rb +0 -0
  56. data/spec/integration/webhook_spec.rb +0 -0
  57. data/spec/spec_helper.rb +3 -1
  58. data/spec/unit/connection/test_client.rb +18 -1
  59. data/spec/unit/events/events_spec.rb +19 -0
  60. data/spec/unit/mailgun_spec.rb +43 -2
  61. data/spec/unit/messages/batch_message_spec.rb +56 -40
  62. data/spec/unit/messages/message_builder_spec.rb +149 -16
  63. data/spec/unit/messages/sample_data/unknown.type +0 -0
  64. data/spec/unit/railgun/mailer_spec.rb +388 -0
  65. data/vcr_cassettes/bounces.yml +12 -12
  66. data/vcr_cassettes/complaints.yml +0 -0
  67. data/vcr_cassettes/domains.todo.yml +0 -0
  68. data/vcr_cassettes/domains.yml +51 -1
  69. data/vcr_cassettes/email_validation.yml +5 -5
  70. data/vcr_cassettes/events.yml +0 -0
  71. data/vcr_cassettes/exceptions-invalid-api-key.yml +52 -0
  72. data/vcr_cassettes/exceptions-invalid-data.yml +52 -0
  73. data/vcr_cassettes/exceptions-not-allowed.yml +54 -0
  74. data/vcr_cassettes/list_members.yml +0 -0
  75. data/vcr_cassettes/mailer_invalid_domain.yml +109 -0
  76. data/vcr_cassettes/mailing_list.todo.yml +0 -0
  77. data/vcr_cassettes/mailing_list.yml +0 -0
  78. data/vcr_cassettes/message_deliver.yml +149 -0
  79. data/vcr_cassettes/routes.yml +0 -0
  80. data/vcr_cassettes/send_message.yml +0 -0
  81. data/vcr_cassettes/stats.yml +0 -0
  82. data/vcr_cassettes/subaccounts.yml +270 -0
  83. data/vcr_cassettes/suppressions.yml +66 -15
  84. data/vcr_cassettes/templates.yml +1065 -0
  85. data/vcr_cassettes/unsubscribes.yml +0 -0
  86. data/vcr_cassettes/webhooks.yml +0 -0
  87. metadata +56 -29
  88. data/.ruby-version +0 -1
  89. /data/spec/unit/{railgun_spec.rb → railgun/content_type_spec.rb} +0 -0
@@ -1,4 +1,5 @@
1
1
  require 'action_mailer'
2
+ require 'json'
2
3
  require 'mailgun'
3
4
  require 'rails'
4
5
  require 'railgun/errors'
@@ -9,6 +10,9 @@ module Railgun
9
10
  # Mailgun.
10
11
  class Mailer
11
12
 
13
+ # List of the headers that will be ignored when copying headers from `mail.header_fields`
14
+ IGNORED_HEADERS = %w[ to from subject reply-to mime-version template ]
15
+
12
16
  # [Hash] config ->
13
17
  # Requires *at least* `api_key` and `domain` keys.
14
18
  attr_accessor :config, :domain, :settings
@@ -23,7 +27,14 @@ module Railgun
23
27
  raise Railgun::ConfigurationError.new("Config requires `#{k}` key", @config) unless @config.has_key?(k)
24
28
  end
25
29
 
26
- @mg_client = Mailgun::Client.new(config[:api_key], config[:api_host] || 'api.mailgun.net', config[:api_version] || 'v3', config[:api_ssl].nil? ? true : config[:api_ssl])
30
+ @mg_client = Mailgun::Client.new(
31
+ config[:api_key],
32
+ config[:api_host] || 'api.mailgun.net',
33
+ config[:api_version] || 'v3',
34
+ config[:api_ssl].nil? ? true : config[:api_ssl],
35
+ false,
36
+ config[:timeout]
37
+ )
27
38
  @domain = @config[:domain]
28
39
 
29
40
  # To avoid exception in mail gem v2.6
@@ -36,8 +47,16 @@ module Railgun
36
47
  end
37
48
 
38
49
  def deliver!(mail)
50
+ @mg_domain = set_mg_domain(mail)
51
+ @mg_client.set_api_key(mail[:api_key].value) if mail[:api_key].present?
52
+ @mg_client.set_subaccount(mail[:subaccount_id].value) if mail[:subaccount_id].present?
53
+
54
+ mail[:domain] = nil if mail[:domain].present?
55
+ mail[:api_key] = nil if mail[:api_key].present?
56
+ mail[:subaccount_id] = nil if mail[:subaccount_id].present?
57
+
39
58
  mg_message = Railgun.transform_for_mailgun(mail)
40
- response = @mg_client.send_message(@domain, mg_message)
59
+ response = @mg_client.send_message(@mg_domain, mg_message)
41
60
 
42
61
  if response.code == 200 then
43
62
  mg_id = response.to_h['id']
@@ -47,7 +66,15 @@ module Railgun
47
66
  end
48
67
 
49
68
  def mailgun_client
50
- @mg_obj
69
+ @mg_client
70
+ end
71
+
72
+ private
73
+
74
+ # Set @mg_domain from mail[:domain] header if present, then remove it to prevent being sent.
75
+ def set_mg_domain(mail)
76
+ return mail[:domain].value if mail[:domain]
77
+ domain
51
78
  end
52
79
 
53
80
  end
@@ -58,24 +85,60 @@ module Railgun
58
85
  # After prefixing them with the proper option type, they are added to
59
86
  # the message hash where they will then be sent to the API as JSON.
60
87
  #
88
+ # It is important to note that headers set in `mailgun_headers` on the message
89
+ # WILL overwrite headers set via `mail.headers()`.
90
+ #
61
91
  # @param [Mail::Message] mail message to transform
62
92
  #
63
93
  # @return [Hash] transformed message hash
64
94
  def transform_for_mailgun(mail)
65
95
  message = build_message_object(mail)
66
96
 
67
- # v:* attributes (variables)
68
- mail.mailgun_variables.try(:each) do |k, v|
69
- message["v:#{k}"] = v
70
- end
71
-
72
97
  # o:* attributes (options)
73
98
  mail.mailgun_options.try(:each) do |k, v|
74
- message["o:#{k}"] = v
99
+ message["o:#{k}"] = v.dup
75
100
  end
76
101
 
102
+ # t:* attributes (options)
103
+ mail.mailgun_template_variables.try(:each) do |k, v|
104
+ message["t:#{k}"] = v.dup
105
+ end
106
+
107
+ # support for using ActionMailer's `headers()` inside of the mailer
108
+ # note: this will filter out parameters such as `from`, `to`, and so forth
109
+ # as they are accepted as POST parameters on the message endpoint.
110
+
111
+ msg_headers = Hash.new
112
+
77
113
  # h:* attributes (headers)
78
- mail.mailgun_headers.try(:each) do |k, v|
114
+
115
+ # Let's set all of these headers on the [Mail::Message] so that
116
+ # the are created inside of a [Mail::Header] instance and processed there.
117
+ mail.headers(mail.mailgun_headers || {})
118
+ mail.header_fields.each do |field|
119
+ header = field.name.downcase
120
+ if msg_headers.include? header
121
+ msg_headers[header] = [msg_headers[header], field.value].flatten
122
+ else
123
+ msg_headers[header] = field.value
124
+ end
125
+ end
126
+
127
+ msg_headers.each do |k, v|
128
+ if Railgun::Mailer::IGNORED_HEADERS.include? k.downcase
129
+ Rails.logger.debug("[railgun] ignoring header (using envelope instead): #{k}")
130
+ next
131
+ end
132
+
133
+ # Cover cases like `cc`, `bcc` where parameters are valid
134
+ # headers BUT they are submitted as separate POST params
135
+ # and already exist on the message because of the call to
136
+ # `build_message_object`.
137
+ if message.include? k.downcase
138
+ Rails.logger.debug("[railgun] ignoring header (already set): #{k}")
139
+ next
140
+ end
141
+
79
142
  message["h:#{k}"] = v
80
143
  end
81
144
 
@@ -84,7 +147,12 @@ module Railgun
84
147
 
85
148
  # reject blank values
86
149
  message.delete_if do |k, v|
87
- v.nil? or (v.respond_to?(:empty) and v.empty?)
150
+ next true if v.nil?
151
+
152
+ # if it's an array remove empty elements
153
+ v.delete_if { |i| i.respond_to?(:empty?) && i.empty? } if v.is_a?(Array)
154
+
155
+ v.respond_to?(:empty?) && v.empty?
88
156
  end
89
157
 
90
158
  return message
@@ -101,6 +169,7 @@ module Railgun
101
169
 
102
170
  mb.from mail[:from]
103
171
  mb.reply_to(mail[:reply_to].to_s) if mail[:reply_to].present?
172
+ mb.template(mail[:template].to_s) if mail[:template].present?
104
173
  mb.subject mail.subject
105
174
  mb.body_html extract_body_html(mail)
106
175
  mb.body_text extract_body_text(mail)
@@ -120,6 +189,11 @@ module Railgun
120
189
  end
121
190
  end
122
191
 
192
+ # v:* attributes (variables)
193
+ mail.mailgun_variables.try(:each) do |name, value|
194
+ mb.variable(name, value)
195
+ end
196
+
123
197
  return mb.message if mail.attachments.empty?
124
198
 
125
199
  mail.attachments.each do |attach|
@@ -181,5 +255,4 @@ module Railgun
181
255
  return mail.html_part if mail.multipart?
182
256
  (mail.mime_type =~ /^text\/html$/i) && mail
183
257
  end
184
-
185
258
  end
@@ -11,7 +11,8 @@ module Mail
11
11
  attr_accessor :mailgun_variables,
12
12
  :mailgun_options,
13
13
  :mailgun_recipient_variables,
14
- :mailgun_headers
14
+ :mailgun_headers,
15
+ :mailgun_template_variables
15
16
 
16
17
  end
17
18
  end
@@ -2,8 +2,9 @@ require 'railgun/mailer'
2
2
 
3
3
  module Railgun
4
4
  class Railtie < ::Rails::Railtie
5
- config.before_configuration do
6
- ActionMailer::Base.add_delivery_method :mailgun, Railgun::Mailer
5
+ ActiveSupport.on_load(:action_mailer) do
6
+ add_delivery_method :mailgun, Railgun::Mailer
7
+ ActiveSupport.run_load_hooks(:mailgun_mailer, Railgun::Mailer)
7
8
  end
8
9
  end
9
10
  end
data/mailgun.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
 
8
8
  spec.name = 'mailgun-ruby'
9
9
  spec.version = Mailgun::VERSION
10
- spec.homepage = 'http://www.mailgun.com'
10
+ spec.homepage = 'https://www.mailgun.com/'
11
11
  spec.platform = Gem::Platform::RUBY
12
12
  spec.license = 'Apache-2.0'
13
13
 
@@ -17,21 +17,24 @@ Gem::Specification.new do |spec|
17
17
  spec.authors = ['Mailgun', 'Travis Swientek']
18
18
  spec.email = 'support@mailgunhq.com'
19
19
 
20
+ spec.metadata['documentation_uri'] = 'https://documentation.mailgun.com/'
21
+ spec.metadata['source_code_uri'] = 'https://github.com/mailgun/mailgun-ruby'
22
+
20
23
  spec.files = `git ls-files -z`.split("\x0")
21
24
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
25
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
26
  spec.require_paths = ["lib"]
24
27
 
25
- spec.required_ruby_version = '>= 2.0.0'
26
-
27
- spec.add_development_dependency 'bundler', '~> 1.5'
28
- spec.add_development_dependency 'rspec', '~> 3.0'
29
- spec.add_development_dependency 'rake', '~> 10.0'
30
- spec.add_development_dependency 'webmock', '~> 1.22'
31
- spec.add_development_dependency 'pry', '~> 0.9'
32
- spec.add_development_dependency 'vcr', '~> 3.0'
33
- spec.add_development_dependency 'simplecov', '~> 0.11'
34
- spec.add_development_dependency "rails"
35
- spec.add_dependency 'rest-client', '~> 2.0'
28
+ spec.required_ruby_version = '>= 2.2.2'
29
+
30
+ spec.add_development_dependency 'bundler', '>= 1.16.2'
31
+ spec.add_development_dependency 'rspec', '~> 3.8.0'
32
+ spec.add_development_dependency 'rake', '~> 12.3.2'
33
+ spec.add_development_dependency 'webmock', '~> 3.7'
34
+ spec.add_development_dependency 'pry', '~> 0.11.3'
35
+ spec.add_development_dependency 'vcr', '~> 3.0.3'
36
+ spec.add_development_dependency 'simplecov', '~> 0.16.1'
37
+ spec.add_development_dependency 'rails'
38
+ spec.add_dependency 'rest-client', '>= 2.0.2'
36
39
 
37
40
  end
@@ -7,7 +7,7 @@ describe 'For the Bounces endpoint', order: :defined, vcr: vcr_opts do
7
7
  before(:all) do
8
8
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
9
9
  @domain = TESTDOMAIN
10
- @email = "integration-test-email@#{TESTDOMAIN}"
10
+ @email = "integration-test+email@#{TESTDOMAIN}"
11
11
  end
12
12
 
13
13
  it 'creates a bounce' do
@@ -22,7 +22,7 @@ describe 'For the Bounces endpoint', order: :defined, vcr: vcr_opts do
22
22
  end
23
23
 
24
24
  it 'get a bounce.' do
25
- result = @mg_obj.get("#{@domain}/bounces/#{@email}")
25
+ result = @mg_obj.get("#{@domain}/bounces/#{CGI.escape(@email)}")
26
26
 
27
27
  result.to_h!
28
28
  expect(result.body["code"]).to eq("550")
@@ -38,7 +38,7 @@ describe 'For the Bounces endpoint', order: :defined, vcr: vcr_opts do
38
38
  end
39
39
 
40
40
  it 'deletes a bounce' do
41
- @mg_obj.delete("#{@domain}/bounces/#{@email}")
41
+ @mg_obj.delete("#{@domain}/bounces/#{CGI.escape(@email)}")
42
42
  end
43
43
 
44
44
  end
File without changes
File without changes
@@ -36,4 +36,12 @@ describe 'For the domains endpoint', vcr: vcr_opts do
36
36
 
37
37
  expect(result).to be_truthy
38
38
  end
39
+
40
+ it 'updates the domain' do
41
+ result = @mg_obj.update(@domain, { spam_action: 'block', web_scheme: 'https', wildcard: true })
42
+
43
+ expect(result['domain']["spam_action"]).to eq('block')
44
+ expect(result['domain']["web_scheme"]).to eq('https')
45
+ expect(result['domain']["wildcard"]).to eq(true)
46
+ end
39
47
  end
@@ -7,7 +7,7 @@ vcr_opts = { :cassette_name => "email_validation" }
7
7
 
8
8
  describe 'For the email validation endpoint', order: :defined, vcr: vcr_opts do
9
9
  before(:all) do
10
- @mg_obj = Mailgun::Address.new(PUB_APIKEY)
10
+ @mg_obj = Mailgun::Address.new
11
11
 
12
12
  @valid = ["Alice <alice@example.com>", "bob@example.com"]
13
13
  @invalid = ["example.org"]
@@ -19,7 +19,7 @@ describe 'For the email validation endpoint', order: :defined, vcr: vcr_opts do
19
19
  res = @mg_obj.parse(@all_addrs)
20
20
 
21
21
  expect(res["parsed"]).to eq(@valid)
22
- expect(res["unparseable"]).to eq(@invalid)
22
+ expect(res["unparsable"]).to eq(@invalid)
23
23
  end
24
24
 
25
25
  it 'validates alice@mailgun.net with info' do
@@ -28,7 +28,11 @@ describe 'For the email validation endpoint', order: :defined, vcr: vcr_opts do
28
28
  expected = {
29
29
  "address" => "alice@mailgun.net",
30
30
  "did_you_mean" => nil,
31
+ "is_disposable_address" => false,
32
+ "is_role_address" => false,
31
33
  "is_valid" => true,
34
+ "mailbox_verification" => "true",
35
+ "reason" => nil,
32
36
  "parts" => {
33
37
  "display_name" => nil,
34
38
  "domain" => "mailgun.net",
@@ -50,7 +54,11 @@ describe 'For the email validation endpoint', order: :defined, vcr: vcr_opts do
50
54
  expected = {
51
55
  "address" => "example.org",
52
56
  "did_you_mean" => nil,
57
+ "is_disposable_address" => false,
58
+ "is_role_address" => false,
53
59
  "is_valid" => false,
60
+ "mailbox_verification" => "unknown",
61
+ "reason" => "Validation failed for 'example.org', reason: 'malformed address; missing @ sign'",
54
62
  "parts" => {
55
63
  "display_name" => nil,
56
64
  "domain" => nil,
@@ -22,7 +22,7 @@ describe 'For the Events endpoint', vcr: vcr_opts do
22
22
 
23
23
  it 'can iterate over all events with `each`' do
24
24
  @events.each do |e|
25
- expect(e.id).to eq("JAx9z641TuGGUyaJlD9sCQ")
25
+ expect(e["id"]).to eq("JAx9z641TuGGUyaJlD9sCQ")
26
26
  end
27
27
  end
28
28
  end
File without changes
File without changes
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+ require 'logger'
4
+ require 'railgun'
5
+ require 'mailgun'
6
+ require 'mailgun/exceptions/exceptions'
7
+
8
+ ActionMailer::Base.raise_delivery_errors = true
9
+ Rails.logger = Logger.new('/dev/null')
10
+ Rails.logger.level = Logger::DEBUG
11
+
12
+ class UnitTestMailer < ActionMailer::Base
13
+ default from: 'unittest@example.org'
14
+
15
+ def plain_message(address, from, subject, headers)
16
+ headers(headers)
17
+ mail(to: address, from: from, subject: subject) do |format|
18
+ format.text { render plain: 'Test!' }
19
+ format.html { render html: '<p>Test!</p>'.html_safe }
20
+ end
21
+ end
22
+ end
23
+
24
+ vcr_opts = { :cassette_name => 'message_deliver' }
25
+
26
+ describe 'Message deliver', vcr: vcr_opts do
27
+ let(:domain) { TESTDOMAIN }
28
+ let(:config) do
29
+ {
30
+ api_key: APIKEY,
31
+ domain: domain
32
+ }
33
+ end
34
+ let(:mail) { UnitTestMailer.plain_message("bob@#{domain}", "bob@#{domain}", 'subject', {}) }
35
+
36
+ it 'successfully delivers message' do
37
+ result = Railgun::Mailer.new(config).deliver!(mail)
38
+ result.to_h!
39
+
40
+ expect(result.body['message']).to eq('Queued. Thank you.')
41
+ expect(result.body).to include('id')
42
+ expect(result.code).to eq(200)
43
+ end
44
+ end
45
+
46
+ vcr_opts = { :cassette_name => 'mailer_invalid_domain' }
47
+
48
+ describe 'Invalid domain', vcr: vcr_opts do
49
+ let(:domain) { 'not-our-doma.in' }
50
+ let(:config) do
51
+ {
52
+ api_key: APIKEY,
53
+ domain: domain
54
+ }
55
+ end
56
+ let(:mail) { UnitTestMailer.plain_message("bob@#{domain}", 'sally@not-our-doma.in' 'subject', {}) }
57
+
58
+ it 'raises expected error' do
59
+
60
+ Railgun::Mailer.new(config).deliver!(mail)
61
+ rescue Mailgun::CommunicationError => err
62
+ expect(err.message).to eq('401 Unauthorized: Forbidden - Invalid Domain or API key')
63
+ else
64
+ fail
65
+
66
+ end
67
+ end
@@ -34,6 +34,78 @@ describe 'Client exceptions', vcr: vcr_opts do
34
34
  end
35
35
  end
36
36
 
37
+ vcr_opts = { :cassette_name => "exceptions-invalid-api-key" }
38
+
39
+ describe 'Client exceptions', vcr: vcr_opts do
40
+ before(:all) do
41
+ @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
42
+ @domain = TESTDOMAIN
43
+ end
44
+
45
+ it 'displays error information that API key is invalid' do
46
+ begin
47
+ @mg_obj.send_message(@domain, {
48
+ :from => "sally@#{@domain}",
49
+ :to => "sally@#{@domain}",
50
+ :subject => 'Exception Integration Test',
51
+ :text => 'INTEGRATION TESTING'
52
+ })
53
+ rescue Mailgun::Unauthorized => err
54
+ expect(err.message).to eq('401 Unauthorized - Invalid Domain or API key: Forbidden')
55
+ else
56
+ fail
57
+ end
58
+ end
59
+ end
60
+
61
+ vcr_opts = { :cassette_name => "exceptions-invalid-data" }
62
+
63
+ describe 'Client exceptions', vcr: vcr_opts do
64
+ before(:all) do
65
+ @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
66
+ @domain = TESTDOMAIN
67
+ end
68
+
69
+ it 'display useful error information' do
70
+ begin
71
+ @mg_obj.send_message(@domain, {
72
+ :from => "sally@#{@domain}",
73
+ :to => "sally#{@domain}",
74
+ :subject => 'Exception Integration Test',
75
+ :text => 'INTEGRATION TESTING'
76
+ })
77
+ rescue Mailgun::BadRequest => err
78
+ expect(err.message).to eq('400 Bad Request: to parameter is not a valid address. please check documentation')
79
+ else
80
+ fail
81
+ end
82
+ end
83
+ end
84
+
85
+ vcr_opts = { :cassette_name => "exceptions-not-allowed" }
86
+
87
+ describe 'Client exceptions', vcr: vcr_opts do
88
+ before(:all) do
89
+ @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
90
+ @domain = TESTDOMAIN
91
+ end
92
+
93
+ it 'display useful error information' do
94
+ begin
95
+ @mg_obj.send_message(@domain, {
96
+ :from => "invalid@#{@domain}",
97
+ :to => "invalid#{@domain}",
98
+ :subject => 'Exception Integration Test',
99
+ :text => 'INTEGRATION TESTING'
100
+ })
101
+ rescue Mailgun::CommunicationError => err
102
+ expect(err.message).to include('403 Forbidden')
103
+ else
104
+ fail
105
+ end
106
+ end
107
+ end
108
+
37
109
  vcr_opts = { :cassette_name => "send_message" }
38
110
 
39
111
  describe 'The method send_message()', vcr: vcr_opts do
@@ -63,6 +135,9 @@ describe 'The method send_message()', vcr: vcr_opts do
63
135
  :to => "bob@#{@domain}",
64
136
  :subject => "Test",
65
137
  :text => "Test Data" }
138
+ uuid = 'uuid'
139
+
140
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
66
141
 
67
142
  result = @mg_obj.send_message(@domain, data)
68
143
 
@@ -72,7 +147,7 @@ describe 'The method send_message()', vcr: vcr_opts do
72
147
  expect(result.body).to include("id")
73
148
 
74
149
  expect(result.code).to eq(200)
75
- expect(result.body['id']).to eq("test-mode-mail@localhost")
150
+ expect(result.body['id']).to eq("test-mode-mail-#{uuid}@localhost")
76
151
  expect(result.body['message']).to eq("Queued. Thank you.")
77
152
  end
78
153
 
@@ -117,5 +192,21 @@ Testing some Mailgun awesomness!'
117
192
  expect(result.body).to include("message")
118
193
  expect(result.body).to include("id")
119
194
  end
195
+
196
+ it 'receives success response code' do
197
+ @mg_obj.enable_test_mode!
198
+
199
+ expect(@mg_obj.test_mode?).to eq(true)
200
+
201
+ data = { :from => "joe@#{@domain}",
202
+ :to => "bob@#{@domain}",
203
+ :subject => "Test",
204
+ :text => "Test Data" }
205
+
206
+ result = @mg_obj.send_message(@domain, data)
207
+ result.to_h!
208
+
209
+ expect(result.success?).to be(true)
210
+ end
120
211
  end
121
212
 
File without changes
File without changes
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'mailgun'
3
+
4
+ vcr_opts = { :cassette_name => "subaccounts" }
5
+
6
+ describe 'For the subaccounts endpoints', vcr: vcr_opts do
7
+ let(:name) { 'test.subaccount' }
8
+ let(:subaccount_id) { 'xxx' }
9
+
10
+ before(:all) do
11
+ mg_client = Mailgun::Client.new(APIKEY, APIHOST, 'v5')
12
+ @mg_obj = Mailgun::Subaccounts.new mg_client
13
+ end
14
+
15
+ describe '#list' do
16
+ it 'returns a list of templates' do
17
+ result = @mg_obj.list
18
+
19
+ expect(result).to eq({"subaccounts"=>[{"id"=>"xxx", "name"=>"test-ruby-lib", "status"=>"open"}], "total"=>1})
20
+ end
21
+ end
22
+
23
+ describe '#create' do
24
+ it 'creates the subaccount' do
25
+ result = @mg_obj.create(name)
26
+
27
+ expect(result).to eq({"subaccount"=>{"id"=>"xxx", "name"=>"test.subaccount", "status"=>"open"}})
28
+ end
29
+ end
30
+
31
+
32
+ describe '#info' do
33
+ it 'gets the templates info' do
34
+ result = @mg_obj.info(subaccount_id)
35
+
36
+ expect(result).to eq({"subaccount"=>{"id"=>"xxx", "name"=>"test-ruby-lib", "status"=>"open"}})
37
+ end
38
+ end
39
+
40
+
41
+
42
+ describe '#enable' do
43
+ it 'enables the subaccount' do
44
+ result = @mg_obj.enable(subaccount_id)
45
+
46
+ expect(result).to eq({"subaccount"=>{"id"=>"xxx", "name"=>"test-ruby-lib", "status"=>"open"}})
47
+ end
48
+ end
49
+
50
+ describe '#disable' do
51
+ it 'disables the subaccount' do
52
+ result = @mg_obj.disable(subaccount_id)
53
+
54
+ expect(result).to eq({"subaccount"=>{"id"=>"xxx", "name"=>"test-ruby-lib", "status"=>"disabled"}})
55
+ end
56
+ end
57
+
58
+ end
@@ -52,7 +52,7 @@ describe 'For the suppressions handling class', order: :defined, vcr: vcr_opts d
52
52
  end
53
53
  end
54
54
 
55
- it 'can batch-add unsubscribes' do
55
+ it 'can batch-add unsubscribes with tags as string' do
56
56
  unsubscribes = []
57
57
  @addresses.each do |addr|
58
58
  unsubscribes.push({
@@ -69,6 +69,23 @@ describe 'For the suppressions handling class', order: :defined, vcr: vcr_opts d
69
69
  expect(nested.length).to eq(0)
70
70
  end
71
71
 
72
+ it 'can batch-add unsubscribes with tags as array' do
73
+ unsubscribes = []
74
+ @addresses.each do |addr|
75
+ unsubscribes.push({
76
+ :address => addr,
77
+ :tags => ['integration'],
78
+ })
79
+ end
80
+
81
+ response, nested = @suppress.create_unsubscribes unsubscribes
82
+ response.to_h!
83
+
84
+ expect(response.code).to eq(200)
85
+ expect(response.body['message']).to eq('4 addresses have been added to the unsubscribes table')
86
+ expect(nested.length).to eq(0)
87
+ end
88
+
72
89
  it 'raises ParameterError if no unsubscribe[:address] is present' do
73
90
  unsubscribes = []
74
91
  unsubscribes.push({
@@ -123,4 +140,3 @@ describe 'For the suppressions handling class', order: :defined, vcr: vcr_opts d
123
140
 
124
141
  # TODO: Add tests for pagination support.
125
142
  end
126
-