Responsive Emails in Rails with Ink
Why Responsive?
These days, a lot of users read their emails through their mobile devices (about 48% according to this statistic) and if you want to provide a good user experience to your subscribers you should consider responsive email design.
There are several ways to approach this. You could build the emails yourself from scratch and use media queries to cater for different screens or you could use premium and non-premium templates that are available online and modify them to suit your needs. The problem with these solutions is getting a consistent look of your emails in all email clients. One email client that is especially hard to work with when it comes to responsive emails is Outlook because of its limited CSS support.
What is the Solution?
Zurb, the same company that came up with the Foundation framework released an Email framework named Ink. According to them, Ink enables you to ‘Quickly create responsive HTML emails that work on any device & client. Even Outlook.’. And that is what we will work with in this tutorial. We are going to create a Rails application that sends an email to a user after they sign up for an account.
First we’ll create a new application called rails_ink.
rails new rails_ink
For demonstration purposes, we won’t be building a large application. I used the scaffold command to generate a User model and its related views and controllers.
rails generate scaffold user name:string email:string
Migrate the database after that.
rake db:migrate
Next we’ll generate the mailer.
rails generate mailer UserMailer
This will create a mailer class, view directory, and a test file.
Next, we’ll add a configuration file to the config/initializers
directory. This will hold the mailer configuration settings. For testing, we’ll be using Gmail’s smtp server. In production, you might be using another delivery method, like sendmail with your local server.
Create a file called mailer_settings
inside the config/initializers
directory and insert the following code, making changes as necessary.
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:user_name => ENV['GMAIL_USERNAME'],
:password => ENV['GMAIL_PASSWORD'],
:authentication => "plain"
}
We need to add a method called registration_email
to the app/mailers/user_mailer.rb
file. This method will send an email to a user who registers. The method will take in a User
object and assign it to an instance variable so that it’s available to our view. Since our email will have an image in the banner, we have to include this as an inline attachment in mailer.
class UserMailer < ActionMailer::Base
default from: 'example@sitepoint.com'
def registration_email(user)
@user = user
attachments.inline['banner.jpeg'] = File.read("#{Rails.root}/app/assets/images/banner.jpeg")
mail(to: user.email, subject: 'Registration Confirmation')
end
end
We now need to create a view file for our email. This will be located in the app/views/user_mailer
directory and has to have the same name as the corresponding method in the UserMailer
class.
Create a file named registration_email.html.erb
inside app/views/user_mailer
.
We are going to use one of the templates on the Ink website. I am using the Basic template for this demonstration.
For simplicity, during testing, I prefer just working with the HTML and CSS, running it directly in the browser instead of running it from the Rails application. When I am done, I will then transfer the code to my Rails app.
You can link the ‘ink.css’ file in the email but this should only be done for testing purposes. When you are satisfied with the result, copy the css and paste it into the HTML document between style
tags. Then you should run your email content through an inliner. An inliner brings all your styles inline, which is important, as some email clients tend to strip out the CSS in the style
tag. There are several online inliners, but we’ll use the Ink Inliner.
Don’t place any ERB code in the HTML file because the inliner won’t understand it and, thus, won’t output the correct HTML. We’ll have to search for and replace the static text with the necessary variables. Here I will be replacing the banner image and the name of the recipient (Susan Calvin) with the name of the registered user.
Once we have the email output, paste this code into the mailer view template app/views/user_mailer/registration_email.html.erb
and insert any needed variables. Here, we will search for the string Susan Calvin
and replace it with the following:
<%= @user.name %>
Now, search for the img
tag to the image we want to replace and insert the corresponding image_tag
. Be sure to include the css styles and attributes that the inliner inserted in the tag.
I changed it from this:
<img src="http://placehold.it/200x50" style="outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; width: auto; max-width: 100%; float: left; clear: both; display: block;" align="left" />
To this:
<%= image_tag attachments['banner.jpeg'].url, :style => "outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; width: auto; max-width: 100%; float: left; clear: both; display: block;", :align=>"left" %></td>
In the UsersController
, after saving the user, we call UserMailer.registration_email
and pass it the User
object.
def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
UserMailer.registration_email(@user).deliver
format.html { redirect_to @user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: @user }
else
format.html { render action: 'new' }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
The UserMailer.registration_email(@user).deliver
sends our email.
And that’s it. Register a user and test out the email on different clients.
Conclusion
If you want to send responsive emails to your users without spending money on a template or writing the code from scratch, give Ink a try. It can be used with any language you choose for your app and it also works well with Email Service Providers like Mailchimp and Campaign Monitor.