From 8b9d4c87f7b155098cca7ce04d6ea65533bf8f8b Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Tue, 26 Mar 2024 20:00:54 +0100 Subject: [PATCH] refactor(mailer): more thread safe defaults tweaks --- app/mailers/application_mailer.rb | 2 +- .../mailer_defaults_configurable_concern.rb | 81 +++++++++++++++++++ .../mailer_headers_configurable_concern.rb | 41 ---------- app/mailers/devise_user_mailer.rb | 2 +- 4 files changed, 83 insertions(+), 43 deletions(-) create mode 100644 app/mailers/concerns/mailer_defaults_configurable_concern.rb delete mode 100644 app/mailers/concerns/mailer_headers_configurable_concern.rb diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 9d1345a1a..cb5124753 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,6 +1,6 @@ class ApplicationMailer < ActionMailer::Base + include MailerDefaultsConfigurableConcern include MailerDolistConcern - include MailerHeadersConfigurableConcern include MailerMonitoringConcern include BalancedDeliveryConcern include PriorityDeliveryConcern diff --git a/app/mailers/concerns/mailer_defaults_configurable_concern.rb b/app/mailers/concerns/mailer_defaults_configurable_concern.rb new file mode 100644 index 000000000..21310ff7c --- /dev/null +++ b/app/mailers/concerns/mailer_defaults_configurable_concern.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +module MailerDefaultsConfigurableConcern + extend ActiveSupport::Concern + + class_methods do + # Save original defaults before they're modified + def save_original_defaults + @original_default_from ||= self.default[:from] + @original_default_host ||= Rails.application.routes.default_url_options[:host] + @original_asset_host ||= asset_host + end + + # Resets mailer settings to their original values + def reset_original_defaults + default from: original_default_from, reply_to: original_default_from + default_url_options[:host] = original_default_host + Rails.application.routes.default_url_options[:host] = original_default_host + self.asset_host = original_asset_host + end + + def original_default_from = @original_default_from + def original_default_host = @original_default_host + def original_asset_host = @original_asset_host + end + + included do + before_action -> { self.class.save_original_defaults } + after_action -> { self.class.reset_original_defaults } + + def configure_defaults_for_user(user) + return if !user.is_a?(User) # not for super-admins + + I18n.locale = user.locale + + if user.preferred_domain_demarches_gouv_fr? + set_currents_for_demarches_gouv_fr + else + set_currents_for_legacy + end + + # Define mailer defaults + from = derive_from_header + self.class.default from: from, reply_to: from + self.class.default_url_options[:host] = Current.host + Rails.application.routes.default_url_options[:host] = Current.host + + original_uri = URI.parse(self.class.original_asset_host) # in local with have http://, but https:// in production + self.class.asset_host = "#{original_uri.scheme}://#{Current.host}" + end + + def configure_defaults_for_email(email) + user = User.find_by(email: email) + configure_defaults_for_user(user) + end + + private + + def set_currents_for_demarches_gouv_fr + Current.application_name = "demarches.gouv.fr" + Current.host = ENV.fetch("APP_HOST") + Current.contact_email = "contact@demarches.gouv.fr" + Current.no_reply_email = NO_REPLY_EMAIL.sub("demarches-simplifiees.fr", "demarches.gouv.fr") # rubocop:disable DS/ApplicationName + end + + def set_currents_for_legacy + Current.application_name = APPLICATION_NAME + Current.host = ENV["APP_HOST_LEGACY"] || ENV.fetch("APP_HOST") # APP_HOST_LEGACY is optional. Without it, we are in the situation withotu double domains + Current.contact_email = CONTACT_EMAIL + Current.no_reply_email = NO_REPLY_EMAIL + end + + def derive_from_header + if self.class.original_default_from.include?(NO_REPLY_EMAIL) + Current.no_reply_email + else + "#{Current.application_name} <#{Current.contact_email}>" + end + end + end +end diff --git a/app/mailers/concerns/mailer_headers_configurable_concern.rb b/app/mailers/concerns/mailer_headers_configurable_concern.rb deleted file mode 100644 index b5d1c1731..000000000 --- a/app/mailers/concerns/mailer_headers_configurable_concern.rb +++ /dev/null @@ -1,41 +0,0 @@ -module MailerHeadersConfigurableConcern - extend ActiveSupport::Concern - - included do - def configure_defaults_for_user(user) - return if user.nil? || !user.is_a?(User) # not for super-admins - - I18n.locale = user.locale - - if user.preferred_domain_demarches_gouv_fr? - Current.application_name = "demarches.gouv.fr" - Current.host = ENV.fetch("APP_HOST") - Current.contact_email = "contact@demarches.gouv.fr" - Current.no_reply_email = NO_REPLY_EMAIL.sub("demarches-simplifiees.fr", "demarches.gouv.fr") # rubocop:disable DS/ApplicationName - else - Current.application_name = APPLICATION_NAME - Current.host = ENV["APP_HOST_LEGACY"] || ENV.fetch("APP_HOST") # _LEGACY is optional, fallbagck to default when unset - Current.contact_email = CONTACT_EMAIL - Current.no_reply_email = NO_REPLY_EMAIL - end - - @@original_default_from ||= self.class.default[:from] - from = if @@original_default_from.include?(NO_REPLY_EMAIL) - Current.no_reply_email - else - "#{Current.application_name} <#{Current.contact_email}>" - end - - self.class.default from: from, reply_to: from - self.class.default_url_options[:host] = Current.host - Rails.application.routes.default_url_options[:host] = Current.host # link generated by url helpers in tags substitutions - self.class.asset_host = Current.application_base_url - end - - def configure_defaults_for_email(email) - user = User.find_by(email: email) - - configure_defaults_for_user(user) - end - end -end diff --git a/app/mailers/devise_user_mailer.rb b/app/mailers/devise_user_mailer.rb index 03ee64bcb..fcebeb0e1 100644 --- a/app/mailers/devise_user_mailer.rb +++ b/app/mailers/devise_user_mailer.rb @@ -3,9 +3,9 @@ class DeviseUserMailer < Devise::Mailer helper :application # gives access to all helpers defined within `application_helper`. helper MailerHelper include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url` + include MailerDefaultsConfigurableConcern include MailerDolistConcern include MailerMonitoringConcern - include MailerHeadersConfigurableConcern include BalancedDeliveryConcern include PriorityDeliveryConcern