diff --git a/app/lib/balancer_delivery_method.rb b/app/lib/balancer_delivery_method.rb index 9052780ad..1fd9be5fb 100644 --- a/app/lib/balancer_delivery_method.rb +++ b/app/lib/balancer_delivery_method.rb @@ -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) diff --git a/spec/lib/balancer_delivery_method_spec.rb b/spec/lib/balancer_delivery_method_spec.rb index 3ba08bb78..bf5e39b52 100644 --- a/spec/lib/balancer_delivery_method_spec.rb +++ b/spec/lib/balancer_delivery_method_spec.rb @@ -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)