emailbutler 0.7.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7a1a7e4cc9dad6d9958abcb9e832e85d6c74a2c44a71c63bc42e7e3be59debc
4
- data.tar.gz: 490337b5946df84317357c9f22d9d189d0434ff215726533b3dc934479b99eb3
3
+ metadata.gz: fb57bd8a59942207f28941dd14e91f17cd5d74982877773415a38b925d49ccaa
4
+ data.tar.gz: 0fc748f32a49291175cccdff3a9e89dfe2aefafaacd1c357df38c545d18d768a
5
5
  SHA512:
6
- metadata.gz: 53580acc1672780cc1b5eca024fc68868cf8ab3f3d2cadc6a02f4edb70787ba1c87b583a04703a1bca718ecc9ef80254d6f6a5d288824cb7a05247ef38c30a50
7
- data.tar.gz: 7565afd9b680a42d2dee0b500b39773e696b2e80a53d7eb7e1f8ddb3f686dca7ef65af0548471416d18cbe2cb4bfd68e6b07128007439341a6e611a29d2e73a8
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
 
@@ -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.6'
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.6
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: 2024-04-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