mailgun-ruby 1.4.1 → 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 +64 -4
- data/Gemfile +3 -1
- data/README.md +1 -1
- data/Rakefile +5 -8
- 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 +56 -56
- data/lib/mailgun/domains/domains.rb +11 -10
- 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 +6 -10
- data/lib/mailgun/logs/logs.rb +4 -2
- data/lib/mailgun/messages/batch_message.rb +10 -10
- data/lib/mailgun/messages/message_builder.rb +40 -56
- data/lib/mailgun/metrics/metrics.rb +12 -6
- data/lib/mailgun/response.rb +12 -10
- data/lib/mailgun/subaccounts/subaccounts.rb +13 -8
- data/lib/mailgun/suppressions.rb +36 -43
- data/lib/mailgun/tags/analytics_tags.rb +37 -2
- data/lib/mailgun/tags/tags.rb +29 -19
- 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 +12 -19
- data/lib/railgun/errors.rb +2 -3
- data/lib/railgun/mailer.rb +37 -41
- data/lib/railgun/railtie.rb +2 -0
- data/lib/railgun.rb +2 -0
- data/mailgun.gemspec +15 -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 +12 -18
- data/spec/integration/email_validation_spec.rb +35 -34
- data/spec/integration/events_spec.rb +8 -8
- data/spec/integration/list_members_spec.rb +27 -26
- data/spec/integration/list_spec.rb +22 -21
- data/spec/integration/logs_spec.rb +49 -47
- data/spec/integration/mailer_spec.rb +7 -3
- data/spec/integration/mailgun_spec.rb +85 -92
- data/spec/integration/metrics_spec.rb +137 -131
- 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 +222 -44
- data/spec/integration/templates_spec.rb +14 -12
- data/spec/integration/unsubscribes_spec.rb +8 -6
- data/spec/integration/webhook_spec.rb +18 -12
- data/spec/spec_helper.rb +15 -8
- data/spec/unit/client_spec.rb +424 -0
- data/spec/unit/connection/test_client.rb +108 -55
- data/spec/unit/events/events_spec.rb +48 -29
- data/spec/unit/exceptions/exceptions_spec.rb +8 -7
- data/spec/unit/helpers/api_version_checker_spec.rb +206 -0
- data/spec/unit/lists/opt_in_handler_spec.rb +11 -7
- data/spec/unit/mailgun_spec.rb +71 -68
- data/spec/unit/messages/batch_message_spec.rb +37 -36
- data/spec/unit/messages/message_builder_spec.rb +170 -169
- data/spec/unit/railgun/content_type_spec.rb +31 -30
- data/spec/unit/railgun/mailer_spec.rb +62 -59
- 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/analytics_tags.yml +187 -0
- data/vcr_cassettes/suppressions.yml +1053 -170
- metadata +95 -29
- data/.rubocop_todo.yml +0 -22
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mailgun
|
|
2
4
|
module Exceptions
|
|
3
5
|
end
|
|
@@ -6,7 +8,6 @@ module Mailgun
|
|
|
6
8
|
# Inherits from StandardError (previously RuntimeError) as not all errors are
|
|
7
9
|
# runtime errors.
|
|
8
10
|
class Error < StandardError
|
|
9
|
-
|
|
10
11
|
# Public: get an object an error is instantiated with
|
|
11
12
|
attr_reader :object
|
|
12
13
|
|
|
@@ -35,7 +36,7 @@ module Mailgun
|
|
|
35
36
|
attr_reader :status
|
|
36
37
|
|
|
37
38
|
# Public: fallback if there is no response status on the object
|
|
38
|
-
NOCODE =
|
|
39
|
+
NOCODE = 0o00
|
|
39
40
|
FORBIDDEN = 'Forbidden'
|
|
40
41
|
|
|
41
42
|
# Public: initialization of new error given a message and/or object
|
|
@@ -46,10 +47,10 @@ module Mailgun
|
|
|
46
47
|
def initialize(message = nil, response = nil)
|
|
47
48
|
@response = response
|
|
48
49
|
@status = if response.nil?
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
NOCODE
|
|
51
|
+
else
|
|
52
|
+
response[:status]
|
|
53
|
+
end
|
|
53
54
|
|
|
54
55
|
begin
|
|
55
56
|
json = JSON.parse(response[:body])
|
|
@@ -57,13 +58,13 @@ module Mailgun
|
|
|
57
58
|
rescue JSON::ParserError
|
|
58
59
|
api_message = response.response_body
|
|
59
60
|
rescue NoMethodError
|
|
60
|
-
api_message =
|
|
61
|
-
rescue
|
|
61
|
+
api_message = 'Unknown API error'
|
|
62
|
+
rescue StandardError
|
|
62
63
|
api_message = 'Unknown API error'
|
|
63
64
|
end
|
|
64
65
|
|
|
65
|
-
message
|
|
66
|
-
message = message
|
|
66
|
+
message ||= ''
|
|
67
|
+
message = "#{message}: #{api_message || ''}"
|
|
67
68
|
|
|
68
69
|
super(message, response)
|
|
69
70
|
rescue NoMethodError, JSON::ParserError
|
|
@@ -78,7 +79,7 @@ module Mailgun
|
|
|
78
79
|
CODE = 401
|
|
79
80
|
|
|
80
81
|
def initialize(error_message, response)
|
|
81
|
-
error_message
|
|
82
|
+
error_message += ' - Invalid Domain or API key'
|
|
82
83
|
super(error_message, response)
|
|
83
84
|
end
|
|
84
85
|
end
|
|
@@ -87,9 +88,5 @@ module Mailgun
|
|
|
87
88
|
# Inherits from Mailgun::CommunicationError
|
|
88
89
|
class BadRequest < CommunicationError
|
|
89
90
|
CODE = 400
|
|
90
|
-
|
|
91
|
-
def initialize(error_message, response)
|
|
92
|
-
super(error_message, response)
|
|
93
|
-
end
|
|
94
91
|
end
|
|
95
92
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mailgun
|
|
2
4
|
module ApiVersionChecker
|
|
3
5
|
def self.included(base)
|
|
@@ -35,7 +37,10 @@ module Mailgun
|
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def require_api_version(expected_version)
|
|
38
|
-
|
|
40
|
+
return if @client.api_version == expected_version
|
|
41
|
+
|
|
42
|
+
raise(ParameterError, "Client api version must be #{expected_version}",
|
|
43
|
+
caller)
|
|
39
44
|
end
|
|
40
45
|
end
|
|
41
46
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Mailgun
|
|
3
4
|
# Public: Provides methods for creating and handling opt-in URLs,
|
|
4
5
|
# particularlly for mailing lists.
|
|
5
6
|
#
|
|
6
7
|
# See: https://github.com/mailgun/mailgun-ruby/blob/master/OptInHandler.md
|
|
7
8
|
class OptInHandler
|
|
8
|
-
|
|
9
9
|
# Generates a hash that can be used to validate opt-in recipients. Encodes
|
|
10
10
|
# all the necessary data in the URL.
|
|
11
11
|
#
|
|
@@ -32,7 +32,8 @@ module Mailgun
|
|
|
32
32
|
#
|
|
33
33
|
# @param [String] secret_app_id A secret passphrase used as a constant for the hash.
|
|
34
34
|
# @param [Hash] unique_hash The hash from the user. Likely via link click.
|
|
35
|
-
# @return [Hash or Boolean] A hash with 'recipient_address' and 'mailing_list', if validates.
|
|
35
|
+
# @return [Hash or Boolean] A hash with 'recipient_address' and 'mailing_list', if validates.
|
|
36
|
+
# Otherwise, boolean false.
|
|
36
37
|
def self.validate_hash(secret_app_id, unique_hash)
|
|
37
38
|
outer_payload = JSON.parse(base64_decode(CGI.unescape(unique_hash)))
|
|
38
39
|
|
|
@@ -46,6 +47,7 @@ module Mailgun
|
|
|
46
47
|
if generated_hash == hash_provided
|
|
47
48
|
return { 'recipient_address' => inner_payload['r'], 'mailing_list' => inner_payload['l'] }
|
|
48
49
|
end
|
|
50
|
+
|
|
49
51
|
false
|
|
50
52
|
end
|
|
51
53
|
|
|
@@ -56,15 +58,9 @@ module Mailgun
|
|
|
56
58
|
|
|
57
59
|
# Equivalent to Base64.decode64
|
|
58
60
|
def self.base64_decode(input)
|
|
59
|
-
|
|
60
|
-
if input.respond_to?(:unpack1)
|
|
61
|
-
input.unpack1('m')
|
|
62
|
-
else
|
|
63
|
-
input.unpack('m').first
|
|
64
|
-
end
|
|
61
|
+
input.unpack1('m')
|
|
65
62
|
end
|
|
66
63
|
|
|
67
64
|
private_class_method :base64_encode, :base64_decode
|
|
68
65
|
end
|
|
69
|
-
|
|
70
66
|
end
|
data/lib/mailgun/logs/logs.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mailgun
|
|
2
4
|
# A Mailgun::Logs object is a simple interface to Mailgun Logs.
|
|
3
5
|
# Uses Mailgun
|
|
@@ -30,8 +32,8 @@ module Mailgun
|
|
|
30
32
|
# limit - [Integer] The maximum number of items returned (100 max).
|
|
31
33
|
#
|
|
32
34
|
# Returns [Hash] Logs
|
|
33
|
-
def account_logs(options={})
|
|
34
|
-
@client.post('analytics/logs', options.to_json, {
|
|
35
|
+
def account_logs(options = {})
|
|
36
|
+
@client.post('analytics/logs', options.to_json, { 'Content-Type' => 'application/json' }).to_h!
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module Mailgun
|
|
3
4
|
# A Mailgun::BatchMessage object is used to create a valid payload
|
|
4
5
|
# for Batch Sending. Batch Sending can be difficult to implement, therefore
|
|
5
6
|
# this code makes it dead simple to send millions of messages in batches of
|
|
@@ -18,7 +19,6 @@ module Mailgun
|
|
|
18
19
|
#
|
|
19
20
|
# See the Github documentation for full examples.
|
|
20
21
|
class BatchMessage < MessageBuilder
|
|
21
|
-
|
|
22
22
|
attr_reader :message_ids, :domain, :recipient_variables
|
|
23
23
|
|
|
24
24
|
# Public: Creates a new BatchMessage object.
|
|
@@ -39,7 +39,8 @@ module Mailgun
|
|
|
39
39
|
#
|
|
40
40
|
# @param [String] recipient_type The type of recipient. "to".
|
|
41
41
|
# @param [String] address The email address of the recipient to add to the message object.
|
|
42
|
-
# @param [Hash] variables A hash of the variables associated with the recipient.
|
|
42
|
+
# @param [Hash] variables A hash of the variables associated with the recipient.
|
|
43
|
+
# We recommend "first" and "last" at a minimum!
|
|
43
44
|
# @return [void]
|
|
44
45
|
def add_recipient(recipient_type, address, variables = nil)
|
|
45
46
|
# send the message when we have 1000, not before
|
|
@@ -68,9 +69,10 @@ module Mailgun
|
|
|
68
69
|
#
|
|
69
70
|
# @return [Boolean]
|
|
70
71
|
def any_recipients_left?
|
|
71
|
-
return true if @counters[:recipients][:to]
|
|
72
|
-
return true if @counters[:recipients][:cc]
|
|
73
|
-
return true if @counters[:recipients][:bcc]
|
|
72
|
+
return true if @counters[:recipients][:to].positive?
|
|
73
|
+
return true if @counters[:recipients][:cc].positive?
|
|
74
|
+
return true if @counters[:recipients][:bcc].positive?
|
|
75
|
+
|
|
74
76
|
false
|
|
75
77
|
end
|
|
76
78
|
|
|
@@ -86,7 +88,7 @@ module Mailgun
|
|
|
86
88
|
@message[rkey] = @message[rkey].first if @message.key?(rkey)
|
|
87
89
|
|
|
88
90
|
response = @client.send_message(@domain, @message).to_h!
|
|
89
|
-
message_id = response['id'].gsub(
|
|
91
|
+
message_id = response['id'].gsub(/>|</, '')
|
|
90
92
|
@message_ids[message_id] = count_recipients
|
|
91
93
|
reset_message
|
|
92
94
|
end
|
|
@@ -94,7 +96,7 @@ module Mailgun
|
|
|
94
96
|
# This method stores recipient variables for each recipient added, if
|
|
95
97
|
# variables exist.
|
|
96
98
|
def store_recipient_variables(recipient_type, address, variables)
|
|
97
|
-
variables
|
|
99
|
+
variables ||= { id: @counters[:recipients][recipient_type] }
|
|
98
100
|
@recipient_variables[address] = variables
|
|
99
101
|
end
|
|
100
102
|
|
|
@@ -118,7 +120,5 @@ module Mailgun
|
|
|
118
120
|
@counters[:recipients][:cc] = 0
|
|
119
121
|
@counters[:recipients][:bcc] = 0
|
|
120
122
|
end
|
|
121
|
-
|
|
122
123
|
end
|
|
123
|
-
|
|
124
124
|
end
|
|
@@ -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.
|
|
@@ -25,16 +25,17 @@ module Mailgun
|
|
|
25
25
|
#
|
|
26
26
|
# @param [String] recipient_type The type of recipient. "to", "cc", "bcc" or "h:reply-to".
|
|
27
27
|
# @param [String] address The email address of the recipient to add to the message object.
|
|
28
|
-
# @param [Hash] variables A hash of the variables associated with the recipient.
|
|
28
|
+
# @param [Hash] variables A hash of the variables associated with the recipient.
|
|
29
|
+
# We recommend "first" and "last" at a minimum!
|
|
29
30
|
# @return [void]
|
|
30
31
|
def add_recipient(recipient_type, address, variables = nil)
|
|
31
|
-
if recipient_type ==
|
|
32
|
+
if recipient_type == 'h:reply-to'
|
|
32
33
|
warn 'DEPRECATION: "add_recipient("h:reply-to", ...)" is deprecated. Please use "reply_to" instead.'
|
|
33
34
|
return reply_to(address, variables)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
if (@counters[:recipients][recipient_type] || 0) >= Mailgun::Chains::MAX_RECIPIENTS
|
|
37
|
-
|
|
38
|
+
raise Mailgun::ParameterError, 'Too many recipients added to message.', address
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
compiled_address = parse_address(address, variables)
|
|
@@ -46,7 +47,8 @@ module Mailgun
|
|
|
46
47
|
# Sets the from address for the message
|
|
47
48
|
#
|
|
48
49
|
# @param [String] address The address of the sender.
|
|
49
|
-
# @param [Hash] variables A hash of the variables associated with the recipient.
|
|
50
|
+
# @param [Hash] variables A hash of the variables associated with the recipient.
|
|
51
|
+
# We recommend "first" and "last" at a minimum!
|
|
50
52
|
# @return [void]
|
|
51
53
|
def from(address, vars = nil)
|
|
52
54
|
add_recipient(:from, address, vars)
|
|
@@ -68,7 +70,7 @@ module Mailgun
|
|
|
68
70
|
# @return [void]
|
|
69
71
|
def reply_to(address, variables = nil)
|
|
70
72
|
compiled_address = parse_address(address, variables)
|
|
71
|
-
header(
|
|
73
|
+
header('reply-to', compiled_address)
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
# Set a subject for the message object
|
|
@@ -155,12 +157,6 @@ module Mailgun
|
|
|
155
157
|
set_multi_simple('o:testmode', bool_lookup(mode))
|
|
156
158
|
end
|
|
157
159
|
|
|
158
|
-
# Deprecated: 'set_test_mode' is depreciated. Please use 'test_mode' instead.
|
|
159
|
-
def set_test_mode(mode)
|
|
160
|
-
warn 'DEPRECATION: "set_test_mode" is deprecated. Please use "test_mode" instead.'
|
|
161
|
-
test_mode(mode)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
160
|
# Turn DKIM on or off per message
|
|
165
161
|
#
|
|
166
162
|
# @param [Boolean] mode The boolean or string value(will fix itself)
|
|
@@ -169,18 +165,15 @@ module Mailgun
|
|
|
169
165
|
set_multi_simple('o:dkim', bool_lookup(mode))
|
|
170
166
|
end
|
|
171
167
|
|
|
172
|
-
# Deprecated: 'set_dkim' is deprecated. Please use 'dkim' instead.
|
|
173
|
-
def set_dkim(mode)
|
|
174
|
-
warn 'DEPRECATION: "set_dkim" is deprecated. Please use "dkim" instead.'
|
|
175
|
-
dkim(mode)
|
|
176
|
-
end
|
|
177
|
-
|
|
178
168
|
# Add campaign IDs to message. Limit of 3 per message.
|
|
179
169
|
#
|
|
180
170
|
# @param [String] campaign_id A defined campaign ID to add to the message.
|
|
181
171
|
# @return [void]
|
|
182
172
|
def add_campaign_id(campaign_id)
|
|
183
|
-
|
|
173
|
+
if @counters[:attributes][:campaign_id] >= Mailgun::Chains::MAX_CAMPAIGN_IDS
|
|
174
|
+
raise(Mailgun::ParameterError, 'Too many campaigns added to message.',
|
|
175
|
+
campaign_id)
|
|
176
|
+
end
|
|
184
177
|
|
|
185
178
|
set_multi_complex('o:campaign', campaign_id)
|
|
186
179
|
@counters[:attributes][:campaign_id] += 1
|
|
@@ -192,8 +185,9 @@ module Mailgun
|
|
|
192
185
|
# @return [void]
|
|
193
186
|
def add_tag(tag)
|
|
194
187
|
if @counters[:attributes][:tag] >= Mailgun::Chains::MAX_TAGS
|
|
195
|
-
|
|
188
|
+
raise Mailgun::ParameterError, 'Too many tags added to message.', tag
|
|
196
189
|
end
|
|
190
|
+
|
|
197
191
|
set_multi_complex('o:tag', tag)
|
|
198
192
|
@counters[:attributes][:tag] += 1
|
|
199
193
|
end
|
|
@@ -208,12 +202,6 @@ module Mailgun
|
|
|
208
202
|
set_multi_simple('o:tracking', value)
|
|
209
203
|
end
|
|
210
204
|
|
|
211
|
-
# Deprecated: 'set_open_tracking' is deprecated. Please use 'track_opens' instead.
|
|
212
|
-
def set_open_tracking(tracking)
|
|
213
|
-
warn 'DEPRECATION: "set_open_tracking" is deprecated. Please use "track_opens" instead.'
|
|
214
|
-
track_opens(tracking)
|
|
215
|
-
end
|
|
216
|
-
|
|
217
205
|
# Turn Click Tracking on and off, on a per message basis.
|
|
218
206
|
#
|
|
219
207
|
# @param [String] mode True, False, or HTML (for HTML only tracking)
|
|
@@ -224,12 +212,6 @@ module Mailgun
|
|
|
224
212
|
set_multi_simple('o:tracking', value)
|
|
225
213
|
end
|
|
226
214
|
|
|
227
|
-
# Depreciated: 'set_click_tracking. is deprecated. Please use 'track_clicks' instead.
|
|
228
|
-
def set_click_tracking(tracking)
|
|
229
|
-
warn 'DEPRECATION: "set_click_tracking" is deprecated. Please use "track_clicks" instead.'
|
|
230
|
-
track_clicks(tracking)
|
|
231
|
-
end
|
|
232
|
-
|
|
233
215
|
# Enable Delivery delay on message. Specify an RFC2822 date, and Mailgun
|
|
234
216
|
# will not deliver the message until that date/time. For conversion
|
|
235
217
|
# options, see Ruby "Time". Example: "October 25, 2013 10:00PM CST" will
|
|
@@ -242,12 +224,6 @@ module Mailgun
|
|
|
242
224
|
set_multi_simple('o:deliverytime', time_str.rfc2822)
|
|
243
225
|
end
|
|
244
226
|
|
|
245
|
-
# Deprecated: 'set_delivery_time' is deprecated. Please use 'deliver_at' instead.
|
|
246
|
-
def set_delivery_time(timestamp)
|
|
247
|
-
warn 'DEPRECATION: "set_delivery_time" is deprecated. Please use "deliver_at" instead.'
|
|
248
|
-
deliver_at timestamp
|
|
249
|
-
end
|
|
250
|
-
|
|
251
227
|
# Add custom data to the message. The data should be either a hash or JSON
|
|
252
228
|
# encoded. The custom data will be added as a header to your message.
|
|
253
229
|
#
|
|
@@ -255,7 +231,8 @@ module Mailgun
|
|
|
255
231
|
# @param [Hash] data Either a hash or JSON string.
|
|
256
232
|
# @return [void]
|
|
257
233
|
def header(name, data)
|
|
258
|
-
|
|
234
|
+
raise(Mailgun::ParameterError, 'Header name for message must be specified') if name.to_s.empty?
|
|
235
|
+
|
|
259
236
|
begin
|
|
260
237
|
jsondata = make_json data
|
|
261
238
|
set_single("h:#{name}", jsondata)
|
|
@@ -278,7 +255,8 @@ module Mailgun
|
|
|
278
255
|
# can not be converted to JSON, ParameterError will be raised.
|
|
279
256
|
# @return [void]
|
|
280
257
|
def variable(name, data)
|
|
281
|
-
|
|
258
|
+
raise(Mailgun::ParameterError, 'Variable name must be specified') if name.to_s.empty?
|
|
259
|
+
|
|
282
260
|
begin
|
|
283
261
|
jsondata = make_json data
|
|
284
262
|
set_single("v:#{name}", jsondata)
|
|
@@ -308,6 +286,7 @@ module Mailgun
|
|
|
308
286
|
def message_id(data = nil)
|
|
309
287
|
key = 'h:Message-Id'
|
|
310
288
|
return @message.delete(key) if data.to_s.empty?
|
|
289
|
+
|
|
311
290
|
set_single(key, data)
|
|
312
291
|
end
|
|
313
292
|
|
|
@@ -326,6 +305,7 @@ module Mailgun
|
|
|
326
305
|
def template(template_name = nil)
|
|
327
306
|
key = 'template'
|
|
328
307
|
return @message.delete(key) if template_name.to_s.empty?
|
|
308
|
+
|
|
329
309
|
set_single(key, template_name)
|
|
330
310
|
end
|
|
331
311
|
|
|
@@ -337,6 +317,7 @@ module Mailgun
|
|
|
337
317
|
def template_version(version = nil)
|
|
338
318
|
key = 't:version'
|
|
339
319
|
return @message.delete(key) if version.to_s.empty?
|
|
320
|
+
|
|
340
321
|
set_single(key, version)
|
|
341
322
|
end
|
|
342
323
|
|
|
@@ -358,7 +339,7 @@ module Mailgun
|
|
|
358
339
|
# @param [String] value The value of the parameter.
|
|
359
340
|
# @return [void]
|
|
360
341
|
def set_single(parameter, value)
|
|
361
|
-
@message[parameter] = value
|
|
342
|
+
@message[parameter] = value || ''
|
|
362
343
|
end
|
|
363
344
|
|
|
364
345
|
# Sets values within the multidict, however, prevents
|
|
@@ -397,8 +378,9 @@ module Mailgun
|
|
|
397
378
|
# @param [String] value The item to convert
|
|
398
379
|
# @return [void]
|
|
399
380
|
def bool_lookup(value)
|
|
400
|
-
return 'yes' if %w
|
|
401
|
-
return 'no' if %w
|
|
381
|
+
return 'yes' if %w[true yes yep].include? value.to_s.downcase
|
|
382
|
+
return 'no' if %w[false no nope].include? value.to_s.downcase
|
|
383
|
+
|
|
402
384
|
warn 'WARN: for bool type actions next values are preferred: true yes yep | false no nope | htmlonly'
|
|
403
385
|
value
|
|
404
386
|
end
|
|
@@ -409,7 +391,7 @@ module Mailgun
|
|
|
409
391
|
# @return [void]
|
|
410
392
|
def valid_json?(json_)
|
|
411
393
|
JSON.parse(json_)
|
|
412
|
-
|
|
394
|
+
true
|
|
413
395
|
rescue JSON::ParserError
|
|
414
396
|
false
|
|
415
397
|
end
|
|
@@ -422,8 +404,9 @@ module Mailgun
|
|
|
422
404
|
def make_json(obj)
|
|
423
405
|
return JSON.parse(obj).to_json if obj.is_a?(String)
|
|
424
406
|
return obj.to_json if obj.is_a?(Hash)
|
|
407
|
+
|
|
425
408
|
JSON.generate(obj).to_json
|
|
426
|
-
rescue
|
|
409
|
+
rescue StandardError
|
|
427
410
|
raise Mailgun::ParameterError, 'Provided data could not be made into JSON. Try a JSON string or Hash.', obj
|
|
428
411
|
end
|
|
429
412
|
|
|
@@ -436,9 +419,9 @@ module Mailgun
|
|
|
436
419
|
# @return [void]
|
|
437
420
|
def parse_address(address, vars)
|
|
438
421
|
return address unless vars.is_a? Hash
|
|
439
|
-
|
|
440
|
-
if vars['full_name']
|
|
441
|
-
|
|
422
|
+
raise(Mailgun::ParameterError, 'Email address not specified') unless address.is_a? String
|
|
423
|
+
if !vars['full_name'].nil? && (!vars['first'].nil? || !vars['last'].nil?)
|
|
424
|
+
raise(Mailgun::ParameterError, "Must specify at most one of full_name or first/last. Vars passed: #{vars}")
|
|
442
425
|
end
|
|
443
426
|
|
|
444
427
|
if vars['full_name']
|
|
@@ -448,6 +431,7 @@ module Mailgun
|
|
|
448
431
|
end
|
|
449
432
|
|
|
450
433
|
return "'#{full_name}' <#{address}>" if full_name
|
|
434
|
+
|
|
451
435
|
address
|
|
452
436
|
end
|
|
453
437
|
|
|
@@ -461,24 +445,24 @@ module Mailgun
|
|
|
461
445
|
# Returns nothing
|
|
462
446
|
def add_file(disposition, filedata, filename)
|
|
463
447
|
attachment = File.open(filedata, 'r') if filedata.is_a?(String)
|
|
464
|
-
attachment
|
|
448
|
+
attachment ||= filedata.dup
|
|
465
449
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
450
|
+
unless attachment.respond_to?(:read)
|
|
451
|
+
raise(Mailgun::ParameterError,
|
|
452
|
+
'Unable to access attachment file object.')
|
|
453
|
+
end
|
|
469
454
|
|
|
470
455
|
if attachment.respond_to?(:path) && !attachment.respond_to?(:content_type)
|
|
471
456
|
mime_types = MiniMime.lookup_by_filename(attachment.path)
|
|
472
457
|
content_type = mime_types.nil? ? 'application/octet-stream' : mime_types.content_type
|
|
473
|
-
attachment.instance_eval "def content_type; '#{content_type}'; end"
|
|
458
|
+
attachment.instance_eval "def content_type; '#{content_type}'; end", __FILE__, __LINE__
|
|
474
459
|
end
|
|
475
460
|
|
|
476
461
|
unless filename.nil?
|
|
477
462
|
attachment.instance_variable_set :@original_filename, filename
|
|
478
|
-
attachment.instance_eval 'def original_filename; @original_filename; end'
|
|
463
|
+
attachment.instance_eval 'def original_filename; @original_filename; end', __FILE__, __LINE__
|
|
479
464
|
end
|
|
480
465
|
add_faraday_attachment(disposition, attachment, filename)
|
|
481
466
|
end
|
|
482
467
|
end
|
|
483
|
-
|
|
484
468
|
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
|
|
@@ -14,7 +16,9 @@ module Mailgun
|
|
|
14
16
|
# start - [String] A start date (default: 7 days before current time). Must be in RFC 2822 format.
|
|
15
17
|
# end - [String] An end date (default: current time). Must be in RFC 2822 format.
|
|
16
18
|
# resolution - [String] A resolution in the format of 'day' 'hour' 'month'. Default is day.
|
|
17
|
-
# duration - [String] A duration in the format of '1d' '2h' '2m'.
|
|
19
|
+
# duration - [String] A duration in the format of '1d' '2h' '2m'.
|
|
20
|
+
# If duration is provided then it is calculated from the end date
|
|
21
|
+
# and overwrites the start date.
|
|
18
22
|
# dimensions - [Array] Attributes of the metric data such as 'subaccount'.
|
|
19
23
|
# metrics - [Array] Name of the metrics to receive the stats for such as 'processed_count'
|
|
20
24
|
# filter - [Object]
|
|
@@ -28,8 +32,8 @@ module Mailgun
|
|
|
28
32
|
# include_aggregates - [Boolean] Include top-level aggregate metrics.
|
|
29
33
|
#
|
|
30
34
|
# Returns [Hash] Metrics
|
|
31
|
-
def account_metrics(options={})
|
|
32
|
-
@client.post('analytics/metrics', options.to_json, {
|
|
35
|
+
def account_metrics(options = {})
|
|
36
|
+
@client.post('analytics/metrics', options.to_json, { 'Content-Type' => 'application/json' }).to_h!
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
# Public: Post query to get account usage metrics
|
|
@@ -38,7 +42,9 @@ module Mailgun
|
|
|
38
42
|
# start - [String] A start date (default: 7 days before current time). Must be in RFC 2822 format.
|
|
39
43
|
# end - [String] An end date (default: current time). Must be in RFC 2822 format.
|
|
40
44
|
# resolution - [String] A resolution in the format of 'day' 'hour' 'month'. Default is day.
|
|
41
|
-
# duration - [String] A duration in the format of '1d' '2h' '2m'.
|
|
45
|
+
# duration - [String] A duration in the format of '1d' '2h' '2m'.
|
|
46
|
+
# If duration is provided then it is calculated from the end date and
|
|
47
|
+
# overwrites the start date.
|
|
42
48
|
# dimensions - [Array] Attributes of the metric data such as 'subaccount'.
|
|
43
49
|
# metrics - [Array] Name of the metrics to receive the stats for such as 'processed_count'
|
|
44
50
|
# filter - [Object]
|
|
@@ -52,8 +58,8 @@ module Mailgun
|
|
|
52
58
|
# include_aggregates - [Boolean] Include top-level aggregate metrics.
|
|
53
59
|
#
|
|
54
60
|
# Returns [Hash] Metrics
|
|
55
|
-
def account_usage_metrics(options={})
|
|
56
|
-
@client.post('analytics/usage/metrics', options.to_json, {
|
|
61
|
+
def account_usage_metrics(options = {})
|
|
62
|
+
@client.post('analytics/usage/metrics', options.to_json, { 'Content-Type' => 'application/json' }).to_h!
|
|
57
63
|
end
|
|
58
64
|
end
|
|
59
65
|
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
|
|
@@ -11,9 +13,9 @@ module Mailgun
|
|
|
11
13
|
attr_accessor :body, :status, :code
|
|
12
14
|
|
|
13
15
|
ResponseHash = Struct.new(:body, :status)
|
|
14
|
-
def self.from_hash(
|
|
16
|
+
def self.from_hash(hash)
|
|
15
17
|
# Create a "fake" response object with the data passed from h
|
|
16
|
-
|
|
18
|
+
new ResponseHash.new(hash[:body], hash[: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
|