Override Devise Mailer in Rails

The other day, I had to override devise confirmation instructions email. Particularly, subject of the email being sent out from Devise. Devise makes it easy to override subject of the mail, with devise.en.yml file that stores devise translations for different mailer templates that are used.

Devise provides devise.en.yml, it looks like the file given below.

# config/locales/devise.en.yml
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n

en:
  devise:
    mailer:
      confirmation_instructions:
        subject: "Confirmation instructions"
      reset_password_instructions:
        subject: "Reset password instructions"
      unlock_instructions:
        subject: "Unlock instructions"
      email_changed:
        subject: "Email Changed"
      password_change:
        subject: "Password Changed"

I’ve trimmed down this YAML configuration just to have the context for this particular post.

Now, to override the subject, we can edit value of subject key, under confirmation_instructions key.

subject: "Confirmation instructions for User"

This is useful if we want to change the subject and do not want to add dynamic information in the subject. Let’s say, we want to add name of the person logged in, this is not possible with variable interpolation in strings of YAML files.

subject: "Confirmation instructions for ${user_name}"

This is not possible, as we don’t have a control over when the subject interpolation is called before sending our an email from Devise.

Override Devise::Mailer

We can override Devise::Mailer and customize behavior. Listing down some of the common needs where we would want to implement Custom Mailer from Devise::Mailer.

  • Override Subject with dynamic interpolation of the emails (confirmation_instructions, password_change, ..etc)
  • Pass some extra header information in the emails being sent out in email

Override Subject in Devise Mailer

1. Create devise_mailer.rb file

Create a new mailer, that override default Devise::Mailer as given below.

class DeviseMailer < Devise::Mailer

  def confirmation_instructions(record, token, opts={})
    mail = super
    mail.subject = "Confirmation instructions for ${record.first_name}"
    mail
  end

end

Here, we have created a new Custom Mailer with name DeviseMailer, that inherits from Devise::Mailer and overriden behavior for confirmation_instructions mail sent from devise.

The arguments received:

  • record: User record for which confirmation instructions are being sent out
  • token: User token information
  • opts: Hash with any extra options
2. Instruct Devise to use Custom Mailer

Now, that we have created a custom mailer DeviseMailer, we need to register this mailer with Devise. Devise already provides a way, to register such custom mailer.

# config/initializers/devise.rb
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'

As we can see, devise by default uses Devise::Mailer class. We need to change this line with a line given below.

# config/initializers/devise.rb
# Configure the class responsible to send e-mails.
  config.mailer = 'DeviseMailer'

Now, devise will override subject as given in devise_mailer.rb file.

Override header in Devise Mailer

Similarly, we can override header information as given below.

class DeviseMailer < Devise::Mailer

  def confirmation_instructions(record, token, opts={})
    opts[:from] = '[email protected]'
    opts[:to] = '[email protected]'
    super
  end

end

This override, from and to for the email being sent out.