HTML Email is hard to get right

By: on July 18, 2006

For a recent project, we developed support for sending
automatically-generated HTML emails. Now, most people do this by
including a message body with MIME-type
text/html. For extra points, sometimes there’s also a
text/plain part alongside the HTML in a
multipart/alternative container.

The problem with doing things this way is that you can’t include any
images or other resources (such as CSS) as separate parts of the email
linked to from the main HTML body-part. For that, you need to use the
MIME-type. Unfortunately, few commonly-used email clients render
multipart/related HTML-plus-resource aggregations well.

We only tried the arrangement where the multipart/related,
containing the main HTML page and its associated resources, was a
sibling of the text/plain part within the
multipart/alternative container. The inverse arrangement,
with the multipart/alternative as the main document within
the multipart/related part, was something we have yet to
experiment with.

Here’s a picture of the structure of our initial attempts:

 +-- text/plain
 +-- multipart/related
      +-- text/html
      +-- image/gif
      +-- text/css

This worked reasonably well in Thunderbird and Outlook 2002,
but we had consistent reports from our customer that the images and
stylesheet would randomly fail to display in Outlook 2003 (SP2). After
lots of mucking around trying to get Outlook to either work reliably
or fail reliably, we gave up on that line and instead simplified the
structure of our emails, putting the CSS styling inline in the HTML
HEAD element:

 +-- text/plain
 +-- multipart/related
      +-- text/html (with text/css inline in HEAD)
      +-- image/gif

This didn’t work particularly well, either: it seems many email
clients ignore styles set in the HEAD element. Finally, we
moved to applying CSS styling inline, using a style attribute
on each styled element. We were able to use an XSLT transformation to
allow us to write clean HTML and apply the CSS style
attribute automatically. The final structure of the emails we sent:

 +-- text/plain
 +-- multipart/related
      +-- text/html (with text/css copied on to each element!)
      +-- image/gif

This seems to work more-or-less reliably across

* Thunderbird
* Outlook 2002
* Outlook 2003 SP2
* Google Gmail
* MS Hotmail

If I was to do it all again, I’d give serious consideration to the
traditional non-multipart text/html solution with images
hosted by some public-facing web server. We managed to get our
multipart-HTML-emails working acceptably, but only by the skin of our


* The MIME
media type registry

* multipart/alternative: RFC 2045, RFC 2046
* multipart/related: RFC 2387


  1. Paul Crowley says:

    I have my email client configured to block remote image loading for security reasons – it gives others a way to see when you’re reading their email. In particular, I don’t want spammers to be able to tune their subject lines to maximize the probability that I’ll read their email, which they can otherwise do using “web bugs”. So your last solution won’t reliably work either – sorry!

  2. mikeb says: is the best summary I’ve seen of what email clients can and will do with HTML emails (and it’s recent).

    It’s worth stating that our problem was mainly with making the emails work perfectly in one email client, rather than good-enough in all clients—in the latter case, this followup to an AListApart article is a handy reference also.

  3. tonyg says:

    ((I accidentally deleted a bunch of comments I didn’t mean to delete today, so I’m having to repost them manually:))

    Matthew Sherborne wrote:

    I’ve just been through the same exercise. Could I get a copy of your XSLT sheet please 🙂

  4. tonyg says:

    ((I accidentally deleted a bunch of comments I didn’t mean to delete today, so I’m having to repost them manually:))

    mikeb wrote:

    @Matthew: the XSLT is from our domain model to a very simple MIME-container + HTML model; the actual assembly of the MIME message is done in Scheme. The XSLT really just lets us apply the style attribute consistently.

  5. josh says:

    can you give me som more info on how you did the XSLT to move the CSS inline? We are looking for the same thing and would love a jump start

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>