emailfuse 0.1.3 → 0.2.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: 1274876b4b77ade250f0c715be10ce93cb49d931bf8f0d76416eee9bba06d895
4
- data.tar.gz: 8dd9a41d488ba5208809541405c8c740018123cbb76107cf9189221a5eceebf9
3
+ metadata.gz: ed5308d363064b9bea74f6d008a55bde447dc2f956689a2d357e8ce8467775b9
4
+ data.tar.gz: 259675d6b858aba7da91e34b31e7a199ab5f98b70b81bbc0c64b8e72c959c01f
5
5
  SHA512:
6
- metadata.gz: 74bd64f6dce3054139754fdd6d5c7102ac432ca8f7427ad6883f21c61ead4ae254b601573ab0fb3ba3f3fde7823ef9b6fd1217b794ce7b21f817b4c989db7b59
7
- data.tar.gz: ede7dab82a61cae0ce9f2741f64491d9122679edd2034d8ede4fad88662db1188d8f52dd4e3a016e5a6d8b76f22c40d2d1e085d6c7239d68691f59257f9f690b
6
+ metadata.gz: eb5deeb16c7d71d1873557cbbdace95c73e3d3c913f4a157f8c55345ce3c06636d16abbbb69d5a268b461b4dbec81faa15d435db1a6e77f311f60183b4127027
7
+ data.tar.gz: cd86a4342f1994e0462f90537de60d36e29baea5b737fa383bd6d5cdb8bde5e943dc4910a3fd3332c4b50eeeba0c9d8132344c641bcb773373f8f319928c0bcf
data/CHANGELOG.md ADDED
@@ -0,0 +1,131 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-10-31
9
+
10
+ ### Overview
11
+
12
+ This major release introduces breaking changes to the Contacts API and deprecates the Audiences API in favor of Segments. **If you only use the SDK for sending emails or the Audiences API, you can upgrade to v1.0.0 without any code changes.** The breaking changes are limited to the Contacts API only.
13
+
14
+ ### ⚠️ BREAKING CHANGES
15
+
16
+ #### Contacts API Changes
17
+
18
+ - ⚠️ **Change `Contacts.create` to accept hash parameter with optional `audience_id`** - Previously required `audience_id` in params, now it's optional. Supports global contacts.
19
+ - ⚠️ **Change `Contacts.get` from `get(audience_id, id)` to `get(params)`** - Now accepts a hash with optional `audience_id` and required `id` or `email`. Raises `ArgumentError: "Missing \`id\` or \`email\` field"` when neither is provided.
20
+ - ⚠️ **Change `Contacts.list` from `list(audience_id, params = {})` to `list(params = {})`** - Now accepts a hash with optional `audience_id` and pagination params
21
+ - ⚠️ **Change `Contacts.remove` from `remove(audience_id, contact_id)` to `remove(params)`** - Now accepts a hash with optional `audience_id` and required `id` or `email`. Raises `ArgumentError: "Missing \`id\` or \`email\` field"` when neither is provided.
22
+ - ⚠️ **Change `Contacts.update` error message** - Error changed from `"id or email is required"` to `"Missing \`id\` or \`email\` field"` to match Node.js SDK format
23
+ - ⚠️ **Change `Contacts.update` to accept optional `audience_id`** - Previously required `audience_id` in params, now it's optional
24
+
25
+ **Before (v0.x):**
26
+
27
+ ```ruby
28
+ # Methods used positional arguments and required audience_id
29
+ Resend::Contacts.create(audience_id: "aud_123", email: "user@example.com", first_name: "John")
30
+ contact = Resend::Contacts.get("aud_123", "contact_123")
31
+ contacts = Resend::Contacts.list("aud_123")
32
+ contacts = Resend::Contacts.list("aud_123", limit: 10)
33
+ Resend::Contacts.update(audience_id: "aud_123", id: "contact_123", first_name: "Jane")
34
+ Resend::Contacts.remove("aud_123", "contact_123")
35
+ ```
36
+
37
+ **After (v1.0.0):**
38
+
39
+ ```ruby
40
+ # Methods use hash parameters and support optional audience_id
41
+ # Global contacts (no audience_id)
42
+ Resend::Contacts.create(email: "user@example.com", first_name: "John")
43
+ contact = Resend::Contacts.get(id: "contact_123")
44
+ contact = Resend::Contacts.get(email: "user@example.com")
45
+ contacts = Resend::Contacts.list
46
+ contacts = Resend::Contacts.list(limit: 10)
47
+ Resend::Contacts.update(id: "contact_123", first_name: "Jane")
48
+ Resend::Contacts.remove(id: "contact_123")
49
+
50
+ # Audience-scoped contacts (with audience_id)
51
+ Resend::Contacts.create(audience_id: "aud_123", email: "user@example.com", first_name: "John")
52
+ contact = Resend::Contacts.get(audience_id: "aud_123", id: "contact_123")
53
+ contacts = Resend::Contacts.list(audience_id: "aud_123", limit: 10)
54
+ Resend::Contacts.update(audience_id: "aud_123", id: "contact_123", first_name: "Jane")
55
+ Resend::Contacts.remove(audience_id: "aud_123", id: "contact_123")
56
+ ```
57
+
58
+ #### Audiences API Deprecated
59
+
60
+ - ⚠️ **Deprecate `Resend::Audiences` in favor of `Resend::Segments`** - The Audiences module has been replaced with Segments. A backward-compatible alias `Audiences = Segments` has been added, so existing code will continue to work.
61
+
62
+ **Migration (Recommended):**
63
+
64
+ Update your code to use `Segments` instead of `Audiences`:
65
+
66
+ ```ruby
67
+ # Before (still works but deprecated)
68
+ Resend::Audiences.create(name: "My Audience")
69
+ Resend::Audiences.get("audience_123")
70
+ Resend::Audiences.list
71
+ Resend::Audiences.remove("audience_123")
72
+
73
+ # After (recommended)
74
+ Resend::Segments.create(name: "My Segment")
75
+ Resend::Segments.get("segment_123")
76
+ Resend::Segments.list
77
+ Resend::Segments.remove("segment_123")
78
+ ```
79
+
80
+ **Note:** The `Audiences` alias is deprecated and may be removed in a future major version. Please migrate to `Segments`.
81
+
82
+ ### Added
83
+
84
+ #### New API Modules
85
+
86
+ - Add `Resend::Templates` API for managing email templates
87
+ - `Templates.create` - Create a new template
88
+ - `Templates.get` - Retrieve a template by ID
89
+ - `Templates.update` - Update an existing template
90
+ - `Templates.publish` - Publish a template
91
+ - `Templates.duplicate` - Duplicate an existing template
92
+ - `Templates.list` - List all templates with pagination
93
+ - `Templates.remove` - Delete a template
94
+ - Add `Resend::Topics` API for managing topics
95
+ - `Topics.create` - Create a new topic
96
+ - `Topics.get` - Retrieve a topic by ID
97
+ - `Topics.update` - Update a topic
98
+ - `Topics.list` - List all topics with pagination
99
+ - `Topics.remove` - Delete a topic
100
+ - Add `Resend::Segments` API for managing segments (replacement for Audiences)
101
+ - `Segments.create` - Create a new segment
102
+ - `Segments.get` - Retrieve a segment by ID
103
+ - `Segments.list` - List all segments
104
+ - `Segments.remove` - Delete a segment
105
+ - Add `Resend::ContactProperties` API for managing custom contact properties
106
+ - `ContactProperties.update` - Update contact properties (validates and raises `ArgumentError: "Missing \`id\` field"` when id is not provided)
107
+ - `ContactProperties.get` - Retrieve contact properties by ID
108
+ - Add `Resend::Contacts::Segments` API for managing contact-segment relationships
109
+ - `Contacts::Segments.list` - List all segments for a contact
110
+ - `Contacts::Segments.add` - Add a contact to a segment
111
+ - `Contacts::Segments.remove` - Remove a contact from a segment
112
+ - Add `Resend::Contacts::Topics` API for managing contact topic subscriptions
113
+ - `Contacts::Topics.list` - List topic subscriptions for a contact
114
+ - `Contacts::Topics.update` - Update topic subscriptions (opt-in/opt-out) for a contact
115
+
116
+ #### Contacts API Enhancements
117
+
118
+ - Add support for `email` parameter in `Contacts.get` and `Contacts.remove` methods (can now use email instead of ID)
119
+ - Add `audience_id` support in Contacts API methods for scoped operations
120
+ - Add support for global contacts (contacts not scoped to a specific audience/segment)
121
+ - Add validation error messages matching Node.js SDK format with backticks around field names
122
+
123
+ #### Broadcasts API Updates
124
+
125
+ - Add deprecation warnings for `audience_id` in `Broadcasts.create` and `Broadcasts.update` (use `segment_id` instead)
126
+
127
+ ### Removed
128
+
129
+ - Remove deprecated `send_email` method from `Resend::Emails` module (use `Resend::Emails.send` instead)
130
+
131
+ [1.0.0]: https://github.com/resend/resend-ruby/compare/v0.26.0...v1.0.0
data/README.md CHANGED
@@ -1,22 +1,103 @@
1
- # Emailfuse Gem
1
+ # EmailFuse Ruby and Rails SDK
2
2
 
