Rails: Developing Email-related features with rspec, email-spec and letter_opener

After years of being a developer, (.NET and Grails, now I’m 3 months into Ruby-land), I always run into productivity problems when developing email-related features. Here’s why:

  1. Write/Fix the code
  2. Send the email to an inbox
  3. Open the inbox
  4. Find something wrong
  5. Repeat 1-4 until satisfied

Sounds easy, but it’s really tedious. Your inbox fills up with test emails. Your ‘flow’ gets broken. So recently, I’ve marked a new milestone in my development career: that doesn’t happen anymore. Instead, this happens:

  1. Write a test, expecting what I want to appear in an email.
  2. Write the code
  3. Run the test, find something wrong
  4. (Optional) Run the mailer in the rails console, email pops up as an HTML file in my browser
  5. Repeat 1-4 until satisfied.

No more inbox related stuff, and I can cycle quickly through the usual development loop.

rspec, email_spec and letter_opener are the keys to how I became productive. Combining these gems are one of the many ways to get productive in churning out email-related code, but so far this is my most favorite.


rspec needs no introduction – simply put, it’s a unit testing framework for ruby.

I don’t write unit tests for all of my code, since I know I’ll go crazy when I do and it’ll be counterproductive. I only write tests for my code when:

  1. It’s a piece of the system that’s really important and prone to errors.
  2. It’s a pain to replicate manually.

To cut it short, Unit tests helps me be confident that whatever I’m expecting to send in an email, is actually written there in that email.

email_spec are helpers for rspec to test emails. Taken right out of the README:

describe "Signup Email" do
  include EmailSpec::Helpers
  include EmailSpec::Matchers
  # include ActionController::UrlWriter - old rails
  include Rails.application.routes.url_helpers

  before(:all) do
     @email = UserMailer.create_signup("jojo@yahoo.com", "Jojo Binks")

  it "should be set to be delivered to the email passed in" do
    @email.should deliver_to("jojo@yahoo.com")

  it "should contain the user's message in the mail body" do
    @email.should have_body_text(/Jojo Binks/)

  it "should contain a link to the confirmation link" do
    @email.should have_body_text(/#{confirm_account_url}/)

  it "should have the correct subject" do
    @email.should have_subject(/Account confirmation/)



letter_opener sends the email in the browser as an HTML file instead of really sending it. This means you do not need to set up email delivery in your development environment. Helpful for styling emails, and for integration tests (Cukes)

Taken right out of the README:

First add the gem to your development environment and run the bundle command to install it.

gem "letter_opener", :group => :development

Then set the delivery method in config/environments/development.rb

config.action_mailer.delivery_method = :letter_opener

Now any email will pop up in your browser instead of being sent. The messages are stored in tmp/letter_opener


rspec + letter_opener = developing any email-related feature is no longer painful.