mailtrap 2.13.0 → 2.15.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e1407023f85d4f46bb34447e8ed5a9cfe5343461ed38008690d9d92006929d1
4
- data.tar.gz: 3efa540454828966a9e6ff4439410d73e69c0c41d8e1e227943ebf1a7cc122dc
3
+ metadata.gz: ba78e8e22574eb5404c0e4d14f5a4ad764dabc559a3fd58bc0ae9ba46a49ea3f
4
+ data.tar.gz: da43055430599e2f496fc794fb145bacb7d589785b2387f6296ed978db57c4ac
5
5
  SHA512:
6
- metadata.gz: 22ae6dbfc35ff8228eb16d4c3444b9e93eb680f6c59bd4b7b0f2d37629b8c471943ea807c583cc50f50c64267920c67eb80c52a2d8e3dcc7b57379e58c7e7b80
7
- data.tar.gz: e7eb3ff7a9592ffc0918a63c9b75dbe7c81342642c624ded9e2d359136e620f0fc32a6889cee0fef5bf58cd66037ed1370c1b7512d99c623f1f9e033dd7971f4
6
+ metadata.gz: 7e5eb305e76d483f99711da0d2c913b1fdab00c8010bd55b697171284bd712d78545096dd5af9ffeab6886c06518b8c8f515edf42cf0b3e41dab4d98f7265a5b
7
+ data.tar.gz: e9c400428a9e86678a2b6fd6c6ef6ddbada0726ecfac29e9b254021b6a9f9143f912e81f6ba967084fa94c16c4ac19aaaa7e01699ad98a31ef4d3e934d37cd9d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## [2.15.0] - 2026-08-28
2
+
3
+ ## What's Changed
4
+ * Accept all sending domain update options by @mklocek in https://github.com/mailtrap/mailtrap-ruby/pull/126
5
+ * Add tracking opt-outs and create-suppression endpoints by @mklocek in https://github.com/mailtrap/mailtrap-ruby/pull/127
6
+
7
+
8
+ **Full Changelog**: https://github.com/mailtrap/mailtrap-ruby/compare/v2.14.0...v2.15.0
9
+
10
+ ## [2.14.0] - 2026-08-14
11
+
12
+ ## What's Changed
13
+ * MT-22401: Add Email Campaigns API by @Rabsztok in https://github.com/mailtrap/mailtrap-ruby/pull/119
14
+
15
+
16
+ **Full Changelog**: https://github.com/mailtrap/mailtrap-ruby/compare/v2.13.0...v2.14.0
17
+
1
18
  ## [2.13.0] - 2026-08-04
2
19
 
3
20
  ## What's Changed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mailtrap (2.13.0)
4
+ mailtrap (2.15.0)
5
5
  base64
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -179,6 +179,8 @@ Email API:
179
179
  - Sending Stats API – [`stats_api.rb`](examples/stats_api.rb)
180
180
  - Email Logs API – [`email_logs_api.rb`](examples/email_logs_api.rb)
181
181
  - Webhooks API – [`webhooks_api.rb`](examples/webhooks_api.rb)
182
+ - Suppressions API – [`suppressions_api.rb`](examples/suppressions_api.rb)
183
+ - Tracking Opt-outs API – [`tracking_opt_outs_api.rb`](examples/tracking_opt_outs_api.rb)
182
184
 
183
185
  Email Sandbox (Testing):
184
186
 
@@ -198,6 +200,10 @@ Contact management:
198
200
 
199
201
  - Contacts CRUD & Listing – [`contacts_api.rb`](examples/contacts_api.rb)
200
202
 
203
+ Email marketing:
204
+
205
+ - Email Campaigns CRUD, Lifecycle Actions & Stats – [`email_campaigns_api.rb`](examples/email_campaigns_api.rb)
206
+
201
207
  General:
202
208
 
203
209
  - Accounts API – [`accounts_api.rb`](examples/accounts_api.rb)
@@ -7,8 +7,6 @@ module Mailtrap
7
7
  class AccountAccessesAPI
8
8
  include BaseAPI
9
9
 
10
- attr_reader :account_id
11
-
12
10
  self.response_class = AccountAccess
13
11
 
14
12
  # Retrieves a list of account accesses with optional filtering by domain, inbox, or project IDs
@@ -9,8 +9,6 @@ module Mailtrap
9
9
 
10
10
  self.response_class = Account
11
11
 
12
- attr_reader :client
13
-
14
12
  # @param client [Mailtrap::Client] The client instance
15
13
  # @raise [ArgumentError] If account_id is nil
16
14
  def initialize(client = Mailtrap::Client.new)
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailtrap
4
+ # Data Transfer Object for Email Campaign Stats
5
+ #
6
+ # Aggregated campaign performance metrics. All counts and rates are +0+ when the
7
+ # campaign has not been started.
8
+ # @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/email-campaigns
9
+ # @attr_reader delivery_count [Integer] Number of delivered messages
10
+ # @attr_reader open_count [Integer] Number of opened messages
11
+ # @attr_reader click_count [Integer] Number of clicked messages
12
+ # @attr_reader bounce_count [Integer] Number of bounced messages
13
+ # @attr_reader unsubscription_count [Integer] Number of unsubscriptions
14
+ # @attr_reader sent_count [Integer] Number of sent messages
15
+ # @attr_reader spam_count [Integer] Number of spam complaints
16
+ # @attr_reader delivery_rate [Float] Share of sent messages that were delivered (0–1)
17
+ # @attr_reader open_rate [Float] Share of delivered messages that were opened (0–1)
18
+ # @attr_reader click_rate [Float] Share of delivered messages that were clicked (0–1)
19
+ # @attr_reader bounce_rate [Float] Share of sent messages that bounced (0–1)
20
+ # @attr_reader spam_rate [Float] Share of sent messages marked as spam (0–1)
21
+ # @attr_reader unsubscription_rate [Float] Share of delivered messages that unsubscribed (0–1)
22
+ EmailCampaignStats = Struct.new(
23
+ :delivery_count,
24
+ :open_count,
25
+ :click_count,
26
+ :bounce_count,
27
+ :unsubscription_count,
28
+ :sent_count,
29
+ :spam_count,
30
+ :delivery_rate,
31
+ :open_rate,
32
+ :click_rate,
33
+ :bounce_rate,
34
+ :spam_rate,
35
+ :unsubscription_rate,
36
+ keyword_init: true
37
+ )
38
+
39
+ # Data Transfer Object for Email Campaign
40
+ # @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/email-campaigns
41
+ # @attr_reader id [Integer] The email campaign ID
42
+ # @attr_reader domain_id [Integer] ID of the sending domain used for the campaign,
43
+ # as returned by the Sending Domains endpoints
44
+ # @attr_reader domain_name [String] Name of the sending domain used for the campaign
45
+ # @attr_reader name [String] Campaign name
46
+ # @attr_reader from_local_part [String] Local part (before the @) of the From address
47
+ # @attr_reader from_display_name [String] Display name shown in the From header
48
+ # @attr_reader reply_to [Hash, nil] Reply-To address parts (+display_name+, +local_part+, +domain+)
49
+ # @attr_reader current_state [String] Lifecycle state (+draft+, +scheduled+, +started+, +queued+,
50
+ # +paused+, +terminating+, +under_review+, +finished+, +failed+, +failed_immediately+)
51
+ # @attr_reader current_state_metadata [Hash, nil] Metadata about the most recent state transition
52
+ # (+reason+, +error+, +errors+ as an array of +{message, rcpt_index}+ objects, +scheduled_at+)
53
+ # @attr_reader created_at [String] The creation timestamp
54
+ # @attr_reader updated_at [String] The last update timestamp
55
+ # @attr_reader last_started_at [String, nil] When the campaign was last started, or +nil+
56
+ # @attr_reader last_started_at_date [String, nil] Date the campaign was last started, present only when started
57
+ # @attr_reader recipient_total_count [Integer, nil] Total number of recipients,
58
+ # or +nil+ until the audience is resolved
59
+ # @attr_reader contact_list_ids [Array<Integer>] IDs of the contact lists included in the campaign's audience
60
+ # @attr_reader contact_segment_ids [Array<Integer>] IDs of the contact segments included in the campaign's audience
61
+ # @attr_reader delivery_mode [String] How the campaign is delivered (+rapid+ or +gradual+)
62
+ # @attr_reader delivery_options [Hash, nil] Delivery throttling options (+emails_per_hour+)
63
+ # @attr_reader template [Hash, nil] The campaign template (+id+, +subject+, +merge_tags+,
64
+ # +body_html+, +body_text+; bodies are omitted on list responses)
65
+ EmailCampaign = Struct.new(
66
+ :id,
67
+ :domain_id,
68
+ :domain_name,
69
+ :name,
70
+ :from_local_part,
71
+ :from_display_name,
72
+ :reply_to,
73
+ :current_state,
74
+ :current_state_metadata,
75
+ :created_at,
76
+ :updated_at,
77
+ :last_started_at,
78
+ :last_started_at_date,
79
+ :recipient_total_count,
80
+ :contact_list_ids,
81
+ :contact_segment_ids,
82
+ :delivery_mode,
83
+ :delivery_options,
84
+ :template,
85
+ keyword_init: true
86
+ )
87
+
88
+ # Response from listing email campaigns (paginated)
89
+ # @see https://api-docs.mailtrap.io/docs/mailtrap-api-docs/email-campaigns
90
+ # @attr_reader data [Array<EmailCampaign>] Page of email campaigns, newest first
91
+ # @attr_reader pagination [Hash] Page-token pagination metadata
92
+ # (+token+, +prev_token+, +next_token+, +first_url+, +prev_url+, +current_url+, +next_url+)
93
+ EmailCampaignsListResponse = Struct.new(
94
+ :data,
95
+ :pagination,
96
+ keyword_init: true
97
+ )
98
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_api'
4
+ require_relative 'email_campaign'
5
+
6
+ module Mailtrap
7
+ class EmailCampaignsAPI
8
+ include BaseAPI
9
+
10
+ self.supported_options = %i[
11
+ name
12
+ domain_id
13
+ from_display_name
14
+ from_local_part
15
+ reply_to
16
+ template_attributes
17
+ delivery_mode
18
+ delivery_options
19
+ contact_list_ids
20
+ contact_segment_ids
21
+ ].freeze
22
+
23
+ self.response_class = EmailCampaign
24
+
25
+ # @param client [Mailtrap::Client] The client instance
26
+ def initialize(client = Mailtrap::Client.new)
27
+ @client = client
28
+ end
29
+
30
+ # Lists email campaigns for the account, newest first
31
+ # @param per_page [Integer, nil] Number of campaigns per page (max 100, default 50)
32
+ # @param search [String, nil] Filter campaigns by name
33
+ # @param token [Integer, nil] Page number to retrieve (page-token pagination, default 1)
34
+ # @return [EmailCampaignsListResponse] The page of campaigns and pagination metadata
35
+ # @!macro api_errors
36
+ def list(per_page: nil, search: nil, token: nil)
37
+ query_params = {}
38
+ query_params[:per_page] = per_page unless per_page.nil?
39
+ query_params[:search] = search unless search.nil?
40
+ query_params[:token] = token unless token.nil?
41
+
42
+ response = client.get(base_path, query_params)
43
+
44
+ EmailCampaignsListResponse.new(
45
+ data: Array(response[:data]).map { |item| build_entity(item, response_class) },
46
+ pagination: response[:pagination]
47
+ )
48
+ end
49
+
50
+ # Retrieves a specific email campaign
51
+ # @param email_campaign_id [Integer] The email campaign ID
52
+ # @return [EmailCampaign] Email campaign object
53
+ # @!macro api_errors
54
+ def get(email_campaign_id)
55
+ base_get(email_campaign_id)
56
+ end
57
+
58
+ # Creates a new email campaign in the +draft+ state
59
+ # @param [Hash] options The parameters to create
60
+ # @option options [String] :name Campaign name (required)
61
+ # @option options [Integer] :domain_id ID of the verified sending domain (required),
62
+ # as returned by the Sending Domains endpoints
63
+ # @option options [String] :from_display_name Display name shown in the From header
64
+ # @option options [String] :from_local_part Local part (before the @) of the From address (required)
65
+ # @option options [Hash] :reply_to Reply-To address parts (+display_name+, +local_part+, +domain+)
66
+ # @option options [Hash] :template_attributes Template attributes (+subject+ (required),
67
+ # +body_html+, +body_text+, +merge_tags+)
68
+ # @option options [String] :delivery_mode How the campaign is delivered (+rapid+ or +gradual+)
69
+ # @option options [Hash] :delivery_options Delivery throttling options (+emails_per_hour+),
70
+ # applies when +delivery_mode+ is +gradual+
71
+ # @option options [Array<Integer>] :contact_list_ids IDs of contact lists to send to
72
+ # @option options [Array<Integer>] :contact_segment_ids IDs of contact segments to send to
73
+ # @return [EmailCampaign] Created email campaign
74
+ # @!macro api_errors
75
+ # @raise [ArgumentError] If invalid options are provided
76
+ def create(options)
77
+ base_create(options)
78
+ end
79
+
80
+ # Updates an existing +draft+ email campaign. Only the provided attributes are changed;
81
+ # +template_attributes+ sub-fields are also updated partially, in place.
82
+ # @param email_campaign_id [Integer] The email campaign ID
83
+ # @param [Hash] options The parameters to update; accepts the same fields as {#create}
84
+ # @option options [String] :name Campaign name
85
+ # @option options [Integer] :domain_id ID of the verified sending domain,
86
+ # as returned by the Sending Domains endpoints
87
+ # @option options [String] :from_display_name Display name shown in the From header
88
+ # @option options [String] :from_local_part Local part (before the @) of the From address
89
+ # @option options [Hash] :reply_to Reply-To address parts (+display_name+, +local_part+, +domain+)
90
+ # @option options [Hash] :template_attributes Template attributes (+subject+, +body_html+,
91
+ # +body_text+, +merge_tags+)
92
+ # @option options [String] :delivery_mode How the campaign is delivered (+rapid+ or +gradual+)
93
+ # @option options [Hash] :delivery_options Delivery throttling options (+emails_per_hour+),
94
+ # applies when +delivery_mode+ is +gradual+
95
+ # @option options [Array<Integer>] :contact_list_ids IDs of contact lists to send to
96
+ # @option options [Array<Integer>] :contact_segment_ids IDs of contact segments to send to
97
+ # @return [EmailCampaign] Updated email campaign
98
+ # @!macro api_errors
99
+ # @raise [ArgumentError] If invalid options are provided
100
+ def update(email_campaign_id, options)
101
+ base_update(email_campaign_id, options)
102
+ end
103
+
104
+ # Deletes an email campaign. Only a campaign in the +draft+ state can be deleted.
105
+ # @param email_campaign_id [Integer] The email campaign ID
106
+ # @return [nil]
107
+ # @!macro api_errors
108
+ def delete(email_campaign_id)
109
+ base_delete(email_campaign_id)
110
+ end
111
+
112
+ # Starts sending a +draft+ campaign immediately
113
+ # @param email_campaign_id [Integer] The email campaign ID
114
+ # @return [EmailCampaign] The started email campaign
115
+ # @!macro api_errors
116
+ def start(email_campaign_id)
117
+ perform_action(email_campaign_id, :start)
118
+ end
119
+
120
+ # Schedules a +draft+ campaign to start sending at a future time.
121
+ # The time is reported back in +current_state_metadata.scheduled_at+.
122
+ # @param email_campaign_id [Integer] The email campaign ID
123
+ # @param datetime [String] When to send the campaign (ISO 8601); must be in the future
124
+ # and no more than 1 month ahead
125
+ # @return [EmailCampaign] The scheduled email campaign
126
+ # @!macro api_errors
127
+ def schedule(email_campaign_id, datetime)
128
+ perform_action(email_campaign_id, :schedule, { datetime: })
129
+ end
130
+
131
+ # Cancels a +scheduled+ campaign, returning it to the +draft+ state
132
+ # @param email_campaign_id [Integer] The email campaign ID
133
+ # @return [EmailCampaign] The cancelled email campaign
134
+ # @!macro api_errors
135
+ def cancel(email_campaign_id)
136
+ perform_action(email_campaign_id, :cancel)
137
+ end
138
+
139
+ # Terminates a campaign that is currently sending (+started+, +queued+, or +paused+),
140
+ # aborting the in-flight send
141
+ # @param email_campaign_id [Integer] The email campaign ID
142
+ # @return [EmailCampaign] The terminated email campaign
143
+ # @!macro api_errors
144
+ def terminate(email_campaign_id)
145
+ perform_action(email_campaign_id, :terminate)
146
+ end
147
+
148
+ # Resets a +scheduled+ campaign back to the +draft+ state
149
+ # @param email_campaign_id [Integer] The email campaign ID
150
+ # @return [EmailCampaign] The reset email campaign
151
+ # @!macro api_errors
152
+ def reset(email_campaign_id)
153
+ perform_action(email_campaign_id, :reset)
154
+ end
155
+
156
+ # Retrieves aggregated performance statistics for an email campaign.
157
+ # By default statistics are aggregated since the campaign was last started.
158
+ # @param email_campaign_id [Integer] The email campaign ID
159
+ # @param start_date [String, nil] Start of the aggregation window (inclusive), +YYYY-MM-DD+
160
+ # @param end_date [String, nil] End of the aggregation window (inclusive), +YYYY-MM-DD+
161
+ # @return [EmailCampaignStats] Aggregated campaign statistics
162
+ # @!macro api_errors
163
+ def stats(email_campaign_id, start_date: nil, end_date: nil)
164
+ query_params = {}
165
+ query_params[:start_date] = start_date unless start_date.nil?
166
+ query_params[:end_date] = end_date unless end_date.nil?
167
+
168
+ response = client.get("#{base_path}/#{email_campaign_id}/stats", query_params)
169
+ build_entity(response[:data], EmailCampaignStats)
170
+ end
171
+
172
+ private
173
+
174
+ def perform_action(email_campaign_id, action, body = nil)
175
+ response = client.post("#{base_path}/#{email_campaign_id}/#{action}", body)
176
+ handle_response(response)
177
+ end
178
+
179
+ def base_path
180
+ '/api/email_campaigns'
181
+ end
182
+
183
+ def handle_response(response)
184
+ build_entity(response[:data], response_class)
185
+ end
186
+ end
187
+ end
@@ -10,7 +10,6 @@ module Mailtrap
10
10
  self.supported_options = %i[name]
