30Dec

MailStyle: A HTML Email Plugin for Ruby on Rails

Posted in Plugins, Ruby on Rails by Jim Neath

Note: MailStyle was originally called Shemail but was changed due to a general negative response to the name from the public.

Background

Writing inline styles for HTML emails is dull and boring but unfortunately a necessary evil. Rather than do it by hand we thought it would be nicer to let our app do it for us. So we wrote MailStyle.

Enter MailStyle

MailStyle allows you to write the css for your html emails as you normally would, then writes the styles inline when you send your emails. It also makes sure that your image paths are absolute rather than relative.

Installation

First install the dependencies:

sudo gem install nokogiri css_parser

Then install MailStyle to your rails app:

script/plugin install http://github.com/purify/mail_style

Usage

Rendering CSS Inline

Simply add the css method to your deliver actions:

class Notifier < ActionMailer::Base
  def welcome_email
    css :email

    subject 'Welcome Aboard'
    recipients 'someone@example.com'
    from 'jimneath@googlemail.com'
    sent_on Time.now
  end
end

This will look for a css file called email.css in your public/stylesheets folder. The css method can take either a string or a symbol. You can also pass the css file name with or without the .css extension.

MailStyle will now write the styles from email.css into html part of the welcome email (eg. welcome_email.text.html.erb). It won’t touch the plain text part, neither will it do anything if you’re only sending a single part email (eg. welcome_email.html.erb). You shouldn’t be sending html emails without a plain text version anyway.

Say that our email.css file looks like the following:

