DEV Community

Pavel Myslik
Pavel Myslik

Posted on

3 Action Mailer Features I Didn't Know Existed

A few weeks ago I needed to check something in the Action Mailer docs, just a quick lookup. I ended up spending much more time there than expected and found a few features I had no idea existed, even though I've been using Action Mailer in production for a while.

One of them lets you see an email before it's ever sent. Another lets you modify an email right before it goes out. And the third one allows you to override the default delivery options dynamically.

I figured I probably wasn't the only one who had missed these, so here are three Action Mailer features that caught my attention.

If you want to explore more, the official Action Mailer documentation is always a great place to start.


1. Previews

Before I found this, testing an email meant sending it to myself, checking my inbox, tweaking the template, and repeating. Turns out ActionMailer has a built-in way to preview emails in the browser, without sending anything.

You add a preview class in test/mailers/previews like:

class InvitationMailerPreview < ActionMailer::Preview
  def team_invitation
    InvitationMailer.with(user: User.first, company: Company.first).team_invitation
  end
end
Enter fullscreen mode Exit fullscreen mode

And visit http://localhost:3000/rails/mailers/invitation_mailer/team_invitation.

This removes the usual feedback loop of tweaking a template. You just refresh the browser instead.

Rails also allows custom preview paths if you want to keep previews in a different location:

config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
Enter fullscreen mode Exit fullscreen mode

This was a small discovery, but it immediately improved my workflow.


2. Interceptors

An interceptor is a hook that runs right before an email is handed off for delivery, letting you modify it.

A common use case is preventing mistakes in staging environments. Nobody wants to accidentally send a real looking email from a staging application to an actual customer. Another common approach is redirecting all outgoing mail in staging or development environments to a single default address, so nothing ever reaches a real inbox by accident.

In my case, I use an interceptor to add a [STAGING] prefix to email subjects.

The interceptor itself is simple, just a class with a delivering_email(message) class method:

# app/mailers/interceptors/staging_subject_interceptor.rb
class Interceptors::StagingSubjectInterceptor
  def self.delivering_email(message)
    message.subject = "[STAGING] #{message.subject}"
  end
end
Enter fullscreen mode Exit fullscreen mode

Then register it in your staging environment:

# config/environments/staging.rb
Rails.application.configure do
  config.action_mailer.interceptors = %w[Interceptors::StagingSubjectInterceptor]
end
Enter fullscreen mode Exit fullscreen mode

That's it. Every email going through Action Mailer can now be modified before it is delivered.

I like this feature because it solves a problem without requiring changes in every individual mailer.


3. Dynamic Delivery Options

This one is different. I haven't needed it in production yet, but it caught my attention enough that I spent some time experimenting with it to see how it works.

By default, Rails applications have a single configured delivery method. For example, all emails might go through the same SMTP provider.

However, there are situations where you might need different delivery settings depending on the email being sent, such as in a multi-tenant application where each customer has their own SMTP credentials, or when transactional and marketing emails are sent through different providers.

Action Mailer lets you override the delivery settings for a specific email by passing delivery_method_options to mail:

class NotificationMailer < ApplicationMailer
  def new_activity(tenant, recipient)
    delivery_options = {
      user_name: tenant.smtp_user,
      password:  tenant.smtp_password,
      address:   tenant.smtp_host
    }

    mail(
       to: recipient.email,
       subject: "New activity",
       delivery_method_options: delivery_options
     )
  end
end
Enter fullscreen mode Exit fullscreen mode

I haven't tried this in a real multi-tenant setup yet, but it's good to know the option exists for when that need comes up.


Wrapping Up

None of these are new features. They've been part of Action Mailer for a while.

It just took an unrelated search for me to slow down and explore the documentation more carefully, and I'm glad I did.

If you've been using Action Mailer for a while, it might be worth revisiting the docs from time to time. You might discover a feature that has been there all along.

Let me know in the comments if you've used any of these features, or if there's another one you'd add to the list.

Top comments (0)