How To Send Transactional Emails from Rails With Mandrill

Jessie Young

There are many libraries and services out there that make sending and tracking transactional emails in your Rails app a breeze. I’ve used Sendgrid and Postmark; both make it possible to start sending emails in a matter of minutes.

But the pain points of transactional emails have not been removed entirely.

The pain points of transactional emails

The first pain point is styling. Tools like roadie can automatically inline CSS in email templates based on stylesheets and Rails 4.1 comes with the ability to preview emails in development out of the box, but determining whether those styles look right in different email clients and devices is a lot of extra work. More than once, I’ve had something look awesome in Gmail and then have a client show me the same email looking completely broken in Outlook.

The second pain point is the need for regular copy changes. After setting up an email template, the copy of an email template rarely stays the same for long. Whether it’s right away or a few days later, I almost always find myself tweaking email copy on several occasions to meet client and other stakeholder requests.

Why use Mandrill?

A couple of years ago, my approach to the this problem was to set up an emails table in my database with name and content fields. The name would correspond with an email template name, and the content would be the main chunk of copy for an email. I would set up RailsAdmin as an interface for stakeholders to log in and update individual email records, which would be used to populate the copy for various transactional emails. While this system worked, it was very brittle because it relied on certain records existing in the database in order for the app to function and only allowed for email layouts with one big chunk of copy. In addition, this did not address the issue of responsive email styles.

So, I was very excited to discover Mandrill, Mailchimp’s transactional email service. While Mandrill is about as easy to set up as other services, it also addresses the two pain points that the others do not. Because Mandrill is a Mailchimp product, you can easily import Mailchimp’s responsive templates into Mandrill to use in transactional emails. In addition, stakeholders can edit email copy within Mailchimp’s WYSIWYG and re-import to Mandrill with the click of a button. This means that copy changes don’t require developer time or a new deploy. Awesome.

I’ve now implemented transactional emails with Mandrill for a handful of Rails apps. It’s pretty simple but much simpler once you’ve seen how it’s done. Let’s go through how to send responsive emails with Mandrill and Rails, step-by-step.

How to set up Mandrill in your Rails app

  1. Sign up for Mailchimp / Mandrill

    You need both a Mandrill account and a Mailchimp account.

  2. Connect your Mailchimp and Mandrill accounts

    Follow these instructions for integrating your Mailchimp and Mandrill accounts

  3. Set up a template in Mailchimp

    Create a basic template in Mailchimp. Don’t worry about nailing down the content, but make sure you give the template a good, clear name since you will be referencing that name in your code. I am creating a welcome email so I am going to name mine welcome.

    Also, if you already know which portions of your email are going to be dynamic, include merge variables for those elements. A merge variable is an element of an email that is dynamic; therefore, it’s values must be set each time an email is sent out. A commonly used merge variable is first_name, since the name in an email changes depending on who the email is being sent to. Mailchimp’s format for merge variables looks like this: *|FIRST_NAME|*. You can also set dynamic links by setting the href value of an a tag to a merge variable, like this: <p>Update your account details <a href=“*|USER_URL|*" target="_blank">here</a></p>

    Here’s what my template looks like with basic merge variables:

    Preview of Mailchimp email template!

  4. Send the Mailchimp template to Mandrill

    Once you save and exit the template editing view in Mailchimp, you will be on a list of all templates. Find the template you just created, and click the dropdown option next to the edit button. You should see the option to “Send to Mandrill”. Click on that link. A few seconds later, you should see a flash message saying that your template was sent to Mandrill. Note: as of right now, this flash message takes several seconds to appear, which can be a bit confusing.

  5. Log into Mandrill and visit your templates

    You should see the template you just created. Make sure your template is set to “published” within Mandrill.

    Once a template is in Mandrill, there is no need to edit it. Editing is best done in Mailchimp and then sent to Mandrill using the “Send to Mandrill” link, since Mailchimp’s templates are optimized for multi-client and multi-device compatibility.

  6. Set up your Rails app to send mail with Mandrill

    Add mandrill-api to your Gemfile and bundle

    Set the following ENV vars in your Rails app:

    SMTP_ADDRESS=smtp.mandrillapp.com
    SMTP_DOMAIN=localhost
    SMTP_PASSWORD=mandrill_api_key
    SMTP_USERNAME=mandrill_username
    

    You need set up your SMTP settings for environments where you’d like to actually send emails via Mandrill (for most, this will be production and staging):

    # config/environments/production.rb
    
    Rails.application.configure do
      ...
      config.action_mailer.smtp_settings = {
        address: ENV.fetch("SMTP_ADDRESS"),
        authentication: :plain
        domain: ENV.fetch("SMTP_DOMAIN"),
        enable_starttls_auto: true,
        password: ENV.fetch("SMTP_PASSWORD"),
        port: "587",
        user_name: ENV.fetch("SMTP_USERNAME")
      }
      config.action_mailer.default_url_options = { host: ENV["SMTP_DOMAIN"] }
      ...
    end
    
  7. Set up your Rails app to send Mandrill templates

    Now that you’ve got the basic setup for Mandrill done, it’s time to set up your mailer to use the template you created in Mailchimp and sent to Mandrill. In my experience, it’s best to encapsulate this logic in a mailer class that all other mailer classes inherit from. Existing system emails that use SMTP but do not need Mandrill templates will still send properly via Mandrill, so no need to update those until you want to.

    # app/mailers/base_mandrill_mailer.rb
    
    require "mandrill"
    
    class BaseMandrillMailer < ActionMailer::Base
      default(
        from: "hello@example.com",
        reply_to: "hello@example.com"
      )
    
      private
    
      def send_mail(email, subject, body)
        mail(to: email, subject: subject, body: body, content_type: "text/html")
      end
    
      def mandrill_template(template_name, attributes)
        mandrill = Mandrill::API.new(ENV["SMTP_PASSWORD"])
    
        merge_vars = attributes.map do |key, value|
          { name: key, content: value }
        end
    
        mandrill.templates.render(template_name, [], merge_vars)["html"]
      end
    end
    

    I set up my UserMailer to inherit from this class and use the private methods to simplify my welcome email logic. This is where it is important to make sure you are referencing the same template name and merge variables as you used when you set up your template in Mailchimp.

    # app/mailers/user_mailer.rb
    
    class UserMailer < BaseMandrillMailer
      def welcome(user_id)
        user = User.find(user_id)
        subject = "Welcome to our awesome app!"
        merge_vars = {
          "FIRST_NAME" => user.first_name,
          "USER_URL" => user_url(user),
        }
        body = mandrill_template("welcome", merge_vars)
    
        send_mail(user.email, subject, body)
      end
    end
    
  8. Iterate on email styles and copy to your heart’s content

    You’re done! Time to celebrate.

    From now on, anyone can go into Mailchimp to edit the template’s style and content. All someone needs to do to update system emails for your Rails app is make updates in Mailchimp and click the “Send to Mandrill” link. Just make sure the template name and merge variables stay the same or you’ll need to make changes on the Rails side, too.

    It’s also easy to send test emails from within Mailchimp, which is great for sharing email content and iterations with stakeholders.

    Make sure your environment variables are set on staging and production and then get going. Mandrill lets you send up to 12k emails per month for free, so if you think you will go over that, make sure you add some payment information to your Mandrill account, too.