11
11
  self.response_class = InboundFolder
12
12
 
13
- # Inbound is scoped to the token's account, so no account_id is required.
14
13
  # @param client [Mailtrap::Client] The client instance
15
14
  def initialize(client = Mailtrap::Client.new)
16
15
  @client = client
@@ -12,7 +12,6 @@ module Mailtrap
12
12
  CREATE_OPTIONS = %i[name domain_id].freeze
13
13
  UPDATE_OPTIONS = %i[name].freeze
14
14
 
15
- # Inbound is scoped to the token's account, so no account_id is required.
16
15
  # @param client [Mailtrap::Client] The client instance
17
16
  def initialize(client = Mailtrap::Client.new)
18
17
  @client = client
@@ -14,7 +14,6 @@ module Mailtrap
14
14
 
15
15
  SEND_OPTIONS = %i[from to cc bcc reply_to text html category attachments headers custom_variables].freeze
16
16
 
17
- # Inbound is scoped to the token's account, so no account_id is required.
18
17
  # @param client [Mailtrap::Client] The client instance
19
18
  def initialize(client = Mailtrap::Client.new)
20
19
  @client = client
@@ -12,7 +12,6 @@ module Mailtrap
12
12
 
13
13
  self.response_class = InboundThread
14
14
 
15
- # Inbound is scoped to the token's account, so no account_id is required.
16
15
  # @param client [Mailtrap::Client] The client instance
17
16
  def initialize(client = Mailtrap::Client.new)
18
17
  @client = client
@@ -7,7 +7,7 @@ module Mailtrap
7
7
  class SandboxAttachmentsAPI
8
8
  include BaseAPI
9
9
 
10
- attr_reader :account_id, :inbox_id, :sandbox_message_id, :client
10
+ attr_reader :inbox_id, :sandbox_message_id
11
11
 
12
12
  self.response_class = SandboxAttachment
13
13
 
@@ -7,7 +7,7 @@ module Mailtrap
7
7
  class SandboxMessagesAPI
8
8
  include BaseAPI
9
9
 
10
- attr_reader :account_id, :inbox_id, :client
10
+ attr_reader :inbox_id
11
11
 
12
12
  self.supported_options = %i[is_read]
13
13
 
@@ -12,6 +12,7 @@ module Mailtrap
12
12
  # @attr_reader dns_records [Array] The DNS records for the sending domain
13
13
  # @attr_reader open_tracking_enabled [Boolean] Whether open tracking is enabled
14
14
  # @attr_reader click_tracking_enabled [Boolean] Whether click tracking is enabled
15
+ # @attr_reader tracking_opt_out_enabled [Boolean] Whether the tracking opt-out link is enabled
15
16
  # @attr_reader auto_unsubscribe_link_enabled [Boolean] Whether auto unsubscribe link is enabled
16
17
  # @attr_reader custom_domain_tracking_enabled [Boolean] Whether custom domain tracking is enabled
17
18
  # @attr_reader health_alerts_enabled [Boolean] Whether health alerts are enabled
@@ -31,6 +32,7 @@ module Mailtrap
31
32
  :dns_records,
32
33
  :open_tracking_enabled,
33
34
  :click_tracking_enabled,
35
+ :tracking_opt_out_enabled,
34
36
  :auto_unsubscribe_link_enabled,
35
37
  :custom_domain_tracking_enabled,
36
38
  :health_alerts_enabled,
@@ -7,7 +7,13 @@ module Mailtrap
7
7
  class SendingDomainsAPI
8
8
  include BaseAPI
9
9
 
10
- self.supported_options = %i[open_tracking_enabled click_tracking_enabled auto_unsubscribe_link_enabled]
10
+ self.supported_options = %i[
11
+ open_tracking_enabled
12
+ click_tracking_enabled
13
+ tracking_opt_out_enabled
14
+ auto_unsubscribe_link_enabled
15
+ inbound_enabled
16
+ ]
11
17
 
12
18
  self.response_class = SendingDomain
13
19
 
@@ -50,7 +56,9 @@ module Mailtrap
50
56
  # @param [Hash] options The parameters to update
