mailgun-ruby 1.2.15 → 1.3.5

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +52 -3
  4. data/Gemfile +1 -0
  5. data/README.md +2 -2
  6. data/docs/MessageBuilder.md +12 -0
  7. data/docs/Metrics.md +108 -0
  8. data/docs/Webhooks.md +4 -2
  9. data/lib/mailgun/chains.rb +1 -1
  10. data/lib/mailgun/client.rb +40 -30
  11. data/lib/mailgun/domains/domains.rb +19 -0
  12. data/lib/mailgun/events/events.rb +4 -4
  13. data/lib/mailgun/exceptions/exceptions.rb +7 -7
  14. data/lib/mailgun/messages/message_builder.rb +14 -2
  15. data/lib/mailgun/metrics/metrics.rb +61 -0
  16. data/lib/mailgun/response.rb +11 -10
  17. data/lib/mailgun/version.rb +1 -1
  18. data/lib/mailgun.rb +2 -1
  19. data/mailgun.gemspec +6 -3
  20. data/spec/integration/domains_spec.rb +95 -92
  21. data/spec/integration/email_validation_spec.rb +2 -1
  22. data/spec/integration/list_spec.rb +1 -1
  23. data/spec/integration/mailer_spec.rb +5 -5
  24. data/spec/integration/mailgun_spec.rb +14 -12
  25. data/spec/integration/metrics_spec.rb +218 -0
  26. data/spec/integration/routes_spec.rb +17 -1
  27. data/spec/integration/stats_spec.rb +1 -1
  28. data/spec/integration/unsubscribes_spec.rb +2 -2
  29. data/spec/integration/webhook_spec.rb +1 -1
  30. data/spec/spec_helper.rb +1 -0
  31. data/spec/unit/connection/test_client.rb +1 -1
  32. data/spec/unit/events/events_spec.rb +1 -1
  33. data/spec/unit/exceptions/exceptions_spec.rb +3 -3
  34. data/spec/unit/messages/message_builder_spec.rb +4 -3
  35. data/vcr_cassettes/bounces.yml +59 -98
  36. data/vcr_cassettes/complaints.yml +237 -97
  37. data/vcr_cassettes/domains.yml +332 -763
  38. data/vcr_cassettes/email_validation.yml +81 -144
  39. data/vcr_cassettes/events.yml +24 -63
  40. data/vcr_cassettes/exceptions.yml +49 -2
  41. data/vcr_cassettes/list_members.yml +187 -179
  42. data/vcr_cassettes/mailing_list.yml +309 -17
  43. data/vcr_cassettes/metrics.yml +116 -0
  44. data/vcr_cassettes/routes.yml +246 -246
  45. data/vcr_cassettes/send_message.yml +54 -3
  46. data/vcr_cassettes/stats.yml +28 -24
  47. data/vcr_cassettes/suppressions.yml +229 -447
  48. data/vcr_cassettes/unsubscribes.yml +219 -9
  49. metadata +58 -15
  50. data/docs/Messages.md +0 -107
  51. /data/docs/{railgun/Templates.md → Templates.md} +0 -0
@@ -15,7 +15,7 @@ vcr_opts = { :cassette_name => "exceptions" }
15
15
  describe 'Client exceptions', vcr: vcr_opts do
16
16
  before(:all) do
17
17
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
18
- @domain = TESTDOMAIN
18
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
19
19
  end
20
20
 
21
21
  it 'display useful error information' do
@@ -27,7 +27,7 @@ describe 'Client exceptions', vcr: vcr_opts do
27
27
  :text => 'INTEGRATION TESTING'
28
28
  })
29
29
  rescue Mailgun::CommunicationError => err
30
- expect(err.message).to eq('404 Not Found: Domain not found: not-our-doma.in')
30
+ expect(err.message).to eq('the server responded with status 404')
31
31
  else
32
32
  fail
33
33
  end
@@ -39,7 +39,7 @@ vcr_opts = { :cassette_name => "exceptions-invalid-api-key" }
39
39
  describe 'Client exceptions', vcr: vcr_opts do
