Merge pull request #8404 from mfo/US/force-email-delivery
Us/force important email delivery
This commit is contained in:
commit
1a6b693312
11 changed files with 166 additions and 1 deletions
4
app/controllers/manager/safe_mailers_controller.rb
Normal file
4
app/controllers/manager/safe_mailers_controller.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
module Manager
|
||||
class SafeMailersController < Manager::ApplicationController
|
||||
end
|
||||
end
|
43
app/dashboards/safe_mailer_dashboard.rb
Normal file
43
app/dashboards/safe_mailer_dashboard.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
require "administrate/base_dashboard"
|
||||
|
||||
class SafeMailerDashboard < Administrate::BaseDashboard
|
||||
# ATTRIBUTE_TYPES
|
||||
# a hash that describes the type of each of the model's fields.
|
||||
#
|
||||
# Each different type represents an Administrate::Field object,
|
||||
# which determines how the attribute is displayed
|
||||
# on pages throughout the dashboard.
|
||||
ATTRIBUTE_TYPES = {
|
||||
id: Field::Number,
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime,
|
||||
forced_delivery_method: Field::Enum
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's index page.
|
||||
#
|
||||
# By default, it's limited to four items to reduce clutter on index pages.
|
||||
# Feel free to add, remove, or rearrange items.
|
||||
COLLECTION_ATTRIBUTES = [
|
||||
:id,
|
||||
:created_at,
|
||||
:updated_at,
|
||||
:forced_delivery_method
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's show page.
|
||||
SHOW_PAGE_ATTRIBUTES = [
|
||||
:created_at,
|
||||
:updated_at,
|
||||
:forced_delivery_method
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
# an array of attributes that will be displayed
|
||||
# on the model's form (`new` and `edit`) pages.
|
||||
FORM_ATTRIBUTES = [
|
||||
:forced_delivery_method
|
||||
].freeze
|
||||
end
|
|
@ -14,6 +14,7 @@
|
|||
#
|
||||
# Be sure to restart your server when you modify this file.
|
||||
class BalancerDeliveryMethod
|
||||
FORCE_DELIVERY_METHOD_HEADER = 'X-deliver-with'
|
||||
# Allows configuring the random number generator used for selecting a delivery method,
|
||||
# mostly for testing purposes.
|
||||
mattr_accessor :random, default: Random.new
|
||||
|
@ -39,7 +40,13 @@ class BalancerDeliveryMethod
|
|||
|
||||
private
|
||||
|
||||
def force_delivery_method?(mail)
|
||||
@delivery_methods.keys.map(&:to_s).include?(mail[FORCE_DELIVERY_METHOD_HEADER]&.value)
|
||||
end
|
||||
|
||||
def delivery_method(mail)
|
||||
return mail[FORCE_DELIVERY_METHOD_HEADER].value.to_sym if force_delivery_method?(mail)
|
||||
|
||||
@delivery_methods
|
||||
.flat_map { |delivery_method, weight| [delivery_method] * weight }
|
||||
.sample(random: self.class.random)
|
||||
|
|
|
@ -5,6 +5,7 @@ class DeviseUserMailer < Devise::Mailer
|
|||
include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
|
||||
include MailerMonitoringConcern
|
||||
layout 'mailers/layout'
|
||||
before_action :add_delivery_method, if: :forced_delivery?
|
||||
|
||||
def template_paths
|
||||
['devise_mailer']
|
||||
|
@ -16,4 +17,12 @@ class DeviseUserMailer < Devise::Mailer
|
|||
@prefill_token = opts[:prefill_token]
|
||||
super
|
||||
end
|
||||
|
||||
def add_delivery_method
|
||||
headers[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER] = SafeMailer.forced_delivery_method
|
||||
end
|
||||
|
||||
def forced_delivery?
|
||||
SafeMailer.forced_delivery_method.present?
|
||||
end
|
||||
end
|
||||
|
|
20
app/models/safe_mailer.rb
Normal file
20
app/models/safe_mailer.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: safe_mailers
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# forced_delivery_method :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
class SafeMailer < ApplicationRecord
|
||||
before_create do
|
||||
raise if SafeMailer.count == 1
|
||||
end
|
||||
|
||||
enum forced_delivery_method: Rails.application.config.action_mailer&.balancer_settings&.keys&.map(&:to_s) || []
|
||||
|
||||
def self.forced_delivery_method
|
||||
first&.forced_delivery_method
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
require "active_support/core_ext/integer/time"
|
||||
require Rails.root.join("app/lib/balancer_delivery_method")
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
@ -76,7 +77,12 @@ Rails.application.configure do
|
|||
config.assets.raise_runtime_errors = true
|
||||
|
||||
# Action Mailer settings
|
||||
config.action_mailer.delivery_method = ENV['HELO_ENABLED'] == 'enabled' ? :helo : :letter_opener
|
||||
ActionMailer::Base.add_delivery_method :balancer, BalancerDeliveryMethod
|
||||
config.action_mailer.balancer_settings = {
|
||||
helo: ENV['HELO_ENABLED'] == 'enabled' ? 100 : 0,
|
||||
letter_opener: ENV['HELO_ENABLED'] == 'enabled' ? 0 : 100
|
||||
}
|
||||
config.action_mailer.delivery_method = :balancer
|
||||
|
||||
config.action_mailer.default_url_options = { host: ENV.fetch("APP_HOST") }
|
||||
config.action_mailer.asset_host = "http://" + ENV.fetch("APP_HOST")
|
||||
|
|
|
@ -71,6 +71,7 @@ Rails.application.routes.draw do
|
|||
resources :outdated_procedures, only: [:index] do
|
||||
patch :bulk_update, on: :collection
|
||||
end
|
||||
resources :safe_mailers, only: [:index, :edit, :update, :destroy]
|
||||
|
||||
post 'demandes/create_administrateur'
|
||||
post 'demandes/refuse_administrateur'
|
||||
|
|
9
db/migrate/20230110153638_create_safe_mailers.rb
Normal file
9
db/migrate/20230110153638_create_safe_mailers.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class CreateSafeMailers < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :safe_mailers do |t|
|
||||
t.string :forced_delivery_method
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -785,6 +785,12 @@ ActiveRecord::Schema.define(version: 2023_01_11_094621) do
|
|||
t.index ["procedure_id"], name: "index_refused_mails_on_procedure_id"
|
||||
end
|
||||
|
||||
create_table "safe_mailers", force: :cascade do |t|
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.string "forced_delivery_method"
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
end
|
||||
|
||||
create_table "services", force: :cascade do |t|
|
||||
t.bigint "administrateur_id"
|
||||
t.text "adresse"
|
||||
|
|
|
@ -5,6 +5,20 @@ RSpec.describe BalancerDeliveryMethod do
|
|||
end
|
||||
end
|
||||
|
||||
class ImportantEmail < ApplicationMailer
|
||||
before_action :set_x_deliver_with
|
||||
|
||||
def greet(name)
|
||||
mail(to: "smtp_to", from: "smtp_from", body: "Hello #{name}")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_x_deliver_with
|
||||
headers['X-deliver-with'] = :mock_smtp
|
||||
end
|
||||
end
|
||||
|
||||
class TestMail
|
||||
def self.deliveries
|
||||
@deliveries ||= []
|
||||
|
@ -46,6 +60,7 @@ RSpec.describe BalancerDeliveryMethod do
|
|||
ActionMailer::Base.add_delivery_method :balancer, BalancerDeliveryMethod
|
||||
|
||||
ExampleMailer.delivery_method = :balancer
|
||||
ImportantEmail.delivery_method = :balancer
|
||||
end
|
||||
|
||||
context 'when a single delivery method is provided' do
|
||||
|
@ -101,6 +116,35 @@ RSpec.describe BalancerDeliveryMethod do
|
|||
end
|
||||
end
|
||||
|
||||
context 'SafeMailer.important_email_use_delivery_method is present' do
|
||||
before do
|
||||
allow(SafeMailer).to receive(:important_email_use_delivery_method).and_return(delivery_method)
|
||||
ActionMailer::Base.balancer_settings = { mock_smtp: 10, mock_sendmail: 5 }
|
||||
|
||||
rng_sequence = [3, 14, 1]
|
||||
BalancerDeliveryMethod.random = FixedSequence.new(rng_sequence)
|
||||
end
|
||||
|
||||
after do
|
||||
BalancerDeliveryMethod.random = Random.new
|
||||
end
|
||||
|
||||
context 'known delivery_method & email is important' do
|
||||
let(:delivery_method) { :mock_smtp }
|
||||
|
||||
it 'sends emails given the forced_delivery_method' do
|
||||
mail1 = ImportantEmail.greet('Lucia').deliver_now
|
||||
expect(mail1).to have_been_delivered_using(MockSmtp)
|
||||
|
||||
mail2 = ImportantEmail.greet('Damian').deliver_now
|
||||
expect(mail2).to have_been_delivered_using(MockSmtp)
|
||||
|
||||
mail3 = ImportantEmail.greet('Rahwa').deliver_now
|
||||
expect(mail3).to have_been_delivered_using(MockSmtp)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Helpers
|
||||
|
||||
def have_been_delivered_using(delivery_class)
|
||||
|
|
16
spec/mailers/devise_user_mailer_spec.rb
Normal file
16
spec/mailers/devise_user_mailer_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
RSpec.describe DeviseUserMailer, type: :mailer do
|
||||
let(:user) { create(:user) }
|
||||
let(:token) { SecureRandom.hex }
|
||||
describe '.confirmation_instructions' do
|
||||
context 'without SafeMailer configured' do
|
||||
subject { described_class.confirmation_instructions(user, token, opts = {}) }
|
||||
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
|
||||
end
|
||||
context 'with SafeMailer configured' do
|
||||
let(:forced_delivery_method) { :kikoo }
|
||||
before { allow(SafeMailer).to receive(:forced_delivery_method).and_return(forced_delivery_method) }
|
||||
subject { described_class.confirmation_instructions(user, token, opts = {}) }
|
||||
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(forced_delivery_method.to_s) }
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue