mailgun-ruby 1.4.3 → 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.
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailgun
4
+ # A Mailgun::AccountWebhooks object is a simple CRUD interface to Account Mailgun Webhooks.
5
+ # Uses Mailgun
6
+ class AccountWebhooks
7
+ include ApiVersionChecker
8
+
9
+ # Public creates a new Mailgun::Webhooks 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 account-level webhooks
16
+ #
17
+ # webhook_ids - [String] Comma-separated list of webhook IDs to filter results. If specified,
18
+ # only webhooks with matching IDs will be returned.
19
+ #
20
+ # Retrieve all account-level webhooks or filter by specific webhook IDs.
21
+ # Returns webhook details including associated event types.
22
+ def list(webhook_ids = '')
23
+ res = @client.get('webhooks', webhook_ids: webhook_ids)
24
+ res.to_h['webhooks']
25
+ end
26
+
27
+ # Public: Create an account-level webhook
28
+ #
29
+ # description - [String] Description for the webhook
30
+ # event_types - [String] Event types to subscribe to. Use multiple times to specify multiple event types.
31
+ # Maximum of 3 unique URLs per event type.
32
+ # url - [String] URL for webhook to be sent to
33
+ #
34
+ # Returns the Unique identifier for the webhook
35
+ def create(description:, event_types:, url:)
36
+ res = @client.post('webhooks', { description: description, event_types: event_types, url: url })
37
+ res.to_h
38
+ end
39
+
40
+ # Public: Delete account-level webhooks
41
+ #
42
+ # webhook_ids - [String] Comma-separated list of webhook IDs to delete.
43
+ # If provided, only these specific webhooks will be deleted.
44
+ # all - [Boolean] The required String of the webhook action to delete
45
+ #
46
+ # Returns a Boolean of the success
47
+ def remove(webhook_ids = nil, all: false)
48
+ @client.delete('webhooks', { webhook_ids: webhook_ids, all: all }.compact).status == 204
49
+ end
50
+
51
+ # Public: Get account-level webhook by ID
52
+ #
53
+ # webhook_id - [String] The webhook ID to retrieve
54
+ #
55
+ # Returns webhook details including associated event types.
56
+ def get(webhook_id)
57
+ res = @client.get("webhooks/#{webhook_id}")
58
+ res.to_h
59
+ end
60
+
61
+ # Public: Update an account-level webhook
62
+ #
63
+ # description - [String] Description for the webhook
64
+ # event_types - [String] Event types to subscribe to. Use multiple times to specify multiple event types.
65
+ # Maximum of 3 unique URLs per event type.
66
+ # url - [String] URL for webhook to be sent to
67
+ #
68
+ # Returns a Boolean of the success
69
+ def update(webhook_id, description:, event_types:, url:)
70
+ @client.put("webhooks/#{webhook_id}",
71
+ { description: description, event_types: event_types, url: url }).status == 204
72
+ end
73
+
74
+ # Public: Delete account-level webhook by ID
75
+ #
76
+ # webhook_id - [String] The webhook ID to delete
77
+ #
78
+ # Returns a Boolean of the success
79
+ def remove_by_id(webhook_id)
80
+ @client.delete("webhooks/#{webhook_id}").status == 204
81
+ end
82
+
83
+ enforces_api_version 'v1', :list, :create, :remove, :get, :update, :remove_by_id
84
+ end
85
+ end
@@ -4,6 +4,8 @@ module Mailgun
4
4
  # A Mailgun::Webhooks object is a simple CRUD interface to Mailgun Webhooks.
5
5
  # Uses Mailgun
6
6
  class Webhooks
7
+ include ApiVersionChecker
8
+
7
9
  ACTIONS = %w[accepted clicked complained delivered opened permanent_fail temporary_fail unsubscribed].freeze
8
10
 
9
11
  # Public creates a new Mailgun::Webhooks instance.
@@ -22,7 +24,14 @@ module Mailgun
22
24
  res = @client.get("domains/#{domain}/webhooks", options)
23
25
  res.to_h['webhooks']
24
26
  end
25
- alias get_webhooks list
27
+
28
+ # :nocov:
29
+
30
+ def get_webhooks(domain, options = {})
31
+ warn('`get_webhooks` method will be deprecated in future versions of Mailgun. Please use `list` instead.')
32
+ list(domain, options)
33
+ end
34
+ # :nocov:
26
35
 
27
36
  # Public: Get webook information for a specific action
28
37
  #
@@ -31,27 +40,42 @@ module Mailgun
31
40
  #
32
41
  # Returns a String of the url for the identified webhook or an
33
42
  # empty String if one is not set
34
- def info(domain, action)
43
+ def get(domain, action)
35
44
  res = @client.get("domains/#{domain}/webhooks/#{action}")
36
45
  res.to_h['webhook']['urls'] || ''
