Merge pull request #10461 from demarches-simplifiees/infra_email_confirmation_2
ETQ Mainteneur, les emails non vérifiés ne sont pas envoyés
This commit is contained in:
commit
3eafc6bfdc
16 changed files with 138 additions and 12 deletions
|
@ -65,7 +65,7 @@ module Instructeurs
|
||||||
administrateurs: [procedure.administrateurs.first]
|
administrateurs: [procedure.administrateurs.first]
|
||||||
)
|
)
|
||||||
|
|
||||||
user.invite! if user.valid?
|
user.invite_instructeur! if user.valid?
|
||||||
user.instructeur
|
user.instructeur
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Manager
|
||||||
class InstructeursController < Manager::ApplicationController
|
class InstructeursController < Manager::ApplicationController
|
||||||
def reinvite
|
def reinvite
|
||||||
instructeur = Instructeur.find(params[:id])
|
instructeur = Instructeur.find(params[:id])
|
||||||
instructeur.user.invite!
|
instructeur.user.invite_instructeur!
|
||||||
flash[:notice] = "Instructeur réinvité."
|
flash[:notice] = "Instructeur réinvité."
|
||||||
redirect_to manager_instructeur_path(instructeur)
|
redirect_to manager_instructeur_path(instructeur)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#
|
#
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
class BalancerDeliveryMethod
|
class BalancerDeliveryMethod
|
||||||
|
BYPASS_UNVERIFIED_MAIL_PROTECTION = 'BYPASS_UNVERIFIED_MAIL_PROTECTION'.freeze
|
||||||
FORCE_DELIVERY_METHOD_HEADER = 'X-deliver-with'
|
FORCE_DELIVERY_METHOD_HEADER = 'X-deliver-with'
|
||||||
# Allows configuring the random number generator used for selecting a delivery method,
|
# Allows configuring the random number generator used for selecting a delivery method,
|
||||||
# mostly for testing purposes.
|
# mostly for testing purposes.
|
||||||
|
@ -24,6 +25,8 @@ class BalancerDeliveryMethod
|
||||||
end
|
end
|
||||||
|
|
||||||
def deliver!(mail)
|
def deliver!(mail)
|
||||||
|
return if prevent_delivery?(mail)
|
||||||
|
|
||||||
balanced_delivery_method = delivery_method(mail)
|
balanced_delivery_method = delivery_method(mail)
|
||||||
ApplicationMailer.wrap_delivery_behavior(mail, balanced_delivery_method)
|
ApplicationMailer.wrap_delivery_behavior(mail, balanced_delivery_method)
|
||||||
|
|
||||||
|
@ -40,6 +43,18 @@ class BalancerDeliveryMethod
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def prevent_delivery?(mail)
|
||||||
|
return false if mail[BYPASS_UNVERIFIED_MAIL_PROTECTION].present?
|
||||||
|
|
||||||
|
user = User.find_by(email: mail.to.first)
|
||||||
|
return user.unverified_email? if user.present?
|
||||||
|
|
||||||
|
individual = Individual.find_by(email: mail.to.first)
|
||||||
|
return individual.unverified_email? if individual.present?
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def force_delivery_method?(mail)
|
def force_delivery_method?(mail)
|
||||||
@delivery_methods.keys.map(&:to_s).include?(mail[FORCE_DELIVERY_METHOD_HEADER]&.value)
|
@delivery_methods.keys.map(&:to_s).include?(mail[FORCE_DELIVERY_METHOD_HEADER]&.value)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,8 @@ class AdministrateurMailer < ApplicationMailer
|
||||||
@expiration_date = @user.reset_password_sent_at + Devise.reset_password_within
|
@expiration_date = @user.reset_password_sent_at + Devise.reset_password_within
|
||||||
@subject = "N'oubliez pas d’activer votre compte administrateur"
|
@subject = "N'oubliez pas d’activer votre compte administrateur"
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
mail(to: user.email,
|
mail(to: user.email,
|
||||||
subject: @subject,
|
subject: @subject,
|
||||||
reply_to: CONTACT_EMAIL)
|
reply_to: CONTACT_EMAIL)
|
||||||
|
|
|
@ -8,6 +8,8 @@ class AdministrationMailer < ApplicationMailer
|
||||||
@author_name = "Équipe de #{APPLICATION_NAME}"
|
@author_name = "Équipe de #{APPLICATION_NAME}"
|
||||||
subject = "Activez votre compte administrateur"
|
subject = "Activez votre compte administrateur"
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
mail(to: user.email,
|
mail(to: user.email,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
reply_to: CONTACT_EMAIL)
|
reply_to: CONTACT_EMAIL)
|
||||||
|
@ -16,6 +18,8 @@ class AdministrationMailer < ApplicationMailer
|
||||||
def refuse_admin(admin_email)
|
def refuse_admin(admin_email)
|
||||||
subject = "Votre demande de compte a été refusée"
|
subject = "Votre demande de compte a été refusée"
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
mail(to: admin_email,
|
mail(to: admin_email,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
reply_to: CONTACT_EMAIL)
|
reply_to: CONTACT_EMAIL)
|
||||||
|
|
|
@ -8,6 +8,10 @@ module BalancedDeliveryConcern
|
||||||
self.class.critical_email?(action_name)
|
self.class.critical_email?(action_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bypass_unverified_mail_protection!
|
||||||
|
headers[BalancerDeliveryMethod::BYPASS_UNVERIFIED_MAIL_PROTECTION] = true
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def forced_delivery_provider?
|
def forced_delivery_provider?
|
||||||
|
|
|
@ -34,11 +34,19 @@ class DeviseUserMailer < Devise::Mailer
|
||||||
@procedure = opts[:procedure_after_confirmation] || nil
|
@procedure = opts[:procedure_after_confirmation] || nil
|
||||||
@prefill_token = opts[:prefill_token]
|
@prefill_token = opts[:prefill_token]
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
I18n.with_locale(record.locale) do
|
I18n.with_locale(record.locale) do
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reset_password_instructions(record, token, opts = {})
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
def self.critical_email?(action_name)
|
def self.critical_email?(action_name)
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,6 +41,8 @@ class UserMailer < ApplicationMailer
|
||||||
|
|
||||||
configure_defaults_for_user(user)
|
configure_defaults_for_user(user)
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
mail(to: user.email,
|
mail(to: user.email,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
reply_to: Current.contact_email)
|
reply_to: Current.contact_email)
|
||||||
|
@ -54,6 +56,8 @@ class UserMailer < ApplicationMailer
|
||||||
|
|
||||||
configure_defaults_for_user(user)
|
configure_defaults_for_user(user)
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
|
|
||||||
mail(to: user.email,
|
mail(to: user.email,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
reply_to: Current.contact_email)
|
reply_to: Current.contact_email)
|
||||||
|
|
|
@ -58,7 +58,7 @@ class GroupeInstructeur < ApplicationRecord
|
||||||
if not_found_emails.present?
|
if not_found_emails.present?
|
||||||
instructeurs_to_add += not_found_emails.map do |email|
|
instructeurs_to_add += not_found_emails.map do |email|
|
||||||
user = User.create_or_promote_to_instructeur(email, SecureRandom.hex, administrateurs: procedure.administrateurs)
|
user = User.create_or_promote_to_instructeur(email, SecureRandom.hex, administrateurs: procedure.administrateurs)
|
||||||
user.invite!
|
user.invite_instructeur!
|
||||||
user.instructeur
|
user.instructeur
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,4 +29,6 @@ class Individual < ApplicationRecord
|
||||||
gender: fc_information.gender == 'female' ? GENDER_FEMALE : GENDER_MALE
|
gender: fc_information.gender == 'female' ? GENDER_FEMALE : GENDER_MALE
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unverified_email? = !email_verified_at?
|
||||||
end
|
end
|
||||||
|
|
|
@ -79,7 +79,7 @@ class User < ApplicationRecord
|
||||||
owns?(dossier) || invite?(dossier)
|
owns?(dossier) || invite?(dossier)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invite!
|
def invite_instructeur!
|
||||||
UserMailer.invite_instructeur(self, set_reset_password_token).deliver_later
|
UserMailer.invite_instructeur(self, set_reset_password_token).deliver_later
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -267,6 +267,8 @@ class User < ApplicationRecord
|
||||||
super && blocked_at.nil?
|
super && blocked_at.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unverified_email? = !email_verified_at?
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def does_not_merge_on_self
|
def does_not_merge_on_self
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
RSpec.describe BalancerDeliveryMethod do
|
RSpec.describe BalancerDeliveryMethod do
|
||||||
class ExampleMailer < ApplicationMailer
|
class ExampleMailer < ApplicationMailer
|
||||||
def greet(name)
|
include BalancedDeliveryConcern
|
||||||
mail(to: "smtp_to", from: "smtp_from", body: "Hello #{name}")
|
|
||||||
|
def greet(name, bypass_unverified_mail_protection: true)
|
||||||
|
mail(to: name, from: "smtp_from", body: "Hello #{name}")
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection! if bypass_unverified_mail_protection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ImportantEmail < ApplicationMailer
|
class ImportantEmail < ApplicationMailer
|
||||||
|
include BalancedDeliveryConcern
|
||||||
|
|
||||||
before_action :set_x_deliver_with
|
before_action :set_x_deliver_with
|
||||||
|
|
||||||
def greet(name)
|
def greet(name)
|
||||||
mail(to: "smtp_to", from: "smtp_from", body: "Hello #{name}")
|
mail(to: name, from: "smtp_from", body: "Hello #{name}")
|
||||||
|
|
||||||
|
bypass_unverified_mail_protection!
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -145,6 +153,57 @@ RSpec.describe BalancerDeliveryMethod do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the email does not bypass unverified mail protection' do
|
||||||
|
let(:mail) { ExampleMailer.greet(email, bypass_unverified_mail_protection:) }
|
||||||
|
let(:bypass_unverified_mail_protection) { false }
|
||||||
|
|
||||||
|
before do
|
||||||
|
ActionMailer::Base.balancer_settings = { mock_smtp: 10 }
|
||||||
|
mail.deliver_now
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the email belongs to a user' do
|
||||||
|
let(:email) { user.email }
|
||||||
|
let(:user) { create(:user, email: 'u@a.com', email_verified_at:) }
|
||||||
|
|
||||||
|
context 'and the email is not verified' do
|
||||||
|
let(:email_verified_at) { nil }
|
||||||
|
|
||||||
|
it { expect(mail).not_to have_been_delivered_using(MockSmtp) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and the email is not verified but a bypass flag is added' do
|
||||||
|
let(:email_verified_at) { nil }
|
||||||
|
let(:bypass_unverified_mail_protection) { true }
|
||||||
|
|
||||||
|
it { expect(mail).to have_been_delivered_using(MockSmtp) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and the email is verified' do
|
||||||
|
let(:email_verified_at) { Time.current }
|
||||||
|
|
||||||
|
it { expect(mail).to have_been_delivered_using(MockSmtp) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the email belongs to a individual' do
|
||||||
|
let(:email) { individual.email }
|
||||||
|
let(:individual) { create(:individual, email: 'u@a.com', email_verified_at:) }
|
||||||
|
|
||||||
|
context 'and the email is not verified' do
|
||||||
|
let(:email_verified_at) { nil }
|
||||||
|
|
||||||
|
it { expect(mail).not_to have_been_delivered_using(MockSmtp) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and the email is verified' do
|
||||||
|
let(:email_verified_at) { Time.current }
|
||||||
|
|
||||||
|
it { expect(mail).to have_been_delivered_using(MockSmtp) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
|
|
||||||
def have_been_delivered_using(delivery_class)
|
def have_been_delivered_using(delivery_class)
|
||||||
|
|
|
@ -23,7 +23,10 @@ RSpec.describe AdministrateurMailer, type: :mailer do
|
||||||
subject { described_class.activate_before_expiration(user, token) }
|
subject { described_class.activate_before_expiration(user, token) }
|
||||||
|
|
||||||
context 'without SafeMailer configured' do
|
context 'without SafeMailer configured' do
|
||||||
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
|
it do
|
||||||
|
expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil)
|
||||||
|
expect(subject['BYPASS_UNVERIFIED_MAIL_PROTECTION']).to be_present
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with SafeMailer configured' do
|
context 'with SafeMailer configured' do
|
||||||
|
|
|
@ -9,8 +9,11 @@ RSpec.describe AdministrationMailer, type: :mailer do
|
||||||
it { expect(subject.subject).not_to be_empty }
|
it { expect(subject.subject).not_to be_empty }
|
||||||
|
|
||||||
describe "when the user has not been activated" do
|
describe "when the user has not been activated" do
|
||||||
it { expect(subject.body).to include(admin_activate_path(token: token)) }
|
it do
|
||||||
it { expect(subject.body).not_to include(edit_user_password_url(admin_user, reset_password_token: token)) }
|
expect(subject.body).to include(admin_activate_path(token: token))
|
||||||
|
expect(subject.body).not_to include(edit_user_password_url(admin_user, reset_password_token: token))
|
||||||
|
expect(subject['BYPASS_UNVERIFIED_MAIL_PROTECTION']).to be_present
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when the user is already active" do
|
describe "when the user is already active" do
|
||||||
|
@ -25,6 +28,9 @@ RSpec.describe AdministrationMailer, type: :mailer do
|
||||||
|
|
||||||
subject { described_class.refuse_admin(mail) }
|
subject { described_class.refuse_admin(mail) }
|
||||||
|
|
||||||
it { expect(subject.subject).not_to be_empty }
|
it do
|
||||||
|
expect(subject.subject).not_to be_empty
|
||||||
|
expect(subject['BYPASS_UNVERIFIED_MAIL_PROTECTION']).to be_present
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,10 @@ RSpec.describe DeviseUserMailer, type: :mailer do
|
||||||
subject { described_class.confirmation_instructions(user, token, opts = {}) }
|
subject { described_class.confirmation_instructions(user, token, opts = {}) }
|
||||||
|
|
||||||
context 'without SafeMailer configured' do
|
context 'without SafeMailer configured' do
|
||||||
it { expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil) }
|
it do
|
||||||
|
expect(subject[BalancerDeliveryMethod::FORCE_DELIVERY_METHOD_HEADER]&.value).to eq(nil)
|
||||||
|
expect(subject[BalancerDeliveryMethod::BYPASS_UNVERIFIED_MAIL_PROTECTION]).to be_present
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with SafeMailer configured' do
|
context 'with SafeMailer configured' do
|
||||||
|
@ -70,6 +73,7 @@ RSpec.describe DeviseUserMailer, type: :mailer do
|
||||||
it "respect preferred domain" do
|
it "respect preferred domain" do
|
||||||
expect(header_value("From", subject.message)).to include(CONTACT_EMAIL)
|
expect(header_value("From", subject.message)).to include(CONTACT_EMAIL)
|
||||||
expect(subject.message.to_s).to include("#{ENV.fetch("APP_HOST_LEGACY")}/users/password")
|
expect(subject.message.to_s).to include("#{ENV.fetch("APP_HOST_LEGACY")}/users/password")
|
||||||
|
expect(subject[BalancerDeliveryMethod::BYPASS_UNVERIFIED_MAIL_PROTECTION]).to be_present
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -168,4 +168,17 @@ RSpec.describe UserMailer, type: :mailer do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.invite_instructeur' do
|
||||||
|
subject { described_class.invite_instructeur(user, "reset_token") }
|
||||||
|
|
||||||
|
it { expect(subject['BYPASS_UNVERIFIED_MAIL_PROTECTION']).to be_present }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.invite_gestionnaire' do
|
||||||
|
let(:groupe_gestionnaire) { create(:groupe_gestionnaire) }
|
||||||
|
subject { described_class.invite_gestionnaire(user, "reset_token", groupe_gestionnaire) }
|
||||||
|
|
||||||
|
it { expect(subject['BYPASS_UNVERIFIED_MAIL_PROTECTION']).to be_present }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue