resend 1.5.0 → 1.7.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: a131df322ae7ac448440742ce3cda1487b763a094f1940710236cc1e4f76534d
4
- data.tar.gz: bb824f2076b51bf7eb82dd9a75ba4bd86c2d15162e8a499ef6b6e66555c37b2b
3
+ metadata.gz: cc6ad8469a98068e64cbfb9d6c021058d7e640f32eb5617e839a796c46491d39
4
+ data.tar.gz: 499a33038351ff07315bd8b10f9a7e0c9387c6d5b04fe12cf7a6c7ce5d2a80e8
5
5
  SHA512:
6
- metadata.gz: 01efcf455f3b05c468ee1aede05bfeae5d7040b3dae1b2faf6bc38571b422b273a097f1b7eeb41cdc6fcc55f0c2b2f81eb4718814897a982c61915b52aae7a15
7
- data.tar.gz: 4259936777bb6815e5abca38babf4b399efe5e2a0dfa55d87e2b1536b9f85b344683e0e9ee84ef21978630ad4e41dd6bc709d59bb5def667b412a37781af86df
6
+ metadata.gz: 9e3709cd8c049cc638118353571fc575f124132d998d8b69580484f0e2cd9b60ec1ce3c7c981c195b69185e8c70970d7fe30477a8c35a787f62563d2eb7952a6
7
+ data.tar.gz: 4e1fe85c2ba097d460b3cdf56a7ce42da70e91398965bdd2b688581c34db0715c884e66bf330e32b48381afd66d505b03a0ac19758b7eeec1e26c0ff194306ef
data/CHANGELOG.md CHANGED
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.7.0] - 2026-07-31
9
+
10
+ ### Added
11
+
12
+ - **Suppressions** - New `Resend::Suppressions` module to add (`add`), list (`list`), retrieve (`get`), and remove (`remove`) suppressed email addresses. `get` and `remove` accept either a suppression ID or the suppressed email address. `list` supports `origin` filtering (`bounce`, `complaint`, `manual`) plus the standard `limit`/`after`/`before` pagination params. New `Resend::Suppressions::Batch` module handles up to 100 addresses at a time via `add` and `remove`. ([#208](https://github.com/resend/resend-ruby/pull/208))
13
+
14
+ ### Changed
15
+
16
+ - ⚠️ **404 responses now raise `Resend::Error::NotFoundError`** instead of `Resend::Error::InvalidRequestError`, matching the documented intent of the (previously unreachable) `NotFoundError` class. Code rescuing `Resend::Error` or `Resend::Error::ServerError` is unaffected; code rescuing `InvalidRequestError` specifically to catch 404s should rescue `NotFoundError` instead. ([#210](https://github.com/resend/resend-ruby/pull/210))
17
+
18
+ ## [1.6.0] - 2026-07-09
19
+
20
+ ### Added
21
+
22
+ - **OAuth grants** - New `Resend::OAuthGrants` module to list (`GET /oauth/grants`) and revoke (`DELETE /oauth/grants/:id`) OAuth grants. `list` supports the standard `limit`/`after`/`before` pagination params. ([#197](https://github.com/resend/resend-ruby/pull/197))
23
+ - **Domain claims** - New `Resend::Domains::Claims` module to claim a domain verified by another account (`create`), retrieve the latest claim (`get`), and trigger verification/ownership transfer (`verify`). ([#194](https://github.com/resend/resend-ruby/pull/194))
24
+
8
25
  ## [1.0.0] - 2025-10-31
9
26
 
10
27
  ### Overview
@@ -128,4 +145,6 @@ Resend::Segments.remove("segment_123")
128
145
 
129
146
  - Remove deprecated `send_email` method from `Resend::Emails` module (use `Resend::Emails.send` instead)
130
147
 
148
+ [1.7.0]: https://github.com/resend/resend-ruby/compare/v1.6.0...v1.7.0
149
+ [1.6.0]: https://github.com/resend/resend-ruby/compare/v1.5.0...v1.6.0
131
150
  [1.0.0]: https://github.com/resend/resend-ruby/compare/v0.26.0...v1.0.0
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Domains
5
+ # Domain Claims API wrapper
6
+ module Claims
7
+ class << self
8
+ #
9
+ # Start a claim for a domain that another Resend account has already verified.
10
+ # The domain is recreated under your account with fresh DKIM keys, so the
11
+ # previous account's DNS records cannot be reused. Returns a TXT record to add
12
+ # to your DNS to prove ownership. Uses the same request body as creating a domain.
13
+ #
14
+ # @param params [Hash] the parameters
15
+ # @option params [String] :name the name of the domain you want to claim (required)
16
+ # @option params [String] :region the region where emails will be sent from.
17
+ # Possible values: 'us-east-1' | 'eu-west-1' | 'sa-east-1' | 'ap-northeast-1'
18
+ # @option params [String] :custom_return_path subdomain for the Return-Path address (default 'send')
19
+ # @option params [String] :tracking_subdomain the custom subdomain used for click and open tracking links
20
+ # @option params [Boolean] :click_tracking track clicks within the body of each HTML email
21
+ # @option params [Boolean] :open_tracking track the open rate of each email
22
+ #
23
+ # https://resend.com/docs/api-reference/domains/claim-domain
24
+ def create(params)
25
+ path = "domains/claim"
26
+ Resend::Request.new(path, params, "post").perform
27
+ end
28
+
29
+ #
30
+ # Retrieve the latest claim for the placeholder domain created by the claim.
31
+ #
32
+ # @param domain_id [String] the ID of the placeholder domain created by the claim
33
+ #
34
+ # https://resend.com/docs/api-reference/domains/get-domain-claim
35
+ def get(domain_id = "")
36
+ path = "domains/#{domain_id}/claim"
37
+ Resend::Request.new(path, {}, "get").perform
38
+ end
39
+
40
+ #
41
+ # Trigger asynchronous DNS verification and ownership transfer for a domain claim.
42
+ # The claim stays 'pending' while verification runs; poll `get` for status. Once
43
+ # 'completed', the transferred domain has new DKIM records that must be added to
44
+ # DNS and verified via Resend::Domains.verify.
45
+ #
46
+ # @param domain_id [String] the ID of the placeholder domain created by the claim
47
+ #
48
+ # https://resend.com/docs/api-reference/domains/verify-domain-claim
49
+ def verify(domain_id = "")
50
+ path = "domains/#{domain_id}/claim/verify"
51
+ Resend::Request.new(path, {}, "post").perform
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
data/lib/resend/errors.rb CHANGED
@@ -34,7 +34,7 @@ module Resend
34
34
 
35
35
  ERRORS = {
36
36
  401 => Resend::Error::InvalidRequestError,
37
- 404 => Resend::Error::InvalidRequestError,
37
+ 404 => Resend::Error::NotFoundError,
38
38
  422 => Resend::Error::InvalidRequestError,
39
39
  429 => Resend::Error::RateLimitExceededError,
40
40
  400 => Resend::Error::InvalidRequestError,
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # oauth grants api wrapper
5
+ module OAuthGrants
6
+ class << self
7
+ # https://resend.com/docs/api-reference/oauth/list-grants
8
+ def list(params = {})
9
+ path = Resend::PaginationHelper.build_paginated_path("oauth/grants", params)
10
+ Resend::Request.new(path, {}, "get").perform
11
+ end
12
+
13
+ # https://resend.com/docs/api-reference/oauth/revoke-grant
14
+ def revoke(oauth_grant_id = "")
15
+ path = "oauth/grants/#{oauth_grant_id}"
16
+ Resend::Request.new(path, {}, "delete").perform
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Suppressions
5
+ # Suppressions Batch API wrapper
6
+ module Batch
7
+ class << self
8
+ #
9
+ # Add up to 100 email addresses to the suppression list at once. Addresses that
10
+ # are already suppressed come back with their existing suppression instead of failing.
11
+ #
12
+ # @param params [Hash] the parameters
13
+ # @option params [Array<String>] :emails the email addresses to suppress (required, 1 to 100).
14
+ # The API lowercases and trims them.
15
+ #
16
+ # https://resend.com/docs/api-reference/suppressions/add-suppressions
17
+ def add(params)
18
+ Resend::Request.new("suppressions/batch/add", params, "post").perform
19
+ end
20
+
21
+ #
22
+ # Remove up to 100 suppressions at once, either by email address or by
23
+ # suppression ID. Provide exactly one of `emails` or `ids`.
24
+ #
25
+ # @param params [Hash] the parameters
26
+ # @option params [Array<String>] :emails the email addresses to remove (1 to 100)
27
+ # @option params [Array<String>] :ids the suppression IDs to remove (1 to 100), as UUIDs
28
+ #
29
+ # https://resend.com/docs/api-reference/suppressions/remove-suppressions
30
+ def remove(params)
31
+ normalized = params.transform_keys(&:to_sym)
32
+ emails = normalized[:emails]
33
+ ids = normalized[:ids]
34
+ raise ArgumentError, "Missing required `emails` or `ids` field" if emails.nil? && ids.nil?
35
+ raise ArgumentError, "Provide either `emails` or `ids`, but not both" if !emails.nil? && !ids.nil?
36
+
37
+ # The API rejects a null `emails`/`ids`, so the unused key is omitted rather than sent as nil.
38
+ body = emails.nil? ? { ids: ids } : { emails: emails }
39
+ Resend::Request.new("suppressions/batch/remove", body, "post").perform
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # Suppressions API wrapper
5
+ module Suppressions
6
+ class << self
7
+ #
8
+ # Add an email address to the suppression list. Suppressed addresses are
9
+ # skipped by future sends. Adding an address that is already suppressed
10
+ # succeeds and returns the existing suppression.
11
+ #
12
+ # @param params [Hash] the parameters
13
+ # @option params [String] :email the email address to suppress (required).
14
+ # The API lowercases and trims it.
15
+ #
16
+ # https://resend.com/docs/api-reference/suppressions/add-suppression
17
+ def add(params)
18
+ Resend::Request.new("suppressions", params, "post").perform
19
+ end
20
+
21
+ #
22
+ # Retrieve a list of suppressions. Each entry has `id`, `email`, `origin`,
23
+ # `source_id` and `created_at`; unlike `get`, list entries carry no `object` key.
24
+ #
25
+ # @param params [Hash] optional filtering and pagination parameters
26
+ # @option params [String] :origin filter by origin: 'bounce', 'complaint' or 'manual'
27
+ # @option params [Integer] :limit number of results to return (1-100)
28
+ # @option params [String] :after cursor for forward pagination
29
+ # @option params [String] :before cursor for backward pagination
30
+ #
31
+ # https://resend.com/docs/api-reference/suppressions/list-suppressions
32
+ def list(params = {})
33
+ path = Resend::PaginationHelper.build_paginated_path("suppressions", params)
34
+ Resend::Request.new(path, {}, "get").perform
35
+ end
36
+
37
+ #
38
+ # Retrieve a single suppression. The API returns 404 'Suppression not found'
39
+ # when the address or ID is not suppressed.
40
+ #
41
+ # @param id_or_email [String] the suppression ID or the suppressed email address (required)
42
+ #
43
+ # https://resend.com/docs/api-reference/suppressions/get-suppression
44
+ def get(id_or_email)
45
+ raise ArgumentError, "Missing required `id_or_email` field" if id_or_email.nil? || id_or_email.empty?
46
+
47
+ Resend::Request.new("suppressions/#{ERB::Util.url_encode(id_or_email)}", {}, "get").perform
48
+ end
49
+
50
+ #
51
+ # Remove a single suppression, which allows sending to that address again.
52
+ # The API returns 404 'Suppression not found' when the address or ID is not suppressed.
53
+ #
54
+ # @param id_or_email [String] the suppression ID or the suppressed email address (required)
55
+ #
56
+ # https://resend.com/docs/api-reference/suppressions/remove-suppression
57
+ def remove(id_or_email)
58
+ raise ArgumentError, "Missing required `id_or_email` field" if id_or_email.nil? || id_or_email.empty?
59
+
60
+ Resend::Request.new("suppressions/#{ERB::Util.url_encode(id_or_email)}", {}, "delete").perform
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Resend
4
- VERSION = "1.5.0"
4
+ VERSION = "1.7.0"
5
5
  end
data/lib/resend.rb CHANGED
@@ -7,6 +7,7 @@ require "resend/version"
7
7
  require "httparty"
8
8
  require "json"
9
9
  require "cgi"
10
+ require "erb"
10
11
  require "resend/errors"
11
12
  require "resend/response"
12
13
  require "resend/client"
@@ -25,6 +26,7 @@ require "resend/contacts/segments"
25
26
  require "resend/contacts/topics"
26
27
  require "resend/contact_properties"
27
28
  require "resend/domains"
29
+ require "resend/domains/claims"
28
30
  require "resend/emails"
29
31
  require "resend/templates"
30
32
  require "resend/emails/receiving"
@@ -33,9 +35,12 @@ require "resend/emails/receiving/attachments"
33
35
  require "resend/logs"
34
36
  require "resend/topics"
35
37
  require "resend/webhooks"
38
+ require "resend/oauth_grants"
36
39
  require "resend/automations"
37
40
  require "resend/automations/runs"
38
41
  require "resend/events"
42
+ require "resend/suppressions"
43
+ require "resend/suppressions/batch"
39
44
 
40
45
  # Rails
41
46
  require "resend/railtie" if defined?(Rails) && defined?(ActionMailer)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resend
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derich Pacheco
@@ -57,6 +57,7 @@ files:
57
57
  - lib/resend/contacts/segments.rb
58
58
  - lib/resend/contacts/topics.rb
59
59
  - lib/resend/domains.rb
60
+ - lib/resend/domains/claims.rb
60
61
  - lib/resend/emails.rb
61
62
  - lib/resend/emails/attachments.rb
62
63
  - lib/resend/emails/receiving.rb
@@ -66,11 +67,14 @@ files:
66
67
  - lib/resend/logs.rb
67
68
  - lib/resend/mailer.rb
68
69
  - lib/resend/multipart_request.rb
70
+ - lib/resend/oauth_grants.rb
69
71
  - lib/resend/pagination_helper.rb
70
72
  - lib/resend/railtie.rb
71
73
  - lib/resend/request.rb
72
74
  - lib/resend/response.rb
73
75
  - lib/resend/segments.rb
76
+ - lib/resend/suppressions.rb
77
+ - lib/resend/suppressions/batch.rb
74
78
  - lib/resend/templates.rb
75
79
  - lib/resend/topics.rb
76
80
  - lib/resend/version.rb