mailgun-ruby 1.4.2 → 1.4.3
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +30 -8
- data/.rubocop.yml +68 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/Rakefile +0 -5
- data/lib/mailgun/client.rb +12 -8
- data/lib/mailgun/domains/domains.rb +4 -2
- data/lib/mailgun/lists/opt_in_handler.rb +2 -4
- data/lib/mailgun/messages/batch_message.rb +2 -1
- data/lib/mailgun/messages/message_builder.rb +4 -32
- data/lib/mailgun/metrics/metrics.rb +6 -2
- data/lib/mailgun/response.rb +2 -2
- data/lib/mailgun/tags/analytics_tags.rb +9 -5
- data/lib/mailgun/tags/tags.rb +4 -2
- data/lib/mailgun/version.rb +1 -1
- data/lib/railgun/attachment.rb +4 -6
- data/lib/railgun/mailer.rb +2 -2
- data/mailgun.gemspec +4 -1
- data/spec/integration/analytics_tags_spec.rb +1 -1
- data/spec/integration/domains_spec.rb +7 -13
- data/spec/integration/events_spec.rb +1 -3
- data/spec/integration/list_members_spec.rb +1 -1
- data/spec/integration/logs_spec.rb +1 -1
- data/spec/integration/mailgun_spec.rb +3 -2
- data/spec/integration/metrics_spec.rb +9 -3
- data/spec/integration/suppressions_spec.rb +203 -26
- data/spec/integration/webhook_spec.rb +7 -2
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/client_spec.rb +424 -0
- data/spec/unit/connection/test_client.rb +60 -13
- data/spec/unit/events/events_spec.rb +25 -9
- data/spec/unit/helpers/api_version_checker_spec.rb +206 -0
- data/spec/unit/lists/opt_in_handler_spec.rb +4 -2
- data/spec/unit/mailgun_spec.rb +7 -5
- data/spec/unit/messages/batch_message_spec.rb +25 -24
- data/spec/unit/messages/message_builder_spec.rb +83 -86
- data/spec/unit/railgun/content_type_spec.rb +7 -7
- data/spec/unit/railgun/mailer_spec.rb +17 -14
- data/spec/unit/response_spec.rb +225 -0
- data/vcr_cassettes/For_the_suppressions_handling_class/creates_a_single_bounce.yml +55 -0
- data/vcr_cassettes/suppressions.yml +1053 -170
- metadata +55 -5
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
require 'mailgun'
|
|
6
|
+
require 'mailgun/helpers/api_version_checker'
|
|
7
|
+
|
|
8
|
+
describe Mailgun::ApiVersionChecker do
|
|
9
|
+
# Build a minimal host class that includes the module, with a controllable
|
|
10
|
+
# @client so we can set api_version per example.
|
|
11
|
+
subject(:instance) { host_class.new(client) }
|
|
12
|
+
|
|
13
|
+
let(:client) { double(:client) }
|
|
14
|
+
|
|
15
|
+
let(:host_class) do
|
|
16
|
+
Class.new do
|
|
17
|
+
include Mailgun::ApiVersionChecker
|
|
18
|
+
|
|
19
|
+
attr_reader :result
|
|
20
|
+
|
|
21
|
+
def initialize(client)
|
|
22
|
+
@client = client
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def do_something(arg = nil)
|
|
26
|
+
@result = arg || :called
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
32
|
+
# .included / module structure
|
|
33
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
describe '.included' do
|
|
36
|
+
it 'extends the including class with ClassMethods' do
|
|
37
|
+
expect(host_class).to respond_to(:requires_api_version)
|
|
38
|
+
expect(host_class).to respond_to(:enforces_api_version)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'does not expose ClassMethods as instance methods' do
|
|
42
|
+
expect(instance).not_to respond_to(:requires_api_version)
|
|
43
|
+
expect(instance).not_to respond_to(:enforces_api_version)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
48
|
+
# .requires_api_version (warns but still calls through)
|
|
49
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
describe '.requires_api_version' do
|
|
52
|
+
before { host_class.requires_api_version('v3', :do_something) }
|
|
53
|
+
|
|
54
|
+
context 'when the client is on the expected version' do
|
|
55
|
+
before { allow(client).to receive(:api_version).and_return('v3') }
|
|
56
|
+
|
|
57
|
+
it 'does not emit a warning' do
|
|
58
|
+
expect { instance.do_something }.not_to output.to_stderr
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'still calls the original method' do
|
|
62
|
+
instance.do_something(:payload)
|
|
63
|
+
expect(instance.result).to eq(:payload)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'forwards all arguments to the original method' do
|
|
67
|
+
instance.do_something(:forwarded_arg)
|
|
68
|
+
expect(instance.result).to eq(:forwarded_arg)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'when the client is on a different version' do
|
|
73
|
+
before { allow(client).to receive(:api_version).and_return('v4') }
|
|
74
|
+
|
|
75
|
+
it 'emits a warning to stderr' do
|
|
76
|
+
expect { instance.do_something }
|
|
77
|
+
.to output(/WARN: Client api version must be v3/).to_stderr
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'still calls the original method despite the warning' do
|
|
81
|
+
instance.do_something(:payload)
|
|
82
|
+
expect(instance.result).to eq(:payload)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'warning message includes the expected version' do
|
|
86
|
+
expect { instance.do_something }
|
|
87
|
+
.to output(/v3/).to_stderr
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'wraps multiple methods when given a list' do
|
|
92
|
+
host_class.class_eval { def do_other = @result = :other }
|
|
93
|
+
host_class.requires_api_version('v3', :do_something, :do_other)
|
|
94
|
+
|
|
95
|
+
allow(client).to receive(:api_version).and_return('v4')
|
|
96
|
+
|
|
97
|
+
expect { instance.do_something }.to output(/v3/).to_stderr
|
|
98
|
+
expect { instance.do_other }.to output(/v3/).to_stderr
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'wraps only the listed methods, leaving others unwrapped' do
|
|
102
|
+
host_class.class_eval { def unwrapped = @result = :unwrapped }
|
|
103
|
+
host_class.requires_api_version('v3', :do_something)
|
|
104
|
+
|
|
105
|
+
allow(client).to receive(:api_version).and_return('v4')
|
|
106
|
+
|
|
107
|
+
# unwrapped should not warn
|
|
108
|
+
expect { instance.unwrapped }.not_to output.to_stderr
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
113
|
+
# .enforces_api_version (raises on version mismatch)
|
|
114
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
describe '.enforces_api_version' do
|
|
117
|
+
before { host_class.enforces_api_version('v3', :do_something) }
|
|
118
|
+
|
|
119
|
+
context 'when the client is on the expected version' do
|
|
120
|
+
before { allow(client).to receive(:api_version).and_return('v3') }
|
|
121
|
+
|
|
122
|
+
it 'does not raise' do
|
|
123
|
+
expect { instance.do_something }.not_to raise_error
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'calls the original method' do
|
|
127
|
+
instance.do_something(:payload)
|
|
128
|
+
expect(instance.result).to eq(:payload)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'forwards all arguments to the original method' do
|
|
132
|
+
instance.do_something(:forwarded_arg)
|
|
133
|
+
expect(instance.result).to eq(:forwarded_arg)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context 'when the client is on a different version' do
|
|
138
|
+
before { allow(client).to receive(:api_version).and_return('v4') }
|
|
139
|
+
|
|
140
|
+
it 'raises Mailgun::ParameterError' do
|
|
141
|
+
expect { instance.do_something }
|
|
142
|
+
.to raise_error(Mailgun::ParameterError)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'raises with a message including the expected version' do
|
|
146
|
+
expect { instance.do_something }
|
|
147
|
+
.to raise_error(Mailgun::ParameterError, /v3/)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'does not call the original method' do
|
|
151
|
+
begin
|
|
152
|
+
instance.do_something
|
|
153
|
+
rescue StandardError
|
|
154
|
+
nil
|
|
155
|
+
end
|
|
156
|
+
expect(instance.result).to be_nil
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'wraps multiple methods when given a list' do
|
|
161
|
+
host_class.class_eval { def do_other = @result = :other }
|
|
162
|
+
host_class.enforces_api_version('v3', :do_something, :do_other)
|
|
163
|
+
|
|
164
|
+
allow(client).to receive(:api_version).and_return('v4')
|
|
165
|
+
|
|
166
|
+
expect { instance.do_something }.to raise_error(Mailgun::ParameterError)
|
|
167
|
+
expect { instance.do_other }.to raise_error(Mailgun::ParameterError)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'wraps only the listed methods, leaving others unwrapped' do
|
|
171
|
+
host_class.class_eval { def unwrapped = @result = :unwrapped }
|
|
172
|
+
host_class.enforces_api_version('v3', :do_something)
|
|
173
|
+
|
|
174
|
+
allow(client).to receive(:api_version).and_return('v4')
|
|
175
|
+
|
|
176
|
+
expect { instance.unwrapped }.not_to raise_error
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
181
|
+
# requires vs enforces contrast
|
|
182
|
+
# ──────────────────────────────────────────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
describe 'requires_api_version vs enforces_api_version' do
|
|
185
|
+
before do
|
|
186
|
+
host_class.class_eval do
|
|
187
|
+
def soft_method = @result = :soft
|
|
188
|
+
def hard_method = @result = :hard
|
|
189
|
+
end
|
|
190
|
+
host_class.requires_api_version('v3', :soft_method)
|
|
191
|
+
host_class.enforces_api_version('v3', :hard_method)
|
|
192
|
+
|
|
193
|
+
allow(client).to receive(:api_version).and_return('v4')
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'requires_api_version warns but does not raise' do
|
|
197
|
+
expect { instance.soft_method }.to output(/v3/).to_stderr
|
|
198
|
+
expect(instance.result).to eq(:soft)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'enforces_api_version raises and does not call through' do
|
|
202
|
+
expect { instance.hard_method }.to raise_error(Mailgun::ParameterError)
|
|
203
|
+
expect(instance.result).not_to eq(:hard)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
describe 'The method generate_hash' do
|
|
6
|
-
before
|
|
6
|
+
before do
|
|
7
7
|
@mailing_list = 'mylist@example.com'
|
|
8
8
|
@secret_app_id = 'mysupersecretpassword'
|
|
9
9
|
@recipient_address = 'bob@example.com'
|
|
10
|
-
@precalculated_hash =
|
|
10
|
+
@precalculated_hash =
|
|
11
|
+
"eyJoIjoiMmY3ZmY1MzFlOGJmMjA0OWNhMTI3ZmU4ZTQyNjZkOTljYzhkMTdk%0AMiIsInAiOiJleUpzSWpv\
|
|
12
|
+
aWJYbHNhWE4wUUdWNFlXMXdiR1V1WTI5dElpd2lj%0AaUk2SW1KdllrQmxlR0Z0Y0d4bExtTnZcbmJTSjlcbiJ9%0A"
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
it 'generates a web safe hash for the recipient wishing to subscribe' do
|
data/spec/unit/mailgun_spec.rb
CHANGED
|
@@ -9,7 +9,7 @@ describe 'Mailgun instantiation' do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
describe 'The method send_message()' do
|
|
12
|
-
before
|
|
12
|
+
before do
|
|
13
13
|
@mg_obj = Mailgun::UnitClient.new('messages')
|
|
14
14
|
@domain = 'test.com'
|
|
15
15
|
@list_address = 'mylist@test.com'
|
|
@@ -73,10 +73,11 @@ describe 'The method send_message()' do
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
describe 'The method post()' do
|
|
76
|
-
before
|
|
76
|
+
before do
|
|
77
77
|
@mg_obj = Mailgun::UnitClient.new('messages')
|
|
78
78
|
@domain = 'test.com'
|
|
79
79
|
end
|
|
80
|
+
|
|
80
81
|
it 'in this case, sends a simple message.' do
|
|
81
82
|
data = { 'from' => 'joe@test.com',
|
|
82
83
|
'to' => 'bob@example.com',
|
|
@@ -111,7 +112,7 @@ describe 'The method post()' do
|
|
|
111
112
|
end
|
|
112
113
|
|
|
113
114
|
describe 'The method put()' do
|
|
114
|
-
before
|
|
115
|
+
before do
|
|
115
116
|
@mg_obj = Mailgun::UnitClient.new('lists')
|
|
116
117
|
@domain = 'test.com'
|
|
117
118
|
@list_address = 'mylist@test.com'
|
|
@@ -136,10 +137,11 @@ describe 'The method put()' do
|
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
describe 'The method get()' do
|
|
139
|
-
before
|
|
140
|
+
before do
|
|
140
141
|
@mg_obj = Mailgun::UnitClient.new('bounces')
|
|
141
142
|
@domain = 'test.com'
|
|
142
143
|
end
|
|
144
|
+
|
|
143
145
|
it 'in this case, obtains a list of bounces for the domain, limit of 5, skipping the first 10.' do
|
|
144
146
|
query_string = { 'skip' => '10',
|
|
145
147
|
'limit' => '5' }
|
|
@@ -153,7 +155,7 @@ describe 'The method get()' do
|
|
|
153
155
|
end
|
|
154
156
|
|
|
155
157
|
describe 'The method delete()' do
|
|
156
|
-
before
|
|
158
|
+
before do
|
|
157
159
|
@mg_obj = Mailgun::UnitClient.new('campaigns')
|
|
158
160
|
@domain = 'test.com'
|
|
159
161
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
describe 'BatchMessage attribute readers' do
|
|
6
|
-
it '
|
|
6
|
+
it 'is readable' do
|
|
7
7
|
@mb_client = Mailgun::UnitClient.new('messages')
|
|
8
8
|
@mb_obj = Mailgun::BatchMessage.new(@mb_client, 'example.com')
|
|
9
9
|
|
|
@@ -16,7 +16,7 @@ describe 'BatchMessage attribute readers' do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe 'The instantiation of Batch Message' do
|
|
19
|
-
before
|
|
19
|
+
before do
|
|
20
20
|
@mb_client = Mailgun::UnitClient.new('messages')
|
|
21
21
|
@mb_obj = Mailgun::BatchMessage.new(@mb_client, 'example.com')
|
|
22
22
|
end
|
|
@@ -63,30 +63,31 @@ describe 'The instantiation of Batch Message' do
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
describe 'The method add_recipient' do
|
|
66
|
-
before
|
|
66
|
+
before do
|
|
67
67
|
@mb_client = Mailgun::UnitClient.new('messages')
|
|
68
68
|
@mb_obj = Mailgun::BatchMessage.new(@mb_client, 'example.com')
|
|
69
|
-
@
|
|
70
|
-
@
|
|
71
|
-
@
|
|
72
|
-
@
|
|
73
|
-
@
|
|
74
|
-
@
|
|
69
|
+
@address1 = 'jane@example.com'
|
|
70
|
+
@variables1 = { 'first' => 'Jane', 'last' => 'Doe', 'tracking' => 'ABC123' }
|
|
71
|
+
@address2 = 'bob@example.com'
|
|
72
|
+
@variables2 = { 'first' => 'Bob', 'last' => 'Doe', 'tracking' => 'DEF123' }
|
|
73
|
+
@address3 = 'sam@example.com'
|
|
74
|
+
@variables3 = { 'first' => 'Sam', 'last' => 'Doe', 'tracking' => 'GHI123' }
|
|
75
75
|
end
|
|
76
|
+
|
|
76
77
|
context 'when from is present' do
|
|
77
|
-
before
|
|
78
|
+
before do
|
|
78
79
|
@mb_obj.from('example@email.com')
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
it 'adds 1,000 recipients to the message body and validates counter is incremented then reset' do
|
|
82
83
|
recipient_type = :to
|
|
83
84
|
1000.times do
|
|
84
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
85
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
85
86
|
end
|
|
86
87
|
|
|
87
88
|
expect(@mb_obj.counters[:recipients][recipient_type]).to eq(1000)
|
|
88
89
|
|
|
89
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
90
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
90
91
|
|
|
91
92
|
expect(@mb_obj.counters[:recipients][recipient_type]).to eq(1)
|
|
92
93
|
end
|
|
@@ -94,7 +95,7 @@ describe 'The method add_recipient' do
|
|
|
94
95
|
it 'adds recipients to the message, calls finalize, and cleans up' do
|
|
95
96
|
recipient_type = :to
|
|
96
97
|
1000.times do
|
|
97
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
98
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
98
99
|
end
|
|
99
100
|
|
|
100
101
|
expect(@mb_obj.counters[:recipients][recipient_type]).to eq(1000)
|
|
@@ -109,7 +110,7 @@ describe 'The method add_recipient' do
|
|
|
109
110
|
it 'adds 5,005 recipients to the message body and validates we receive message_ids back' do
|
|
110
111
|
recipient_type = :to
|
|
111
112
|
5005.times do
|
|
112
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
113
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
113
114
|
end
|
|
114
115
|
@mb_obj.finalize
|
|
115
116
|
|
|
@@ -118,28 +119,28 @@ describe 'The method add_recipient' do
|
|
|
118
119
|
|
|
119
120
|
it 'sets recipient-variables, for batch expansion' do
|
|
120
121
|
recipient_type = :to
|
|
121
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
122
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
122
123
|
|
|
123
|
-
expect(@mb_obj.recipient_variables[@
|
|
124
|
+
expect(@mb_obj.recipient_variables[@address1]).to eq(@variables1)
|
|
124
125
|
end
|
|
125
126
|
|
|
126
127
|
it 'sets multiple recipient-variables, for batch expansion' do
|
|
127
128
|
recipient_type = :to
|
|
128
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
129
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
130
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
129
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
130
|
+
@mb_obj.add_recipient(recipient_type, @address2, @variables2)
|
|
131
|
+
@mb_obj.add_recipient(recipient_type, @address3, @variables3)
|
|
131
132
|
|
|
132
|
-
expect(@mb_obj.recipient_variables[@
|
|
133
|
-
expect(@mb_obj.recipient_variables[@
|
|
134
|
-
expect(@mb_obj.recipient_variables[@
|
|
133
|
+
expect(@mb_obj.recipient_variables[@address1]).to eq(@variables1)
|
|
134
|
+
expect(@mb_obj.recipient_variables[@address2]).to eq(@variables2)
|
|
135
|
+
expect(@mb_obj.recipient_variables[@address3]).to eq(@variables3)
|
|
135
136
|
end
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
context 'when from is empty' do
|
|
139
140
|
it 'shows error message' do
|
|
140
141
|
recipient_type = :to
|
|
141
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
142
|
-
@mb_obj.add_recipient(recipient_type, @
|
|
142
|
+
@mb_obj.add_recipient(recipient_type, @address1, @variables1)
|
|
143
|
+
@mb_obj.add_recipient(recipient_type, @address2, @variables2)
|
|
143
144
|
expect(@mb_client).to receive(:raise)
|
|
144
145
|
@mb_obj.finalize
|
|
145
146
|
end
|