emailbutler 0.7.5 → 0.8.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 +4 -4
- data/README.md +12 -14
- data/app/assets/stylesheets/emailbutler/views/dashboard.scss +14 -0
- data/app/controllers/emailbutler/webhooks_controller.rb +51 -4
- data/config/routes.rb +2 -1
- data/lib/emailbutler/configuration.rb +53 -3
- data/lib/emailbutler/container.rb +27 -0
- data/lib/emailbutler/version.rb +1 -1
- data/lib/emailbutler/webhooks/mappers/sendgrid.rb +0 -4
- data/lib/emailbutler/webhooks/mappers/smtp2go.rb +0 -4
- data/lib/emailbutler/webhooks/receiver.rb +1 -17
- data/lib/emailbutler.rb +21 -10
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb57bd8a59942207f28941dd14e91f17cd5d74982877773415a38b925d49ccaa
|
4
|
+
data.tar.gz: 0fc748f32a49291175cccdff3a9e89dfe2aefafaacd1c357df38c545d18d768a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b5a8e3d1c292ff847623e7f404c5535d4324d9f206b0a15905b982fda3c42bd566039cb6e01727b085b7f924899ec07ffdd8a2d05e5fa418eba4d048f7012f1
|
7
|
+
data.tar.gz: d1bed20baaadc9b02fe3b8e8f8d4412e575977121d376f2077e18adc35349f5db261c7216f98b0cd0b87a7f875041c7f5614d70cd0c5dc6fe0fd8c6f42091045
|
data/README.md
CHANGED
@@ -27,16 +27,17 @@ $ rails db:migrate
|
|
27
27
|
|
28
28
|
Add configuration line to config/initializers/emailbutler.rb:
|
29
29
|
|
30
|
-
#### ActiveRecord
|
30
|
+
#### For ActiveRecord
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
require 'emailbutler/adapters/active_record'
|
34
34
|
|
35
35
|
Emailbutler.configure do |config|
|
36
|
-
config.adapter = Emailbutler::Adapters::ActiveRecord.new
|
37
|
-
config.
|
38
|
-
config.
|
39
|
-
config.
|
36
|
+
config.adapter = Emailbutler::Adapters::ActiveRecord.new # required
|
37
|
+
config.providers = %w[sendgrid smtp2go] # required at least 1 provider since 0.8
|
38
|
+
config.ui_username = 'username' # optional
|
39
|
+
config.ui_password = 'password' # optional
|
40
|
+
config.ui_secured_environments = ['production'] # optional
|
40
41
|
end
|
41
42
|
```
|
42
43
|
|
@@ -59,9 +60,9 @@ class SendgridController < ApplicationController
|
|
59
60
|
def create
|
60
61
|
... you can add some logic here
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
payload: receiver_params
|
63
|
+
Emailbutler::Container.resolve(:webhooks_receiver).call(
|
64
|
+
mapper: Emailbutler::Container.resolve(:sendgrid_mapper),
|
65
|
+
payload: receiver_params
|
65
66
|
)
|
66
67
|
|
67
68
|
head :ok
|
@@ -70,10 +71,7 @@ class SendgridController < ApplicationController
|
|
70
71
|
private
|
71
72
|
|
72
73
|
def receiver_params
|
73
|
-
params.permit(
|
74
|
-
'event', 'sendtime', 'message-id',
|
75
|
-
'_json' => %w[event timestamp smtp-id sg_message_id]
|
76
|
-
)
|
74
|
+
params.permit('event', 'sendtime', 'message-id').to_h
|
77
75
|
end
|
78
76
|
end
|
79
77
|
```
|
@@ -106,7 +104,7 @@ end
|
|
106
104
|
|
107
105
|
- go to [Mail settings](https://app.sendgrid.com/settings/mail_settings),
|
108
106
|
- turn on Event Webhook,
|
109
|
-
- in the HTTP POST URL field, paste the URL to webhook controller of your app,
|
107
|
+
- in the HTTP POST URL field, paste the URL to webhook controller of your app (host/emailbutler/webhooks/sendgrid),
|
110
108
|
- select all deliverability data,
|
111
109
|
- save settings.
|
112
110
|
|
@@ -114,7 +112,7 @@ end
|
|
114
112
|
|
115
113
|
- go to [Mail settings](https://app-eu.smtp2go.com/settings/webhooks),
|
116
114
|
- turn on Webhooks,
|
117
|
-
- in the HTTP POST URL field, paste the URL to webhook controller of your app,
|
115
|
+
- in the HTTP POST URL field, paste the URL to webhook controller of your app (host/emailbutler/webhooks/smtp2go),
|
118
116
|
- select all deliverability data,
|
119
117
|
- save settings.
|
120
118
|
|
@@ -62,6 +62,7 @@
|
|
62
62
|
flex: 1;
|
63
63
|
height: 100%;
|
64
64
|
|
65
|
+
// styles for backcompability with gem pagy < 7.0
|
65
66
|
.pagination {
|
66
67
|
margin-bottom: 1rem;
|
67
68
|
|
@@ -76,6 +77,19 @@
|
|
76
77
|
}
|
77
78
|
}
|
78
79
|
|
80
|
+
// styles for gem pagy >= 7.0
|
81
|
+
nav.pagy.nav {
|
82
|
+
margin-bottom: 1rem;
|
83
|
+
|
84
|
+
a {
|
85
|
+
padding: .25rem .5rem;
|
86
|
+
margin-right: .25rem;
|
87
|
+
background: #bbf7d0;
|
88
|
+
color: #000;
|
89
|
+
border-radius: .125rem;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
79
93
|
table {
|
80
94
|
width: 100%;
|
81
95
|
|
@@ -2,12 +2,26 @@
|
|
2
2
|
|
3
3
|
module Emailbutler
|
4
4
|
class WebhooksController < Emailbutler::ApplicationController
|
5
|
+
# deprecated constants
|
6
|
+
SENDGRID_USER_AGENT = 'SendGrid Event API'
|
7
|
+
SMTP2GO_USER_AGENT = 'Go-http-client/1.1'
|
8
|
+
|
5
9
|
skip_before_action :verify_authenticity_token
|
10
|
+
before_action :validate_provider, only: %i[create]
|
11
|
+
|
12
|
+
def create_deprecated
|
13
|
+
Emailbutler::Container.resolve(:webhooks_receiver).call(
|
14
|
+
mapper: receiver_mapper_deprecated(request.headers['HTTP_USER_AGENT']),
|
15
|
+
payload: mapper_params_deprecated.to_h
|
16
|
+
)
|
17
|
+
|
18
|
+
head :ok
|
19
|
+
end
|
6
20
|
|
7
21
|
def create
|
8
|
-
|
9
|
-
|
10
|
-
payload:
|
22
|
+
Emailbutler::Container.resolve(:webhooks_receiver).call(
|
23
|
+
mapper: receiver_mapper,
|
24
|
+
payload: mapper_params.to_h
|
11
25
|
)
|
12
26
|
|
13
27
|
head :ok
|
@@ -15,7 +29,40 @@ module Emailbutler
|
|
15
29
|
|
16
30
|
private
|
17
31
|
|
18
|
-
def
|
32
|
+
def validate_provider
|
33
|
+
head :ok if Emailbutler.configuration.providers.exclude?(params[:provider])
|
34
|
+
end
|
35
|
+
|
36
|
+
def receiver_mapper
|
37
|
+
case params[:provider]
|
38
|
+
when 'sendgrid' then Emailbutler::Container.resolve(:sendgrid_mapper)
|
39
|
+
when 'smtp2go' then Emailbutler::Container.resolve(:smtp2go_mapper)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def mapper_params
|
44
|
+
case params[:provider]
|
45
|
+
when 'sendgrid' then sendgrid_params
|
46
|
+
when 'smtp2go' then smtp2go_params
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def sendgrid_params
|
51
|
+
params.permit('_json' => %w[smtp-id event timestamp sg_message_id])
|
52
|
+
end
|
53
|
+
|
54
|
+
def smtp2go_params
|
55
|
+
params.permit('event', 'sendtime', 'message-id')
|
56
|
+
end
|
57
|
+
|
58
|
+
def receiver_mapper_deprecated(user_agent)
|
59
|
+
case user_agent
|
60
|
+
when SENDGRID_USER_AGENT then Emailbutler::Container.resolve(:sendgrid_mapper)
|
61
|
+
when SMTP2GO_USER_AGENT then Emailbutler::Container.resolve(:smtp2go_mapper)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def mapper_params_deprecated
|
19
66
|
params.permit(
|
20
67
|
'event', 'sendtime', 'message-id',
|
21
68
|
'_json' => %w[event timestamp smtp-id sg_message_id]
|
data/config/routes.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Emailbutler::Engine.routes.draw do
|
4
|
-
post '/webhooks', to: 'webhooks#
|
4
|
+
post '/webhooks', to: 'webhooks#create_deprecated'
|
5
|
+
post '/webhooks/:provider', to: 'webhooks#create'
|
5
6
|
|
6
7
|
resources :ui, only: %i[index show]
|
7
8
|
namespace :ui do
|
@@ -2,16 +2,66 @@
|
|
2
2
|
|
3
3
|
module Emailbutler
|
4
4
|
class Configuration
|
5
|
-
|
5
|
+
InitializeError = Class.new(StandardError)
|
6
|
+
|
7
|
+
AVAILABLE_ADAPTERS = %w[
|
8
|
+
Emailbutler::Adapters::ActiveRecord
|
9
|
+
].freeze
|
10
|
+
AVAILABLE_PROVIDERS = %w[sendgrid smtp2go].freeze
|
11
|
+
|
12
|
+
attr_accessor :adapter, :providers, :ui_username, :ui_password, :ui_secured_environments
|
6
13
|
|
7
14
|
def initialize
|
8
15
|
@adapter = nil
|
16
|
+
@providers = []
|
9
17
|
|
10
18
|
# It's required to specify these 3 variables to enable basic auth to UI
|
11
|
-
@ui_username =
|
12
|
-
@ui_password =
|
19
|
+
@ui_username = nil
|
20
|
+
@ui_password = nil
|
13
21
|
# Secured environments variable must directly contains environment names
|
14
22
|
@ui_secured_environments = []
|
15
23
|
end
|
24
|
+
|
25
|
+
def validate
|
26
|
+
validate_adapter
|
27
|
+
validate_providers
|
28
|
+
validate_username
|
29
|
+
validate_password
|
30
|
+
validate_secured_environments
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def validate_adapter
|
36
|
+
raise InitializeError, 'Adapter must be present' if adapter.nil?
|
37
|
+
raise InitializeError, 'Invalid adapter' if AVAILABLE_ADAPTERS.exclude?(adapter.class.name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_providers
|
41
|
+
raise InitializeError, 'Providers list must be array' unless providers.is_a?(Array)
|
42
|
+
raise InitializeError, 'At least 1 provider must be present' if providers.blank?
|
43
|
+
|
44
|
+
return unless providers.any? { |provider| AVAILABLE_PROVIDERS.exclude?(provider) }
|
45
|
+
|
46
|
+
raise InitializeError, 'Providers list contain invalid element'
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_username
|
50
|
+
return if ui_username.blank?
|
51
|
+
return if ui_username.is_a?(String)
|
52
|
+
|
53
|
+
raise InitializeError, 'Username must be nil or filled string'
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_password
|
57
|
+
return if ui_password.blank?
|
58
|
+
return if ui_password.is_a?(String)
|
59
|
+
|
60
|
+
raise InitializeError, 'Password must be nil or filled string'
|
61
|
+
end
|
62
|
+
|
63
|
+
def validate_secured_environments
|
64
|
+
raise InitializeError, 'Environments list must be array' unless ui_secured_environments.is_a?(Array)
|
65
|
+
end
|
16
66
|
end
|
17
67
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/container'
|
4
|
+
require 'emailbutler/webhooks/mappers/sendgrid'
|
5
|
+
require 'emailbutler/webhooks/mappers/smtp2go'
|
6
|
+
require 'emailbutler/webhooks/receiver'
|
7
|
+
|
8
|
+
module Emailbutler
|
9
|
+
class Container
|
10
|
+
extend Dry::Container::Mixin
|
11
|
+
|
12
|
+
DEFAULT_OPTIONS = { memoize: true }.freeze
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def register(key)
|
16
|
+
super(key, DEFAULT_OPTIONS)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# webhook mappers
|
21
|
+
register(:sendgrid_mapper) { Emailbutler::Webhooks::Mappers::Sendgrid.new }
|
22
|
+
register(:smtp2go_mapper) { Emailbutler::Webhooks::Mappers::Smtp2Go.new }
|
23
|
+
|
24
|
+
# webhook receiver
|
25
|
+
register(:webhooks_receiver) { Emailbutler::Webhooks::Receiver.new }
|
26
|
+
end
|
27
|
+
end
|
data/lib/emailbutler/version.rb
CHANGED
@@ -1,25 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'emailbutler/webhooks/mappers/sendgrid'
|
4
|
-
require 'emailbutler/webhooks/mappers/smtp2go'
|
5
|
-
|
6
3
|
module Emailbutler
|
7
4
|
module Webhooks
|
8
5
|
class Receiver
|
9
|
-
|
10
|
-
SMTP2GO_USER_AGENT = 'Go-http-client/1.1'
|
11
|
-
|
12
|
-
RECEIVERS_MAPPER = {
|
13
|
-
'SendGrid Event API' => Emailbutler::Webhooks::Mappers::Sendgrid,
|
14
|
-
'Go-http-client/1.1' => Emailbutler::Webhooks::Mappers::Smtp2Go
|
15
|
-
}.freeze
|
16
|
-
|
17
|
-
def self.call(...)
|
18
|
-
new.call(...)
|
19
|
-
end
|
20
|
-
|
21
|
-
def call(user_agent:, payload:)
|
22
|
-
mapper = RECEIVERS_MAPPER[user_agent]
|
6
|
+
def call(mapper:, payload:)
|
23
7
|
return unless mapper
|
24
8
|
|
25
9
|
mapper
|
data/lib/emailbutler.rb
CHANGED
@@ -6,38 +6,49 @@ require 'emailbutler/version'
|
|
6
6
|
require 'emailbutler/engine'
|
7
7
|
require 'emailbutler/configuration'
|
8
8
|
require 'emailbutler/dsl'
|
9
|
-
require 'emailbutler/webhooks/receiver'
|
10
9
|
require 'emailbutler/helpers'
|
11
10
|
require 'emailbutler/mailers/helpers'
|
11
|
+
require 'emailbutler/container'
|
12
12
|
|
13
13
|
module Emailbutler
|
14
14
|
extend self
|
15
15
|
extend Forwardable
|
16
16
|
|
17
|
-
# Public: Given an adapter returns a handy DSL to all the emailbutler goodness.
|
18
|
-
def new(adapter)
|
19
|
-
DSL.new(adapter)
|
20
|
-
end
|
21
|
-
|
22
17
|
# Public: Configure emailbutler.
|
23
18
|
#
|
19
|
+
# require 'emailbutler/adapters/active_record'
|
20
|
+
#
|
24
21
|
# Emailbutler.configure do |config|
|
25
22
|
# config.adapter = Emailbutler::Adapters::ActiveRecord.new
|
23
|
+
# config.providers = %i[sendgrid]
|
26
24
|
# end
|
27
25
|
#
|
28
26
|
def configure
|
27
|
+
ActiveSupport::Deprecation.new.warn(
|
28
|
+
'Webhook endpoint should receive provider name in params. ' \
|
29
|
+
'Please update webhook url in settings of your SMTP provider.' \
|
30
|
+
'Webhook without provider in params will be removed soon.'
|
31
|
+
)
|
32
|
+
|
29
33
|
yield configuration
|
34
|
+
|
35
|
+
configuration.validate
|
30
36
|
end
|
31
37
|
|
32
38
|
# Public: Returns Emailbutler::Configuration instance.
|
33
39
|
def configuration
|
34
|
-
|
40
|
+
return Emailbutler::Container.resolve(:configuration) if Emailbutler::Container.key?(:configuration)
|
41
|
+
|
42
|
+
Emailbutler::Container.register(:configuration) { Configuration.new }
|
43
|
+
Emailbutler::Container.resolve(:configuration)
|
35
44
|
end
|
36
45
|
|
37
|
-
# Public:
|
38
|
-
# Returns Emailbutler::DSL instance.
|
46
|
+
# Public: Returns Emailbutler::DSL instance.
|
39
47
|
def instance
|
40
|
-
|
48
|
+
return Emailbutler::Container.resolve(:instance) if Emailbutler::Container.key?(:instance)
|
49
|
+
|
50
|
+
Emailbutler::Container.register(:instance) { DSL.new(configuration.adapter) }
|
51
|
+
Emailbutler::Container.resolve(:instance)
|
41
52
|
end
|
42
53
|
|
43
54
|
# Public: All the methods delegated to instance. These should match the interface of Emailbutler::DSL.
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emailbutler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bogdanov Anton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-container
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.11.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.11.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: pagy
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,6 +210,7 @@ files:
|
|
196
210
|
- lib/emailbutler.rb
|
197
211
|
- lib/emailbutler/adapters/active_record.rb
|
198
212
|
- lib/emailbutler/configuration.rb
|
213
|
+
- lib/emailbutler/container.rb
|
199
214
|
- lib/emailbutler/dsl.rb
|
200
215
|
- lib/emailbutler/engine.rb
|
201
216
|
- lib/emailbutler/helpers.rb
|
@@ -229,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
229
244
|
- !ruby/object:Gem::Version
|
230
245
|
version: '0'
|
231
246
|
requirements: []
|
232
|
-
rubygems_version: 3.
|
247
|
+
rubygems_version: 3.4.1
|
233
248
|
signing_key:
|
234
249
|
specification_version: 4
|
235
250
|
summary: Email tracker for Ruby on Rails applications.
|