51
57
  # @option options [Boolean] :open_tracking_enabled Enable open tracking for emails sent from this domain
52
58
  # @option options [Boolean] :click_tracking_enabled Enable click tracking for links in emails sent from this domain
59
+ # @option options [Boolean] :tracking_opt_out_enabled Enable the tracking opt-out link in tracked emails
53
60
  # @option options [Boolean] :auto_unsubscribe_link_enabled Automatically add an unsubscribe link to emails
61
+ # @option options [Boolean] :inbound_enabled Enable inbound email for this domain
54
62
  # @return [SendingDomain] Updated sending domain
55
63
  # @!macro api_errors
56
64
  # @raise [ArgumentError] If invalid options are provided
@@ -7,6 +7,8 @@ module Mailtrap
7
7
  class SuppressionsAPI
8
8
  include BaseAPI
9
9
 
10
+ self.supported_options = %i[email domain_id sending_stream type].freeze
11
+
10
12
  self.response_class = Suppression
11
13
 
12
14
  # Lists all suppressions for the account
@@ -20,12 +22,28 @@ module Mailtrap
20
22
  base_list(query_params)
21
23
  end
22
24
 
25
+ # Adds an email address to the account's suppression list
26
+ # @param [Hash] options The suppression attributes
27
+ # @option options [String] :email Email address to suppress
28
+ # @option options [Integer] :domain_id ID of the domain to suppress this email for
29
+ # @option options [String] :sending_stream The sending stream to suppress for: "transactional" or "bulk"
30
+ # @option options [String] :type Reason for the suppression, defaults to "manual import" when omitted
31
+ # @return [Suppression] Created suppression
32
+ # @!macro api_errors
33
+ # @raise [ArgumentError] If invalid options are provided
34
+ def create(options)
35
+ validate_options!(options, supported_options)
36
+ response = client.post(base_path, options)
37
+ build_entity(response[:data], Suppression)
38
+ end
39
+
23
40
  # Deletes a suppression