3
- An API wrapper for Emailfuse, including a Rails Action Mailer adapter.
3
+ ---
4
4
 
5
- ## Installing
5
+ ## Installation
6
6
 
7
- In your `Gemfile`
7
+ To install EmailFuse Ruby and Rails SDK, simply execute the following command in a terminal:
8
+
9
+ Via RubyGems:
10
+
11
+ ```
12
+ gem install emailfuse
13
+ ```
14
+
15
+ Via Gemfile:
16
+
17
+ ```
18
+ gem 'emailfuse'
19
+ ```
20
+
21
+ ## Setup
8
22
 
9
23
  ```ruby
10
- gem "emailfuse"
24
+ require "emailfuse"
25
+ EmailFuse.api_key = ENV["EMAILFUSE_API_KEY"]
26
+ ```
27
+
28
+ or
29
+
30
+ ```ruby
31
+ require "emailfuse"
32
+ EmailFuse.configure do |config|
33
+ config.api_key = ENV["EMAILFUSE_API_KEY"]
34
+ end
35
+ ```
36
+
37
+ ## Example
38
+
39
+ ```rb
40
+ require "emailfuse"
41
+
42
+ EmailFuse.api_key = ENV["EMAILFUSE_API_KEY"]
43
+
44
+ params = {
45
+ "from": "onboarding@resend.dev",
46
+ "to": ["delivered@resend.dev", "your@email.com"],
47
+ "html": "<h1>Hello World</h1>",
48
+ "subject": "Hey"
49
+ }
50
+ r = EmailFuse::Emails.send(params)
51
+ puts r
11
52
  ```
