forked from mailgun/mailgun-ruby
-
Notifications
You must be signed in to change notification settings - Fork 0
/
suppressions.rb
277 lines (230 loc) · 8.45 KB
/
suppressions.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
require 'uri'
require 'mailgun/exceptions/exceptions'
module Mailgun
# The Mailgun::Suppressions object makes it easy to manage "suppressions"
# attached to an account. "Suppressions" means bounces, unsubscribes, and complaints.
class Suppressions
# @param [Mailgun::Client] client API client to use for requests
# @param [String] domain Domain name to use for the suppression endpoints.
def initialize(client, domain)
@client = client
@domain = domain
@paging_next = nil
@paging_prev = nil
end
####
# Paging operations
####
def next
response = get_from_paging @paging_next[:path], @paging_next[:params]
extract_paging response
response
end
def prev
response = get_from_paging @paging_prev[:path], @paging_prev[:params]
extract_paging response
response
end
####
# Bounces Endpoint (/v3/:domain/bounces)
####
def list_bounces(params = {})
response = @client.get("#{@domain}/bounces", params)
extract_paging response
response
end
def get_bounce(address)
@client.get("#{@domain}/bounces/#{escape_address(address)}", nil)
end
def create_bounce(params = {})
@client.post("#{@domain}/bounces", params)
end
# Creates multiple bounces on the Mailgun API.
# If a bounce does not have a valid structure, it will be added to a list of unsendable bounces.
# The list of unsendable bounces will be returned at the end of this operation.
#
# If more than 999 bounce entries are provided, the list will be split and recursive calls will be made.
#
# @param [Array] data Array of bounce hashes
# @return [Response] Mailgun API response
# @return [Array] Return values from recursive call for list split.
def create_bounces(data)
# `data` should be a list of hashes, with each hash containing *at least* an `address` key.
split_return = []
if data.length >= 1000 then
resp, resp_l = create_bounces data[999..-1]
split_return.push(resp)
split_return.concat(resp_l)
data = data[0..998]
elsif data.length == 0 then
return nil, []
end
valid = []
# Validate the bounces given
# NOTE: `data` could potentially be very large (1000 elements) so it is
# more efficient to pop from data and push into a different array as
# opposed to possibly copying the entire array to another array.
while not data.empty? do
bounce = data.pop
# Bounces MUST contain a `address` key.
if not bounce.include? :address then
raise Mailgun::ParameterError.new "Bounce MUST include a :address key: #{bounce}"
end
bounce.each do |k, v|
# Hash values MUST be strings.
if not v.is_a? String then
bounce[k] = v.to_s
end
end
valid.push bounce
end
response = @client.post("#{@domain}/bounces", valid.to_json, { "Content-Type" => "application/json" })
return response, split_return
end
def delete_bounce(address)
@client.delete("#{@domain}/bounces/#{escape_address(address)}")
end
def delete_all_bounces
@client.delete("#{@domain}/bounces")
end
####
# Unsubscribes Endpoint (/v3/:domain/unsubscribes)
####
def list_unsubscribes(params = {})
response = @client.get("#{@domain}/unsubscribes", params)
extract_paging response
response
end
def get_unsubscribe(address)
@client.get("#{@domain}/unsubscribes/#{escape_address(address)}")
end
def create_unsubscribe(params = {})
@client.post("#{@domain}/unsubscribes", params)
end
# Creates multiple unsubscribes on the Mailgun API.
# If an unsubscribe does not have a valid structure, it will be added to a list of unsendable unsubscribes.
# The list of unsendable unsubscribes will be returned at the end of this operation.
#
# If more than 999 unsubscribe entries are provided, the list will be split and recursive calls will be made.
#
# @param [Array] data Array of unsubscribe hashes
# @return [Response] Mailgun API response
# @return [Array] Return values from recursive call for list split.
def create_unsubscribes(data)
# `data` should be a list of hashes, with each hash containing *at least* an `address` key.
split_return = []
if data.length >= 1000 then
resp, resp_l = create_unsubscribes data[999..-1]
split_return.push(resp)
split_return.concat(resp_l)
data = data[0..998]
elsif data.length == 0 then
return nil, []
end
valid = []
# Validate the unsubscribes given
while not data.empty? do
unsubscribe = data.pop
# unsubscribes MUST contain a `address` key.
if not unsubscribe.include? :address then
raise Mailgun::ParameterError.new "Unsubscribe MUST include a :address key: #{unsubscribe}"
end
unsubscribe.each do |k, v|
# Hash values MUST be strings.
# However, unsubscribes contain an array of tags
if v.is_a? Array
unsubscribe[k] = v.map(&:to_s)
elsif !v.is_a? String
unsubscribe[k] = v.to_s
end
end
valid.push unsubscribe
end
response = @client.post("#{@domain}/unsubscribes", valid.to_json, { "Content-Type" => "application/json" })
return response, split_return
end
def delete_unsubscribe(address, params = {})
@client.delete("#{@domain}/unsubscribes/#{escape_address(address)}")
end
####
# Complaints Endpoint (/v3/:domain/complaints)
####
def list_complaints(params = {})
response = @client.get("#{@domain}/complaints", params)
extract_paging response
response
end
def get_complaint(address)
@client.get("#{@domain}/complaints/#{escape_address(address)}", nil)
end
def create_complaint(params = {})
@client.post("#{@domain}/complaints", params)
end
# Creates multiple complaints on the Mailgun API.
# If a complaint does not have a valid structure, it will be added to a list of unsendable complaints.
# The list of unsendable complaints will be returned at the end of this operation.
#
# If more than 999 complaint entries are provided, the list will be split and recursive calls will be made.
#
# @param [Array] data Array of complaint hashes
# @return [Response] Mailgun API response
# @return [Array] Return values from recursive call for list split.
def create_complaints(data)
# `data` should be a list of hashes, with each hash containing *at least* an `address` key.
split_return = []
if data.length >= 1000 then
resp, resp_l = create_complaints data[999..-1]
split_return.push(resp)
split_return.concat(resp_l)
data = data[0..998]
elsif data.length == 0 then
return nil, []
end
valid = []
# Validate the complaints given
while not data.empty? do
complaint = data.pop
# complaints MUST contain a `address` key.
if not complaint.include? :address then
raise Mailgun::ParameterError.new "Complaint MUST include a :address key: #{complaint}"
end
complaint.each do |k, v|
# Hash values MUST be strings.
if not v.is_a? String then
complaint[k] = v.to_s
end
end
valid.push complaint
end
response = @client.post("#{@domain}/complaints", valid.to_json, { "Content-Type" => "application/json" })
return response, split_return
end
def delete_complaint(address)
@client.delete("#{@domain}/complaints/#{escape_address(address)}")
end
private
def escape_address(address)
CGI.escape address
end
def get_from_paging(uri, params = {})
@client.get(uri, params)
end
def extract_paging(response)
rhash = response.to_h
return nil unless rhash.include? "paging"
page_info = rhash["paging"]
# Build the `next` endpoint
page_next = URI.parse(page_info["next"])
@paging_next = {
:path => page_next.path[/\/v[\d](.+)/, 1],
:params => Hash[URI.decode_www_form page_next.query],
}
# Build the `prev` endpoint
page_prev = URI.parse(page_info["previous"])
@paging_prev = {
:path => page_prev.path[/\/v[\d](.+)/, 1],
:params => Hash[URI.decode_www_form page_prev.query],
}
end
end
end