24
41
  # @param suppression_id [String] The suppression UUID
25
- # @return nil
42
+ # @return [Suppression] The deleted suppression
26
43
  # @!macro api_errors
27
44
  def delete(suppression_id)
28
- client.delete("#{base_path}/#{suppression_id}")
45
+ response = client.delete("#{base_path}/#{suppression_id}")
46
+ build_entity(response, Suppression)
29
47
  end
30
48
 
31
49
  private
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailtrap
4
+ # Data Transfer Object for Tracking Opt-out
5
+ # @see https://docs.mailtrap.io/developers/management/tracking-opt-outs
6
+ # @attr_reader id [String] The tracking opt-out UUID
7
+ # @attr_reader email [String] The email address opted out of tracking
8
+ # @attr_reader created_at [String] The creation timestamp
9
+ # @attr_reader domain_name [String, nil] Sending domain the tracking opt-out applies to
10
+ TrackingOptOut = Struct.new(
11
+ :id,
12
+ :email,
13
+ :created_at,
14
+ :domain_name,
15
+ keyword_init: true
16
+ )
17
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_api'
4
+ require_relative 'tracking_opt_out'
5
+ require_relative 'tracking_opt_outs_list_response'
6
+
7
+ module Mailtrap
8
+ class TrackingOptOutsAPI
9
+ include BaseAPI
10
+
11
+ self.supported_options = %i[email domain_id].freeze
12
+
13
+ self.response_class = TrackingOptOut
14
+
15
+ # @param client [Mailtrap::Client] The client instance
16
+ def initialize(client = Mailtrap::Client.new)
17
+ @client = client
18
+ end
19
+
20
+ # Lists email addresses that have opted out of open and click tracking
21
+ # @param email [String, nil] Filter by exact email address (case-insensitive)
22
+ # @param start_time [String, nil] Only opt-outs created at or after this ISO 8601 timestamp
23
+ # @param end_time [String, nil] Only opt-outs created at or before this ISO 8601 timestamp
24
+ # @param last_id [String, nil] Cursor from the previous response's +last_id+ for the next page
25
+ # @return [TrackingOptOutsListResponse] The page of tracking opt-outs and the next cursor
26
+ # @!macro api_errors
27
+ def list(email: nil, start_time: nil, end_time: nil, last_id: nil)
28
+ query_params = {}
29
+ query_params[:email] = email unless email.nil?
30
+ query_params[:start_time] = start_time unless start_time.nil?
31
+ query_params[:end_time] = end_time unless end_time.nil?
32
+ query_params[:last_id] = last_id unless last_id.nil?
33
+
34
+ response = client.get(base_path, query_params)
35
+
36
+ TrackingOptOutsListResponse.new(
37
+ data: Array(response[:data]).map { |item| build_entity(item, TrackingOptOut) },
38
+ last_id: response[:last_id]
39
+ )
40
+ end
41
+
42
+ # Adds an email address to the tracking opt-out list for a sending domain
43
+ # @param [Hash] options The tracking opt-out attributes
44
+ # @option options [String] :email Email address to opt out of tracking
45
+ # @option options [Integer] :domain_id ID of the sending domain the opt-out applies to
46
+ # @return [TrackingOptOut] Created tracking opt-out
47
+ # @!macro api_errors
48
+ # @raise [ArgumentError] If invalid options are provided
49
+ def create(options)
50
+ validate_options!(options, supported_options)
51
+ response = client.post(base_path, options)
52
+ build_entity(response[:data], TrackingOptOut)
53
+ end
54
+
55
+ # Removes an email address from the tracking opt-out list
56
+ # @param tracking_opt_out_id [String] The tracking opt-out UUID
57
+ # @return [TrackingOptOut] The deleted tracking opt-out
58
+ # @!macro api_errors
59
+ def delete(tracking_opt_out_id)
60
+ response = client.delete("#{base_path}/#{tracking_opt_out_id}")
61
+ build_entity(response, TrackingOptOut)
62
+ end
63
+
64
+ private
65
+
66
+ def base_path
67
+ '/api/tracking_opt_outs'
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailtrap
4
+ # Data Transfer Object for a paginated list of tracking opt-outs
5
+ # @see https://docs.mailtrap.io/developers/management/tracking-opt-outs
6
+ # @attr_reader data [Array<TrackingOptOut>] The tracking opt-outs on this page
7
+ # @attr_reader last_id [String, nil] Cursor for the next page, or nil if this is the last page
8
+ TrackingOptOutsListResponse = Struct.new(
9
+ :data,
10
+ :last_id,
11
+ keyword_init: true
12
+ )
13
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mailtrap
4
- VERSION = '2.13.0'
4
+ VERSION = '2.15.0'
5
5
  end