body { background: #000 }
p { color: #f00; line-height: 1.5 }
.text { font-size: 14px }

And our welcome_email.text.html.erb looks like this:

<p class="text">Hello World</p>

Then the resulting html that will be sent out will resemble the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body style="background: #000">
    <p style="color: #f00;line-height:1.5;font-size: 14px">Hello World</p>
  </body>
</html>

Fixing Image URLs

If you have default_url_options[:host] set in your mailer, then MailStyle will do it’s best to make the urls of images absolute.

In your mailer
ActionMailer::Base.default_url_options[:host] = "example.com"
Example CSS
p { background-image: url(../images/chunky-bacon.png) }
Example HTML View
<img src="/images/header.jpg">
<p>Hello World</p>
Example Output
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
    <img src="http://example.com/images/header.jpg">
    <p style="background-image: url(http://example.com/images/chunky-bacon.png)">Hello World</p>
  </body>
</html>

How You Can Help

The main issue at the moment is speed, so any help speeding things up would be awesome. As always, you can fork the repo at Github.

Further Reading

Below are a couple of links you may find useful regarding HTML emails:

  • shameerm
    Hi,

    Is it possible to pass the css class defnitions instead of passing the css file name?

    Thanks
  • ramontayag
    Friggin awesome! I took a lot less time than I thought I would.

    I have one problem though: I use workling/starling to send emails. When I sent it through a worker it doesn't send as html mail. It's plain text without the inline css.

    When I send it directly from the NewsletterMailer class, it sends the mail fine in html mode, with the inline css. Where do I start looking? Is it a workling thing or a mail_style thing?

    You can see my code here: http://pastie.org/864546
  • Thanks for writing this. We're using mailstyle on thedips.com
  • Just started using this on a project here at Setfire, works great. Makes working on html emails much less painful, thanks!
  • Gordon R E S Blamont
    This new name is THE WORST. I will NEVER use this now. Not just because I DON'T use Ruby, but because I'm SHOCKED and later APPALLED. I go on to be DISTRAUGHT and DEJECTED. This is the worst news since 1991.
  • Great post~i will try to use it
  • rsturim
    I prefer the new name -- thank you for changing it
  • justinshattuck
    Oh how I have waited for thee!
  • Jon
    Three brief thoughts:
    - this plugin looks like a terrific solution for a real problem
    - the old name was (intentionally or not) derogatory, which isn't necessary - the skepticism about that is understandable (there aren't than many transgendered people about there after all), but still misinformed
    - the new name relates to the functionality, which the real win
  • Ivor Ardon
    In my country, MailStyle is a derogatory name for a wench. I'm offended that you'd name a plugin as such. SheMail was a far better, and more professional name. I can't use your plugin unless you change it back, and my 77 followers will all be told of the vile names you give your plugins.
  • Glad to see you changed the name. The other name was a little over the top.
  • This is just awesome. I was about to code something like that for personnel needs, but will definitely use this library and try to help as much as possible !
  • guest
    It's your project, you should name it as you like. They can take it or leave it. I agree with the "lighten up" sentiment.
  • biffle
    bring back the old name you sissy. dont let the corporate squares bully you around. second amendment etc etc etc!!
  • Alas, I've changed the name to MailStyle. Although I still prefer the old name.
  • I prefer the old name too. Sheesh, lighten up a little, people!
  • What about "cuntmail"? Great plugin, which I wish was in Rails core actually since styling emails is a ...cunt. Not the first one doing this (see awesome_email - a bit buggy since css_pool upgrades), but good that more stuff showing up. xD C'mon, don't listen to the conservatives: They never brought any innovations, and so the last ones I listen to myself. Shemail was fine, even though the discussion is a bit lame from the start.
  • I'll probably revert the name in a few days :)

    I had a play around with awesome_email but had nothing but problems (even with your branch :P), so I thought I'd write my own :D
  • Cool.

    Yes the code is somewhat complex to get into (I think it has to do with how the parsing was implemented). I'll probably use your plugin instead when I need HTML e-mails. =)
  • The two main issues I had with awesome_email were that the layout stuff didn't make sense (to me at least) and when I got it working it was taking approximately 17 seconds to write the styles inline. One of my main aims for this plugin is speed. It's not there yet but it will be soon hopefully :)
  • Ouch, sounds like I messed up something badly if it took 17 s. =)
  • Steven Garcia
    How about:

    AwesomeMailer
    EmailMagick
    MOR - MailsOnRails
    HEME - HTML Emails Made Easy

    Really anything is better than shemale - I honestly thought this was a joke
  • @Tobias Crawley - Wordpress gobbled up the class name on the paragraph. Fixed now. Thanks.

    @everyone else - Anyone have any suggestions for a better name for the plugin?
  • How about 'shared_email_css'? Its not very clever, but does describe some of the functionality.
  • sgruhier
    Interesting plugin
    If you are a mac developer you can even use MockSMTP (http://mocksmtpapp.com) to quickly visualize html rendering with using a smtp server.
  • Sarah Mei
    Just FYI, in the US shemale is a highly derogatory and fetishistic term for a transgender woman. It's basically equivalent to calling your plugin cuntmail. It does look useful, but sadly I could never deliver code to a client with this installed.

    I assume it's unintentional (I see from the github page that it's a shortening of "simple HTML email") but I suggest you find another shortening that's less crassly degrading.
  • 0_o Hum, where's the humour? Don't take things so damn seriously; Ruby - nor innovations in general - was developed with constraints in the first place. FYI: In South Asia shemale was a slang for "transgender woman" when I lived there - degrading or not. This world needs to be more relaxed (aka less conservative), and Ruby developers are usually in the front when it comes to this. I hope it stays that way.
  • Nice stuff. I'm confused though - in your p example, you apply the font-size from .text, but there is no .text class on the p. Is that just an omission in the example?

    As for the name, I think it shows too much imagination on your part :). I'm not put off by it being a heterograph for shemale, but am not a fan of names that give little indication of function.
  • sylvanstargazer
    Your choice of name for this plugin is alienating and demonstrates a lack of imagination on your part. Why purposefully call it something that alienates potential users/contributers?
  • Karvė
    Good work! It would be really nice to have such a tool in Java.
blog comments powered by Disqus