HTML email not displaying to some users (System.Net.Mail)

I experienced a problem when using System.Net.Mail with .NET 3.5.

Mails with both an HTML message and a plaintext version weren’t always showing the HTML version, as I intended.  In Outlook and some Webmail services, I got the display I wanted.  In others I didn’t.

PortionOfAlfsLinqEmailOutlookViewViaLitmus

For example two Webmail systems,  GMail and Yahoo, showed plaintext and not the HTML.

The system was coded using AlternateViews in the MailMessage of System.Net.Mail.  The coding was influenced by online code samples.  In these the HTML message (which has an embedded image) was added first followed by the plaintext.

The intent is to show HTML (plaintext is a fallback).

Testing showed that the message had both payloads in the raw source.  (You can easily check this in GMail for instance.)

There are many posts about this same issue on the Internet (PHP, Cold Fusion, .NET…).  Not one that I saw had an answer to the problem.  Some reflected months of frustration.  That convinced me there was no solution.  (Foolish trust in the wisdom of crowds I guess!)

Being convinced there was no easy solution I still scanned the email RFC’s, 2822 and 2046, to see whether I’d missed anything.  I soon found something that looked like an answer.  Here’s a portion from 2046

Systems should recognize that the content of the various parts are interchangeable.  Systems should choose the “best” type based on the local environment and references, in some cases even through user interaction.  As with “multipart/mixed”, the order of body parts is significant.  In this case, the alternatives appear in an order of increasing faithfulness to the original content.  In general, the best choice is the LAST part of a type supported by the recipient system’s local environment.

Elsewhere it notes that it’s a crazy way to define things, but that it’s more compatible with older mail readers (so the past wins not the future!). I didn’t check but I imagine the readers referred to are from the 1970’s or earlier.  (These RFC’s have a long history of revision and number changes, so whatever the date of 2046 the message was likely originally written earlier.)

I rechecked the online documentation for the code I was using.  I didn’t see any explicit mention of the issue.  (Though an example, that I now found, added the views in the order that I wanted, plaintext first, HTML second.  No comment about why, that I saw!)

Changing the order fixed the problem.  Now all mail readers, that I tested, showed HTML.

Vinceremo!

Lessons

Here’s a couple of conclusions, from this incident and the project it is part of:

  1. If you’re doing both HTML and plaintext in an email.  Add plaintext first, HTML second when using System.Net.Mail.  With other systems make sure that the HTML payload occurs later in the raw message stream. (Assuming you want HTML to show up by default.)
  2. If your images are unique to an email, embedding (as opposed to linking) is probably best.  That way you have no need to store a lot of personalised images on your server.
  3. Using both HTML and plaintext is not a bad idea, it can reduce your spam score.  So even though you might not really want the plaintext there are other reasons for putting it in there.
  4. If you’re writing specifications that might last for a long time please consider designs that make sense in the long term.  Short term compromises might be around a long time and if they’re irrational they will waste a lot of programmer time.  Least surprise is a good design philosophy.
  5. Implementations that blindly follow a specification, elderly or not, are sometimes going to cause problems, especially if competing implementations do it differently.  A lot of people have got used to systems that let them prefer HTML.  The specification in fact suggests that, but doesn’t require it.  (There’s a de facto standard, please satisfy it if you are making the choice.)
  6. Documentation should be put together by somebody who knows the details of the underlying code (and why it’s that way) and tells programmers what they need to know. I’m guessing that any thorough programmer who’d use this API would know the issue.  We need that insight in all our documentation.  (If you’re writing the documents please give us the collateral information.  It could save programmers months of unwanted stress.)
  7. One post describing the issue was from somebody who later discovered the solution.  The earlier post was not changed to point to the answer.  Please update your posts. I know it’s easy to treat them as fire and forget, that can do the community a disservice.
  8. Don’t trust the Internet.
  9. Free services on the Internet might not be designed the way they would for a paying customer.  Careful of these things.  (I’ve been bitten by several free forum systems.  They one day realise that it’s no worth doing, they pack up and go away, taking your content, and membership lists with them (unless you saved).  Will the free emails go the same way?)

I like using .NET, but issues like this worry me.

If you want to test the system I’m talking about it’s at this URI at least for the immediate future (2010-04-20).

Advertisements