#312 Sending HTML Email
- Download:
- source codeProject Files in Zip (41.6 KB)
- mp4Full Size H.264 Video (16 MB)
- m4vSmaller H.264 Video (9.19 MB)
- webmFull Size VP8 Video (8.07 MB)
- ogvFull Size Theora Video (23.3 MB)
Let’s say that we want to send an HTML-formatted email. We code up our HTML like normal and use fancy CSS floats and positioning to make it look just how we want to and when we check it in a browser it looks great.
So, we decide to send it out to our thousands of subscribers only to find out that when we do it looks terrible in some email clients. What should we do?
Thankfully there are many articles on the best practices for sending HTML emails that are only a Google search away, this one for example. One important point that it raises is that we should use tables for layout instead of CSS. This means that we’ll have to say goodbye to our beautiful semantic HTML and use old-school tables instead. This isn’t as pretty but it will get the job done.
Another important point the article makes is that when we use CSS in our emails we should use inline styles as many web clients will strip out whatever’s inside the head tag. This means that any CSS we use should be defined inside style attributes in the HTML elements. This can be a headache to write and maintain but thankfully there are some tools that help us here. For example Mailchimp provides a Web application where we can paste in some HTML and CSS and have it converted so that the styles are inline.
If you’re sending HTML emails from a Rails application there are some tools that will do this automatically for us. One of these is the Premailer Rails 3 gem which uses the Premailer gem. Another gem that will do this is Roadie, a fork of the MailStyle gem. These are both simple to set up and to show you how it’s done we’ll create a new Rails application called mailit
and create a new mailer in there called newsletter_mailer
.
$ rails new mailit $ cd mailit $ rails g mailer newsletter_mailer weekly create app/mailers/newsletter_mailer.rb invoke erb create app/views/newsletter_mailer create app/views/newsletter_mailer/weekly.text.erb invoke test_unit create test/functional/newsletter_mailer_test.rb
Here’s what the generated newsletter_mailer
looks like.
class NewsletterMailer < ActionMailer::Base default from: "from@example.com" # Subject can be set in your I18n file at config/locales/en.yml # with the following lookup: # # en.newsletter_mailer.weekly.subject # def weekly @greeting = "Hi" mail to: "to@example.org" end end
We’ll modify the weekly
action so that we can pass in an email address and we’ll set the subject, too.
def weekly(email) @greeting = "Hi" mail to: email, subject: "RailsCasts Weekly" end
There’s already a text template available that will be rendered out and it’s always good to have a plain text version of the emails that we send so we’ll write that first.
RailsCasts - Ruby on Rails Screencasts Weekly Episodes --------------------------------------------- Episode 310: Getting Started with Rails Learning Ruby on Rails can be overwhelming, especially if you are new to programming. Here I will take you on a tour through various resources to help get started with Rails. Watch Episode (7 minutes): http://railscasts.com/episodes/310-getting-started-with-rails --------------------------------------------- (rest of file omitted)
Next we’ll write our HTML version.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>RailsCasts Weekly</title> <style type="text/css"> body, td { color:#000000; font-size:14px; font-family:Verdana,Helvetica,Arial; } .divider { background-color:#555555; height:2px; } .episode h2 { margin-top:0; margin-bottom:8px; font-size:18px; } .episode p { margin:8px 0; } .episode img { border:solid 1px #777777; } .episode .duration { font-size:11px;color:#555555; } #footer { font-size:11px; color:#555555; } #footer a { color:#555555;} </style> </head> <body> <table width="100%" id="background" border="0" cellpadding="0" cellspacing="0"> <tr><td align="center" valign="top"> <table width="650" id="main" border="0" cellpadding="0" cellspacing="20"> <tr> <td id="header" colspan="2"> <a href="http://railscasts.com/"><img src="http://railscasts.com/images/railscasts_logo.png" width="423" height="56" alt="RailsCasts"></a> </td> </tr> <tr> <td class="divider" colspan="2" bgcolor="#555555" height="2"></td> </tr> <tr class="episode"> <td> <a href="#"><img src="http://railscasts.com/assets/episodes/stills/310-getting-started-with-rails.png" width="200" height="125" alt="#310 Getting Started with Rails"></a> </td> <td valign="top"> <h2>#310 Getting Started with Rails</h2> <p>Learning Ruby on Rails can be overwhelming, especially if you are new to programming. Here I will take you on a tour through various resources to help get started with Rails.</p> <p> <a href="#">Watch Episode</a> <span class="duration">(7 minutes)</span> </p> </td> </tr> <tr> <td class="divider" colspan="2" bgcolor="#555555" height="2"></td> </tr> <tr> <td id="footer" colspan="2" align="center"> <p><a href="#">Unsubscribe</a> if you do not wish to receive these emails in the future.</p> <p>©2011 RailsCasts</p> </td> </tr> </table> </td></tr> </table> </body> </html>
Note that we’ve styled the HTML version in a style
tag in the head. These styles will all be moved inline automatically by either Premailer or Roadie. We could also use an external style sheet if we wanted to with a normal stylesheet link and these styles would be moved inline as well. For this to happen we’ll need to add one of these gems to our application. For Premailer we’d need to add its gem and also either Nokogiri or Hpricot as it will use one of these.
gem 'hrpicot' gem 'premailer-rails3'
We’re going to use Roadie so we’ll add that instead then run bundle to install it.
gem 'roadie'
In order to test this out in our Development environment we need to configure some mail settings in the development config file.
Mailit::Application.configure do config.action_mailer.default_url_options = { host: "railscasts.com" } config.action_mailer.raise_delivery_errors = true config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: "smtp.gmail.com", port: 587, domain: "railscasts.com", authentication: "plain", enable_starttls_auto: true, user_name: ENV["GMAIL_USERNAME"], password: ENV["GMAIL_PASSWORD"] } # Rest of file omitted. end
We set several things here. We set the default_url_options
to our domain; we make sure that delivery errors are shown so that we can see the errors if we have trouble sending out the emails and we set the delivery method to SMTP and add the appropriate settings for our email server. We use environment variables for the username and password so that we can set them behind the scenes but you can set them directly if you prefer.
Now that our mailer is set up we can try it out through the Rails console. When we do we might see a warning from the CSS Parser gem. There’s nothing we can do about this but it shouldn’t cause any problems and it should be fixed soon. We can then send out a test email.
> NewsletterMailer.weekly('railscasts.example@gmail.com').deliver
When we do this our email is sent and it looks great.
If you’re going to use one of these gems you should read the documentation available on its Github page as we’ve not covered everything here. For example with the Roadie gem we can pass a css
option to the mail method to specify which files should be made inline.