mailgun-ruby 1.4.4 → 1.4.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.
- checksums.yaml +4 -4
- data/.github_changelog_generator +1 -0
- data/CHANGELOG.md +705 -71
- data/README.md +2 -1
- data/docs/ApiKeys.md +65 -0
- data/docs/Webhooks.md +27 -4
- data/lib/mailgun/api_keys/api_keys.rb +65 -0
- data/lib/mailgun/client.rb +1 -1
- data/lib/mailgun/version.rb +1 -1
- data/lib/mailgun/webhooks/webhooks.rb +49 -10
- data/lib/mailgun.rb +1 -0
- data/spec/integration/api_keys_spec.rb +50 -0
- data/spec/integration/webhook_spec.rb +34 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/client_spec.rb +24 -0
- data/spec/unit/webhooks_spec.rb +121 -0
- data/vcr_cassettes/api_keys.yml +212 -0
- data/vcr_cassettes/webhooks_v4.yml +275 -0
- metadata +11 -2
data/README.md
CHANGED
|
@@ -19,7 +19,7 @@ gem install mailgun-ruby
|
|
|
19
19
|
Gemfile:
|
|
20
20
|
|
|
21
21
|
```ruby
|
|
22
|
-
gem 'mailgun-ruby', '~>1.4.
|
|
22
|
+
gem 'mailgun-ruby', '~>1.4.5'
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Usage
|
|
@@ -187,6 +187,7 @@ This SDK includes the following components:
|
|
|
187
187
|
- [Domains](docs/Domains.md)
|
|
188
188
|
- [Webhooks](docs/Webhooks.md)
|
|
189
189
|
- [Account Webhooks](docs/AccountWebhooks.md)
|
|
190
|
+
- [API Keys](docs/ApiKeys.md)
|
|
190
191
|
- [Events](docs/Events.md)
|
|
191
192
|
- [Snippets](docs/Snippets.md)
|
|
192
193
|
- [Subaccounts](docs/Subaccounts.md)
|
data/docs/ApiKeys.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Mailgun - API Keys
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
This is the Mailgun Ruby *API Keys* utilities.
|
|
5
|
+
|
|
6
|
+
The below assumes you've already installed the Mailgun Ruby SDK in to your
|
|
7
|
+
project. If not, go back to the master README for instructions.
|
|
8
|
+
|
|
9
|
+
Usage - API Keys
|
|
10
|
+
-----------------------
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
# First, instantiate the Mailgun Client with your API key
|
|
14
|
+
mg_client = Mailgun::Client.new('your-api-key', 'api.mailgun.net', 'v1')
|
|
15
|
+
api_keys = Mailgun::ApiKeys.new(mg_client)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
API Keys methods:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
# List API keys
|
|
22
|
+
api_keys.list
|
|
23
|
+
|
|
24
|
+
# List API keys filtered by kind and domain
|
|
25
|
+
api_keys.list(kind: 'domain', domain_name: 'my.perfect.domain')
|
|
26
|
+
|
|
27
|
+
# Create a user API key
|
|
28
|
+
api_keys.create(
|
|
29
|
+
kind: 'user',
|
|
30
|
+
role: 'admin',
|
|
31
|
+
description: 'desc'
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Create a sending key for a domain, expiring in 1 day
|
|
35
|
+
api_keys.create(
|
|
36
|
+
kind: 'domain',
|
|
37
|
+
domain_name: 'my.perfect.domain',
|
|
38
|
+
role: 'sending',
|
|
39
|
+
expiration: 86_400
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Delete an API key
|
|
43
|
+
api_keys.remove('key-id')
|
|
44
|
+
|
|
45
|
+
# Regenerate the public API key
|
|
46
|
+
api_keys.regenerate
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Supported `create` options:
|
|
50
|
+
|
|
51
|
+
| Option | Description |
|
|
52
|
+
|---------------|-------------|
|
|
53
|
+
| `kind` | Type of API key: `domain`, `user` or `web`. Defaults to `user` |
|
|
54
|
+
| `role` | Key role: `admin`, `basic`, `sending` (for `domain` keys) or `developer` |
|
|
55
|
+
| `domain_name` | Domain to associate with the key, for `domain` keys |
|
|
56
|
+
| `description` | Key description |
|
|
57
|
+
| `expiration` | Key lifetime in seconds, must be greater than 0 if set |
|
|
58
|
+
| `user_id` | API key user's ID, should be provided for `web` keys |
|
|
59
|
+
| `user_name` | API key user's name |
|
|
60
|
+
| `email` | API key user's email address, should be provided for `web` keys |
|
|
61
|
+
|
|
62
|
+
More Documentation
|
|
63
|
+
------------------
|
|
64
|
+
See the official [Mailgun API Keys Docs](https://documentation.mailgun.com/docs/mailgun/api-reference/send/mailgun/keys)
|
|
65
|
+
for more information
|
data/docs/Webhooks.md
CHANGED
|
@@ -18,24 +18,47 @@ hook = Mailgun::Webhooks.new(mg_client)
|
|
|
18
18
|
hook.list 'my.perfect.domain'
|
|
19
19
|
|
|
20
20
|
# View a single webhook detail
|
|
21
|
-
hook.info 'my.perfect.domain', '
|
|
21
|
+
hook.info 'my.perfect.domain', 'delivered'
|
|
22
22
|
|
|
23
23
|
# Add a single url for all webhooks
|
|
24
24
|
hook.create_all 'my.perfect.domain', 'https://the.webhook.url/'
|
|
25
25
|
|
|
26
26
|
# Add a url for a specific webhook
|
|
27
|
-
hook.create 'my.perfect.domain', '
|
|
27
|
+
hook.create 'my.perfect.domain', 'delivered', 'https://the.webhook.url/'
|
|
28
28
|
|
|
29
29
|
# Update the url for a specific webhook
|
|
30
|
-
hook.update 'my.perfect.domain', '
|
|
30
|
+
hook.update 'my.perfect.domain', 'delivered', 'https://the.webhook.url/'
|
|
31
31
|
|
|
32
32
|
# Remove a url for a specific webhook
|
|
33
|
-
hook.remove 'my.perfect.domain', '
|
|
33
|
+
hook.remove 'my.perfect.domain', 'delivered'
|
|
34
34
|
|
|
35
35
|
# Remove all webhooks for a domain
|
|
36
36
|
hook.remove_all 'my.perfect.domain'
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
Usage - Webhooks (v4)
|
|
40
|
+
-----------------------
|
|
41
|
+
|
|
42
|
+
The v4 endpoints work with a URL across multiple event types in a single request.
|
|
43
|
+
They require a client configured for the `v4` API.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
mg_client = Mailgun::Client.new('your-api-key', 'api.mailgun.net', 'v4')
|
|
47
|
+
hook = Mailgun::Webhooks.new(mg_client)
|
|
48
|
+
|
|
49
|
+
# Associate a url with one or more event types
|
|
50
|
+
hook.create_v4 'my.perfect.domain', url: 'https://the.webhook.url/', event_types: %w[delivered opened]
|
|
51
|
+
|
|
52
|
+
# Replace the event types associated with a url
|
|
53
|
+
hook.update_v4 'my.perfect.domain', url: 'https://the.webhook.url/', event_types: %w[clicked]
|
|
54
|
+
|
|
55
|
+
# Remove one or more urls from all event types they are associated with
|
|
56
|
+
hook.remove_v4 'my.perfect.domain', url: 'https://the.webhook.url/'
|
|
57
|
+
hook.remove_v4 'my.perfect.domain', url: ['https://the.webhook.url/', 'https://another.webhook.url/']
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Each v4 method returns a Hash of the domain's webhooks keyed by event type.
|
|
61
|
+
|
|
39
62
|
More Documentation
|
|
40
63
|
------------------
|
|
41
64
|
See the official [Mailgun Webhooks Docs](https://documentation.mailgun.com/docs/mailgun/api-reference/send/mailgun/domain-webhooks)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mailgun
|
|
4
|
+
# A Mailgun::ApiKeys object is a simple CRUD interface to Mailgun Api Keys.
|
|
5
|
+
# Uses Mailgun
|
|
6
|
+
class ApiKeys
|
|
7
|
+
include ApiVersionChecker
|
|
8
|
+
|
|
9
|
+
# Public creates a new Mailgun::ApiKeys instance.
|
|
10
|
+
# Defaults to Mailgun::Client
|
|
11
|
+
def initialize(client = Mailgun::Client.new(Mailgun.api_key, Mailgun.api_host || 'api.mailgun.net', 'v1'))
|
|
12
|
+
@client = client
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Public: List Mailgun API keys
|
|
16
|
+
#
|
|
17
|
+
# options - [Hash] of
|
|
18
|
+
# domain_name - [String] Domain name filter for domain keys
|
|
19
|
+
# kind - [String] Key kind filter ('domain', 'user', or 'web')
|
|
20
|
+
#
|
|
21
|
+
# Retrieve filtered api keys.
|
|
22
|
+
def list(options = {})
|
|
23
|
+
res = @client.get('keys', options)
|
|
24
|
+
res.to_h['items']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Public: Create Mailgun API key
|
|
28
|
+
|
|
29
|
+
# options - [Hash] of
|
|
30
|
+
# domain_name - [String] Web domain to associate with the key, for keys of 'domain' kind
|
|
31
|
+
# kind - [String] Type of API key ('domain', 'user', or 'web'). Defaults to 'user' if not provided.
|
|
32
|
+
# description - [String] Key description
|
|
33
|
+
# expiration - [String] Key lifetime in seconds, must be greater than 0 if set
|
|
34
|
+
# role - [String] Key role ('admin', 'basic' [use in place of analyst],
|
|
35
|
+
# 'sending' [use with keys of domain kind], or 'developer')
|
|
36
|
+
# user_id - [String] API Key user's string user ID; should be provided for all keys of 'web' kind
|
|
37
|
+
# user_name - [String] API Key user's name
|
|
38
|
+
# email - [String] API Key user's email address; should be provided for all keys of 'web' kind
|
|
39
|
+
#
|
|
40
|
+
# Returns the Api Key object
|
|
41
|
+
def create(options = {})
|
|
42
|
+
res = @client.post('keys', options)
|
|
43
|
+
res.to_h['key']
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Public: Delete Mailgun API key
|
|
47
|
+
#
|
|
48
|
+
# key_id - [String] The Key ID generated by Mailgun on key creation
|
|
49
|
+
#
|
|
50
|
+
# Returns a Boolean of the success
|
|
51
|
+
def remove(key_id)
|
|
52
|
+
@client.delete("keys/#{key_id}").status == 200
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Public: Regenerate Mailgun Public API key
|
|
56
|
+
#
|
|
57
|
+
# Returns new Mailgun Public API key.
|
|
58
|
+
def regenerate
|
|
59
|
+
res = @client.post('keys/public', {})
|
|
60
|
+
res.to_h['key']
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
enforces_api_version 'v1', :list, :create, :remove, :regenerate
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/mailgun/client.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Mailgun
|
|
|
13
13
|
api_host = Mailgun.api_host || 'api.mailgun.net',
|
|
14
14
|
api_version = Mailgun.api_version || 'v3',
|
|
15
15
|
ssl = true,
|
|
16
|
-
test_mode =
|
|
16
|
+
test_mode = Mailgun.test_mode ? true : false,
|
|
17
17
|
timeout = nil,
|
|
18
18
|
proxy_url = Mailgun.proxy_url)
|
|
19
19
|
endpoint = endpoint_generator(api_host, api_version, ssl)
|
data/lib/mailgun/version.rb
CHANGED
|
@@ -58,12 +58,13 @@ module Mailgun
|
|
|
58
58
|
#
|
|
59
59
|
# domain - A String of the domain name (ex. domain.com)
|
|
60
60
|
# action - A String of the action to create a webhook for
|
|
61
|
-
# url - A String of the url of the webhook
|
|
61
|
+
# url - A String of the url of the webhook, or an Array of up to 3 urls
|
|
62
62
|
#
|
|
63
63
|
# Returns a Boolean of whether the webhook was created
|
|
64
64
|
def create(domain, action, url = '')
|
|
65
65
|
res = @client.post("domains/#{domain}/webhooks", id: action, url: url)
|
|
66
|
-
res.to_h['webhook']['urls']
|
|
66
|
+
urls = res.to_h['webhook']['urls']
|
|
67
|
+
Array(url).all? { |u| urls.include?(u) } && res.to_h['message'] == 'Webhook has been created'
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
# :nocov:
|
|
@@ -84,7 +85,8 @@ module Mailgun
|
|
|
84
85
|
# Returns true or false
|
|
85
86
|
# :nocov:
|
|
86
87
|
%i[create_all add_all_webhooks].each do |method|
|
|
87
|
-
define_method(method) do |domain|
|
|
88
|
+
define_method(method) do |domain, url|
|
|
89
|
+
url ||= ''
|
|
88
90
|
warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `create` instead.")
|
|
89
91
|
|
|
90
92
|
ACTIONS.each do |action|
|
|
@@ -97,13 +99,13 @@ module Mailgun
|
|
|
97
99
|
# Public: Update webhook
|
|
98
100
|
#
|
|
99
101
|
# domain - A String of the domain name (ex. domain.com)
|
|
100
|
-
# action - A String of the action to
|
|
101
|
-
# url - A String of the url of the webhook
|
|
102
|
+
# action - A String of the action to update the webhook for
|
|
103
|
+
# url - A String of the url of the webhook, or an Array of up to 3 urls
|
|
102
104
|
#
|
|
103
105
|
# Returns a Boolean of whether the webhook was updated
|
|
104
106
|
def update(domain, action, url = '')
|
|
105
|
-
raise Mailgun::ParameterError
|
|
106
|
-
raise Mailgun::ParameterError
|
|
107
|
+
raise Mailgun::ParameterError, 'Domain not provided to update webhooks' if domain.to_s.empty?
|
|
108
|
+
raise Mailgun::ParameterError, 'Action not provided to identify webhook to update' if action.to_s.empty?
|
|
107
109
|
|
|
108
110
|
res = @client.put("domains/#{domain}/webhooks/#{action}", id: action, url: url)
|
|
109
111
|
res.to_h['message'] == 'Webhook has been updated'
|
|
@@ -123,8 +125,8 @@ module Mailgun
|
|
|
123
125
|
#
|
|
124
126
|
# Returns a Boolean of the success
|
|
125
127
|
def remove(domain, action)
|
|
126
|
-
raise Mailgun::ParameterError
|
|
127
|
-
raise Mailgun::ParameterError
|
|
128
|
+
raise Mailgun::ParameterError, 'Domain not provided to remove webhook from' if domain.to_s.empty?
|
|
129
|
+
raise Mailgun::ParameterError, 'Action not provided to identify webhook to remove' if action.to_s.empty?
|
|
128
130
|
|
|
129
131
|
@client.delete("domains/#{domain}/webhooks/#{action}").to_h['message'] == 'Webhook has been deleted'
|
|
130
132
|
end
|
|
@@ -148,7 +150,7 @@ module Mailgun
|
|
|
148
150
|
define_method(method) do |domain|
|
|
149
151
|
warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `remove` instead.")
|
|
150
152
|
|
|
151
|
-
raise Mailgun::ParameterError
|
|
153
|
+
raise Mailgun::ParameterError, 'Domain not provided to remove webhooks from' if domain.to_s.empty?
|
|
152
154
|
|
|
153
155
|
ACTIONS.each do |action|
|
|
154
156
|
remove domain, action
|
|
@@ -157,6 +159,43 @@ module Mailgun
|
|
|
157
159
|
end
|
|
158
160
|
# :nocov:
|
|
159
161
|
|
|
162
|
+
# Public: Create webhooks for multiple event types (v4)
|
|
163
|
+
#
|
|
164
|
+
# domain - [String] The domain name to create webhooks for
|
|
165
|
+
# url - [String] The webhook URL that will receive POST requests
|
|
166
|
+
# event_types - [String, Array<String>] Event types to associate with the URL
|
|
167
|
+
#
|
|
168
|
+
# Returns a Hash of the domain webhooks keyed by event type
|
|
169
|
+
def create_v4(domain, url:, event_types:)
|
|
170
|
+
res = @client.post("domains/#{domain}/webhooks", { url: url, event_types: event_types })
|
|
171
|
+
res.to_h['webhooks']
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Public: Update the event types associated with a webhook URL (v4)
|
|
175
|
+
#
|
|
176
|
+
# domain - [String] The domain name to update webhooks for
|
|
177
|
+
# url - [String] The webhook URL to update
|
|
178
|
+
# event_types - [String, Array<String>] Event types to associate with the URL.
|
|
179
|
+
# Replaces the existing associations.
|
|
180
|
+
#
|
|
181
|
+
# Returns a Hash of the domain webhooks keyed by event type
|
|
182
|
+
def update_v4(domain, url:, event_types:)
|
|
183
|
+
res = @client.put("domains/#{domain}/webhooks", { url: url, event_types: event_types })
|
|
184
|
+
res.to_h['webhooks']
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Public: Delete webhook URLs from all event types they are associated with (v4)
|
|
188
|
+
#
|
|
189
|
+
# domain - [String] The domain name to delete webhooks from
|
|
190
|
+
# url - [String, Array<String>] The webhook URL(s) to delete
|
|
191
|
+
#
|
|
192
|
+
# Returns a Hash of the remaining domain webhooks keyed by event type
|
|
193
|
+
def remove_v4(domain, url:)
|
|
194
|
+
res = @client.delete("domains/#{domain}/webhooks", { url: url })
|
|
195
|
+
res.to_h['webhooks']
|
|
196
|
+
end
|
|
197
|
+
|
|
160
198
|
enforces_api_version 'v3', :list, :get, :create, :update, :remove
|
|
199
|
+
enforces_api_version 'v4', :create_v4, :update_v4, :remove_v4
|
|
161
200
|
end
|
|
162
201
|
end
|
data/lib/mailgun.rb
CHANGED
|
@@ -23,6 +23,7 @@ Zeitwerk::Loader.for_gem.tap do |loader|
|
|
|
23
23
|
loader.ignore("#{__dir__}/railgun.rb")
|
|
24
24
|
loader.ignore("#{__dir__}/railgun")
|
|
25
25
|
|
|
26
|
+
loader.collapse("#{__dir__}/mailgun/api_keys")
|
|
26
27
|
loader.collapse("#{__dir__}/mailgun/analytics_tags")
|
|
27
28
|
loader.collapse("#{__dir__}/mailgun/domains")
|
|
28
29
|
loader.collapse("#{__dir__}/mailgun/events")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'mailgun'
|
|
5
|
+
|
|
6
|
+
vcr_opts = { cassette_name: 'api_keys' }
|
|
7
|
+
|
|
8
|
+
describe 'ApiKeys', order: :defined, vcr: vcr_opts do
|
|
9
|
+
let(:api_version) { 'v1' }
|
|
10
|
+
let(:mg_client) { Mailgun::Client.new(APIKEY, APIHOST, api_version, SSL) }
|
|
11
|
+
let(:mg_obj) { Mailgun::ApiKeys.new(mg_client) }
|
|
12
|
+
|
|
13
|
+
it 'creates an api key' do
|
|
14
|
+
result = mg_obj.create(
|
|
15
|
+
{
|
|
16
|
+
kind: 'user',
|
|
17
|
+
'description': 'test test',
|
|
18
|
+
'role': 'admin'
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
expect(result['description']).to eq('test test')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'gets api keys' do
|
|
26
|
+
result = mg_obj.list
|
|
27
|
+
|
|
28
|
+
expect(result[0]['id']).to eq('test')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'gets api keys filtered by kind and domain' do
|
|
32
|
+
result = mg_obj.list(kind: 'domain', domain_name: 'DOMAIN.TEST')
|
|
33
|
+
|
|
34
|
+
domain_keys = result.select { |key| key['kind'] == 'domain' }
|
|
35
|
+
expect(domain_keys.map { |key| key['domain_name'] }).to eq(['DOMAIN.TEST'])
|
|
36
|
+
expect(result.map { |key| key['kind'] }).not_to include('user', 'web')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'removes an api key' do
|
|
40
|
+
result = mg_obj.remove('test')
|
|
41
|
+
|
|
42
|
+
expect(result).to be_truthy
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'regenerates public api key' do
|
|
46
|
+
result = mg_obj.regenerate
|
|
47
|
+
|
|
48
|
+
expect(result).to be_truthy
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -43,3 +43,37 @@ describe 'For the webhooks endpoint', order: :defined, vcr: vcr_opts do
|
|
|
43
43
|
expect(result).to be_truthy
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
+
|
|
47
|
+
describe 'For the v4 webhooks endpoint', vcr: { cassette_name: 'webhooks_v4' } do
|
|
48
|
+
let(:mg_client) { Mailgun::Client.new(APIKEY, APIHOST, 'v4', SSL) }
|
|
49
|
+
let(:mg_obj) { Mailgun::Webhooks.new(mg_client) }
|
|
50
|
+
let(:domain) { 'DOMAIN.TEST' }
|
|
51
|
+
let(:url) { 'http://example.com/mailgun/events/v4' }
|
|
52
|
+
|
|
53
|
+
describe '#create_v4' do
|
|
54
|
+
it 'creates webhooks for multiple event types' do
|
|
55
|
+
result = mg_obj.create_v4(domain, url: url, event_types: %w[accepted delivered])
|
|
56
|
+
|
|
57
|
+
expect(result.keys).to contain_exactly('accepted', 'delivered')
|
|
58
|
+
expect(result['accepted']['urls']).to include(url)
|
|
59
|
+
expect(result['delivered']['urls']).to include(url)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#update_v4' do
|
|
64
|
+
it 'replaces the event types associated with a url' do
|
|
65
|
+
result = mg_obj.update_v4(domain, url: url, event_types: %w[clicked opened])
|
|
66
|
+
|
|
67
|
+
expect(result.keys).to contain_exactly('clicked', 'opened')
|
|
68
|
+
expect(result['clicked']['urls']).to include(url)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe '#remove_v4' do
|
|
73
|
+
it 'removes the urls from all event types' do
|
|
74
|
+
result = mg_obj.remove_v4(domain, url: [url, 'http://example.com/mailgun/events/v4-other'])
|
|
75
|
+
|
|
76
|
+
expect(result).to eq({})
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -17,6 +17,8 @@ require 'mailgun'
|
|
|
17
17
|
|
|
18
18
|
require 'vcr'
|
|
19
19
|
require 'webmock/rspec'
|
|
20
|
+
# Keep repeated query keys (e.g. ?url=a&url=b) instead of collapsing them to the last value
|
|
21
|
+
WebMock::Config.instance.query_values_notation = :flat_array
|
|
20
22
|
require 'rspec/its'
|
|
21
23
|
|
|
22
24
|
# WebMock.disable_net_connect!(allow_localhost: true)
|
|
@@ -43,6 +45,7 @@ VCR.configure do |c|
|
|
|
43
45
|
c.hook_into :webmock
|
|
44
46
|
c.default_cassette_options = { record: :new_episodes }
|
|
45
47
|
c.filter_sensitive_data('<APIKEY>') { APIKEY }
|
|
48
|
+
c.filter_sensitive_data('<BASIC_AUTH>') { ["api:#{APIKEY}"].pack('m0') } if APIKEY
|
|
46
49
|
c.filter_sensitive_data('DOMAIN.TEST') { TESTDOMAIN }
|
|
47
50
|
c.filter_sensitive_data('<PUBKEY>') { PUB_APIKEY }
|
|
48
51
|
|
data/spec/unit/client_spec.rb
CHANGED
|
@@ -54,6 +54,30 @@ describe Mailgun::Client do
|
|
|
54
54
|
it 'supports EU api host' do
|
|
55
55
|
expect { described_class.new(api_key, 'api.eu.mailgun.net') }.not_to raise_error
|
|
56
56
|
end
|
|
57
|
+
|
|
58
|
+
context 'when test_mode is not passed' do
|
|
59
|
+
around do |example|
|
|
60
|
+
original = Mailgun.test_mode
|
|
61
|
+
example.run
|
|
62
|
+
ensure
|
|
63
|
+
Mailgun.test_mode = original
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'enables test mode when Mailgun.test_mode is true' do
|
|
67
|
+
Mailgun.test_mode = true
|
|
68
|
+
expect(described_class.new(api_key).test_mode?).to be(true)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'disables test mode when Mailgun.test_mode is false' do
|
|
72
|
+
Mailgun.test_mode = false
|
|
73
|
+
expect(described_class.new(api_key).test_mode?).to be(false)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'disables test mode when Mailgun.test_mode is not set' do
|
|
77
|
+
Mailgun.test_mode = nil
|
|
78
|
+
expect(described_class.new(api_key).test_mode?).to be(false)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
57
81
|
end
|
|
58
82
|
|
|
59
83
|
# ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Mailgun::Webhooks do
|
|
6
|
+
let(:client) { double(:client) }
|
|
7
|
+
let(:webhooks) { described_class.new(client) }
|
|
8
|
+
let(:domain) { 'example.com' }
|
|
9
|
+
let(:url) { 'https://example.com/mailgun/events' }
|
|
10
|
+
|
|
11
|
+
%i[create_all add_all_webhooks].each do |method|
|
|
12
|
+
describe "##{method}" do
|
|
13
|
+
it 'creates every webhook action with the provided URL' do
|
|
14
|
+
described_class::ACTIONS.each do |action|
|
|
15
|
+
expect(webhooks).to receive(:create).with(domain, action, url).ordered
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
expect { webhooks.public_send(method, domain, url) }
|
|
19
|
+
.to output(/`#{method}` method will be deprecated/).to_stderr
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'with v3 endpoints' do
|
|
25
|
+
let(:client) { instance_double(Mailgun::Client, api_version: 'v3') }
|
|
26
|
+
|
|
27
|
+
describe '#create' do
|
|
28
|
+
let(:urls) { [url, 'https://example.com/other'] }
|
|
29
|
+
let(:response) do
|
|
30
|
+
instance_double(Mailgun::Response,
|
|
31
|
+
to_h: { 'message' => 'Webhook has been created', 'webhook' => { 'urls' => urls } })
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
before { allow(client).to receive(:post).and_return(response) }
|
|
35
|
+
|
|
36
|
+
it 'returns true when a single url was created' do
|
|
37
|
+
expect(webhooks.create(domain, 'delivered', url)).to be(true)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'returns true when multiple urls were created' do
|
|
41
|
+
expect(webhooks.create(domain, 'delivered', urls)).to be(true)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'returns false when a url is missing from the response' do
|
|
45
|
+
expect(webhooks.create(domain, 'delivered', [url, 'https://example.com/missing'])).to be(false)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe 'parameter validation' do
|
|
50
|
+
it 'raises a ParameterError when the domain is missing' do
|
|
51
|
+
[nil, ''].each do |blank|
|
|
52
|
+
expect { webhooks.update(blank, 'delivered', url) }
|
|
53
|
+
.to raise_error(Mailgun::ParameterError, 'Domain not provided to update webhooks')
|
|
54
|
+
expect { webhooks.remove(blank, 'delivered') }
|
|
55
|
+
.to raise_error(Mailgun::ParameterError, 'Domain not provided to remove webhook from')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'raises a ParameterError when the action is missing' do
|
|
60
|
+
[nil, ''].each do |blank|
|
|
61
|
+
expect { webhooks.update(domain, blank, url) }
|
|
62
|
+
.to raise_error(Mailgun::ParameterError, 'Action not provided to identify webhook to update')
|
|
63
|
+
expect { webhooks.remove(domain, blank) }
|
|
64
|
+
.to raise_error(Mailgun::ParameterError, 'Action not provided to identify webhook to remove')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'with v4 endpoints' do
|
|
71
|
+
let(:api_version) { 'v4' }
|
|
72
|
+
let(:client) { instance_double(Mailgun::Client, api_version: api_version) }
|
|
73
|
+
let(:response) { instance_double(Mailgun::Response, to_h: { 'webhooks' => { 'accepted' => { 'urls' => [url] } } }) }
|
|
74
|
+
|
|
75
|
+
describe '#create_v4' do
|
|
76
|
+
it 'posts the url and event types to the domain webhooks endpoint' do
|
|
77
|
+
expect(client).to receive(:post)
|
|
78
|
+
.with("domains/#{domain}/webhooks", { url: url, event_types: %w[accepted delivered] })
|
|
79
|
+
.and_return(response)
|
|
80
|
+
|
|
81
|
+
expect(webhooks.create_v4(domain, url: url, event_types: %w[accepted delivered]))
|
|
82
|
+
.to eq('accepted' => { 'urls' => [url] })
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe '#update_v4' do
|
|
87
|
+
it 'puts the url and event types to the domain webhooks endpoint' do
|
|
88
|
+
expect(client).to receive(:put)
|
|
89
|
+
.with("domains/#{domain}/webhooks", { url: url, event_types: 'accepted' })
|
|
90
|
+
.and_return(response)
|
|
91
|
+
|
|
92
|
+
expect(webhooks.update_v4(domain, url: url, event_types: 'accepted'))
|
|
93
|
+
.to eq('accepted' => { 'urls' => [url] })
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe '#remove_v4' do
|
|
98
|
+
it 'sends the urls as query params' do
|
|
99
|
+
urls = [url, 'https://example.com/other']
|
|
100
|
+
expect(client).to receive(:delete)
|
|
101
|
+
.with("domains/#{domain}/webhooks", { url: urls })
|
|
102
|
+
.and_return(response)
|
|
103
|
+
|
|
104
|
+
webhooks.remove_v4(domain, url: urls)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context 'when the client api version is not v4' do
|
|
109
|
+
let(:api_version) { 'v3' }
|
|
110
|
+
|
|
111
|
+
it 'raises a ParameterError' do
|
|
112
|
+
expect { webhooks.create_v4(domain, url: url, event_types: 'accepted') }
|
|
113
|
+
.to raise_error(Mailgun::ParameterError, /must be v4/)
|
|
114
|
+
expect { webhooks.update_v4(domain, url: url, event_types: 'accepted') }
|
|
115
|
+
.to raise_error(Mailgun::ParameterError, /must be v4/)
|
|
116
|
+
expect { webhooks.remove_v4(domain, url: url) }
|
|
117
|
+
.to raise_error(Mailgun::ParameterError, /must be v4/)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|