mailgun-ruby 1.4.1 → 1.4.2
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/Gemfile +3 -1
- data/README.md +1 -1
- data/Rakefile +5 -3
- data/docs/AnalyticsTags.md +63 -0
- data/lib/mailgun/address.rb +5 -5
- data/lib/mailgun/chains.rb +2 -3
- data/lib/mailgun/client.rb +47 -51
- data/lib/mailgun/domains/domains.rb +7 -8
- data/lib/mailgun/events/events.rb +4 -3
- data/lib/mailgun/exceptions/exceptions.rb +12 -15
- data/lib/mailgun/helpers/api_version_checker.rb +6 -1
- data/lib/mailgun/lists/opt_in_handler.rb +4 -6
- data/lib/mailgun/logs/logs.rb +4 -2
- data/lib/mailgun/messages/batch_message.rb +8 -9
- data/lib/mailgun/messages/message_builder.rb +36 -24
- data/lib/mailgun/metrics/metrics.rb +6 -4
- data/lib/mailgun/response.rb +11 -9
- data/lib/mailgun/subaccounts/subaccounts.rb +13 -8
- data/lib/mailgun/suppressions.rb +36 -43
- data/lib/mailgun/tags/analytics_tags.rb +33 -2
- data/lib/mailgun/tags/tags.rb +25 -17
- data/lib/mailgun/templates/templates.rb +40 -29
- data/lib/mailgun/version.rb +3 -1
- data/lib/mailgun/webhooks/webhooks.rb +22 -19
- data/lib/mailgun-ruby.rb +2 -0
- data/lib/mailgun.rb +4 -4
- data/lib/railgun/attachment.rb +9 -14
- data/lib/railgun/errors.rb +2 -3
- data/lib/railgun/mailer.rb +35 -39
- data/lib/railgun/railtie.rb +2 -0
- data/lib/railgun.rb +2 -0
- data/mailgun.gemspec +12 -11
- data/spec/integration/analytics_tags_spec.rb +54 -0
- data/spec/integration/bounces_spec.rb +12 -11
- data/spec/integration/campaign_spec.rb +20 -18
- data/spec/integration/complaints_spec.rb +8 -6
- data/spec/integration/domains_spec.rb +6 -6
- data/spec/integration/email_validation_spec.rb +35 -34
- data/spec/integration/events_spec.rb +7 -5
- data/spec/integration/list_members_spec.rb +27 -26
- data/spec/integration/list_spec.rb +22 -21
- data/spec/integration/logs_spec.rb +48 -46
- data/spec/integration/mailer_spec.rb +7 -3
- data/spec/integration/mailgun_spec.rb +82 -90
- data/spec/integration/metrics_spec.rb +130 -130
- data/spec/integration/routes_spec.rb +41 -40
- data/spec/integration/stats_spec.rb +4 -2
- data/spec/integration/subaccounts_spec.rb +9 -10
- data/spec/integration/suppressions_spec.rb +21 -20
- data/spec/integration/templates_spec.rb +14 -12
- data/spec/integration/unsubscribes_spec.rb +8 -6
- data/spec/integration/webhook_spec.rb +13 -12
- data/spec/spec_helper.rb +8 -8
- data/spec/unit/connection/test_client.rb +61 -55
- data/spec/unit/events/events_spec.rb +25 -22
- data/spec/unit/exceptions/exceptions_spec.rb +8 -7
- data/spec/unit/lists/opt_in_handler_spec.rb +8 -6
- data/spec/unit/mailgun_spec.rb +64 -63
- data/spec/unit/messages/batch_message_spec.rb +15 -15
- data/spec/unit/messages/message_builder_spec.rb +98 -94
- data/spec/unit/railgun/content_type_spec.rb +24 -23
- data/spec/unit/railgun/mailer_spec.rb +58 -58
- data/vcr_cassettes/analytics_tags.yml +187 -0
- metadata +49 -33
- data/.rubocop.yml +0 -8
- data/.rubocop_todo.yml +0 -22
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Mailgun
|
|
3
4
|
# A Mailgun::MessageBuilder object is used to create a valid payload
|
|
4
5
|
# for the Mailgun API messages endpoint. If you prefer step by step message
|
|
5
6
|
# generation through your code, this class is for you.
|
|
6
7
|
#
|
|
7
8
|
# See the Github documentation for full examples.
|
|
8
9
|
class MessageBuilder
|
|
9
|
-
|
|
10
10
|
attr_reader :message, :counters
|
|
11
11
|
|
|
12
12
|
# Public: Creates a new MessageBuilder object.
|
|
@@ -28,13 +28,13 @@ module Mailgun
|
|
|
28
28
|
# @param [Hash] variables A hash of the variables associated with the recipient. We recommend "first" and "last" at a minimum!
|
|
29
29
|
# @return [void]
|
|
30
30
|
def add_recipient(recipient_type, address, variables = nil)
|
|
31
|
-
if recipient_type ==
|
|
31
|
+
if recipient_type == 'h:reply-to'
|
|
32
32
|
warn 'DEPRECATION: "add_recipient("h:reply-to", ...)" is deprecated. Please use "reply_to" instead.'
|
|
33
33
|
return reply_to(address, variables)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
if (@counters[:recipients][recipient_type] || 0) >= Mailgun::Chains::MAX_RECIPIENTS
|
|
37
|
-
|
|
37
|
+
raise Mailgun::ParameterError, 'Too many recipients added to message.', address
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
compiled_address = parse_address(address, variables)
|
|
@@ -68,7 +68,7 @@ module Mailgun
|
|
|
68
68
|
# @return [void]
|
|
69
69
|
def reply_to(address, variables = nil)
|
|
70
70
|
compiled_address = parse_address(address, variables)
|
|
71
|
-
header(
|
|
71
|
+
header('reply-to', compiled_address)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
# Set a subject for the message object
|
|
@@ -180,7 +180,10 @@ module Mailgun
|
|
|
180
180
|
# @param [String] campaign_id A defined campaign ID to add to the message.
|
|
181
181
|
# @return [void]
|
|
182
182
|
def add_campaign_id(campaign_id)
|
|
183
|
-
|
|
183
|
+
if @counters[:attributes][:campaign_id] >= Mailgun::Chains::MAX_CAMPAIGN_IDS
|
|
184
|
+
raise(Mailgun::ParameterError, 'Too many campaigns added to message.',
|
|
185
|
+
campaign_id)
|
|
186
|
+
end
|
|
184
187
|
|
|
185
188
|
set_multi_complex('o:campaign', campaign_id)
|
|
186
189
|
@counters[:attributes][:campaign_id] += 1
|
|
@@ -192,8 +195,9 @@ module Mailgun
|
|
|
192
195
|
# @return [void]
|
|
193
196
|
def add_tag(tag)
|
|
194
197
|
if @counters[:attributes][:tag] >= Mailgun::Chains::MAX_TAGS
|
|
195
|
-
|
|
198
|
+
raise Mailgun::ParameterError, 'Too many tags added to message.', tag
|
|
196
199
|
end
|
|
200
|
+
|
|
197
201
|
set_multi_complex('o:tag', tag)
|
|
198
202
|
@counters[:attributes][:tag] += 1
|
|
199
203
|
end
|
|
@@ -255,7 +259,8 @@ module Mailgun
|
|
|
255
259
|
# @param [Hash] data Either a hash or JSON string.
|
|
256
260
|
# @return [void]
|
|
257
261
|
def header(name, data)
|
|
258
|
-
|
|
262
|
+
raise(Mailgun::ParameterError, 'Header name for message must be specified') if name.to_s.empty?
|
|
263
|
+
|
|
259
264
|
begin
|
|
260
265
|
jsondata = make_json data
|
|
261
266
|
set_single("h:#{name}", jsondata)
|
|
@@ -278,7 +283,8 @@ module Mailgun
|
|
|
278
283
|
# can not be converted to JSON, ParameterError will be raised.
|
|
279
284
|
# @return [void]
|
|
280
285
|
def variable(name, data)
|
|
281
|
-
|
|
286
|
+
raise(Mailgun::ParameterError, 'Variable name must be specified') if name.to_s.empty?
|
|
287
|
+
|
|
282
288
|
begin
|
|
283
289
|
jsondata = make_json data
|
|
284
290
|
set_single("v:#{name}", jsondata)
|
|
@@ -308,6 +314,7 @@ module Mailgun
|
|
|
308
314
|
def message_id(data = nil)
|
|
309
315
|
key = 'h:Message-Id'
|
|
310
316
|
return @message.delete(key) if data.to_s.empty?
|
|
317
|
+
|
|
311
318
|
set_single(key, data)
|
|
312
319
|
end
|
|
313
320
|
|
|
@@ -326,6 +333,7 @@ module Mailgun
|
|
|
326
333
|
def template(template_name = nil)
|
|
327
334
|
key = 'template'
|
|
328
335
|
return @message.delete(key) if template_name.to_s.empty?
|
|
336
|
+
|
|
329
337
|
set_single(key, template_name)
|
|
330
338
|
end
|
|
331
339
|
|
|
@@ -337,6 +345,7 @@ module Mailgun
|
|
|
337
345
|
def template_version(version = nil)
|
|
338
346
|
key = 't:version'
|
|
339
347
|
return @message.delete(key) if version.to_s.empty?
|
|
348
|
+
|
|
340
349
|
set_single(key, version)
|
|
341
350
|
end
|
|
342
351
|
|
|
@@ -358,7 +367,7 @@ module Mailgun
|
|
|
358
367
|
# @param [String] value The value of the parameter.
|
|
359
368
|
# @return [void]
|
|
360
369
|
def set_single(parameter, value)
|
|
361
|
-
@message[parameter] = value
|
|
370
|
+
@message[parameter] = value || ''
|
|
362
371
|
end
|
|
363
372
|
|
|
364
373
|
# Sets values within the multidict, however, prevents
|
|
@@ -397,8 +406,9 @@ module Mailgun
|
|
|
397
406
|
# @param [String] value The item to convert
|
|
398
407
|
# @return [void]
|
|
399
408
|
def bool_lookup(value)
|
|
400
|
-
return 'yes' if %w
|
|
401
|
-
return 'no' if %w
|
|
409
|
+
return 'yes' if %w[true yes yep].include? value.to_s.downcase
|
|
410
|
+
return 'no' if %w[false no nope].include? value.to_s.downcase
|
|
411
|
+
|
|
402
412
|
warn 'WARN: for bool type actions next values are preferred: true yes yep | false no nope | htmlonly'
|
|
403
413
|
value
|
|
404
414
|
end
|
|
@@ -409,7 +419,7 @@ module Mailgun
|
|
|
409
419
|
# @return [void]
|
|
410
420
|
def valid_json?(json_)
|
|
411
421
|
JSON.parse(json_)
|
|
412
|
-
|
|
422
|
+
true
|
|
413
423
|
rescue JSON::ParserError
|
|
414
424
|
false
|
|
415
425
|
end
|
|
@@ -422,8 +432,9 @@ module Mailgun
|
|
|
422
432
|
def make_json(obj)
|
|
423
433
|
return JSON.parse(obj).to_json if obj.is_a?(String)
|
|
424
434
|
return obj.to_json if obj.is_a?(Hash)
|
|
435
|
+
|
|
425
436
|
JSON.generate(obj).to_json
|
|
426
|
-
rescue
|
|
437
|
+
rescue StandardError
|
|
427
438
|
raise Mailgun::ParameterError, 'Provided data could not be made into JSON. Try a JSON string or Hash.', obj
|
|
428
439
|
end
|
|
429
440
|
|
|
@@ -436,9 +447,9 @@ module Mailgun
|
|
|
436
447
|
# @return [void]
|
|
437
448
|
def parse_address(address, vars)
|
|
438
449
|
return address unless vars.is_a? Hash
|
|
439
|
-
|
|
440
|
-
if vars['full_name']
|
|
441
|
-
|
|
450
|
+
raise(Mailgun::ParameterError, 'Email address not specified') unless address.is_a? String
|
|
451
|
+
if !vars['full_name'].nil? && (!vars['first'].nil? || !vars['last'].nil?)
|
|
452
|
+
raise(Mailgun::ParameterError, "Must specify at most one of full_name or first/last. Vars passed: #{vars}")
|
|
442
453
|
end
|
|
443
454
|
|
|
444
455
|
if vars['full_name']
|
|
@@ -448,6 +459,7 @@ module Mailgun
|
|
|
448
459
|
end
|
|
449
460
|
|
|
450
461
|
return "'#{full_name}' <#{address}>" if full_name
|
|
462
|
+
|
|
451
463
|
address
|
|
452
464
|
end
|
|
453
465
|
|
|
@@ -461,24 +473,24 @@ module Mailgun
|
|
|
461
473
|
# Returns nothing
|
|
462
474
|
def add_file(disposition, filedata, filename)
|
|
463
475
|
attachment = File.open(filedata, 'r') if filedata.is_a?(String)
|
|
464
|
-
attachment
|
|
476
|
+
attachment ||= filedata.dup
|
|
465
477
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
478
|
+
unless attachment.respond_to?(:read)
|
|
479
|
+
raise(Mailgun::ParameterError,
|
|
480
|
+
'Unable to access attachment file object.')
|
|
481
|
+
end
|
|
469
482
|
|
|
470
483
|
if attachment.respond_to?(:path) && !attachment.respond_to?(:content_type)
|
|
471
484
|
mime_types = MiniMime.lookup_by_filename(attachment.path)
|
|
472
485
|
content_type = mime_types.nil? ? 'application/octet-stream' : mime_types.content_type
|
|
473
|
-
attachment.instance_eval "def content_type; '#{content_type}'; end"
|
|
486
|
+
attachment.instance_eval "def content_type; '#{content_type}'; end", __FILE__, __LINE__
|
|
474
487
|
end
|
|
475
488
|
|
|
476
489
|
unless filename.nil?
|
|
477
490
|
attachment.instance_variable_set :@original_filename, filename
|
|
478
|
-
attachment.instance_eval 'def original_filename; @original_filename; end'
|
|
491
|
+
attachment.instance_eval 'def original_filename; @original_filename; end', __FILE__, __LINE__
|
|
479
492
|
end
|
|
480
493
|
add_faraday_attachment(disposition, attachment, filename)
|
|
481
494
|
end
|
|
482
495
|
end
|
|
483
|
-
|
|
484
496
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mailgun
|
|
2
4
|
# A Mailgun::Metrics object is a simple interface to Mailgun Metrics.
|
|
3
5
|
# Uses Mailgun
|
|
@@ -28,8 +30,8 @@ module Mailgun
|
|
|
28
30
|
# include_aggregates - [Boolean] Include top-level aggregate metrics.
|
|
29
31
|
#
|
|
30
32
|
# Returns [Hash] Metrics
|
|
31
|
-
def account_metrics(options={})
|
|
32
|
-
@client.post('analytics/metrics', options.to_json, {
|
|
33
|
+
def account_metrics(options = {})
|
|
34
|
+
@client.post('analytics/metrics', options.to_json, { 'Content-Type' => 'application/json' }).to_h!
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
# Public: Post query to get account usage metrics
|
|
@@ -52,8 +54,8 @@ module Mailgun
|
|
|
52
54
|
# include_aggregates - [Boolean] Include top-level aggregate metrics.
|
|
53
55
|
#
|
|
54
56
|
# Returns [Hash] Metrics
|
|
55
|
-
def account_usage_metrics(options={})
|
|
56
|
-
@client.post('analytics/usage/metrics', options.to_json, {
|
|
57
|
+
def account_usage_metrics(options = {})
|
|
58
|
+
@client.post('analytics/usage/metrics', options.to_json, { 'Content-Type' => 'application/json' }).to_h!
|
|
57
59
|
end
|
|
58
60
|
end
|
|
59
61
|
end
|
data/lib/mailgun/response.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mailgun
|
|
2
4
|
# A Mailgun::Response object is instantiated for each response generated
|
|
3
5
|
# by the Client request. The Response object supports deserialization of
|
|
@@ -13,7 +15,7 @@ module Mailgun
|
|
|
13
15
|
ResponseHash = Struct.new(:body, :status)
|
|
14
16
|
def self.from_hash(h)
|
|
15
17
|
# Create a "fake" response object with the data passed from h
|
|
16
|
-
|
|
18
|
+
new ResponseHash.new(h[:body], h[:status])
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def initialize(response)
|
|
@@ -28,8 +30,8 @@ module Mailgun
|
|
|
28
30
|
|
|
29
31
|
def to_h
|
|
30
32
|
JSON.parse(@body)
|
|
31
|
-
rescue =>
|
|
32
|
-
raise ParseError.new(
|
|
33
|
+
rescue StandardError => e
|
|
34
|
+
raise ParseError.new(e), e
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
# Replace @body with Ruby Hash
|
|
@@ -37,8 +39,8 @@ module Mailgun
|
|
|
37
39
|
# @return [Hash] A standard Ruby Hash containing the HTTP result.
|
|
38
40
|
def to_h!
|
|
39
41
|
@body = JSON.parse(@body)
|
|
40
|
-
rescue =>
|
|
41
|
-
raise ParseError.new(
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
raise ParseError.new(e), e
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
# Return response as Yaml
|
|
@@ -46,8 +48,8 @@ module Mailgun
|
|
|
46
48
|
# @return [String] A string containing response as YAML
|
|
47
49
|
def to_yaml
|
|
48
50
|
YAML.dump(to_h)
|
|
49
|
-
rescue =>
|
|
50
|
-
raise ParseError.new(
|
|
51
|
+
rescue StandardError => e
|
|
52
|
+
raise ParseError.new(e), e
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
# Replace @body with YAML
|
|
@@ -55,8 +57,8 @@ module Mailgun
|
|
|
55
57
|
# @return [String] A string containing response as YAML
|
|
56
58
|
def to_yaml!
|
|
57
59
|
@body = YAML.dump(to_h)
|
|
58
|
-
rescue =>
|
|
59
|
-
raise ParseError.new(
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
raise ParseError.new(e), e
|
|
60
62
|
end
|
|
61
63
|
|
|
62
64
|
# Returns true if response status is 2xx
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Mailgun
|
|
3
4
|
# A Mailgun::Subaccounts object is a simple CRUD interface to Mailgun Subaccounts.
|
|
4
5
|
# Uses Mailgun
|
|
5
6
|
class Subaccounts
|
|
@@ -22,9 +23,9 @@ module Mailgun
|
|
|
22
23
|
#
|
|
23
24
|
# Returns [Array] A list of subaccounts (hash)
|
|
24
25
|
def list(options = {})
|
|
25
|
-
client.get(
|
|
26
|
+
client.get('accounts/subaccounts', options).to_h!
|
|
26
27
|
end
|
|
27
|
-
|
|
28
|
+
alias get_subaccounts list
|
|
28
29
|
|
|
29
30
|
# Public: Get subaccount information
|
|
30
31
|
#
|
|
@@ -35,7 +36,8 @@ module Mailgun
|
|
|
35
36
|
#
|
|
36
37
|
# Returns [Hash] Information on the requested subaccount.
|
|
37
38
|
def info(subaccount_id, options = {})
|
|
38
|
-
|
|
39
|
+
raise(ParameterError, 'No Id of subaccount specified', caller) unless subaccount_id
|
|
40
|
+
|
|
39
41
|
client.get("accounts/subaccounts/#{subaccount_id}", options).to_h!
|
|
40
42
|
end
|
|
41
43
|
|
|
@@ -49,8 +51,9 @@ module Mailgun
|
|
|
49
51
|
#
|
|
50
52
|
# Returns [Hash] of created subaccount
|
|
51
53
|
def create(name, options = {})
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
raise(ParameterError, 'No name given to create subaccount', caller) unless name
|
|
55
|
+
|
|
56
|
+
client.post('accounts/subaccounts', options.merge!(name: name)).to_h!
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
# Public: Disable a subaccount
|
|
@@ -62,7 +65,8 @@ module Mailgun
|
|
|
62
65
|
#
|
|
63
66
|
# Returns [Hash] Information on the requested subaccount.
|
|
64
67
|
def disable(subaccount_id, options = {})
|
|
65
|
-
|
|
68
|
+
raise(ParameterError, 'No Id of subaccount specified', caller) unless subaccount_id
|
|
69
|
+
|
|
66
70
|
client.post("accounts/subaccounts/#{subaccount_id}/disable", options).to_h!
|
|
67
71
|
end
|
|
68
72
|
|
|
@@ -75,7 +79,8 @@ module Mailgun
|
|
|
75
79
|
#
|
|
76
80
|
# Returns [Hash] Information on the requested subaccount.
|
|
77
81
|
def enable(subaccount_id, options = {})
|
|
78
|
-
|
|
82
|
+
raise(ParameterError, 'No Id of subaccount specified', caller) unless subaccount_id
|
|
83
|
+
|
|
79
84
|
client.post("accounts/subaccounts/#{subaccount_id}/enable", options).to_h!
|
|
80
85
|
end
|
|
81
86
|
end
|
data/lib/mailgun/suppressions.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Mailgun
|
|
3
4
|
# The Mailgun::Suppressions object makes it easy to manage "suppressions"
|
|
4
5
|
# attached to an account. "Suppressions" means bounces, unsubscribes, and complaints.
|
|
5
6
|
class Suppressions
|
|
6
|
-
|
|
7
7
|
# @param [Mailgun::Client] client API client to use for requests
|
|
8
8
|
# @param [String] domain Domain name to use for the suppression endpoints.
|
|
9
9
|
def initialize(client, domain)
|
|
@@ -60,12 +60,12 @@ module Mailgun
|
|
|
60
60
|
def create_bounces(data)
|
|
61
61
|
# `data` should be a list of hashes, with each hash containing *at least* an `address` key.
|
|
62
62
|
split_return = []
|
|
63
|
-
if data.length >= 1000
|
|
64
|
-
resp, resp_l = create_bounces data[999
|
|
63
|
+
if data.length >= 1000
|
|
64
|
+
resp, resp_l = create_bounces data[999..]
|
|
65
65
|
split_return.push(resp)
|
|
66
66
|
split_return.concat(resp_l)
|
|
67
67
|
data = data[0..998]
|
|
68
|
-
elsif data.
|
|
68
|
+
elsif data.empty?
|
|
69
69
|
return nil, []
|
|
70
70
|
end
|
|
71
71
|
|
|
@@ -74,25 +74,21 @@ module Mailgun
|
|
|
74
74
|
# NOTE: `data` could potentially be very large (1000 elements) so it is
|
|
75
75
|
# more efficient to pop from data and push into a different array as
|
|
76
76
|
# opposed to possibly copying the entire array to another array.
|
|
77
|
-
|
|
77
|
+
until data.empty?
|
|
78
78
|
bounce = data.pop
|
|
79
79
|
# Bounces MUST contain a `address` key.
|
|
80
|
-
|
|
81
|
-
raise Mailgun::ParameterError.new "Bounce MUST include a :address key: #{bounce}"
|
|
82
|
-
end
|
|
80
|
+
raise Mailgun::ParameterError, "Bounce MUST include a :address key: #{bounce}" unless bounce.include? :address
|
|
83
81
|
|
|
84
82
|
bounce.each do |k, v|
|
|
85
83
|
# Hash values MUST be strings.
|
|
86
|
-
|
|
87
|
-
bounce[k] = v.to_s
|
|
88
|
-
end
|
|
84
|
+
bounce[k] = v.to_s unless v.is_a? String
|
|
89
85
|
end
|
|
90
86
|
|
|
91
87
|
valid.push bounce
|
|
92
88
|
end
|
|
93
89
|
|
|
94
|
-
response = @client.post("#{@domain}/bounces", valid.to_json, {
|
|
95
|
-
|
|
90
|
+
response = @client.post("#{@domain}/bounces", valid.to_json, { 'Content-Type' => 'application/json' })
|
|
91
|
+
[response, split_return]
|
|
96
92
|
end
|
|
97
93
|
|
|
98
94
|
def delete_bounce(address)
|
|
@@ -133,22 +129,22 @@ module Mailgun
|
|
|
133
129
|
def create_unsubscribes(data)
|
|
134
130
|
# `data` should be a list of hashes, with each hash containing *at least* an `address` key.
|
|
135
131
|
split_return = []
|
|
136
|
-
if data.length >= 1000
|
|
137
|
-
resp, resp_l = create_unsubscribes data[999
|
|
132
|
+
if data.length >= 1000
|
|
133
|
+
resp, resp_l = create_unsubscribes data[999..]
|
|
138
134
|
split_return.push(resp)
|
|
139
135
|
split_return.concat(resp_l)
|
|
140
136
|
data = data[0..998]
|
|
141
|
-
elsif data.
|
|
137
|
+
elsif data.empty?
|
|
142
138
|
return nil, []
|
|
143
139
|
end
|
|
144
140
|
|
|
145
141
|
valid = []
|
|
146
142
|
# Validate the unsubscribes given
|
|
147
|
-
|
|
143
|
+
until data.empty?
|
|
148
144
|
unsubscribe = data.pop
|
|
149
145
|
# unsubscribes MUST contain a `address` key.
|
|
150
|
-
|
|
151
|
-
raise Mailgun::ParameterError
|
|
146
|
+
unless unsubscribe.include? :address
|
|
147
|
+
raise Mailgun::ParameterError, "Unsubscribe MUST include a :address key: #{unsubscribe}"
|
|
152
148
|
end
|
|
153
149
|
|
|
154
150
|
unsubscribe.each do |k, v|
|
|
@@ -164,11 +160,11 @@ module Mailgun
|
|
|
164
160
|
valid.push unsubscribe
|
|
165
161
|
end
|
|
166
162
|
|
|
167
|
-
response = @client.post("#{@domain}/unsubscribes", valid.to_json, {
|
|
168
|
-
|
|
163
|
+
response = @client.post("#{@domain}/unsubscribes", valid.to_json, { 'Content-Type' => 'application/json' })
|
|
164
|
+
[response, split_return]
|
|
169
165
|
end
|
|
170
166
|
|
|
171
|
-
def delete_unsubscribe(address,
|
|
167
|
+
def delete_unsubscribe(address, _params = {})
|
|
172
168
|
@client.delete("#{@domain}/unsubscribes/#{escape_address(address)}")
|
|
173
169
|
end
|
|
174
170
|
|
|
@@ -202,36 +198,34 @@ module Mailgun
|
|
|
202
198
|
def create_complaints(data)
|
|
203
199
|
# `data` should be a list of hashes, with each hash containing *at least* an `address` key.
|
|
204
200
|
split_return = []
|
|
205
|
-
if data.length >= 1000
|
|
206
|
-
resp, resp_l = create_complaints data[999
|
|
201
|
+
if data.length >= 1000
|
|
202
|
+
resp, resp_l = create_complaints data[999..]
|
|
207
203
|
split_return.push(resp)
|
|
208
204
|
split_return.concat(resp_l)
|
|
209
205
|
data = data[0..998]
|
|
210
|
-
elsif data.
|
|
206
|
+
elsif data.empty?
|
|
211
207
|
return nil, []
|
|
212
208
|
end
|
|
213
209
|
|
|
214
210
|
valid = []
|
|
215
211
|
# Validate the complaints given
|
|
216
|
-
|
|
212
|
+
until data.empty?
|
|
217
213
|
complaint = data.pop
|
|
218
214
|
# complaints MUST contain a `address` key.
|
|
219
|
-
|
|
220
|
-
raise Mailgun::ParameterError
|
|
215
|
+
unless complaint.include? :address
|
|
216
|
+
raise Mailgun::ParameterError, "Complaint MUST include a :address key: #{complaint}"
|
|
221
217
|
end
|
|
222
218
|
|
|
223
219
|
complaint.each do |k, v|
|
|
224
220
|
# Hash values MUST be strings.
|
|
225
|
-
|
|
226
|
-
complaint[k] = v.to_s
|
|
227
|
-
end
|
|
221
|
+
complaint[k] = v.to_s unless v.is_a? String
|
|
228
222
|
end
|
|
229
223
|
|
|
230
224
|
valid.push complaint
|
|
231
225
|
end
|
|
232
226
|
|
|
233
|
-
response = @client.post("#{@domain}/complaints", valid.to_json, {
|
|
234
|
-
|
|
227
|
+
response = @client.post("#{@domain}/complaints", valid.to_json, { 'Content-Type' => 'application/json' })
|
|
228
|
+
[response, split_return]
|
|
235
229
|
end
|
|
236
230
|
|
|
237
231
|
def delete_complaint(address)
|
|
@@ -250,24 +244,23 @@ module Mailgun
|
|
|
250
244
|
|
|
251
245
|
def extract_paging(response)
|
|
252
246
|
rhash = response.to_h
|
|
253
|
-
return nil unless rhash.include?
|
|
247
|
+
return nil unless rhash.include? 'paging'
|
|
254
248
|
|
|
255
|
-
page_info = rhash[
|
|
249
|
+
page_info = rhash['paging']
|
|
256
250
|
|
|
257
251
|
# Build the `next` endpoint
|
|
258
|
-
page_next = URI.parse(page_info[
|
|
252
|
+
page_next = URI.parse(page_info['next'])
|
|
259
253
|
@paging_next = {
|
|
260
|
-
:
|
|
261
|
-
:
|
|
254
|
+
path: page_next.path[%r{/v\d/(.+)}, 1],
|
|
255
|
+
params: Hash[URI.decode_www_form page_next.query]
|
|
262
256
|
}
|
|
263
257
|
|
|
264
258
|
# Build the `prev` endpoint
|
|
265
|
-
page_prev = URI.parse(page_info[
|
|
259
|
+
page_prev = URI.parse(page_info['previous'])
|
|
266
260
|
@paging_prev = {
|
|
267
|
-
:
|
|
268
|
-
:
|
|
261
|
+
path: page_prev.path[%r{/v\d/(.+)}, 1],
|
|
262
|
+
params: Hash[URI.decode_www_form page_prev.query]
|
|
269
263
|
}
|
|
270
264
|
end
|
|
271
|
-
|
|
272
265
|
end
|
|
273
266
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Mailgun
|
|
3
4
|
# A Mailgun::AnalyticsTags object is a simple CRUD interface to Mailgun Tags.
|
|
4
5
|
# Uses Mailgun
|
|
5
6
|
class AnalyticsTags
|
|
@@ -11,18 +12,48 @@ module Mailgun
|
|
|
11
12
|
@client = client
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
# Public: Update account tag
|
|
16
|
+
#
|
|
17
|
+
# tag - [String] The tag to update.
|
|
18
|
+
# description - [String] The updated tag description.
|
|
19
|
+
#
|
|
20
|
+
# Returns [Boolean] true or false
|
|
14
21
|
def update(tag, description)
|
|
15
|
-
@client.put('analytics/tags', { tag: tag, description: description },
|
|
22
|
+
@client.put('analytics/tags', { tag: tag, description: description }.to_json,
|
|
23
|
+
{ 'Content-Type' => 'application/json' }).to_h['message'] == 'Tag updated'
|
|
16
24
|
end
|
|
17
25
|
|
|
26
|
+
# Public: Post query to list account tags or search for single tag
|
|
27
|
+
#
|
|
28
|
+
# options - [Hash] of
|
|
29
|
+
# include_subaccounts - [Boolean] Boolean indicating whether or not to include data from all subaccounts. Default false.
|
|
30
|
+
# include_metrics - [Boolean] Boolean indicating whether or not to include metrics for tags. Default false. When true max limit is 20.
|
|
31
|
+
# tag - [string] The tag or tag prefix.
|
|
32
|
+
# pagination - [Object]
|
|
33
|
+
# sort - [String] Colon-separated value indicating column name and sort direction e.g. 'timestamp:desc'.
|
|
34
|
+
# skip - [Integer] The number of items to skip over when satisfying the request.
|
|
35
|
+
# limit - [Integer] The maximum number of items returned (100 max).
|
|
36
|
+
# total - [Integer] The total number of tags matching the search criteria.
|
|
37
|
+
# include_total - [Boolean] Boolean indicating whether or not to include total number of items. Default false.
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Returns [Hash] Information on the requested tags.
|
|
18
41
|
def list(options = {})
|
|
19
42
|
@client.post('analytics/tags', options).to_h['items']
|
|
20
43
|
end
|
|
21
44
|
|
|
45
|
+
# Public: Delete account tag
|
|
46
|
+
#
|
|
47
|
+
# tag - [String] The tag to delete.
|
|
48
|
+
#
|
|
49
|
+
# Returns [Boolean] true or false
|
|
22
50
|
def remove(tag)
|
|
23
51
|
@client.delete('analytics/tags', { tag: tag }, body_params: true).to_h['message'] == 'Tag deleted'
|
|
24
52
|
end
|
|
25
53
|
|
|
54
|
+
# Public: Get account tag limit information
|
|
55
|
+
#
|
|
56
|
+
# Returns [Hash] Information on the tag limits.
|
|
26
57
|
def limits
|
|
27
58
|
@client.get('analytics/tags/limits').to_h
|
|
28
59
|
end
|