Keeping Test Emails out of the Wild In Rails

Posted by Tejus Parikh on June 29, 2010

There are a few cardinal sins for a developer: deleting the production database, deploying code to the wrong machine, and sending out emails to all the mock users. These situations happen because the terminal window on production looks an awful lot like the terminal window on dev. I don’t have solutions to the first two problems, but preventing emails to the test user database is pretty easy in Ruyb on Rails. Two solutions I’ve found are santize_email and mail_safe. These are both ActiveRecord extensions that allow the user to set an override address that will be the recipient of the email. Sanitize_email is the first solution I tried. It’s configuration is straight forward and it can either be installed as a plugin or gem. Personally, I like gems because they can be shared across multiple projects. Once you’ve installed the gem, you need to configure an initializer with the following (from their README):


    # Settings for sanitize_email gem.  These can be overridden in individual config/%env%/environment.rb files.



    require 'sanitize_email'

    ActionMailer::Base.sanitized_recipients = "jtrupiano@gmail.com"

    ActionMailer::Base.sanitized_bcc = nil

    ActionMailer::Base.sanitized_cc = nil



    # optionally, you can configure sanitize_email to to include the "real" email address as the 'user name' of the

    # "sanitized" email (e.g. "real@address.com ")

    ActionMailer::Base.use_actual_email_as_sanitized_user_name = true # defaults to false



    # These are the environments whose outgoing email BCC, CC and recipients fields will be overridden!

    # All environments not listed will be treated as normal.

    ActionMailer::Base.local_environments = %w( development test staging )

You can set the configuration to override the recipients, the cc, and the bcc. One could use sanitize_email to automatically set a bcc for all production emails, along with setting all three to prevent emails from going into the wild. Another neat feature is that it provides all Mailers with the force_sanitize method, which programmatically traps emails through a specific path. Mail_safe is available strictly as a gem. It’s configuration is a little simpler. The following is the basic config from their README:

  if defined?(MailSafe::Config)

    MailSafe::Config.internal_address_definition = /.*@my-domain\.com/i

    MailSafe::Config.replacement_address = 'me@my-domain.com'

  end

It doesn’t allow distinct addresses for bcc, cc, and recipients, preventing it’s use for automatic override addresses. While it lacks that feature, it does allow addresses for white-listed domains to be delivered, as well as allowing users to provide a proc for the options settings. For example:

    MailSafe::Config.internal_address_definition = lambda { |address|

      address =~ /.*@domain1\.com/i ||

      address =~ /.*@domain2\.com/i ||

      address == 'full-address@domain.com'

    }



    # Useful if your mail server allows + dynamic email addresses like gmail.

    MailSafe::Config.replacement_address = lambda { |address| "my-address+#{address.gsub(/[\w\-.]/, '_')}@gmail.com" }

Our choice was to use mail_safe since it did allow white-listed domains to be delivered normally. This fit the feature set of giving us a safety net incase our mock data got pushed to a system with a live mail-server, while still enabling our test users to use the application.

Tejus Parikh

I'm a software engineer that writes occasionally about building software, software culture, and tech adjacent hobbies. If you want to get in touch, send me an email at [my_first_name]@tejusparikh.com.