brevo-extras 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +113 -0
- data/Rakefile +6 -0
- data/app/helpers/brevo/extras/application_helper.rb +6 -0
- data/app/jobs/brevo/extras/application_job.rb +6 -0
- data/app/jobs/brevo/extras/delivery_job.rb +16 -0
- data/app/mailers/brevo/extras/application_mailer.rb +8 -0
- data/app/models/brevo/extras/application_record.rb +7 -0
- data/config/routes.rb +2 -0
- data/lib/brevo/extras/base.rb +73 -0
- data/lib/brevo/extras/engine.rb +7 -0
- data/lib/brevo/extras/version.rb +5 -0
- data/lib/brevo/extras.rb +10 -0
- data/lib/tasks/brevo/extras_tasks.rake +4 -0
- metadata +87 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a72266c6461dcf2931b8e1db860f7c2b292fb67a12e447974f8f3f2fe38232b7
|
|
4
|
+
data.tar.gz: 8a0179c5cb72befd993590538b828dd2149e8c24c02fb0249e30e9868f8df2ea
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5dcd2ea1fbd345dd700c4746390cb608203bc4a3dd12bbe7f8b02eef8c03e37e460364816325e4c466da61a58a0abad8991828854ff95b40b4532f0610e20daf
|
|
7
|
+
data.tar.gz: c9a2f577a21cd4a3ac4126d8b194ed1b6aa2fa634cd24d89a96441ac02d3230e18fae8893632ed34c3eb7fb7823a13a1b2957f021242ed353aee7b6b2cde3f37
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright Bruno Perles
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
[](https://github.com/atnos/brevo-extras/actions/workflows/ci.yml)
|
|
2
|
+
[](https://github.com/atnos/brevo-extras/actions/workflows/github-code-scanning/codeql)
|
|
3
|
+
[](https://github.com/atnos/brevo-extras/actions/workflows/dependabot/dependabot-updates)
|
|
4
|
+
|
|
5
|
+
# Brevo::Extras
|
|
6
|
+
|
|
7
|
+
A Rails engine that provides a clean abstraction layer for sending transactional emails via the [Brevo](https://www.brevo.com/) API, with built-in safety features to prevent accidental email delivery in development and test environments.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Abstract base class for creating email sender classes
|
|
12
|
+
- Asynchronous delivery via Active Job
|
|
13
|
+
- Automatic retry on API errors with polynomial backoff
|
|
14
|
+
- **Sandbox mode** - prevents actual email delivery (enabled by default)
|
|
15
|
+
- **Safe mode** - filters recipients by allowed domains (enabled by default in local environments)
|
|
16
|
+
- Template-based emails with parameters
|
|
17
|
+
- Reply-to address support
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Add this line to your application's Gemfile:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gem "brevo-extras", github: "atnos/brevo-extras"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
And then execute:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
$ bundle
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
The engine is configured through environment variables:
|
|
36
|
+
|
|
37
|
+
| Variable | Default | Description |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `BREVO_SANDBOX_MODE` | `"1"` | When enabled, adds `X-Sib-Sandbox: drop` header so Brevo accepts the request but does not send the email |
|
|
40
|
+
| `BREVO_SAFE_MODE` | `"1"` | When enabled, filters recipients to only allowed domains. Always active in local Rails environments (`development`, `test`) regardless of this setting |
|
|
41
|
+
| `BREVO_SAFE_MODE_ALLOWED_DOMAINS` | `""` | Comma-separated list of allowed email domains (e.g. `"example.com,mycompany.com"`) |
|
|
42
|
+
|
|
43
|
+
You also need to configure the Brevo API key as required by the [brevo gem](https://github.com/getbrevo/brevo-ruby).
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### Creating an email sender
|
|
48
|
+
|
|
49
|
+
Subclass `Brevo::Extras::Base` and implement the `#call` method:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
class WelcomeEmail < Brevo::Extras::Base
|
|
53
|
+
def call
|
|
54
|
+
send_email(
|
|
55
|
+
template_id: 1,
|
|
56
|
+
to: [{ email: params[:email], name: params[:name] }]
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Sending an email
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
WelcomeEmail.call(email: "user@example.com", name: "John")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The email is enqueued as an Active Job and delivered asynchronously.
|
|
69
|
+
|
|
70
|
+
### Reply-to support
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
send_email(
|
|
74
|
+
template_id: 1,
|
|
75
|
+
to: [{ email: params[:email], name: params[:name] }],
|
|
76
|
+
reply_to: { email: "support@example.com" }
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Template parameters
|
|
81
|
+
|
|
82
|
+
Parameters passed to `.call` are forwarded to the Brevo template as `params`:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
# These params will be available in your Brevo template
|
|
86
|
+
OrderConfirmation.call(
|
|
87
|
+
email: "user@example.com",
|
|
88
|
+
order_id: "12345",
|
|
89
|
+
total: "$99.00"
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Retry behavior
|
|
94
|
+
|
|
95
|
+
The `DeliveryJob` automatically retries on `Brevo::ApiError` with polynomial backoff, up to 5 attempts.
|
|
96
|
+
|
|
97
|
+
## Development
|
|
98
|
+
|
|
99
|
+
### Running tests
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
bin/rails test
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Linting
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
bin/rubocop
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Brevo
|
|
4
|
+
module Extras
|
|
5
|
+
class DeliveryJob < ApplicationJob
|
|
6
|
+
retry_on Brevo::ApiError, wait: :polynomially_longer, attempts: 5
|
|
7
|
+
|
|
8
|
+
def perform(data)
|
|
9
|
+
api_instance = Brevo::TransactionalEmailsApi.new
|
|
10
|
+
api_instance.send_transac_email(
|
|
11
|
+
Brevo::SendSmtpEmail.new(data)
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Brevo
|
|
4
|
+
module Extras
|
|
5
|
+
class Base
|
|
6
|
+
class << self
|
|
7
|
+
def call(params)
|
|
8
|
+
new(params).call
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(params)
|
|
13
|
+
@params = params
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
raise NotImplementedError, "Subclasses must implement #call"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
def send_email(template_id:, to:, reply_to: nil)
|
|
23
|
+
data = build_email_data(template_id:, to:, reply_to:)
|
|
24
|
+
data[:to] = safe_mode_recipients(data[:to])
|
|
25
|
+
data[:headers] = { "X-Sib-Sandbox" => "drop" } if sandbox_mode?
|
|
26
|
+
deliver_later(data)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def build_email_data(template_id:, to:, reply_to:)
|
|
32
|
+
{
|
|
33
|
+
templateId: template_id,
|
|
34
|
+
to: to,
|
|
35
|
+
replyTo: reply_to,
|
|
36
|
+
params: @params
|
|
37
|
+
}.tap do |data|
|
|
38
|
+
data.delete(:replyTo) if reply_to.nil?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def safe_mode_recipients(recipients)
|
|
43
|
+
return recipients unless safe_mode?
|
|
44
|
+
|
|
45
|
+
recipients = recipients.is_a?(Array) ? recipients : [ recipients ]
|
|
46
|
+
recipients.select do |recipient|
|
|
47
|
+
email = recipient[:email].to_s.gsub(/\s/, "").downcase
|
|
48
|
+
safe_mode_domains.any? { |domain| email.end_with?("@#{domain}") }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def sandbox_mode?
|
|
53
|
+
ActiveModel::Type::Boolean.new.cast(
|
|
54
|
+
ENV.fetch("BREVO_SANDBOX_MODE", "1")
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def safe_mode_domains
|
|
59
|
+
ENV.fetch("BREVO_SAFE_MODE_ALLOWED_DOMAINS", "").split(",").map(&:strip)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def safe_mode?
|
|
63
|
+
ActiveModel::Type::Boolean.new.cast(
|
|
64
|
+
ENV.fetch("BREVO_SAFE_MODE", "1")
|
|
65
|
+
) || Rails.env.local?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def deliver_later(data)
|
|
69
|
+
DeliveryJob.perform_later(data)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/brevo/extras.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: brevo-extras
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Bruno Perles
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 8.1.2
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 8.1.2
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: brevo
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '4.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '4.0'
|
|
40
|
+
description: A Rails engine that provides a clean abstraction layer for sending transactional
|
|
41
|
+
emails via the Brevo API, with built-in sandbox and safe modes, async delivery via
|
|
42
|
+
Active Job, and automatic retry with polynomial backoff.
|
|
43
|
+
email:
|
|
44
|
+
- contact@atnos.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- MIT-LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- Rakefile
|
|
52
|
+
- app/helpers/brevo/extras/application_helper.rb
|
|
53
|
+
- app/jobs/brevo/extras/application_job.rb
|
|
54
|
+
- app/jobs/brevo/extras/delivery_job.rb
|
|
55
|
+
- app/mailers/brevo/extras/application_mailer.rb
|
|
56
|
+
- app/models/brevo/extras/application_record.rb
|
|
57
|
+
- config/routes.rb
|
|
58
|
+
- lib/brevo/extras.rb
|
|
59
|
+
- lib/brevo/extras/base.rb
|
|
60
|
+
- lib/brevo/extras/engine.rb
|
|
61
|
+
- lib/brevo/extras/version.rb
|
|
62
|
+
- lib/tasks/brevo/extras_tasks.rake
|
|
63
|
+
homepage: https://github.com/atnos/brevo-extras
|
|
64
|
+
licenses:
|
|
65
|
+
- MIT
|
|
66
|
+
metadata:
|
|
67
|
+
allowed_push_host: https://rubygems.org
|
|
68
|
+
homepage_uri: https://github.com/atnos/brevo-extras
|
|
69
|
+
source_code_uri: https://github.com/atnos/brevo-extras
|
|
70
|
+
rdoc_options: []
|
|
71
|
+
require_paths:
|
|
72
|
+
- lib
|
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
requirements: []
|
|
84
|
+
rubygems_version: 4.0.3
|
|
85
|
+
specification_version: 4
|
|
86
|
+
summary: A Rails engine for sending transactional emails via the Brevo API.
|
|
87
|
+
test_files: []
|