40
40
  before(:all) do
41
41
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
42
- @domain = TESTDOMAIN
42
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
43
43
  end
44
44
 
45
45
  it 'displays error information that API key is invalid' do
@@ -51,7 +51,7 @@ describe 'Client exceptions', vcr: vcr_opts do
51
51
  :text => 'INTEGRATION TESTING'
52
52
  })
53
53
  rescue Mailgun::Unauthorized => err
54
- expect(err.message).to eq('401 Unauthorized - Invalid Domain or API key: Forbidden')
54
+ expect(err.message).to eq('the server responded with status 401 - Invalid Domain or API key')
55
55
  else
56
56
  fail
57
57
  end
@@ -63,7 +63,7 @@ vcr_opts = { :cassette_name => "exceptions-invalid-data" }
63
63
  describe 'Client exceptions', vcr: vcr_opts do
64
64
  before(:all) do
65
65
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
66
- @domain = TESTDOMAIN
66
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
67
67
  end
68
68
 
69
69
  it 'display useful error information' do
@@ -75,7 +75,7 @@ describe 'Client exceptions', vcr: vcr_opts do
75
75
  :text => 'INTEGRATION TESTING'
76
76
  })
77
77
  rescue Mailgun::BadRequest => err
78
- expect(err.message).to eq('400 Bad Request: to parameter is not a valid address. please check documentation')
78
+ expect(err.message).to eq('the server responded with status 400')
79
79
  else
80
80
  fail
81
81
  end
@@ -87,7 +87,7 @@ vcr_opts = { :cassette_name => "exceptions-not-allowed" }
87
87
  describe 'Client exceptions', vcr: vcr_opts do
88
88
  before(:all) do
89
89
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
90
- @domain = TESTDOMAIN
90
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
91
91
  end
92
92
 
93
93
  it 'display useful error information' do
@@ -99,7 +99,7 @@ describe 'Client exceptions', vcr: vcr_opts do
99
99
  :text => 'INTEGRATION TESTING'
100
100
  })
101
101
  rescue Mailgun::CommunicationError => err
102
- expect(err.message).to include('403 Forbidden')
102
+ expect(err.message).to include('403')
103
103
  else
104
104
  fail
105
105
  end
@@ -111,10 +111,11 @@ vcr_opts = { :cassette_name => "send_message" }
111
111
  describe 'The method send_message()', vcr: vcr_opts do
112
112
  before(:all) do
113
113
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
114
- @domain = TESTDOMAIN
114
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
115
115
  end
116
116
 
117
117
  it 'sends a standard message in test mode.' do