37
- rescue NoMethodError
38
- ''
39
46
  end
40
- alias get_webhook_url info
47
+
48
+ # :nocov:
49
+ %i[info get_webhook_url].each do |method|
50
+ define_method(method) do |domain, action|
51
+ warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `get` instead.")
52
+ get(domain, action)
53
+ end
54
+ end
55
+ # :nocov:
41
56
 
42
57
  # Public: Add webhook
43
58
  #
44
59
  # domain - A String of the domain name (ex. domain.com)
45
60
  # action - A String of the action to create a webhook for
46
- # 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
47
62
  #
48
63
  # Returns a Boolean of whether the webhook was created
49
64
  def create(domain, action, url = '')
50
65
  res = @client.post("domains/#{domain}/webhooks", id: action, url: url)
51
- res.to_h['webhook']['urls'].include?(url) && res.to_h['message'] == 'Webhook has been created'
66
+ urls = res.to_h['webhook']['urls']
67
+ Array(url).all? { |u| urls.include?(u) } && res.to_h['message'] == 'Webhook has been created'
52
68
  end
53
- alias add create
54
- alias add_webhook create
69
+
70
+ # :nocov:
71
+ %i[add add_webhook].each do |method|
72
+ define_method(method) do |domain, action, url|
73
+ url ||= ''
74
+ warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `create` instead.")
75
+ create(domain, action, url)
76
+ end
77
+ end
78
+ # :nocov:
55
79
 
56
80
  # Public: Sets all webhooks to the same URL
57
81
  #
@@ -59,31 +83,40 @@ module Mailgun
59
83
  # url - A String of the url to set all webhooks to
60
84
  #
61
85
  # Returns true or false
62
- def create_all(domain, url = '')
63
- ACTIONS.each do |action|
64
- add_webhook domain, action, url
86
+ # :nocov:
87
+ %i[create_all add_all_webhooks].each do |method|
88
+ define_method(method) do |domain, url|
89
+ url ||= ''
90
+ warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `create` instead.")
91
+
92
+ ACTIONS.each do |action|
93
+ create domain, action, url
94
+ end
65
95
  end
66
- true
67
- rescue StandardError
68
- false
69
96
  end
70
- alias add_all_webhooks create_all
97
+ # :nocov:
71
98
 
72
99
  # Public: Update webhook
73
100
  #
74
101
  # domain - A String of the domain name (ex. domain.com)
75
- # action - A String of the action to create a webhook for
76
- # 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
77
104
  #
78
105
  # Returns a Boolean of whether the webhook was updated
79
106
  def update(domain, action, url = '')
80
- raise Mailgun::ParameterError('Domain not provided to update webhooks') unless domain
81
- raise Mailgun::ParameterError('Action not provided to identify webhook to update') unless action
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?
82
109
 
83
110
  res = @client.put("domains/#{domain}/webhooks/#{action}", id: action, url: url)
84
- res.to_h['webhook']['urls'] == url && res.to_h['message'] == 'Webhook has been updated'
111
+ res.to_h['message'] == 'Webhook has been updated'
112
+ end
113
+
114
+ # :nocov:
115
+ def update_webhook(domain, action, url = '')
116
+ warn('`update_webhook` method will be deprecated in future versions of Mailgun. Please use `update` instead.')
117
+ update(domain, action, url)
85
118
  end
86
- alias update_webhook update
119
+ # :nocov:
87
120
 
88
121
  # Public: Delete a specific webhook
89
122
  #
@@ -92,29 +125,77 @@ module Mailgun
92
125
  #
93
126
  # Returns a Boolean of the success
94
127
  def remove(domain, action)
95
- raise Mailgun::ParameterError('Domain not provided to remove webhook from') unless domain
96
- raise Mailgun::ParameterError('Action not provided to identify webhook to remove') unless action
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?
97
130
 
98
131
  @client.delete("domains/#{domain}/webhooks/#{action}").to_h['message'] == 'Webhook has been deleted'
99
- rescue Mailgun::CommunicationError
100
- false
101
132
  end
102
- alias delete remove
103
- alias delete_webhook remove
133
+
134
+ # :nocov:
135
+ %i[delete delete_webhook].each do |method|
136
+ define_method(method) do |domain, action|
137
+ warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `remove` instead.")
138
+ remove(domain, action)
139
+ end
140
+ end
141
+ # :nocov:
104
142
 
105
143
  # Public: Delete all webhooks for a domain
106
144
  #
107
145
  # domain - A required String of the domain to remove all webhooks for
108
146
  #
109
147
  # Returns a Boolean on the success
110
- def remove_all(domain)
111
- raise Mailgun::ParameterError('Domain not provided to remove webhooks from') unless domain
148
+ # :nocov:
149
+ %i[remove_all delete_all delete_all_webooks].each do |method|
150
+ define_method(method) do |domain|
151
+ warn("`#{method}` method will be deprecated in future versions of Mailgun. Please use `remove` instead.")
112
152
 
