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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d52c909134e2f3b77b2458f302694c82774d99e8b2796228e68b4c0a89bba8d
4
- data.tar.gz: e4d8414a09f7ba180ba92afb6296d538a279a226256bfe835bc3e19f67f13d8f
3
+ metadata.gz: fb57bd8a59942207f28941dd14e91f17cd5d74982877773415a38b925d49ccaa
4
+ data.tar.gz: 0fc748f32a49291175cccdff3a9e89dfe2aefafaacd1c357df38c545d18d768a
5
5
  SHA512:
6
- metadata.gz: 44aeeefa0da557fe1c2393ae6df65e0d560bd2a840e334e4123204dd459dc355b3c6b8bdbcc5180b18c6c85c4ebcec9403d4d4fc909c2c7231c854b2a3a00d39
7
- data.tar.gz: 74a4bd2dbc4bcd2aa8bb54adb757cce56d5c8bb408332e7acb639ae7bb80c15a083d597d4e3272bd6ae71de84666b856722cde6088456b52c9f29c4f651d34cf
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.ui_username = 'username'
38
- config.ui_password = 'password'
39
- config.ui_secured_environments = ['production']
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
- ::Emailbutler::Webhooks::Receiver.call(
63
- user_agent: request.headers['HTTP_USER_AGENT'],
64
- payload: receiver_params.to_h
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
- ::Emailbutler::Webhooks::Receiver.call(
9
- user_agent: request.headers['HTTP_USER_AGENT'],
10
- payload: receiver_params.to_h
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 receiver_params
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#create'
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
- attr_accessor :adapter, :ui_username, :ui_password, :ui_secured_environments
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Emailbutler
4
- VERSION = '0.7.5'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -15,10 +15,6 @@ module Emailbutler
15
15
  'spamreport' => 'failed'
16
16
  }.freeze
17
17
 
18
- def self.call(...)
19
- new.call(...)
20
- end
21
-
22
18
  def call(payload:)
23
19
  payload['_json'].filter_map { |message|
24
20
  message.stringify_keys!
@@ -14,10 +14,6 @@ module Emailbutler
14
14
  'spam' => 'failed'
15
15
  }.freeze
16
16
 
17
- def self.call(...)
18
- new.call(...)
19
- end
20
-
21
17
  def call(payload:)
22
18
  payload.stringify_keys!
23
19
  # message-id contains data like <uuid>
@@ -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
- SENDGRID_USER_AGENT = 'SendGrid Event API'
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
- @configuration ||= Configuration.new
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: Default per thread emailbutler instance if configured.
38
- # Returns Emailbutler::DSL instance.
46
+ # Public: Returns Emailbutler::DSL instance.
39
47
  def instance
40
- Thread.current[:emailbutler_instance] ||= new(configuration.adapter)
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.7.5
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: 2023-12-19 00:00:00.000000000 Z
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.3.7
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.