Introducing Supermail

An easier way to work with emails in Rails.

Supermail 0.2.x has been released! It’s a better way to work with emails in Rails.

Here’s what a Supermail email looks like:


# $ rails generate supermail:email User::Welcome
# ./app/emails/user/welcome.rb
class User::WelcomeEmail < ApplicationEmail
  def initialize(person:)
    @person = person
  end

  def to = @person.email
  def subject = "Welcome to Beautiful Ruby"
  def body
    super do
      <<~_
      Hi #{@person.name},

      You're going to learn a ton at https://beautifulruby.com.
      _
    end
  end
end

When you want to use it to send an email, you just initialize the thing like you would any Ruby class and send it.

# You might call this from a controller
User::WelcomeEmail.new(person: @person).deliver_now

ActionMailer is frustrating

Action Mailer is one of the most frustrating parts of Rails. The problem I have with it is I can never remember how to initialize it and send an email.

# Is it this?
UserMailer.welcome(@user).deliver_now

# Or is it this?
UserMailer.with(user: @user).welcome.deliver_now

# Mabye this?
UserMailer.new.welcome(@user).deliver_now

# Or is it something else? 🤷

There are too many levels of indirection for no apparent reason and it doesn’t really make sense to group a bunch of emails into one class.

class UserMailer < ApplicationMailer
  # Why a `default1 class method with a hash? Methods are cool!
  default from: "notifications@example.com"

  def welcome_email
    # This is weird, where do params come from? Can I access these from the template?
    @user = params[:user]
    # Ok this is reasonable.
    @url  = "http://example.com/login"
    # Is this mailing the thing or just generating a message? Where is the body?
    mail(to: @user.email, subject: "Welcome to My Awesome Site")
  end
end

All of that can be modeled more simply in a plain ‘ol Ruby object. In fact, here’s the source code for Supermail’s base email class:

class Base
  delegate :deliver, :deliver_now, :deliver_later, to: :message_delivery

  def to = nil
  def from = nil
  def subject = nil
  def body = ""

  def message
    message_delivery.message
  end

  def message_delivery
    ActionMailer::Base.mail(to:, from:, subject:, body:)
  end
end

Watch the video

I shot a late night Read the Friendly Source Code video that covers ActionMailer and Supermail.

Start using Supermail

If you want to start using Supermail, you can install it by adding it to your Gemfile:

bundle add supermail

Then run the install generator:

rails generate supermail:install

You’ll see a new file at app/emails/application_email.rb that can be customized as your base email class.

It’s already hooked up to your Rails ActionMailer configuration, so there’s no additional configuration required.

Do you want to learn Phlex 💪 and enjoy these code examples?

Support Beautiful Ruby by pre-ordering the Phlex on Rails video course.

Order the Phlex on Rails video course for $379 $289