data/lib/mailtrap.rb CHANGED
@@ -18,6 +18,8 @@ require_relative 'mailtrap/contact_imports_api'
18
18
  require_relative 'mailtrap/contact_exports_api'
19
19
  require_relative 'mailtrap/contact_events_api'
20
20
  require_relative 'mailtrap/suppressions_api'
21
+ require_relative 'mailtrap/tracking_opt_outs_api'
22
+ require_relative 'mailtrap/email_campaigns_api'
21
23
  require_relative 'mailtrap/sending_domains_api'
22
24
  require_relative 'mailtrap/company_info_api'
23
25
  require_relative 'mailtrap/email_logs_api'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailtrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.0
4
+ version: 2.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Railsware Products Studio LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-04 00:00:00.000000000 Z
11
+ date: 2026-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -72,6 +72,8 @@ files:
72
72
  - lib/mailtrap/contact_lists_api.rb
73
73
  - lib/mailtrap/contacts_api.rb
74
74
  - lib/mailtrap/contacts_import_request.rb
75
+ - lib/mailtrap/email_campaign.rb
76
+ - lib/mailtrap/email_campaigns_api.rb
75
77
  - lib/mailtrap/email_log_event.rb
76
78
  - lib/mailtrap/email_log_event_details.rb
77
79
  - lib/mailtrap/email_log_message.rb
@@ -115,6 +117,9 @@ files:
115
117
  - lib/mailtrap/sub_accounts_api.rb
116
118
  - lib/mailtrap/suppression.rb
117
119
  - lib/mailtrap/suppressions_api.rb
120
+ - lib/mailtrap/tracking_opt_out.rb
121
+ - lib/mailtrap/tracking_opt_outs_api.rb
122
+ - lib/mailtrap/tracking_opt_outs_list_response.rb
118
123
  - lib/mailtrap/version.rb
119
124
  - lib/mailtrap/webhook.rb
120
125
  - lib/mailtrap/webhooks.rb