118
+ @mg_obj.enable_test_mode!
118
119
  result = @mg_obj.send_message(@domain, {:from => "bob@#{@domain}",
119
120
  :to => "sally@#{@domain}",
120
121
  :subject => 'Hash Integration Test',
@@ -183,7 +184,8 @@ Sender: me@samples.mailgun.org
183
184
 
184
185
  Testing some Mailgun awesomness!'
185
186
 
186
- message_params = {:to => "sally@#{@domain}",
187
+ message_params = {:from => "bobby@#{@domain}",
188
+ :to => "sally@#{@domain}",
187
189
  :message => mime_string}
188
190
 
189
191
  result = @mg_obj.send_message(@domain, message_params)
@@ -192,7 +194,7 @@ Testing some Mailgun awesomness!'
192
194
  expect(result.body).to include("message")
193
195
  expect(result.body).to include("id")
194
196
  end
195
-
197
+
196
198
  it 'receives success response code' do
197
199
  @mg_obj.enable_test_mode!
198
200
 
@@ -205,7 +207,7 @@ Testing some Mailgun awesomness!'
205
207
 
206
208
  result = @mg_obj.send_message(@domain, data)
207
209
  result.to_h!
208
-
210
+
209
211
  expect(result.success?).to be(true)
210
212
  end
211
213
  end
@@ -0,0 +1,218 @@
1
+ require 'spec_helper'
2
+ require 'mailgun'
3
+
4
+ vcr_opts = { cassette_name: 'metrics' }
5
+
6
+ describe Mailgun::Metrics, vcr: vcr_opts do
7
+ let(:metrics) { Mailgun::Metrics.new(Mailgun::Client.new(APIKEY, APIHOST, 'v1')) }
8
+
9
+ describe '#account_metrics' do
10
+ let(:options) do
11
+ {
12
+ resolution: 'hour',
13
+ metrics: [
14
+ 'accepted_count',
15
+ 'delivered_count',
16
+ 'clicked_rate',
17
+ 'opened_rate'
18
+ ],
19
+ include_aggregates: true,
20
+ start: 'Tue, 26 Nov 2024 20:56:50 -0500',
21
+ duration: '1m',
22
+ filter: {
23
+ AND: [
24
+ {
25
+ attribute: 'domain',
26
+ comparator: '!=',
27
+ values: [
28
+ {
29
+ label: 'example.com',
30
+ value: 'example.com'
31
+ }
32
+ ]
33
+ }
34
+ ]
35
+ },
36
+ dimensions: ['time'],
37
+ end: 'Tue, 30 Nov 2024 20:56:50 -0500',
38
+ include_subaccounts: true
39
+ }
40
+ end
41
+
42
+ it 'responds with account metrics' do
43
+ expect(metrics.account_metrics(options)).to eq(
44
+ {
45
+ "start" => "Fri, 01 Nov 2024 01:00:00 +0000",
46
+ "end" => "Sun, 01 Dec 2024 01:00:00 +0000",
47
+ "resolution" => "hour",
48
+ "duration" => "1m",
49
+ "dimensions" => ["time"],
50
+ "pagination" => {
51
+ "sort" => "", "skip" => 0, "limit" => 1500, "total" => 3
52
+ },
53
+ "items" => [{
54
+ "dimensions" => [{
55
+ "dimension" => "time",
56
+ "value" => "Wed, 27 Nov 2024 12:00:00 +0000",
57
+ "display_value" => "Wed, 27 Nov 2024 12:00:00 +0000"
58
+ }],
59
+ "metrics" => {
60
+ "accepted_count" => 1, "delivered_count" => 1, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
61
+ }
62
+ },
63
+ {
64
+ "dimensions" => [{
65
+ "dimension" => "time",
66
+ "value" => "Wed, 27 Nov 2024 13:00:00 +0000",
67
+ "display_value" => "Wed, 27 Nov 2024 13:00:00 +0000"
68
+ }],
69
+ "metrics" => {
70
+ "accepted_count" => 1, "delivered_count" => 1, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
71
+ }
72
+ },
73
+ {
74
+ "dimensions" => [{
75
+ "dimension" => "time",
76
+ "value" => "Thu, 28 Nov 2024 15:00:00 +0000",
77
+ "display_value" => "Thu, 28 Nov 2024 15:00:00 +0000"
78
+ }],
79
+ "metrics" => {
80
+ "accepted_count" => 1, "delivered_count" => 1, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
81
+ }
82
+ }
83
+ ],
84
+ "aggregates" => {
85
+ "metrics" => {
86
+ "accepted_count" => 3, "delivered_count" => 3, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
87
+ }
88
+ }
89
+ }
90
+ )
91
+ end
92
+ end
93
+
94
+ describe '#account_usage_metrics' do
95
+ let(:options) do
96
+ {
97
+ resolution: 'hour',
98
+ metrics: [
99
+ 'email_preview_count',
100
+ 'email_preview_failed_count',
101
+ 'email_validation_bulk_count',
102
+ 'email_validation_count',
103
+ 'email_validation_list_count',
104
+ 'email_validation_mailgun_count',
105
+ 'email_validation_mailjet_count',
106
+ 'email_validation_public_count',
107
+ 'email_validation_single_count',
108
+ 'email_validation_valid_count',
109
+ 'link_validation_count',
110
+ 'link_validation_failed_count',
111
+ 'processed_count',
112
+ 'seed_test_count'
113
+ ],
114
+ include_aggregates: true,
115
+ start: 'Tue, 26 Nov 2024 20:56:50 -0500',
116
+ duration: '1m',
117
+ filter: {
118
+ AND: [
119
+ {
120
+ attribute: 'subaccount',
121
+ comparator: '!=',
122
+ values: [
123
+ {
124
+ label: '12345',
125
+ value: '12345'
126
+ }
127
+ ]
128
+ }
129
+ ]
130
+ },
131
+ dimensions: ['time'],
132
+ end: 'Tue, 28 Nov 2024 20:56:50 -0500',
133
+ include_subaccounts: true
134
+ }
135
+ end
136
+
137
+ it 'responds with account usage metrics' do
138
+ expect(metrics.account_usage_metrics(options)).to eq(
139
+ {
140
+ "start" => "Tue, 29 Oct 2024 01:00:00 +0000",
141
+ "end" => "Fri, 29 Nov 2024 01:00:00 +0000",
142
+ "resolution" => "hour",
143
+ "duration" => "1m",
144
+ "dimensions" => ["time"],
145
+ "pagination" => {
146
+ "sort" => "", "skip" => 0, "limit" => 1500, "total" => 2
147
+ },
148
+ "items" => [{
149
+ "dimensions" => [{
150
+ "dimension" => "time",
151
+ "value" => "Wed, 27 Nov 2024 00:00:00 +0000",
152
+ "display_value" => "Wed, 27 Nov 2024 00:00:00 +0000"
153
+ }],
154
+ "metrics" => {
155
+ "processed_count" => 2,
156
+ "email_validation_count" => 0,
157
+ "email_validation_public_count" => 0,
158
+ "email_validation_valid_count" => 0,
159
+ "email_validation_single_count" => 0,
160
+ "email_validation_bulk_count" => 0,
161
+ "email_validation_list_count" => 0,
162
+ "email_validation_mailgun_count" => 0,
163
+ "email_validation_mailjet_count" => 0,
164
+ "email_preview_count" => 0,
165
+ "email_preview_failed_count" => 0,
166
+ "link_validation_count" => 0,
167
+ "link_validation_failed_count" => 0,
168
+ "seed_test_count" => 0
169
+ }
170
+ },
171
+ {
172
+ "dimensions" => [{
173
+ "dimension" => "time",
174
+ "value" => "Thu, 28 Nov 2024 00:00:00 +0000",
175
+ "display_value" => "Thu, 28 Nov 2024 00:00:00 +0000"
176
+ }],
177
+ "metrics" => {
178
+ "processed_count" => 1,
179
+ "email_validation_count" => 0,
180
+ "email_validation_public_count" => 0,
181
+ "email_validation_valid_count" => 0,
182
+ "email_validation_single_count" => 0,
183
+ "email_validation_bulk_count" => 0,
184
+ "email_validation_list_count" => 0,
185
+ "email_validation_mailgun_count" => 0,
186
+ "email_validation_mailjet_count" => 0,
187
+ "email_preview_count" => 0,
188
+ "email_preview_failed_count" => 0,
189
+ "link_validation_count" => 0,
190
+ "link_validation_failed_count" => 0,
191
+ "seed_test_count" => 0
192
+ }
193
+ }
194
+ ],
195
+ "aggregates" => {
196
+ "metrics" => {
197
+ "permanent_failed_count" => 0,
198
+ "processed_count" => 3,
199
+ "email_validation_count" => 0,
200
+ "email_validation_public_count" => 0,
201
+ "email_validation_valid_count" => 0,
202
+ "email_validation_single_count" => 0,
203
+ "email_validation_bulk_count" => 0,
204
+ "email_validation_list_count" => 0,
205
+ "email_validation_mailgun_count" => 0,
206
+ "email_validation_mailjet_count" => 0,
207
+ "email_preview_count" => 0,
208
+ "email_preview_failed_count" => 0,
209
+ "link_validation_count" => 0,
210
+ "link_validation_failed_count" => 0,
211
+ "seed_test_count" => 0
212
+ }
213
+ }
214
+ }
215
+ )
216
+ end
217
+ end
218
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'mailgun'
3
3
 
4
- vcr_opts = { :cassette_name => "routes" }
4
+ vcr_opts = { :cassette_name => "routes", :match_requests_on => [:uri, :method, :body] }
5
5
 
6
6
  describe 'For the Routes endpoint', order: :defined, vcr: vcr_opts do
7
7
  before(:all) do
@@ -25,6 +25,22 @@ describe 'For the Routes endpoint', order: :defined, vcr: vcr_opts do
25
25
  expect(result.body["route"]["priority"]).to eq(10)
26
26
  end
27
27
 
28
+ it 'creates a route with multiple actions' do
29
+ result = @mg_obj.post("routes", { priority: 10,
30
+ description: 'Integration Test Route',
31
+ expression: "match_recipient(\"#{@forward_to}\")",
32
+ action: ["forward(\"#{@recipient}\")", "stop()"] })
33
+
34
+ result.to_h!
35
+ expect(result.body["message"]).to eq("Route has been created")
36
+ expect(result.body["route"]["description"]).to eq("Integration Test Route")
37
+ expect(result.body["route"]["actions"].count).to eq 2
38
+ expect(result.body["route"]["actions"][0]).to include("forward(\"#{@recipient}\")")
39
+ expect(result.body["route"]["actions"][1]).to include("stop()")
40
+ expect(result.body["route"]["expression"]).to include("match_recipient(\"#{@forward_to}\")")
41
+ expect(result.body["route"]["priority"]).to eq(10)
42
+ end
43
+
28
44
  it 'gets a list of all routes.' do
29
45
  result = @mg_obj.get("routes", {:limit => 50})
30
46
 
@@ -6,7 +6,7 @@ vcr_opts = { :cassette_name => "stats" }
6
6
  describe 'For the Stats endpoint', vcr: vcr_opts do
7
7
  before(:all) do
8
8
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
9
- @domain = TESTDOMAIN
9
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
10
10
  end
11
11
 
12
12
  it 'get some stats.' do
@@ -6,8 +6,8 @@ vcr_opts = { :cassette_name => "unsubscribes" }
6
6
  describe 'For the Unsubscribes endpoint', order: :defined, vcr: vcr_opts do
7
7
  before(:all) do
8
8
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
9
- @domain = TESTDOMAIN
10
- @email = "integration-test-email@#{TESTDOMAIN}"
9
+ @domain = TESTDOMAIN || 'DOMAIN.TEST'
10
+ @email = "integration-test-email@#{@domain}"
11
11
  end
12
12
 
13
13
  it 'adds an unsubscriber' do
@@ -6,7 +6,7 @@ vcr_opts = { :cassette_name => "webhooks" }
6
6
  describe 'For the webhooks endpoint', order: :defined, vcr: vcr_opts do
7
7
  before(:all) do
8
8
  @mg_obj = Mailgun::Client.new(APIKEY, APIHOST, APIVERSION, SSL)
9
- @domain = TESTDOMAIN
9
+ @domain = 'DOMAIN.TEST'
10
10
  @testhook = 'accepted'
11
11
  @testhookup = 'accepted'
12
12
  end
data/spec/spec_helper.rb CHANGED
@@ -13,6 +13,7 @@ require 'mailgun'
13
13
 
14
14
  require 'vcr'
15
15
  require 'webmock/rspec'
16
+ require 'rspec/its'
16
17
 
17
18
  #WebMock.disable_net_connect!(allow_localhost: true)
18
19
  require_relative 'unit/connection/test_client'
@@ -99,7 +99,7 @@ module Mailgun
99
99
  return Response.from_hash({ body: JSON.generate({"message" => "Queued. Thank you.", "id" => id}) })
100
100
  end
101
101
  if resource_endpoint == "bounces"
102
- return Response.from_hash({ body: JSON.generate({"total_count" => 1, "items" => {"created_at" => "Fri, 21 Oct 2011 11:02:55 GMT", "code" => 550, "address" => "baz@example.com", "error" => "Message was not accepted -- invalid mailbox. Local mailbox baz@example.com is unavailable: user not found"}}) })
102
+ return Response.from_hash({ body: JSON.generate({"total_count" => 1, "items" => {"created_at" => "Fri, 21 Oct 2011 11:02:55 GMT", "status" => 550, "address" => "baz@example.com", "error" => "Message was not accepted -- invalid mailbox. Local mailbox baz@example.com is unavailable: user not found"}}) })
103
103
  end
104
104
  if resource_endpoint == "lists"
105
105
  return Response.from_hash({ body: JSON.generate({"member" => {"vars" => {"age" => 26}, "name" => "Foo Bar", "subscribed" => false, "address" => "bar@example.com"}, "message" => "Mailing list member has been updated"}) })
@@ -20,7 +20,7 @@ describe 'Pagination' do
20
20
  json = JSON.parse(result.body)
21
21
  expect(json).to include("paging")
22
22
  expect(json["paging"]).to include("next")
23
- expect(json["paging"]).to include{"previous"}
23
+ expect(json["paging"]).to include("previous")
24
24
  end
25
25
 
26
26
  it 'should calculate proper next-page url' do
@@ -5,13 +5,13 @@ RSpec.describe Mailgun::CommunicationError do
5
5
  context "when the Response body doesn't have a `message` property" do
6
6
  it "doesn't raise an error" do
7
7
  expect do
8
- described_class.new('Boom!', Mailgun::Response.from_hash({ code: 401, body: '{}' }))
8
+ described_class.new('Boom!', Mailgun::Response.from_hash({ status: 401, body: '{}' }))
9
9
  end.not_to raise_error
10
10
  end
11
11
 
12
12
  context "when the Response body has an `Error` property" do
13
13
  it "uses the `Error` property as the API message" do
14
- subject = described_class.new('Boom!', Mailgun::Response.from_hash({ code: 401, body: '{"Error":"unauthorized"}' }))
14
+ subject = described_class.new('Boom!', Mailgun::Response.from_hash({ status: 401, body: '{"Error":"unauthorized"}' }))
15
15
 
16
16
  expect(subject.message).to eq("Boom!: unauthorized")
17
17
  end
@@ -19,7 +19,7 @@ RSpec.describe Mailgun::CommunicationError do
19
19
 
20
20
  context "when the Response body has an `error` property" do
21
21
  it "uses the `Error` property as the API message" do
22
- subject = described_class.new('Boom!', Mailgun::Response.from_hash({ code: 401, body: '{"error":"not found"}' }))
22
+ subject = described_class.new('Boom!', Mailgun::Response.from_hash({ status: 401, body: '{"error":"not found"}' }))
23
23
 
24
24
  expect(subject.message).to eq("Boom!: not found")
25
25
  end
@@ -262,10 +262,11 @@ describe 'The method add_attachment' do
262
262
  io = StringIO.new
263
263
  io << File.binread(File.dirname(__FILE__) + "/sample_data/mailgun_icon.png")
264
264
 
265
- @mb_obj.add_attachment io, 'mailgun_icon.png'
265
+ @mb_obj.add_attachment io, 'cool_attachment.png'
266
266
 
267
267
  expect(@mb_obj.message[:attachment].length).to eq(1)
268
- expect(@mb_obj.message[:attachment].first.original_filename).to eq 'mailgun_icon.png'
268
+ expect(@mb_obj.message[:attachment].first.io.original_filename).to eq 'cool_attachment.png'
269
+ expect(@mb_obj.message[:attachment].first.original_filename).to eq 'cool_attachment.png'
269
270
  end
270
271
 
271
272
  context 'when attachment has unknown type' do
@@ -450,7 +451,7 @@ describe 'The method add_tag' do
450
451
  end
451
452
  it 'adds too many tags to the message' do
452
453
  expect{
453
- 10.times do
454
+ 12.times do
454
455
  @mb_obj.add_tag('My-Tag')
455
456
  end }.to raise_error(Mailgun::ParameterError)
456
457
  end