Send transactional emails with Mandrill in Rails

Transaction email is a big phrase for something quite simple: an email that your app sends on a given event. A typical example would be the Welcome email that you send to a user who just signed up to your app.

Sure, you can do that in Rails with ActionMailer and email templates. But there are at least 2 good reasons to do this with a service like Mandrill instead (more on Mandrill later):

  1. Your Welcome email will look the same as all the other emails you send using MailChimp (for instance) for your weekly newsletter. Beautiful.
  2. You will have analytics on those emails, thus getting feedback on the effectiveness of your Welcome email.

Why Mandrill? 

ImageWell, I already use MailChimp for all my marketing campaigns. It’s cheap, simple to use, and does everything I need. Mandrill was created by the MailChimp folks to address the need for transactional emails. So you get for free the integration between Mandrill and MailChimp, while still having the same user experience you’re used to in MailChimp. The coolest integration feature we’ll use here is to export to Mandrill email templates designed in MailChimp.

So… if you’re still with me, let’s see how to integrate Mandrill in your Rails app.

Mandrill in Rails

Here’s my initial setup : Rails 3.2 app, with Ruby 2.0, hosted on Heroku. I already have an SMTP config to send email notifications to my users (with ActionMailer and email templates), and I don’t want to get rid of it. It’s possible to set up 2 different mailers in Rails, but it looks like an ugly hack, which I try to avoid. Fortunately Mandrill offers an API (which looks much better than the SMTP service), so we’ll use that instead.

Get the Heroku add-on 

If you’re on Heroku, getting the Mandrill add-on is as simple as a command-line:

$ heroku addons:add mandrill:starter

At this time of writing, the free plan gives you up to 12,000 emails per month. Check the other plans if that’s not enough for you.

You now have a Mandrill username (like app1234567890@heroku.com) and an API key, which we’ll use later. To see them, use this command:

$ heroku config | grep MANDRILL

Integrate MailChimp with Mandrill

Now go to MailChimp to connect Mandrill to your account. It’s in your Account settings, under Extra > Integrations. Use the Mandrill username (the heroku.com email address) as username, and the API key as password. Follow this article if you’re having troubles.

It’s recommended that you also add DKIM and SPF records for better deliverability. It’s explained in Mandrill in the “Sending Domains” section.

Create your Welcome email

Create your email template in MailChimp as you would normally do, then click on “Send to Mandrill” in the menu. That’s it, you can now use it in Mandrill!

How to handle dynamic content in the email?

You might have in your emails dynamic content, or content specific to each user. In my Welcome email, I write the user’s username to make sure she knows how to log back in later. How should I handle that in the template?

Because Mandrill is made by MailChimp, you can diretly use MailChimp’s merge tags. Please note though that currently most MailChimp default merge tags like LIST:COMPANY are not processed by Mandrill. The only one that worked for me was CURRENT_YEAR. I replaced *|LIST:COMPANY|* with *|LIST_COMPANY|* (with the underscore) to be able to set this variable myself.

If I want to output a user identifier in my template, I’ll simply write it like a merge tag, for instance *|USER_IDENTIFIER|*. And when calling the API, I’ll send this variable with its value. Check here for more info on the use of those merge tags in Mandrill.

Calling the API from Rails

Now that we have a beautiful email template with variables ready for dynamic content, let’s send our Welcome email when a user signs up. Let’s look at the code top-down:

In my User controller, here’s the call to send the email:

TransactionMailer.welcome(@user).deliver

It’s calling the welcome method of a new mailer, that I called TransactionMailer.

# app/mailers/transaction_mailer.rb
class TransactionMailer > MandrillMailer::TemplateMailer
  default from: 'team@yourcompany.com', from_name: 'Your Company'

  def welcome(user)
    mandrill_mail template: 'welcome_email',
      subject: I18n.t('email.welcome.subject'),
      to: {email: user.email, name: user.name},
      vars: {
        'USER_IDENTIFIER' => user.email,
        'LIST_COMPANY' => 'Your Company'
      },
      important: true,
      inline_css: true,
      async: true
  end
end

You’ve noticed that my mailer inherits from MandrillMailer::TemplateMailer. This is provided by a nice little gem called mandrill_mailer wrapping the Mandrill API. Add it to your Gemfile:

gem 'mandrill_mailer'

welcome_email‘ is the name of my template in Mandrill. The vars parameter is self-explanatory: I’m setting values for all the merge tags defined in my template. I’ve set important to true to make sure this email is sent before others (I want the Welcome email to be received right at the signup time). Inline_css forces Mandrill to inline the CSS in the email content, which is only possible for emails smaller than 256KB. And async true will deliver the email asynchronously, thus removing the need to use a background worker to handle email tasks, another nice benefit of using Mandrill’s API.

You’ll see here all the params you can use with this method.

Finally, configure the Mandrill Mailer gem:

# config/initializers/setup_mail.rb
ActionMailer::Base.smtp_settings = {
  :address              => "smtp.yourcompany.com",
  :port                 => 587,
  ... (whatever config you already had)
}

MandrillMailer.configure do |config|
  config.api_key = ENV['MANDRILL_APIKEY']
end

The MANDRILL_APIKEY is already defined on Heroku, but you’ll have to set it in your local environment (have a .env file setting these kinds of variables, and load it when Rails boots).

And for each environment, you have to set a default URL option:

# config/environments/production.rb
config.mandrill_mailer.default_url_options = { :host => 'www.yourcompany.com' }
# config/environments/development.rb
config.mandrill_mailer.default_url_options = { :host => 'localhost' }

That’s it, enjoy! To summarize the main benefits with this config:

  • Your app emails look as pretty as your marketing emails.
  • You get analytics on your app emails.
  • Your app can deliver emails asynchronously without the need of background jobs.
  • It’s free!

You can also have your app schedule emails for a later delivery, at a rather low cost: $0.05 for every 1000 emails + $0.02 for every 1000 emails currently in storage waiting to be delivered. It’s a great way to keep your new users engaged by sending them regular emails over their first month on your app.

This entry was posted in Ruby on Rails and tagged , , , , . Bookmark the permalink.

4 Responses to Send transactional emails with Mandrill in Rails

  1. Jamie says:

    Thanks for this write up. Could you explain what’s happening in the welcome method:
    subject: I18n.t(’email.welcome.subject’),

    I’m a little confused where the subject is coming from.

    • Hi Jamie,
      Glad you liked the article!
      subject is a parameter of the mandrill_mail method, this is where you set the email subject. In my example I set it to a predefined string that I stored in an internationalized file, using the I18n mechanism provided by Rails (YAML file).
      Hope it helps!

  2. Jamie says:

    Thanks for the reply. I was able to set up everything for my hobby app on account of this tutorial. This is beyond the scope of this post, but do your mandrill transaction emails get sent to “primary” tab in gmail? For some, reason I’m seeing them added to the “promotion” tab.

    • Yes, it happens to many people. I believe it might be because of Google classifying MailChimp emails as promotion by default.
      I’ve seen websites warn their users that this might happen, to make sure they don’t miss any email…

Leave a comment