resend 0.2.1 → 0.4.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: aab8a1f078990a6a2c6e40c01f4b72771915d74e5ad8fa19fec67d9e0d00dc7e
4
- data.tar.gz: c440488de4a502b5abf3fbe79a83cd3535039fab30533308176f7b39b24477df
3
+ metadata.gz: e3e46d09490b1ad19c59f04e55fd16b0da3d3c2573ed5c9dcba3297f0f92f5fc
4
+ data.tar.gz: 6c9dfb7910fd6199bc9c75aa9f3c2e9200677ce9e2ba1e9a29e124908489e714
5
5
  SHA512:
6
- metadata.gz: 577cb058bcada5f1cb56820c7ae1a6ba0f93da4035b1ac82d487fc3768a3c9b77a091a76b9cb5a91d5cb4a0331c8d6294f1b629ac40e86e6452e2d99c237b765
7
- data.tar.gz: 037aa163eea257ab8c8a779d58dad4bbc166d69d979d258a578843d3229a35d5a90b337d4dd0d4d8680d27707c2ead0be5b8142fa7cf190ab4bbc0674a4149ca
6
+ metadata.gz: 58e0cdd7ae1d48654ff33761b1fcb8a4e96061142d154232f85bac348c38956505d11ee3a0cdf6d86592389d2d8c69eba48941d7d97e1c4de904d0c8b5b6d7a6
7
+ data.tar.gz: 2069dfd99a67245da05ebf8e58658c2771de51cd6999d8d824116174b0aeba38dcc4f4423f05cb73e63388f5497377dba4c4b98eebddba2b2205864530790d3a
data/README.md CHANGED
@@ -16,7 +16,7 @@ gem install resend
16
16
 
17
17
  Via Gemfile:
18
18
  ```
19
- gem 'resend', '~>0.2.1'
19
+ gem 'resend', '~>0.3.0'
20
20
  ```
21
21
 
22
22
  ## Setup