113
- ACTIONS.each do |action|
114
- delete_webhook domain, action
153
+ raise Mailgun::ParameterError, 'Domain not provided to remove webhooks from' if domain.to_s.empty?
154
+
155
+ ACTIONS.each do |action|
156
+ remove domain, action
157
+ end
115
158
  end
116
159
  end
117
- alias delete_all remove_all
118
- alias delete_all_webooks remove_all
160
+ # :nocov:
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
+
198
+ enforces_api_version 'v3', :list, :get, :create, :update, :remove
199
+ enforces_api_version 'v4', :create_v4, :update_v4, :remove_v4
119
200
  end
120
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,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'mailgun'
5
+
6
+ vcr_opts = { cassette_name: 'account_webhooks' }
7
+
8
+ describe 'For the webhooks endpoint', 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::AccountWebhooks.new(mg_client) }
12
+
13
+ it 'creates a webhook' do
14
+ result = mg_obj.create(
15
+ description: 'test',
16
+ event_types: 'accepted',
17
+ url: 'http://example.com/mailgun/events'
18
+ )
19
+
20
+ expect(result).to have_key('webhook_id')
21
+ end
22
+
23
+ it 'gets a webhook' do
24
+ result = mg_obj.get('test')
25
+
26
+ expect(result['url']).to eq('http://example.com/mailgun/events')
27
+ end
28
+
29
+ it 'gets a list of all account webhooks' do
30
+ result = mg_obj.list
31
+
32
+ expect(result[0]['url']).to eq('http://example.com/mailgun/events')
33
+ end
34
+
35
+ it 'updates a webhook' do
36
+ result = mg_obj.update(
37
+ 'test',
38
+ description: 'test2',
39
+ event_types: 'accepted',
40
+ url: 'http://example.com/mailgun/events'
41
+ )
42
+
43
+ expect(result).to be_truthy
44
+ end
45
+
46
+ it 'removes a webhook' do
47
+ result = mg_obj.remove_by_id('test')
48
+
49
+ expect(result).to be_truthy
50
+ end
51
+
52
+ it 'removes all webhooks' do
53
+ result = mg_obj.remove(all: true)
54
+
55
+ expect(result).to be_truthy
56
+ end
57
+ end
@@ -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
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'mailgun'
5
+
6
+ vcr_opts = { cassette_name: 'domains' }
7
+
8
+ describe 'DomainKeys', vcr: vcr_opts do
9
+ let(:api_version) { APIVERSION }
10
+ let(:mg_client) { Mailgun::Client.new(APIKEY, APIHOST, api_version, SSL) }
11
+ let(:mg_obj) { Mailgun::DomainKeys.new(mg_client) }
12
+ let(:domain) { 'integration-test.domain.invalid' }
13
+
14
+ describe '#list_domain_keys' do
15
+ let(:api_version) { 'v1' }
16
+
17
+ it 'lists all domain keys' do
18
+ result = mg_obj.list_domain_keys(
19
+ {
20
+ signing_domain: domain
21
+ }
22
+ )
23
+
24
+ expect(result).to include('items')
25
+ expect(result['items'].first['selector']).to eq('k1')
26
+ end
27
+ end
28
+
29
+ describe '#create_domain_key' do
30
+ let(:api_version) { 'v1' }
31
+
32
+ it 'creates a domain key' do
33
+ result = mg_obj.create_domain_key(
34
+ {
35
+ signing_domain: domain,
36
+ selector: 'test'
37
+ }
38
+ )
39
+
40
+ expect(result['signing_domain']).to eq(domain)
41
+ expect(result['selector']).to eq('test')
42
+ end
43
+ end
44
+
45
+ describe '#delete_domain_key' do
46
+ let(:api_version) { 'v1' }
47
+
48
+ it 'deletes a domain key' do
49
+ result = mg_obj.delete_domain_key(
50
+ {
51
+ signing_domain: domain,
52
+ selector: 'test'
53
+ }
54
+ )
55
+
56
+ expect(result['message']).to eq('success')
57
+ end
58
+ end
59
+
60
+ describe '#activate_domain_key' do
61
+ let(:api_version) { 'v4' }
62
+
63
+ it 'activates a domain key' do
64
+ result = mg_obj.activate_domain_key(
65
+ domain,
66
+ 'mailo1'
67
+ )
68
+
69
+ expect(result['message']).to eq('domain key activated')
70
+ end
71
+ end
72
+
73
+ describe '#get_domain_keys' do
74
+ let(:api_version) { 'v4' }
75
+
76
+ it 'lists the domain keys for a specified signing domain' do
77
+ result = mg_obj.get_domain_keys(
78
+ domain
79
+ )
80
+
81
+ expect(result).to include('items')
82
+ expect(result['items'].first['selector']).to eq('mailo1')
83
+ end
84
+ end
85
+
86
+ describe '#deactivate_domain_key' do
87
+ let(:api_version) { 'v4' }
88
+
89
+ it 'deactivates a domain key' do
90
+ result = mg_obj.deactivate_domain_key(
91
+ domain,
92
+ 'tetetet'
93
+ )
94
+
95
+ expect(result['message']).to eq('domain key deactivated')
96
+ end
97
+ end
98
+
99
+ describe '#update_domain_dkim_authority' do
100
+ it 'updates the DKIM authority for a domain' do
101
+ result = mg_obj.update_domain_dkim_authority(
102
+ domain,
103
+ {
104
+ self: true
105
+ }
106
+ )
107
+
108
+ expect(result['message']).to eq('Domain DKIM authority has not been changed')
109
+ end
110
+ end
111
+
112
+ describe '#update_domain_dkim_selector' do
113
+ it 'updates the DKIM selector for a domain' do
114
+ result = mg_obj.update_domain_dkim_selector(
115
+ domain,
116
+ {
117
+ dkim_selector: 'mailo1'
118
+ }
119
+ )
120
+
121
+ expect(result['message']).to eq('DKIM selector changed')
122
+ end
123
+ end
124
+ end
@@ -73,119 +73,6 @@ describe 'For the domains endpoint', vcr: vcr_opts do
73
73
  end
