Illustration of Yeti character writing with a pencil.

Using Cucumber to make sure your site is sending emails when it should

Profile picture for user Silas
Silas Albrecht
Senior Developer

I’ve been playing a bit with Cucumber lately. I needed a way to test whether my site was sending emails in certain situations. So far, I’ve found Cucumber to be a highly flexible tool for behavior-driven development. Paired up with Watir WebDriver, it controls your browser and makes sure your site functions as it should based on the test definitions you provide. Overall, it’s pretty easy to pick up, partly because Ruby is pretty elegant. Cucumber reads from “features” files. The format of these files is similar to scrum story definitions and acceptance criteria. Here’s what I used:

  Scenario: As a user, I visit service site and subscribe to the newsletter
    Given I am on the service site
    When I subscribe to the newsletter with my test email address
    Then I should receive an email with the subject
      Thank you for subscribing

So, that was great. I could have WebDriver go to the site and fill out the subscription form. Pretty close. But I didn’t have a way to check whether the confirmation email arrived. Ruby made that part pretty easy. Ruby comes with an IMAP class in its stdlib, and I found a Gmail library that I could borrow code from to create a class that would connect to Gmail and poll for new emails. Here’s my class:

require 'net/imap.rb'

class TestEmail
  def init_email(username, password, folder = 'inbox')
    @imap ='', 993, true, nil, false)
    res = @imap.login(username, password)

    if == 'OK'
      @logged_in = true
      @folder = folder["NOT", "SEEN"]).each do |message_id|, "+FLAGS", [:Seen])

      at_exit {
        if @logged_in

  def poll(retries, timeout = 5)
    while retries > 0 do
      retries -= 1

      # it does seem to be necessary to reselect this["UNSEEN"]).each do |message_id|, "+FLAGS", [:Seen])
        envelope = @imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
        return envelope

      sleep timeout

I call and init_email() and assign the object to @mail when I setup the webdriver browser. The last step was to write the step definition to verify that we found the right email:

Then /I should receive an email with the subject/ do |text|
  email = @mail.poll(5)
  email.subject.should =~ /#{text}/m
comments powered by Disqus