@@ -25,7 +25,16 @@ First, you need to get an API key, which is available in the [Resend Dashboard](
25
25
 
26
26
  ```ruby
27
27
  require "resend"
28
- client = Resend::Client.new "re_YOUR_API_KEY"
28
+ Resend.api_key = ENV["RESEND_API_KEY"]
29
+ ```
30
+
31
+ or
32
+
33
+ ```ruby
34
+ require "resend"
35
+ Resend.configure do |config|
36
+ config.api_key = ENV["RESEND_API_KEY"]
37
+ end
29
38
  ```
30
39
 
31
40
  ## Example
@@ -33,18 +42,21 @@ client = Resend::Client.new "re_YOUR_API_KEY"
33
42
  ```rb
34
43
  require "resend"
35
44
 
36
- client = Resend::Client.new "re_YOUR_API_KEY"
45
+ Resend.api_key = ENV["RESEND_API_KEY"]
37
46
 
38
47
  params = {
39
- "from": "team@recomendo.io",
40
- "to": "carlosderich@gmail.com",
48
+ "from": "from@email.io",
49
+ "to": ["to@email.com", "to1@gmail.com"],
41
50
  "html": "<h1>Hello World</h1>",
42
51
  "subject": "Hey"
43
52
  }
44
- r = client.send_email(params)
53
+ r = Resend::Emails.send(params)
45
54
  puts r
46
55
  ```
47
56
 
57
+ You can view all the examples in the [examples folder](https://github.com/drish/resend-ruby/tree/main/examples)
58
+
59
+
48
60
  # Rails and ActiveMailer support
49
61
 
50
62
  This gem can be used as an ActionMailer delivery method, add this to your `config/environments/environment.rb` file and replace with your api key.
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resend/request"
4
+ require "resend/errors"
5
+
6
+ module Resend
7
+ # api keys api wrapper
8
+ module ApiKeys
9
+ class << self
10
+ # https://resend.com/docs/api-reference/api-keys/create-api-key
11
+ def create(params)
12
+ path = "/api-keys"
13
+ Resend::Request.new(path, params, "post").perform
14
+ end
15
+
16
+ # https://resend.com/docs/api-reference/api-keys/list-api-keys
17
+ def list
18
+ path = "/api-keys"
19
+ Resend::Request.new(path, {}, "get").perform
20
+ end
21
+
22
+ # https://resend.com/docs/api-reference/api-keys/delete-api-key
23
+ def remove(api_key_id = "")
24
+ path = "/api-keys/#{api_key_id}"
25
+ Resend::Request.new(path, {}, "delete").perform
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/resend/client.rb CHANGED
@@ -1,62 +1,21 @@
1
- require_relative "./version"
2
- require_relative "./errors"
1
+ # frozen_string_literal: true
2
+
3
+ require "resend/api_keys"
4
+ require "resend/domains"
5
+ require "resend/emails"
3
6
  require "httparty"
4
7
 
5
8
  module Resend
6
-
9
+ # Client class.
7
10
  class Client
8
- BASE_URL = "https://api.klotty.com/".freeze
11
+ include Resend::Emails
9
12
 
10
- attr_reader :api_key, :base_url, :timeout
13
+ attr_reader :api_key
11
14
 
12
15
  def initialize(api_key)
13
- raise ArgumentError.new("API Key is not a string") unless api_key.is_a?(String)
14
- @api_key = api_key
15
- @timeout = nil
16
- end
17
-
18
- def send_email(params)
19
- validate!(params)
20
-
21
- options = {
22
- headers: {
23
- 'Content-Type' => 'application/json',
24
- "Accept" => "application/json",
25
- "User-Agent" => "ruby:#{Resend::VERSION}",
26
- "Authorization" => "Bearer #{@api_key}",
27
- },
28
- body: params.to_json
29
- }
30
-
31
- resp = HTTParty.post("#{BASE_URL}/email", options)
32
- resp.transform_keys!(&:to_sym)
33
- if not resp[:error].nil?
34
- handle_error!(resp[:error])
35
- end
36
- resp
37
- end
16
+ raise ArgumentError, "API Key is not a string" unless api_key.is_a?(String)
38
17
 
39
- private
40
-
41
- def validate!(params)
42
- raise ArgumentError.new("'to' should be an Array or String") unless params[:to].is_a?(String) or params[:to].is_a?(Array)
43
- raise ArgumentError.new("Argument 'to' is missing") if params[:to].nil?
44
- raise ArgumentError.new("'to' can not be empty") if params[:to].empty?
45
-
46
- raise ArgumentError.new("'from' should be a String") unless params[:from].is_a?(String)
47
- raise ArgumentError.new("Argument 'from' is missing") if params[:from].nil?
48
- raise ArgumentError.new("'from' can not be empty") if params[:from].empty?
49
-
50
- raise ArgumentError.new("'from' should be a String") unless params[:from].is_a?(String)
51
- raise ArgumentError.new("Argument 'subject' is missing") if params[:subject].nil?
52
- raise ArgumentError.new("'subject' can not be empty") if params[:subject].empty?
53
-
54
- raise ArgumentError.new("Argument 'text' and 'html' are missing") if params[:text].nil? and params[:html].nil?
55
- end
56
-
57
- def handle_error!(error)
58
- err = error.transform_keys(&:to_sym)
59
- raise Resend::ResendError.new(err[:message])
18
+ @api_key = api_key
60
19
  end
61
20
  end
62
- end
21
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resend/request"
4
+ require "resend/errors"
5
+
6
+ module Resend
7
+ # domains api wrapper
8
+ module Domains
9
+ class << self
10
+ # https://resend.com/docs/api-reference/domains/create-domain
11
+ def create(params)
12
+ path = "/domains"
13
+ Resend::Request.new(path, params, "post").perform
14
+ end
15
+
16
+ # https://resend.com/docs/api-reference/api-keys/list-api-keys
17
+ def list
18
+ path = "/domains"
19
+ Resend::Request.new(path, {}, "get").perform
20
+ end
21
+
22
+ # https://resend.com/docs/api-reference/domains/delete-domain
23
+ def remove(domain_id = "")
24
+ path = "/domains/#{domain_id}"
25
+ Resend::Request.new(path, {}, "delete").perform
26
+ end
27
+
28
+ # https://resend.com/docs/api-reference/domains/verify-domain
29
+ def verify(domain_id = "")
30
+ path = "/domains/#{domain_id}/verify"
31
+ Resend::Request.new(path, {}, "post").perform
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resend/request"
4
+
5
+ module Resend
6
+ # Module responsible for wrapping email sending API
7
+ module Emails
8
+ class << self
9
+ # send email functionality
10
+ # https://resend.com/docs/api-reference/send-email
11
+ def send(params)
12
+ path = "emails"
13
+ Resend::Request.new(path, params, "post").perform
14
+ end
15
+
16
+ def get(email_id = "")
17
+ path = "emails/#{email_id}"
18
+ Resend::Request.new(path, {}, "get").perform
19
+ end
20
+ end
21
+
22
+ # This method is kept here for backwards compatibility
23
+ # Use Resend::Emails.send instead.
24
+ def send_email(params)
25
+ warn "[DEPRECATION] `send_email` is deprecated. Please use `Resend::Emails.send` instead."
26
+ Resend::Emails.send(params)
27
+ end
28
+ end
29
+ end
data/lib/resend/errors.rb CHANGED
@@ -1,5 +1,36 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Resend
2
- class ResendError < StandardError
4
+ # Errors wrapper class
5
+ # For more info: https://resend.com/docs/api-reference/error-codes
6
+ class Error < StandardError
7
+
8
+ # 4xx HTTP status code
9
+ ClientError = Class.new(self)
10
+
11
+ # 5xx HTTP status code
12
+ ServerError = Class.new(self)
13
+
14
+ # code 500
15
+ InternalServerError = Class.new(ServerError)
16
+
17
+ # code 422
18
+ InvalidRequestError = Class.new(ServerError)
19
+
20
+ # code 404
21
+ NotFoundError = Class.new(ServerError)
22
+
23
+ ERRORS = {
24
+ 401 => Resend::Error::InvalidRequestError,
25
+ 404 => Resend::Error::InvalidRequestError,
26
+ 422 => Resend::Error::InvalidRequestError,
27
+ 400 => Resend::Error::InvalidRequestError,
28
+ 500 => Resend::Error::InternalServerError
29
+ }.freeze
30
+
31
+ def initialize(msg, code = nil)
32
+ super(msg)
33
+ @code = code
34
+ end
3
35
  end
4
36
  end
5
-
data/lib/resend/mailer.rb CHANGED
@@ -1,39 +1,76 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "resend"
2
4
 
3
5
  module Resend
6
+ # Mailer class used by railtie
4
7
  class Mailer
5
-
6
8
  attr_accessor :config, :settings
7
9
 
8
10
  def initialize(config)
9
11
  @config = config
10
- raise Resend::ResendError.new("Config requires api_key", @config) unless @config.has_key?(:api_key)
12
+ raise Resend::ResendError.new("Config requires api_key", @config) unless @config.key?(:api_key)
13
+
11
14
  @settings = { return_response: true } # avoids NilError exception
12
- @resend_client = Resend::Client.new config[:api_key]
13
15
  end
14
16
 
15
17
  def deliver!(mail)
18
+ params = build_resend_params(mail)
19
+ resp = Resend::Emails.send(params)
20
+ mail.message_id = resp[:id] if resp[:error].nil?
21
+ resp
22
+ end
23
+
24
+ def build_resend_params(mail)
16
25
  params = {
17
- from: mail[:from].to_s,
26
+ from: get_from(mail.from),
18
27
  to: mail.to,
19
- subject: mail.subject,
28
+ subject: mail.subject
20
29
  }
21
- params[:cc] = mail[:cc].to_s if mail[:cc].present?
22
- params[:bcc] = mail[:bcc].to_s if mail[:bcc].present?
23
- params[:reply_to] = mail[:reply_to].to_s if mail[:reply_to].present?
24
- params[:html] = mail.body.decoded
30
+ params.merge!(get_addons(mail))
31
+ params[:attachments] = get_attachments(mail) if mail.attachments.present?
32
+ params.merge!(get_contents(mail))
33
+ params
34
+ end
25
35
 
26
- resp = @resend_client.send_email(params)
36
+ def get_addons(mail)
37
+ params = {}
38
+ params[:cc] = mail.cc if mail.cc.present?
39
+ params[:bcc] = mail.bcc if mail.bcc.present?
40
+ params[:reply_to] = mail.reply_to if mail.reply_to.present?
41
+ params
42
+ end
27
43
 
28
- if resp[:error].nil? then
29
- mail.message_id = resp[:id]
44
+ def get_contents(mail)
45
+ params = {}
46
+ case mail.mime_type
47
+ when "text/plain"
48
+ params[:text] = mail.body.decoded
49
+ when "text/html"
50
+ params[:html] = mail.body.decoded
51
+ when "multipart/alternative", "multipart/mixed", "multipart/related"
52
+ params[:text] = mail.text_part.decoded if mail.text_part
53
+ params[:html] = mail.html_part.decoded if mail.html_part
30
54
  end
55
+ params
56
+ end
31
57
 
32
- resp
58
+ def get_from(input)
59
+ return input.first if input.is_a? Array
60
+
61
+ input
33
62
  end
34
63
 
35
- def resend_client
36
- @resend_client
64
+ def get_attachments(mail)
65
+ attachments = []
66
+ mail.attachments.each do |part|
67
+ attachment = {
68
+ filename: part.filename,
69
+ content: part.body.decoded.bytes
70
+ }
71
+ attachments.append(attachment)
72
+ end
73
+ attachments
37
74
  end
38
75
  end
39
- end
76
+ end
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "resend"
2
4
  require "resend/mailer"
3
5
 
4
6
  module Resend
7
+ # Main railtime class
5
8
  class Railtie < ::Rails::Railtie
6
9
  ActiveSupport.on_load(:action_mailer) do
7
10
  add_delivery_method :resend, Resend::Mailer
8
11
  ActiveSupport.run_load_hooks(:resend_mailer, Resend::Mailer)
9
12
  end
10
13
  end
11
- end
14
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resend/version"
4
+ require "resend/errors"
5
+ require "httparty"
6
+
7
+ module Resend
8
+ # This class is responsible for making the appropriate HTTP calls
9
+ # and raising the specific errors based on the response.
10
+ class Request
11
+ BASE_URL = "https://api.resend.com/"
12
+
13
+ attr_accessor :body, :verb
14
+
15
+ def initialize(path = "", body = {}, verb = "POST")
16
+ raise if Resend.api_key.nil?
17
+
18
+ @path = path
19
+ @body = body
20
+ @verb = verb
21
+ @headers = {
22
+ "Content-Type" => "application/json",
23
+ "Accept" => "application/json",
24
+ "User-Agent" => "ruby:#{Resend::VERSION}",
25
+ "Authorization" => "Bearer #{Resend.api_key}"
26
+ }
27
+ end
28
+
29
+ # Performs the HTTP call
30
+ def perform
31
+ options = {
32
+ headers: @headers
33
+ }
34
+ options[:body] = @body.to_json unless @body.empty?
35
+ resp = HTTParty.send(@verb.to_sym, "#{BASE_URL}#{@path}", options)
36
+ resp.transform_keys!(&:to_sym) unless resp.body.empty?
37
+ handle_error!(resp) if resp[:statusCode] && resp[:statusCode] != 200
38
+ resp
39
+ end
40
+
41
+ def handle_error!(resp)
42
+ code = resp[:statusCode]
43
+ body = resp[:message]
44
+ error = Resend::Error::ERRORS[code]
45
+ raise(error.new(body, code)) if error
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Resend
4
- VERSION = "0.2.1"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/resend.rb CHANGED
@@ -3,15 +3,17 @@
3
3
  require "resend/version"
4
4
  require "resend/client"
5
5
 
6
- require 'resend/railtie' if defined?(Rails) && defined?(ActionMailer)
6
+ require "resend/railtie" if defined?(Rails) && defined?(ActionMailer)
7
7
 
8
+ # Main Resend module
8
9
  module Resend
9
10
  class << self
10
- attr_accessor :api_key,
11
+ attr_accessor :api_key
12
+
11
13
  def configure
12
14
  yield self if block_given?
13
15
  true
14
16
  end
15
- alias_method :config, :configure
17
+ alias config configure
16
18
  end
17
- end
19
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resend
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derich Pacheco
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-02 00:00:00.000000000 Z
11
+ date: 2023-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.20.0
19
+ version: 0.19.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.20.0
26
+ version: 0.19.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -46,12 +46,16 @@ extra_rdoc_files: []
46
46
  files:
47
47
  - README.md
48
48
  - lib/resend.rb
49
+ - lib/resend/api_keys.rb
49
50
  - lib/resend/client.rb
51
+ - lib/resend/domains.rb
52
+ - lib/resend/emails.rb
50
53
  - lib/resend/errors.rb
51
54
  - lib/resend/mailer.rb
52
55
  - lib/resend/railtie.rb
56
+ - lib/resend/request.rb
53
57
  - lib/resend/version.rb
54
- homepage: https://github.com/drish/resend-ruby
58
+ homepage: https://github.com/resendlabs/resend-ruby
55
59
  licenses:
56
60
  - MIT
57
61
  metadata: {}