mailgun-ruby 1.2.14 → 1.2.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3905ad8ab1dae85ea3b87b10d2ac01700de085adab73d9e02373f4d54e70451d
4
- data.tar.gz: e5794e301066318205a9ffb6de455d73642d3162b1ad75900cefed7aa95db798
3
+ metadata.gz: 230e91483a287bc0ed69c568a1a76f87eca69685274a5027ab8ada2206930205
4
+ data.tar.gz: 78bc23c4966213a45577b279c3de82e01a04292205007d2d07f9b3ad173d0d9f
5
5
  SHA512:
6
- metadata.gz: af8ed54564c2f13b818aa7da6a550b9000b4148ee437b108d01219d80b610580fde3a1973dd831db3ffd8b0dbe934d9288b479a335a5521e3f275815a9f30c8e
7
- data.tar.gz: 5d11d20420e6333e9e71104fc529d80f19ed689cb300bc5b19ec4c2b855e9c92e24e59d7de83122d2bcdc910a0ec60f783ea277e011e8d375bb1e471be30802e
6
+ metadata.gz: 596a9fec66b1f46fb94d713906b37f472f80f8c2e0187c2df7d88e7609e2658a2c428c3bf68e7f2c41b5adc4a74c647e78f84b4ff94f4431b976d771bb4bf201
7
+ data.tar.gz: 94966b3b0325f188a6c9d28fea2e39c45f9a40a7e486f264fac53f111a6c7eada486cf7755698d29f8115b799b9ef39d98160f9ab50d964c48eb60051583f081
data/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.2.16] - 2024-11-29
8
+
9
+ ### Added
10
+
11
+ - Metrics API support (https://github.com/mailgun/mailgun-ruby/pull/326)
12
+
13
+ ## [1.2.15] - 2024-02-13
14
+
15
+ ### Fixed
16
+
17
+ - Remove Openstruct usage (- Remove OpenStruct usage, will warn in Ruby 3.4, raise in Ruby 3.5 (https://github.com/mailgun/mailgun-ruby/issues/321)).
18
+ - Error handling (- Work around error responses without message property (https://github.com/mailgun/mailgun-ruby/pull/324)).
19
+
7
20
  ## [1.2.14] - 2024-02-13
8
21
 
9
22
  ### Added
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.2.14'
22
+ gem 'mailgun-ruby', '~>1.2.16'
23
23
  ```
24
24
 
25
25
  Usage
data/docs/Metrics.md ADDED
@@ -0,0 +1,108 @@
1
+ Mailgun - Metrics
2
+ ====================
3
+
4
+ This is the Mailgun Ruby *Metrics* 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. It currently supports
8
+ all calls except credentials.
9
+
10
+ ---
11
+
12
+ Mailgun collects many different events and generates event metrics which are available
13
+ in your Control Panel. This data is also available via our analytics metrics API endpoint.
14
+
15
+ You can view additional samples in the [metrics_spec.rb](/spec/integration/metrics_spec.rb)
16
+ or the Metrics client API in [metrics.rb](/lib/metrics/metrics.rb).
17
+
18
+ Usage
19
+ -----
20
+
21
+ To get an instance of the Metrics client:
22
+
23
+ ```ruby
24
+ require 'mailgun'
25
+
26
+ mg_client = Mailgun::Client.new('your-api-key', 'mailgun-api-host', 'v1')
27
+ metrics = Mailgun::Metrics.new(mg_client)
28
+ ````
29
+ ---
30
+ Get filtered metrics for an account:
31
+ ```ruby
32
+ options = {
33
+ {
34
+ resolution: 'hour',
35
+ metrics: [
36
+ 'accepted_count',
37
+ 'delivered_count',
38
+ 'clicked_rate',
39
+ 'opened_rate'
40
+ ],
41
+ include_aggregates: true,
42
+ start: 'Tue, 26 Nov 2024 20:56:50 -0500',
43
+ duration: '1m',
44
+ filter: {
45
+ AND: [
46
+ {
47
+ attribute: 'domain',
48
+ comparator: '!=',
49
+ values: [
50
+ {
51
+ label: 'example.com',
52
+ value: 'example.com'
53
+ }
54
+ ]
55
+ }
56
+ ]
57
+ },
58
+ dimensions: ['time'],
59
+ end: 'Tue, 30 Nov 2024 20:56:50 -0500',
60
+ include_subaccounts: true
61
+ }
62
+ }
63
+
64
+ metrics.account_metrics(options)
65
+ ```
66
+ ---
67
+
68
+ Get filtered usage metrics for an account:
69
+ ```ruby
70
+ options = {
71
+ resolution: 'hour',
72
+ metrics: [
73
+ 'accepted_count',
74
+ 'delivered_count',
75
+ 'clicked_rate',
76
+ 'opened_rate'
77
+ ],
78
+ include_aggregates: true,
79
+ start: 'Tue, 26 Nov 2024 20:56:50 -0500',
80
+ duration: '1m',
81
+ filter: {
82
+ AND: [
83
+ {
84
+ attribute: 'domain',
85
+ comparator: '!=',
86
+ values: [
87
+ {
88
+ label: 'example.com',
89
+ value: 'example.com'
90
+ }
91
+ ]
92
+ }
93
+ ]
94
+ },
95
+ dimensions: ['time'],
96
+ end: 'Tue, 30 Nov 2024 20:56:50 -0500',
97
+ include_subaccounts: true
98
+ }
99
+
100
+ metrics.account_usage_metrics(options)
101
+ ```
102
+
103
+ ---
104
+
105
+ More Documentation
106
+ ------------------
107
+ See the official [Mailgun Domain Docs](https://documentation.mailgun.com/docs/mailgun/api-reference/openapi-final/tag/Metrics/)
108
+ for more information
@@ -50,7 +50,8 @@ module Mailgun
50
50
  end
51
51
 
52
52
  begin
53
- api_message = JSON.parse(response.body)['message']
53
+ json = JSON.parse(response.body)
54
+ api_message = json['message'] || json['Error'] || json['error']
54
55
  rescue JSON::ParserError
55
56
  api_message = response.body
56
57
  rescue NoMethodError
@@ -60,7 +61,7 @@ module Mailgun
60
61
  end
61
62
 
62
63
  message = message || ''
63
- message = message + ': ' + api_message
64
+ message = message + ': ' + (api_message || "")
64
65
 
65
66
  super(message, response)
66
67
  rescue NoMethodError, JSON::ParserError
@@ -0,0 +1,61 @@
1
+ require 'mailgun/exceptions/exceptions'
2
+
3
+ module Mailgun
4
+ # A Mailgun::Metrics object is a simple interface to Mailgun Metrics.
5
+ # Uses Mailgun
6
+ class Metrics
7
+ # Public: creates a new Mailgun::Metrics instance.
8
+ # Defaults to Mailgun::Client
9
+ def initialize(client = Mailgun::Client.new(Mailgun.api_key, Mailgun.api_host || 'api.mailgun.net', 'v1'))
10
+ @client = client
11
+ end
12
+
13
+ # Public: Post query to get account metrics
14
+ #
15
+ # options - [Hash] of
16
+ # start - [String] A start date (default: 7 days before current time). Must be in RFC 2822 format.
17
+ # end - [String] An end date (default: current time). Must be in RFC 2822 format.
18
+ # resolution - [String] A resolution in the format of 'day' 'hour' 'month'. Default is day.
19
+ # duration - [String] A duration in the format of '1d' '2h' '2m'. If duration is provided then it is calculated from the end date and overwrites the start date.
20
+ # dimensions - [Array] Attributes of the metric data such as 'subaccount'.
21
+ # metrics - [Array] Name of the metrics to receive the stats for such as 'processed_count'
22
+ # filter - [Object]
23
+ # AND: - [Array] of objects
24
+ # attribute - [String]
25
+ # comparator - [String]
26
+ # values - [Array] of objects
27
+ # label - [String]
28
+ # value - [String]
29
+ # include_subaccounts - [Boolean] Include stats from all subaccounts.
30
+ # include_aggregates - [Boolean] Include top-level aggregate metrics.
31
+ #
32
+ # Returns [Hash] Metrics
33
+ def account_metrics(options={})
34
+ @client.post('analytics/metrics', options.to_json, { "Content-Type" => "application/json" }).to_h!
35
+ end
36
+
37
+ # Public: Post query to get account usage metrics
38
+ #
39
+ # options - [Hash] of
40
+ # start - [String] A start date (default: 7 days before current time). Must be in RFC 2822 format.
41
+ # end - [String] An end date (default: current time). Must be in RFC 2822 format.
42
+ # resolution - [String] A resolution in the format of 'day' 'hour' 'month'. Default is day.
43
+ # duration - [String] A duration in the format of '1d' '2h' '2m'. If duration is provided then it is calculated from the end date and overwrites the start date.
44
+ # dimensions - [Array] Attributes of the metric data such as 'subaccount'.
45
+ # metrics - [Array] Name of the metrics to receive the stats for such as 'processed_count'
46
+ # filter - [Object]
47
+ # AND: - [Array] of objects
48
+ # attribute - [String]
49
+ # comparator - [String]
50
+ # values - [Array] of objects
51
+ # label - [String]
52
+ # value - [String]
53
+ # include_subaccounts - [Boolean] Include stats from all subaccounts.
54
+ # include_aggregates - [Boolean] Include top-level aggregate metrics.
55
+ #
56
+ # Returns [Hash] Metrics
57
+ def account_usage_metrics(options={})
58
+ @client.post('analytics/usage/metrics', options.to_json, { "Content-Type" => "application/json" }).to_h!
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,3 @@
1
- require 'ostruct'
2
-
3
1
  module Mailgun
4
2
  # A Mailgun::Response object is instantiated for each response generated
5
3
  # by the Client request. The Response object supports deserialization of
@@ -12,9 +10,10 @@ module Mailgun
12
10
  # slightly different
13
11
  attr_accessor :body, :code
14
12
 
13
+ ResponseHash = Struct.new(:body, :code)
15
14
  def self.from_hash(h)
16
15
  # Create a "fake" response object with the data passed from h
17
- self.new OpenStruct.new(h)
16
+ self.new ResponseHash.new(h[:body], h[:code])
18
17
  end
19
18
 
20
19
  def initialize(response)
@@ -1,4 +1,4 @@
1
1
  # It's the version. Yeay!
2
2
  module Mailgun
3
- VERSION = '1.2.14'
3
+ VERSION = '1.2.16'
4
4
  end
data/lib/mailgun.rb CHANGED
@@ -18,6 +18,7 @@ require 'mailgun/webhooks/webhooks'
18
18
  require 'mailgun/templates/templates'
19
19
  require 'mailgun/subaccounts/subaccounts'
20
20
  require 'mailgun/tags/tags'
21
+ require 'mailgun/metrics/metrics'
21
22
 
22
23
  # Module for interacting with the sweet Mailgun API.
23
24
  #
@@ -0,0 +1,218 @@
1
+ require 'spec_helper'
2
+ require 'mailgun'
3
+
4
+ vcr_opts = { cassette_name: 'metrics' }
5
+
6
+ describe Mailgun::Metrics, vcr: vcr_opts do
7
+ let(:metrics) { Mailgun::Metrics.new(Mailgun::Client.new(APIKEY, APIHOST, 'v1')) }
8
+
9
+ describe '#account_metrics' do
10
+ let(:options) do
11
+ {
12
+ resolution: 'hour',
13
+ metrics: [
14
+ 'accepted_count',
15
+ 'delivered_count',
16
+ 'clicked_rate',
17
+ 'opened_rate'
18
+ ],
19
+ include_aggregates: true,
20
+ start: 'Tue, 26 Nov 2024 20:56:50 -0500',
21
+ duration: '1m',
22
+ filter: {
23
+ AND: [
24
+ {
25
+ attribute: 'domain',
26
+ comparator: '!=',
27
+ values: [
28
+ {
29
+ label: 'example.com',
30
+ value: 'example.com'
31
+ }
32
+ ]
33
+ }
34
+ ]
35
+ },
36
+ dimensions: ['time'],
37
+ end: 'Tue, 30 Nov 2024 20:56:50 -0500',
38
+ include_subaccounts: true
39
+ }
40
+ end
41
+
42
+ it 'responds with account metrics' do
43
+ expect(metrics.account_metrics(options)).to eq(
44
+ {
45
+ "start" => "Fri, 01 Nov 2024 01:00:00 +0000",
46
+ "end" => "Sun, 01 Dec 2024 01:00:00 +0000",
47
+ "resolution" => "hour",
48
+ "duration" => "1m",
49
+ "dimensions" => ["time"],
50
+ "pagination" => {
51
+ "sort" => "", "skip" => 0, "limit" => 1500, "total" => 3
52
+ },
53
+ "items" => [{
54
+ "dimensions" => [{
55
+ "dimension" => "time",
56
+ "value" => "Wed, 27 Nov 2024 12:00:00 +0000",
57
+ "display_value" => "Wed, 27 Nov 2024 12:00:00 +0000"
58
+ }],
59
+ "metrics" => {
60
+ "accepted_count" => 1, "delivered_count" => 1, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
61
+ }
62
+ },
63
+ {
64
+ "dimensions" => [{
65
+ "dimension" => "time",
66
+ "value" => "Wed, 27 Nov 2024 13:00:00 +0000",
67
+ "display_value" => "Wed, 27 Nov 2024 13:00:00 +0000"
68
+ }],
69
+ "metrics" => {
70
+ "accepted_count" => 1, "delivered_count" => 1, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
71
+ }
72
+ },
73
+ {
74
+ "dimensions" => [{
75
+ "dimension" => "time",
76
+ "value" => "Thu, 28 Nov 2024 15:00:00 +0000",
77
+ "display_value" => "Thu, 28 Nov 2024 15:00:00 +0000"
78
+ }],
79
+ "metrics" => {
80
+ "accepted_count" => 1, "delivered_count" => 1, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
81
+ }
82
+ }
83
+ ],
84
+ "aggregates" => {
85
+ "metrics" => {
86
+ "accepted_count" => 3, "delivered_count" => 3, "opened_rate" => "0.0000", "clicked_rate" => "0.0000"
87
+ }
88
+ }
89
+ }
90
+ )
91
+ end
92
+ end
93
+
94
+ describe '#account_usage_metrics' do
95
+ let(:options) do
96
+ {
97
+ resolution: 'hour',
98
+ metrics: [
99
+ 'email_preview_count',
100
+ 'email_preview_failed_count',
101
+ 'email_validation_bulk_count',
102
+ 'email_validation_count',
103
+ 'email_validation_list_count',
104
+ 'email_validation_mailgun_count',
105
+ 'email_validation_mailjet_count',
106
+ 'email_validation_public_count',
107
+ 'email_validation_single_count',
108
+ 'email_validation_valid_count',
109
+ 'link_validation_count',
110
+ 'link_validation_failed_count',
111
+ 'processed_count',
112
+ 'seed_test_count'
113
+ ],
114
+ include_aggregates: true,
115
+ start: 'Tue, 26 Nov 2024 20:56:50 -0500',
116
+ duration: '1m',
117
+ filter: {
118
+ AND: [
119
+ {
120
+ attribute: 'subaccount',
121
+ comparator: '!=',
122
+ values: [
123
+ {
124
+ label: '12345',
125
+ value: '12345'
126
+ }
127
+ ]
128
+ }
129
+ ]
130
+ },
131
+ dimensions: ['time'],
132
+ end: 'Tue, 28 Nov 2024 20:56:50 -0500',
133
+ include_subaccounts: true
134
+ }
135
+ end
136
+
137
+ it 'responds with account usage metrics' do
138
+ expect(metrics.account_usage_metrics(options)).to eq(
139
+ {
140
+ "start" => "Tue, 29 Oct 2024 01:00:00 +0000",
141
+ "end" => "Fri, 29 Nov 2024 01:00:00 +0000",
142
+ "resolution" => "hour",
143
+ "duration" => "1m",
144
+ "dimensions" => ["time"],
145
+ "pagination" => {
146
+ "sort" => "", "skip" => 0, "limit" => 1500, "total" => 2
147
+ },
148
+ "items" => [{
149
+ "dimensions" => [{
150
+ "dimension" => "time",
151
+ "value" => "Wed, 27 Nov 2024 00:00:00 +0000",
152
+ "display_value" => "Wed, 27 Nov 2024 00:00:00 +0000"
153
+ }],
154
+ "metrics" => {
155
+ "processed_count" => 2,
156
+ "email_validation_count" => 0,
157
+ "email_validation_public_count" => 0,
158
+ "email_validation_valid_count" => 0,
159
+ "email_validation_single_count" => 0,
160
+ "email_validation_bulk_count" => 0,
161
+ "email_validation_list_count" => 0,
162
+ "email_validation_mailgun_count" => 0,
163
+ "email_validation_mailjet_count" => 0,
164
+ "email_preview_count" => 0,
165
+ "email_preview_failed_count" => 0,
166
+ "link_validation_count" => 0,
167
+ "link_validation_failed_count" => 0,
168
+ "seed_test_count" => 0
169
+ }
170
+ },
171
+ {
172
+ "dimensions" => [{
173
+ "dimension" => "time",
174
+ "value" => "Thu, 28 Nov 2024 00:00:00 +0000",
175
+ "display_value" => "Thu, 28 Nov 2024 00:00:00 +0000"
176
+ }],
177
+ "metrics" => {
178
+ "processed_count" => 1,
179
+ "email_validation_count" => 0,
180
+ "email_validation_public_count" => 0,
181
+ "email_validation_valid_count" => 0,
182
+ "email_validation_single_count" => 0,
183
+ "email_validation_bulk_count" => 0,
184
+ "email_validation_list_count" => 0,
185
+ "email_validation_mailgun_count" => 0,
186
+ "email_validation_mailjet_count" => 0,
187
+ "email_preview_count" => 0,
188
+ "email_preview_failed_count" => 0,
189
+ "link_validation_count" => 0,
190
+ "link_validation_failed_count" => 0,
191
+ "seed_test_count" => 0
192
+ }
193
+ }
194
+ ],
195
+ "aggregates" => {
196
+ "metrics" => {
197
+ "permanent_failed_count" => 0,
198
+ "processed_count" => 3,
199
+ "email_validation_count" => 0,
200
+ "email_validation_public_count" => 0,
201
+ "email_validation_valid_count" => 0,
202
+ "email_validation_single_count" => 0,
203
+ "email_validation_bulk_count" => 0,
204
+ "email_validation_list_count" => 0,
205
+ "email_validation_mailgun_count" => 0,
206
+ "email_validation_mailjet_count" => 0,
207
+ "email_preview_count" => 0,
208
+ "email_preview_failed_count" => 0,
209
+ "link_validation_count" => 0,
210
+ "link_validation_failed_count" => 0,
211
+ "seed_test_count" => 0
212
+ }
213
+ }
214
+ }
215
+ )
216
+ end
217
+ end
218
+ end
@@ -96,19 +96,19 @@ module Mailgun
96
96
  if resource_endpoint == "messages"
97
97
  t = Time.now
98
98
  id = "<#{t.to_i}.#{rand(99999999)}.5817@example.com>"
99
- return OpenStruct.new({ "body" => JSON.generate({"message" => "Queued. Thank you.", "id" => id}) })
99
+ return Response.from_hash({ body: JSON.generate({"message" => "Queued. Thank you.", "id" => id}) })
100
100
  end
101
101
  if resource_endpoint == "bounces"
102
- return OpenStruct.new({ "body" => JSON.generate({"total_count" => 1, "items" => {"created_at" => "Fri, 21 Oct 2011 11:02:55 GMT", "code" => 550, "address" => "baz@example.com", "error" => "Message was not accepted -- invalid mailbox. Local mailbox baz@example.com is unavailable: user not found"}}) })
102
+ return Response.from_hash({ body: JSON.generate({"total_count" => 1, "items" => {"created_at" => "Fri, 21 Oct 2011 11:02:55 GMT", "code" => 550, "address" => "baz@example.com", "error" => "Message was not accepted -- invalid mailbox. Local mailbox baz@example.com is unavailable: user not found"}}) })
103
103
  end
104
104
  if resource_endpoint == "lists"
105
- return OpenStruct.new({ "body" => JSON.generate({"member" => {"vars" => {"age" => 26}, "name" => "Foo Bar", "subscribed" => false, "address" => "bar@example.com"}, "message" => "Mailing list member has been updated"}) })
105
+ return Response.from_hash({ body: JSON.generate({"member" => {"vars" => {"age" => 26}, "name" => "Foo Bar", "subscribed" => false, "address" => "bar@example.com"}, "message" => "Mailing list member has been updated"}) })
106
106
  end
107
107
  if resource_endpoint == "campaigns"
108
- return OpenStruct.new({ "body" => JSON.generate({"message" => "Campaign has been deleted", "id" => "ABC123"}) })
108
+ return Response.from_hash({ body: JSON.generate({"message" => "Campaign has been deleted", "id" => "ABC123"}) })
109
109
  end
110
110
  if resource_endpoint == "events"
111
- return OpenStruct.new({ "body" => JSON.generate({"items" => [], "paging" => {"next"=> "https://api.mailgun.net/v3/thisisatestdomainformailgun.com/events/W3siYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDVUMDA6NDU6NTEuNzQwOTgzKzAwOjAwIn0sIHsiYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDVUMDA6NDU6NTEuNzQwOTgzKzAwOjAwIn0sIFsiZiJdLCBudWxsLCB7ImFjY291bnQuaWQiOiAiNGU4MjMwZjYxNDc2ZDg2NzEzMDBjNDc2IiwgImRvbWFpbi5uYW1lIjogInRoaXNpc2F0ZXN0ZG9tYWluZm9ybWFpbGd1bi5jb20iLCAic2V2ZXJpdHkiOiAiTk9UIGludGVybmFsIn0sIDEwMCwgbnVsbF0=", "previous"=> "https://api.mailgun.net/v2/thisisatestdomainformailgun.com/events/W3siYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDVUMDA6NDU6NTEuNzQwOTgzKzAwOjAwIn0sIHsiYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDdUMDA6NDU6NTEuNzQxODkyKzAwOjAwIn0sIFsicCIsICJmIl0sIG51bGwsIHsiYWNjb3VudC5pZCI6ICI0ZTgyMzBmNjE0NzZkODY3MTMwMGM0NzYiLCAiZG9tYWluLm5hbWUiOiAidGhpc2lzYXRlc3Rkb21haW5mb3JtYWlsZ3VuLmNvbSIsICJzZXZlcml0eSI6ICJOT1QgaW50ZXJuYWwifSwgMTAwLCBudWxsXQ=="}}) })
111
+ return Response.from_hash({ body: JSON.generate({"items" => [], "paging" => {"next"=> "https://api.mailgun.net/v3/thisisatestdomainformailgun.com/events/W3siYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDVUMDA6NDU6NTEuNzQwOTgzKzAwOjAwIn0sIHsiYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDVUMDA6NDU6NTEuNzQwOTgzKzAwOjAwIn0sIFsiZiJdLCBudWxsLCB7ImFjY291bnQuaWQiOiAiNGU4MjMwZjYxNDc2ZDg2NzEzMDBjNDc2IiwgImRvbWFpbi5uYW1lIjogInRoaXNpc2F0ZXN0ZG9tYWluZm9ybWFpbGd1bi5jb20iLCAic2V2ZXJpdHkiOiAiTk9UIGludGVybmFsIn0sIDEwMCwgbnVsbF0=", "previous"=> "https://api.mailgun.net/v2/thisisatestdomainformailgun.com/events/W3siYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDVUMDA6NDU6NTEuNzQwOTgzKzAwOjAwIn0sIHsiYiI6ICIyMDE0LTA1LTA3VDAwOjQ1OjUxLjc0MDg5MiswMDowMCIsICJlIjogIjIwMTQtMDUtMDdUMDA6NDU6NTEuNzQxODkyKzAwOjAwIn0sIFsicCIsICJmIl0sIG51bGwsIHsiYWNjb3VudC5pZCI6ICI0ZTgyMzBmNjE0NzZkODY3MTMwMGM0NzYiLCAiZG9tYWluLm5hbWUiOiAidGhpc2lzYXRlc3Rkb21haW5mb3JtYWlsZ3VuLmNvbSIsICJzZXZlcml0eSI6ICJOT1QgaW50ZXJuYWwifSwgMTAwLCBudWxsXQ=="}}) })
112
112
  end
113
113
  end
114
114
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Mailgun::CommunicationError do
4
+ describe '.new' do
5
+ context "when the Response body doesn't have a `message` property" do
6
+ it "doesn't raise an error" do
7
+ expect do
8
+ described_class.new('Boom!', Mailgun::Response.from_hash({ code: 401, body: '{}' }))
9
+ end.not_to raise_error
10
+ end
11
+
12
+ context "when the Response body has an `Error` property" do
13
+ it "uses the `Error` property as the API message" do
14
+ subject = described_class.new('Boom!', Mailgun::Response.from_hash({ code: 401, body: '{"Error":"unauthorized"}' }))
15
+
16
+ expect(subject.message).to eq("Boom!: unauthorized")
17
+ end
18
+ end
19
+
20
+ context "when the Response body has an `error` property" do
21
+ it "uses the `Error` property as the API message" do
22
+ subject = described_class.new('Boom!', Mailgun::Response.from_hash({ code: 401, body: '{"error":"not found"}' }))
23
+
24
+ expect(subject.message).to eq("Boom!: not found")
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,116 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.mailgun.net/v1/analytics/metrics
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"resolution":"hour","metrics":["accepted_count","delivered_count","clicked_rate","opened_rate"],"include_aggregates":true,"start":"Tue,
9
+ 26 Nov 2024 20:56:50 -0500","duration":"1m","filter":{"AND":[{"attribute":"domain","comparator":"!=","values":[{"label":"example.com","value":"example.com"}]}]},"dimensions":["time"],"end":"Tue,
10
+ 30 Nov 2024 20:56:50 -0500","include_subaccounts":true}'
11
+ headers:
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - rest-client/2.1.0 (darwin23 x86_64) ruby/3.1.4p223
16
+ Content-Type:
17
+ - application/json
18
+ Content-Length:
19
+ - '387'
20
+ Accept-Encoding:
21
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
22
+ Host:
23
+ - api.mailgun.net
24
+ Authorization:
25
+ - Basic xxx
26
+ response:
27
+ status:
28
+ code: 200
29
+ message: OK
30
+ headers:
31
+ Access-Control-Allow-Credentials:
32
+ - 'true'
33
+ Access-Control-Allow-Origin:
34
+ - "*"
35
+ Cache-Control:
36
+ - no-store
37
+ Content-Length:
38
+ - '1006'
39
+ Content-Type:
40
+ - application/json; charset=utf-8
41
+ Date:
42
+ - Thu, 28 Nov 2024 18:20:22 GMT
43
+ Strict-Transport-Security:
44
+ - max-age=63072000; includeSubDomains
45
+ X-Mailgun-Key-Id:
46
+ - c02fd0ba-d8dbad66
47
+ X-Xss-Protection:
48
+ - 1; mode=block
49
+ body:
50
+ encoding: UTF-8
51
+ string: '{"start":"Fri, 01 Nov 2024 01:00:00 +0000","end":"Sun, 01 Dec 2024
52
+ 01:00:00 +0000","resolution":"hour","duration":"1m","dimensions":["time"],"pagination":{"sort":"","skip":0,"limit":1500,"total":3},"items":[{"dimensions":[{"dimension":"time","value":"Wed,
53
+ 27 Nov 2024 12:00:00 +0000","display_value":"Wed, 27 Nov 2024 12:00:00 +0000"}],"metrics":{"accepted_count":1,"delivered_count":1,"opened_rate":"0.0000","clicked_rate":"0.0000"}},{"dimensions":[{"dimension":"time","value":"Wed,
54
+ 27 Nov 2024 13:00:00 +0000","display_value":"Wed, 27 Nov 2024 13:00:00 +0000"}],"metrics":{"accepted_count":1,"delivered_count":1,"opened_rate":"0.0000","clicked_rate":"0.0000"}},{"dimensions":[{"dimension":"time","value":"Thu,
55
+ 28 Nov 2024 15:00:00 +0000","display_value":"Thu, 28 Nov 2024 15:00:00 +0000"}],"metrics":{"accepted_count":1,"delivered_count":1,"opened_rate":"0.0000","clicked_rate":"0.0000"}}],"aggregates":{"metrics":{"accepted_count":3,"delivered_count":3,"opened_rate":"0.0000","clicked_rate":"0.0000"}}}
56
+
57
+ '
58
+ http_version:
59
+ recorded_at: Thu, 28 Nov 2024 18:20:22 GMT
60
+ - request:
61
+ method: post
62
+ uri: https://api.mailgun.net/v1/analytics/usage/metrics
63
+ body:
64
+ encoding: UTF-8
65
+ string: '{"resolution":"hour","metrics":["email_preview_count","email_preview_failed_count","email_validation_bulk_count","email_validation_count","email_validation_list_count","email_validation_mailgun_count","email_validation_mailjet_count","email_validation_public_count","email_validation_single_count","email_validation_valid_count","link_validation_count","link_validation_failed_count","processed_count","seed_test_count"],"include_aggregates":true,"start":"Tue,
66
+ 26 Nov 2024 20:56:50 -0500","duration":"1m","filter":{"AND":[{"attribute":"subaccount","comparator":"!=","values":[{"label":"12345","value":"12345"}]}]},"dimensions":["time"],"end":"Tue,
67
+ 28 Nov 2024 20:56:50 -0500","include_subaccounts":true}'
68
+ headers:
69
+ Accept:
70
+ - "*/*"
71
+ User-Agent:
72
+ - rest-client/2.1.0 (darwin23 x86_64) ruby/3.1.4p223
73
+ Content-Type:
74
+ - application/json
75
+ Content-Length:
76
+ - '703'
77
+ Accept-Encoding:
78
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
79
+ Host:
80
+ - api.mailgun.net
81
+ Authorization:
82
+ - Basic xxx
83
+ response:
84
+ status:
85
+ code: 200
86
+ message: OK
87
+ headers:
88
+ Access-Control-Allow-Credentials:
89
+ - 'true'
90
+ Access-Control-Allow-Origin:
91
+ - "*"
92
+ Cache-Control:
93
+ - no-store
94
+ Content-Length:
95
+ - '1795'
96
+ Content-Type:
97
+ - application/json; charset=utf-8
98
+ Date:
99
+ - Thu, 28 Nov 2024 18:20:23 GMT
100
+ Strict-Transport-Security:
101
+ - max-age=63072000; includeSubDomains
102
+ X-Mailgun-Key-Id:
103
+ - c02fd0ba-d8dbad66
104
+ X-Xss-Protection:
105
+ - 1; mode=block
106
+ body:
107
+ encoding: UTF-8
108
+ string: '{"start":"Tue, 29 Oct 2024 01:00:00 +0000","end":"Fri, 29 Nov 2024
109
+ 01:00:00 +0000","resolution":"hour","duration":"1m","dimensions":["time"],"pagination":{"sort":"","skip":0,"limit":1500,"total":2},"items":[{"dimensions":[{"dimension":"time","value":"Wed,
110
+ 27 Nov 2024 00:00:00 +0000","display_value":"Wed, 27 Nov 2024 00:00:00 +0000"}],"metrics":{"processed_count":2,"email_validation_count":0,"email_validation_public_count":0,"email_validation_valid_count":0,"email_validation_single_count":0,"email_validation_bulk_count":0,"email_validation_list_count":0,"email_validation_mailgun_count":0,"email_validation_mailjet_count":0,"email_preview_count":0,"email_preview_failed_count":0,"link_validation_count":0,"link_validation_failed_count":0,"seed_test_count":0}},{"dimensions":[{"dimension":"time","value":"Thu,
111
+ 28 Nov 2024 00:00:00 +0000","display_value":"Thu, 28 Nov 2024 00:00:00 +0000"}],"metrics":{"processed_count":1,"email_validation_count":0,"email_validation_public_count":0,"email_validation_valid_count":0,"email_validation_single_count":0,"email_validation_bulk_count":0,"email_validation_list_count":0,"email_validation_mailgun_count":0,"email_validation_mailjet_count":0,"email_preview_count":0,"email_preview_failed_count":0,"link_validation_count":0,"link_validation_failed_count":0,"seed_test_count":0}}],"aggregates":{"metrics":{"permanent_failed_count":0,"processed_count":3,"email_validation_count":0,"email_validation_public_count":0,"email_validation_valid_count":0,"email_validation_single_count":0,"email_validation_bulk_count":0,"email_validation_list_count":0,"email_validation_mailgun_count":0,"email_validation_mailjet_count":0,"email_preview_count":0,"email_preview_failed_count":0,"link_validation_count":0,"link_validation_failed_count":0,"seed_test_count":0}}}
112
+
113
+ '
114
+ http_version:
115
+ recorded_at: Thu, 28 Nov 2024 18:20:23 GMT
116
+ recorded_with: VCR 3.0.3
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailgun-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.14
4
+ version: 1.2.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mailgun
8
8
  - Travis Swientek
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-02-13 00:00:00.000000000 Z
12
+ date: 2024-11-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -158,6 +158,7 @@ files:
158
158
  - docs/Events.md
159
159
  - docs/MessageBuilder.md
160
160
  - docs/Messages.md
161
+ - docs/Metrics.md
161
162
  - docs/OptInHandler.md
162
163
  - docs/Snippets.md
163
164
  - docs/Subaccounts.md
@@ -178,6 +179,7 @@ files:
178
179
  - lib/mailgun/lists/opt_in_handler.rb
179
180
  - lib/mailgun/messages/batch_message.rb
180
181
  - lib/mailgun/messages/message_builder.rb
182
+ - lib/mailgun/metrics/metrics.rb
181
183
  - lib/mailgun/response.rb
182
184
  - lib/mailgun/subaccounts/subaccounts.rb
183
185
  - lib/mailgun/suppressions.rb
@@ -203,6 +205,7 @@ files:
203
205
  - spec/integration/mailer_spec.rb
204
206
  - spec/integration/mailgun_spec.rb
205
207
  - spec/integration/messages/sample_data/mime.txt
208
+ - spec/integration/metrics_spec.rb
206
209
  - spec/integration/routes_spec.rb
207
210
  - spec/integration/stats_spec.rb
208
211
  - spec/integration/subaccounts_spec.rb
@@ -214,6 +217,7 @@ files:
214
217
  - spec/spec_helper.rb
215
218
  - spec/unit/connection/test_client.rb
216
219
  - spec/unit/events/events_spec.rb
220
+ - spec/unit/exceptions/exceptions_spec.rb
217
221
  - spec/unit/lists/opt_in_handler_spec.rb
218
222
  - spec/unit/mailgun_spec.rb
219
223
  - spec/unit/messages/batch_message_spec.rb
@@ -239,6 +243,7 @@ files:
239
243
  - vcr_cassettes/mailing_list.todo.yml
240
244
  - vcr_cassettes/mailing_list.yml
241
245
  - vcr_cassettes/message_deliver.yml
246
+ - vcr_cassettes/metrics.yml
242
247
  - vcr_cassettes/routes.yml
243
248
  - vcr_cassettes/send_message.yml
244
249
  - vcr_cassettes/stats.yml
@@ -254,7 +259,7 @@ licenses:
254
259
  metadata:
255
260
  documentation_uri: https://documentation.mailgun.com/
256
261
  source_code_uri: https://github.com/mailgun/mailgun-ruby
257
- post_install_message:
262
+ post_install_message:
258
263
  rdoc_options: []
259
264
  require_paths:
260
265
  - lib
@@ -269,9 +274,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
269
274
  - !ruby/object:Gem::Version
270
275
  version: '0'
271
276
  requirements: []
272
- rubyforge_project:
273
- rubygems_version: 2.7.6
274
- signing_key:
277
+ rubygems_version: 3.3.26
278
+ signing_key:
275
279
  specification_version: 4
276
280
  summary: Mailgun's Official Ruby SDK
277
281
  test_files:
@@ -286,6 +290,7 @@ test_files:
286
290
  - spec/integration/mailer_spec.rb
287
291
  - spec/integration/mailgun_spec.rb
288
292
  - spec/integration/messages/sample_data/mime.txt
293
+ - spec/integration/metrics_spec.rb
289
294
  - spec/integration/routes_spec.rb
290
295
  - spec/integration/stats_spec.rb
291
296
  - spec/integration/subaccounts_spec.rb
@@ -297,6 +302,7 @@ test_files:
297
302
  - spec/spec_helper.rb
298
303
  - spec/unit/connection/test_client.rb
299
304
  - spec/unit/events/events_spec.rb
305
+ - spec/unit/exceptions/exceptions_spec.rb
300
306
  - spec/unit/lists/opt_in_handler_spec.rb
301
307
  - spec/unit/mailgun_spec.rb
302
308
  - spec/unit/messages/batch_message_spec.rb