Override the default ActionMailer by a method called inside any mailer
Considering we have a custom set of headers in application.rb as
config.action_mailer.default_options = {
'X-MyCustomHeader' => "Default_value" }
I would like to be able to call a method, for example remove_custom_header
, from within any mailer and it has the header removed, or at least set to zero.
Since its custom header (starting with X-) ActionMailer allows you to create more than one and not overwrite it as you would with standard headers.
What is the best way to define a method that can overcome it?
The problem is when you call headers['X-MyCustomHeader'] = nil
inside the mailer method, it won't override it, it just creates a second header where the entry is zero, leaving the original from application.rb via email.
The only way you can override the default set is to call it default 'X-MyCustomHeader' => nil
inside ApplicationMailer (or any inherited mail server class) as shown below, but not in a method.
class ApplicatioMailer < ActionMailer::Base
helper :application
default 'X-MyCustomHeader' => nil
end
but I would like to call this based on the method and not in the mailer class itself as the application has many mailbox classes and they need to disable this for one or two methods in some mail servers.
My current solution:
class ApplicatioMailer < ActionMailer::Base
helper :application
default 'X-MyCustomHeader' => Proc.new { @is_disabled ? nil : Rails.config.action_mailer.default_header }
def remove_custom_header
@is_disabled = true
end
end
and this seems to work as you are using the call default
from ActionMailer to override. Now I've tested this and it works with multiple calls, so the value @is_disabled
doesn't seem to persist between calls to the mailer. I don't understand how the var class works here in the mailer superclass that calls it and when no new class object is created, but it seems to be null every new ApplicationMailer call, so it works for me. However, is this a good solution? Am I missing something obvious? I don't feel compatible using the var class in this situation, but I can think of something else!
Thanks in advance for your help!
EDIT :: For example, I would like to call my mailers, like ...
class MyMailer < ApplicatioMailer
def mail_method_one(email)
# my call
remove_custom_header
mail from: a.format, subject: email.subject
end
end
And if my method above setting the var class is valid and sane (which I doubt in some way), someone can explain why, as I'll be wondering how it works and will have to justify it to the lead developer! :)
source to share
Unlike what it looks like, @is_disabled
it is not a class variable, it is an instance variable. Just like a method you defined is defined as an instance class
Please note what you are doing ...
def mail_method_one(email)
... not...
def self.mail_method_one(email)
You can confirm this yourself by stopping the execution with a gem pry
or other verification tool ...
def mail_method_one(email)
binding.pry
And if you look self
, you will see that you are in an instance of the mailer.
You call it as a class method, but that is because the action mailer uses the method_missing method to check if the missing class method is actually an instance method and creates a new MessageDelivery instance passing the class name, method name and arguments, and then calls the method on an instance of the mailer class.
Here's the code where it does it ...
def method_missing(method_name, *args)
if action_methods.include?(method_name.to_s)
MessageDelivery.new(self, method_name, *args)
else
super
end
end
You can check the code here ... https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb
source to share