A couple of days ago I discovered a bug in Hotmail that you can read about here. As it turns out it was both a bug in Hotmail and in my code (sort of), and a type error in my blog post causing some confusion. Thanks to Rune Grothaug for getting me in touch with the Hotmail team.
The bug in Hotmail is related to how they query for content id’s in the email. It’s too expensive to load the email into a html parser to get the id’s, so they do a string match instead. Here’s how I understand it: When they try to match nnug10 they actually get nnug1 back (as the first match). One solution suggested by them was to reverse the order of the searches allowing nnug10 to be found first. I’m not sure if this is what they’re going to do. (Update: I got confirmation that this is the solution they’re going for)
As for my bug it was that I forgot to add the file extension to the ContentType.Name (see code below). This is the name that actually gets displayed for the attachment image in the mail. In Hotmail (and Gmail for that matter) it shows all linked resources as attachments, and the name of these attachments had no extensions (e.g. jpg). A workaround for the Hotmail bug could have been to do the same with the ContentId. When the id is nnug10.jpg it actually works! In my blog post I said that the cid’s where nnug0.jpg, nnug1.jpg etc. which was not the case. It did not have the .jpg extensions.
Taking the above into account this makes the Hotmail bug far less serious than I originally thought.
But…, when you see the property ContentId you’re thinking it can be whatever only it’s unique right? This is why I didn’t think much of what the ContentId was as long as it was unique. However, to be absolutely sure that something like this will not happen again I changed the cid’s to be guid’s instead (this was also suggested by the Hotmail team). Better safe than sorry :-)
Here’s the code after my modifications:
LinkedResource img = new LinkedResource(stream, mediaType); img.ContentId = guid; img.ContentType.MediaType = mediaType; img.TransferEncoding = TransferEncoding.Base64; img.ContentType.Name = img.ContentId + fileExtension; img.ContentLink = new Uri("cid:" + img.ContentId); resources.Add(img);