Charlie Massry

Send Email on Rails with ActionMailer

September 03, 2014

In Ruby on Rails, ActionMailer allows you to email users from your server with processed Ruby code, which can serve any number of uses. There is some configuration required on the back-end to actually set up ActionMailer to actually send mail, but you can fake it for development purposes. There are certain things to be aware of when using ActionMailer. Specifically, you must define instance methods in the mailer class and you must call the instance methods on the mailer class when attempting to send the mail.

# app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
  ...
  def welcome(user)
    @user = user
    mail to: @user.email,
      subject: "Welcome to My Fabulous Web App!"
  end
  ...
end

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  ...
  def create
    user = sign_up(user_params)

    if user.valid?
      UserMailer.welcome(user).deliver
      redirect_to user
    else
      render :new
    end
  end
  ...
end

# app/views/user_mailer/welcome.html.erb
<h1>Welcome <%= @user.email %> to my <em>Fabulous</em> Web App.</h1>
<p>Visit <%= link_to "my site", root_url %> as much as you can.</p>

There are quite a few things going on here, not the least of which is the UserMailer.welcome(user) call. In this particular snippet of code, the user is created and sent a welcoming email. The view is also noteworthy, as it is being called by the mailer, which functions as a sort of controller and renders its view. Another thing about the view is when you include links, you must use url helper instead of path helper as the user’s computer has no base reference of the path to the site, and so, you must configure Rails to know what the domain name it is being hosted at.

Testing emails can be difficult as you have to check that the mail got sent, and that the view contains the appropriate text. Rails provides a method for testing if mail was sent, which is ActionMailer::Base.deliveries. This returns an array of the different mail that was sent, but testing the views won’t be so easy. Luckily there’s a gem for that. The email_spec gem makes testing the email contents really simple, so you can write your expectations clearly about the mailer and not worry about your tests failing but your code actually working.