Previewing email in Rails with ActionMailer::Preview and Letter Opener

Developing email templates to be sent by our Rails application may sometimes be a long and tedious operation because under development you must continuously send to yourself the email in order to test the changes.

If you don’t want to waste your time, Rails provides a very helpful tool for those who need to build the layout for the emails of our application: ActionMailer::Preview. In fact, with this tool (available from Rails 4.1), you are able to generate the Rails mailer view without the need to actually send the email.

Let’s start by setting up the email template and controller action with ActionMailer. We will generate a Mailer which sends a welcome email to users who sign up on our website.

First of all, generate the Mailer:

rails generate mailer UserMailer welcome_email

This will also produce the view, called app/views/user_mailer/welcome_email.html.erb

Great! Let’s define the method that allows us to send the welcome email:

# /app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  def welcome_email(user)
    @user = user
    mail to: user.email, subject: "Welcome"
  end
end
# /app/models/user.rb
def send_welcome_email
  UserMailer.welcome_email(self).deliver_now
end

Now we have to tell the user_controller to deliver the welcome email when a user signs up successfully:

# /app/controllers/users_controller.rb
def create
  @user = User.new(user_params)
  ...
  if @user.save
    ...
    @user.send_welcome_email
  end
end

Now we want our email template to show the username that our application has just recorded.

# /app/views/user_mailer/welcome_email.html.erb
<h1>Welcome <%= @user.name %></h1>
<p>
  This is a welcome email!
</p>

Now, what if we wanted to see our welcome email in our browser to check that it looks as expected? There’s where ActionMailer::Preview comes in handy. Actually the Rails generator has already done most of the work for us. The command we launched at the beginning not only generated the Mailer but it created also this file: /test/mailers/previews/user_mailer_preview.rb (note: if you have rspec bundled in your project the file will be created under /spec)

The file already contains the code needed for the preview to work:

# /test/mailers/previews/user_mailer_preview.rb

# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailerPreview < ActionMailer::Preview

# Preview this email at http://localhost:3000/rails/mailers/user_mailer/welcome_email
  def welcome_email
    UserMailer.welcome_email
  end
end

All we have to do is edit it, since we have modified welcome_email to accept the username as parameter:

# /test/mailers/previews/user_mailer_preview.rb

# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailerPreview < ActionMailer::Preview

# Preview this email at http://localhost:3000/rails/mailers/user_mailer/welcome_email
  def welcome_email
    UserMailer.welcome_email(User.last)
  end
end

Et voila! As the comment in the file says, the email preview is now visible at http://localhost:3000/rails/mailers/user_mailer/welcome_email when the rails server is up and running.

Convenient as this approach is, it still requires us to take care of the test/mailer/previews file in addition to the mailer proper: we have to modify it and keep it up to date to reflect changes in our mailer methods. A different approach which avoids this extra work is using the Letter Opener gem. This gem reroutes all mail sent through our Rails application to be displayed in the browser instead. This is also very useful in the staging environment, if for some reason you have to use production data, because it avoids the risk of sending out test email to production addresses while testing.

The gem is added to the gemfile the usual way:

group :development do
  gem 'letter_opener_web'
end

and then you run bundle install

In our routes:

if Rails.env.development?
  mount LetterOpenerWeb::Engine, at: "/letter_opener"
end

Configure delivery method on your config/environments/development.rb:

config.action_mailer.delivery_method = :letter_opener_web

At this point we can do the action that would trigger the email notification (in our case signing up to the application) and the welcome email is generated and “sent” to the letter opener mailbox. All email generated by the application can now be seen at this url: http://localhost:3000/letter_opener

The development environment is ready to be used. From now on, you will notice that working on mail templates will be much faster!

View Letter_Opener_Web on GitHub

Leave a Reply

wpDiscuz