74
74
  end
75
75
 
76
- context 'Domain::Keys methods' do
77
- describe '#list_domain_keys' do
78
- let(:api_version) { 'v1' }
79
-
80
- it 'lists all domain keys' do
81
- result = mg_obj.list_domain_keys(
82
- {
83
- signing_domain: domain
84
- }
85
- )
86
-
87
- expect(result).to include('items')
88
- expect(result['items'].first['selector']).to eq('k1')
89
- end
90
- end
91
-
92
- describe '#create_domain_key' do
93
- let(:api_version) { 'v1' }
94
-
95
- it 'creates a domain key' do
96
- result = mg_obj.create_domain_key(
97
- {
98
- signing_domain: domain,
99
- selector: 'test'
100
- }
101
- )
102
-
103
- expect(result['signing_domain']).to eq(domain)
104
- expect(result['selector']).to eq('test')
105
- end
106
- end
107
-
108
- describe '#delete_domain_key' do
109
- let(:api_version) { 'v1' }
110
-
111
- it 'deletes a domain key' do
112
- result = mg_obj.delete_domain_key(
113
- {
114
- signing_domain: domain,
115
- selector: 'test'
116
- }
117
- )
118
-
119
- expect(result['message']).to eq('success')
120
- end
121
- end
122
-
123
- describe '#activate_domain_key' do
124
- let(:api_version) { 'v4' }
125
-
126
- it 'activates a domain key' do
127
- result = mg_obj.activate_domain_key(
128
- domain,
129
- 'mailo1'
130
- )
131
-
132
- expect(result['message']).to eq('domain key activated')
133
- end
134
- end
135
-
136
- describe '#get_domain_keys' do
137
- let(:api_version) { 'v4' }
138
-
139
- it 'lists the domain keys for a specified signing domain' do
140
- result = mg_obj.get_domain_keys(
141
- domain
142
- )
143
-
144
- expect(result).to include('items')
145
- expect(result['items'].first['selector']).to eq('mailo1')
146
- end
147
- end
148
-
149
- describe '#deactivate_domain_key' do
150
- let(:api_version) { 'v4' }
151
-
152
- it 'deactivates a domain key' do
153
- result = mg_obj.deactivate_domain_key(
154
- domain,
155
- 'tetetet'
156
- )
157
-
158
- expect(result['message']).to eq('domain key deactivated')
159
- end
160
- end
161
-
162
- describe '#update_domain_dkim_authority' do
163
- it 'updates the DKIM authority for a domain' do
164
- result = mg_obj.update_domain_dkim_authority(
165
- domain,
166
- {
167
- self: true
168
- }
169
- )
170
-
171
- expect(result['message']).to eq('Domain DKIM authority has not been changed')
172
- end
173
- end
174
-
175
- describe '#update_domain_dkim_selector' do
176
- it 'updates the DKIM selector for a domain' do
177
- result = mg_obj.update_domain_dkim_selector(
178
- domain,
179
- {
180
- dkim_selector: 'mailo1'
181
- }
182
- )
183
-
184
- expect(result['message']).to eq('DKIM selector changed')
185
- end
186
- end
187
- end
188
-
189
76
  context 'Domain::Tracking methods' do
190
77
  # TODO: add missing:
191
78
  # get_domain_tracking_certificate