12
53
 
13
- ## Usage
54
+ # Rails and ActionMailer support
14
55
 
15
- Create an initializer file in `config/initializers/emailfuse.rb` with the following:
56
+ This gem can be used as an ActionMailer delivery method, add this to your `config/environments/environment.rb` file.
16
57
 
17
58
  ```ruby
18
59
  config.action_mailer.delivery_method = :emailfuse
19
- Emailfuse.configure do |config|
20
- config.token = ENV["EMAILFUSE_TOKEN"]
60
+ ```
61
+
62
+ ### Configuration Options
63
+
64
+ You can configure the API key and host in two ways:
65
+
66
+ #### Option 1: Global Configuration (Initializer)
67
+
68
+ Create or update your mailer initializer file:
69
+
70
+ ```rb
71
+ # /config/initializers/emailfuse.rb
72
+ EmailFuse.configure do |config|
73
+ config.api_key = ENV["EMAILFUSE_API_KEY"]
74
+ config.base_url = "https://api.emailfuse.net" # optional, defaults to https://api.emailfuse.net
21
75
  end
22
76
  ```
77
+
78
+ #### Option 2: Rails Mailer Settings
79
+
80
+ Configure directly in your environment file:
81
+
82
+ ```ruby
83
+ # config/environments/production.rb
84
+ config.action_mailer.delivery_method = :emailfuse
85
+ config.action_mailer.emailfuse_settings = {
86
+ api_key: ENV["EMAILFUSE_API_KEY"],
87
+ host: "https://api.emailfuse.net" # optional
88
+ }
89
+ ```
90
+
91
+ Settings configured via `emailfuse_settings` take precedence over the global configuration, allowing you to use different credentials per environment.
92
+
93
+ ### Sending Emails
94
+
95
+ After configuration, you can use `deliver_now!`:
96
+
97
+ ```ruby
98
+ mailer = EmailMailer.email(self)
99
+ response = mailer.deliver_now!
100
+
101
+ puts response[:id]
102
+ # => "b8f94710-0d84-429c-925a-22d3d8f86916"
103
+ ```
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailFuse
4
+ # Module responsible for wrapping Batch email sending API
5
+ module Batch
6
+ class << self
7
+ # Send a batch of emails
8
+ #
9
+ # @param params [Array<Hash>] Array of email parameters (max 100 emails)
10
+ # @param options [Hash] Additional options for the request
11
+ # @option options [String] :idempotency_key Optional idempotency key
12
+ # @option options [String] :batch_validation Batch validation mode: "strict" (default) or "permissive"
13
+ # - "strict": Entire batch fails if any email is invalid
14
+ # - "permissive": Sends valid emails and returns errors for invalid ones
15
+ #
16
+ # @return [Hash] Response with :data array and optional :errors array (in permissive mode)
17
+ #
18
+ # @example Send batch with strict validation (default)
19
+ # EmailFuse::Batch.send([
20
+ # { from: "sender@example.com", to: ["recipient@example.com"], subject: "Hello", html: "<p>Hi</p>" }
21
+ # ])
22
+ #
23
+ # @example Send batch with permissive validation
24
+ # response = EmailFuse::Batch.send(emails, options: { batch_validation: "permissive" })
25
+ # # response[:data] contains successful email IDs
26
+ # # response[:errors] contains validation errors with index and message
27
+ #
28
+ # https://resend.com/docs/api-reference/emails/send-batch-emails
29
+ def send(params = [], options: {})
30
+ path = "emails/batch"
31
+
32
+ EmailFuse::Request.new(path, params, "post", options: options).perform
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # backwards compatibility
4
+ require "email_fuse/emails"
5
+
6
+ module EmailFuse
7
+ # Client class.
8
+ class Client
9
+ include EmailFuse::Emails
10
+
11
+ attr_reader :api_key
12
+
13
+ def initialize(api_key)
14
+ raise ArgumentError, "API Key is not a string" unless api_key.is_a?(String)
15
+
16
+ @api_key = api_key
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailFuse
4
+ module Emails
5
+ # Module for sent email attachments API operations
6
+ module Attachments
7
+ class << self
8
+ # Retrieve a single attachment from a sent email
9
+ #
10
+ # @param params [Hash] Parameters for retrieving the attachment
11
+ # @option params [String] :id The attachment ID (required)
12
+ # @option params [String] :email_id The email ID (required)
13
+ # @return [Hash] The attachment object
14
+ #
15
+ # @example
16
+ # EmailFuse::Emails::Attachments.get(
17
+ # id: "2a0c9ce0-3112-4728-976e-47ddcd16a318",
18
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
19
+ # )
20
+ def get(params = {})
21
+ attachment_id = params[:id]
22
+ email_id = params[:email_id]
23
+
24
+ path = "emails/#{email_id}/attachments/#{attachment_id}"
25
+ EmailFuse::Request.new(path, {}, "get").perform
26
+ end
27
+
28
+ # List attachments from a sent email with optional pagination
29
+ #
30
+ # @param params [Hash] Parameters for listing attachments
31
+ # @option params [String] :email_id The email ID (required)
32
+ # @option params [Integer] :limit Maximum number of attachments to return (1-100)
33
+ # @option params [String] :after Cursor for pagination (newer attachments)
34
+ # @option params [String] :before Cursor for pagination (older attachments)
35
+ # @return [Hash] List of attachments with pagination info
36
+ #
37
+ # @example List all attachments
38
+ # EmailFuse::Emails::Attachments.list(
39
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
40
+ # )
41
+ #
42
+ # @example List with custom limit
43
+ # EmailFuse::Emails::Attachments.list(
44
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
45
+ # limit: 50
46
+ # )
47
+ #
48
+ # @example List with pagination
49
+ # EmailFuse::Emails::Attachments.list(
50
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
51
+ # limit: 20,
52
+ # after: "attachment_id_123"
53
+ # )
54
+ def list(params = {})
55
+ email_id = params[:email_id]
56
+ base_path = "emails/#{email_id}/attachments"
57
+
58
+ # Extract pagination parameters
59
+ pagination_params = params.slice(:limit, :after, :before)
60
+
61
+ path = EmailFuse::PaginationHelper.build_paginated_path(base_path, pagination_params)
62
+ EmailFuse::Request.new(path, {}, "get").perform
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailFuse
4
+ module Emails
5
+ module Receiving
6
+ # Module for received email attachments API operations
7
+ module Attachments
8
+ class << self
9
+ # Retrieve a single attachment from a received email
10
+ #
11
+ # @param params [Hash] Parameters for retrieving the attachment
12
+ # @option params [String] :id The attachment ID (required)
13
+ # @option params [String] :email_id The email ID (required)
14
+ # @return [Hash] The attachment object
15
+ #
16
+ # @example
17
+ # EmailFuse::Emails::Receiving::Attachments.get(
18
+ # id: "2a0c9ce0-3112-4728-976e-47ddcd16a318",
19
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
20
+ # )
21
+ def get(params = {})
22
+ attachment_id = params[:id]
23
+ email_id = params[:email_id]
24
+
25
+ path = "emails/receiving/#{email_id}/attachments/#{attachment_id}"
26
+ EmailFuse::Request.new(path, {}, "get").perform
27
+ end
28
+
29
+ # List attachments from a received email with optional pagination
30
+ #
31
+ # @param params [Hash] Parameters for listing attachments
32
+ # @option params [String] :email_id The email ID (required)
33
+ # @option params [Integer] :limit Maximum number of attachments to return (1-100)
34
+ # @option params [String] :after Cursor for pagination (newer attachments)
35
+ # @option params [String] :before Cursor for pagination (older attachments)
36
+ # @return [Hash] List of attachments with pagination info
37
+ #
38
+ # @example List all attachments
39
+ # EmailFuse::Emails::Receiving::Attachments.list(
40
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
41
+ # )
42
+ #
43
+ # @example List with custom limit
44
+ # EmailFuse::Emails::Receiving::Attachments.list(
45
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
46
+ # limit: 50
47
+ # )
48
+ #
49
+ # @example List with pagination
50
+ # EmailFuse::Emails::Receiving::Attachments.list(
51
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
52
+ # limit: 20,
53
+ # after: "attachment_id_123"
54
+ # )
55
+ def list(params = {})
56
+ email_id = params[:email_id]
57
+ base_path = "emails/receiving/#{email_id}/attachments"
58
+
59
+ # Extract pagination parameters
60
+ pagination_params = params.slice(:limit, :after, :before)
61
+
62
+ path = EmailFuse::PaginationHelper.build_paginated_path(base_path, pagination_params)
63
+ EmailFuse::Request.new(path, {}, "get").perform
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailFuse
4
+ module Emails
5
+ # Module for receiving emails API operations
6
+ module Receiving
7
+ class << self
8
+ # Retrieve a single received email
9
+ #
10
+ # @param email_id [String] The ID of the received email
11
+ # @return [Hash] The received email object
12
+ #
13
+ # @example
14
+ # EmailFuse::Emails::Receiving.get("4ef9a417-02e9-4d39-ad75-9611e0fcc33c")
15
+ def get(email_id = "")
16
+ path = "emails/receiving/#{email_id}"
17
+ EmailFuse::Request.new(path, {}, "get").perform
18
+ end
19
+
20
+ # List received emails with optional pagination
21
+ #
22
+ # @param params [Hash] Optional parameters for pagination
23
+ # @option params [Integer] :limit Maximum number of emails to return (1-100)
24
+ # @option params [String] :after Cursor for pagination (newer emails)
25
+ # @option params [String] :before Cursor for pagination (older emails)
26
+ # @return [Hash] List of received emails with pagination info
27
+ #
28
+ # @example List all received emails
29
+ # EmailFuse::Emails::Receiving.list
30
+ #
31
+ # @example List with custom limit
32
+ # EmailFuse::Emails::Receiving.list(limit: 50)
33
+ #
34
+ # @example List with pagination
35
+ # EmailFuse::Emails::Receiving.list(limit: 20, after: "email_id_123")
36
+ def list(params = {})
37
+ path = EmailFuse::PaginationHelper.build_paginated_path("emails/receiving", params)
38
+ EmailFuse::Request.new(path, {}, "get").perform
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailFuse
4
+ # Module responsible for wrapping email sending API
5
+ module Emails
6
+ class << self
7
+ # Sends or schedules an email.
8
+ # see more: https://resend.com/docs/api-reference/emails/send-email
9
+ def send(params, options: {})
10
+ path = "emails"
11
+ EmailFuse::Request.new(path, params, "post", options: options).perform
12
+ end
13
+
14
+ # Retrieve a single email.
15
+ # see more: https://resend.com/docs/api-reference/emails/retrieve-email
16
+ def get(email_id = "")
17
+ path = "emails/#{email_id}"
18
+ EmailFuse::Request.new(path, {}, "get").perform
19
+ end
20
+
21
+ # Update a scheduled email.
22
+ # see more: https://resend.com/docs/api-reference/emails/update-email
23
+ def update(params)
24
+ path = "emails/#{params[:email_id]}"
25
+ EmailFuse::Request.new(path, params, "patch").perform
26
+ end
27
+
28
+ # Cancel a scheduled email.
29
+ # see more: https://resend.com/docs/api-reference/emails/cancel-email
30
+ def cancel(email_id = "")
31
+ path = "emails/#{email_id}/cancel"
32
+ EmailFuse::Request.new(path, {}, "post").perform
33
+ end
34
+
35
+ # List emails with optional pagination.
36
+ # see more: https://resend.com/docs/api-reference/emails/list-emails
37
+ #
38
+ # @param options [Hash] Optional parameters for pagination
39
+ # @option options [Integer] :limit Maximum number of emails to return (1-100, default 20)
40
+ # @option options [String] :after Cursor for pagination (newer emails)
41
+ # @option options [String] :before Cursor for pagination (older emails)
42
+ def list(options = {})
43
+ path = "emails"
44
+
45
+ # Build query parameters, filtering out nil values
46
+ query_params = {}
47
+ query_params[:limit] = options[:limit] if options[:limit]
48
+ query_params[:after] = options[:after] if options[:after]
49
+ query_params[:before] = options[:before] if options[:before]
50
+
51
+ EmailFuse::Request.new(path, query_params, "get").perform
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EmailFuse
4
+ # Errors wrapper class
5
+ # For more info: https://resend.com/docs/api-reference/error-codes
6
+ class Error < StandardError
7
+ # 4xx HTTP status code
8
+ ClientError = Class.new(self)
9
+
10
+ # 5xx HTTP status code
11
+ ServerError = Class.new(self)
12
+
13
+ # code 500
14
+ InternalServerError = Class.new(ServerError)
15
+
16
+ # code 422
17
+ InvalidRequestError = Class.new(ServerError)
18
+
19
+ # code 429
20
+ class RateLimitExceededError < ServerError
21
+ attr_reader :rate_limit_limit, :rate_limit_remaining, :rate_limit_reset, :retry_after
22
+
23
+ def initialize(msg, code = nil, headers = {})
24
+ super(msg, code, headers)
25
+ @rate_limit_limit = headers["ratelimit-limit"]&.to_i
26
+ @rate_limit_remaining = headers["ratelimit-remaining"]&.to_i
27
+ @rate_limit_reset = headers["ratelimit-reset"]&.to_i
28
+ @retry_after = headers["retry-after"]&.to_i
29
+ end
30
+ end
31
+
32
+ # code 404
33
+ NotFoundError = Class.new(ServerError)
34
+
35
+ ERRORS = {
36
+ 401 => EmailFuse::Error::InvalidRequestError,
37
+ 404 => EmailFuse::Error::InvalidRequestError,
38
+ 422 => EmailFuse::Error::InvalidRequestError,
39
+ 429 => EmailFuse::Error::RateLimitExceededError,
40
+ 400 => EmailFuse::Error::InvalidRequestError,
41
+ 500 => EmailFuse::Error::InternalServerError
42
+ }.freeze
43
+
44
+ attr_reader :headers
45
+
46
+ def initialize(msg, code = nil, headers = {})
47
+ super(msg)
48
+ @code = code
49
+ @headers = headers
50
+ end
51
+ end
52
+ end