Copy From: http://www.bizbert.com/bizbert/2007/06/12/Sending+HTML+Emails+With+Embedded+Images+In+BizTalk.aspx
Sending HTML emails with embedded images in BizTalk
Ever wanted to send emails from BizTalk (using the SMTP
Adapter) which have Images embedded in them? I did recently.
Sending html
Emails (or text emails) in BizTalk without embedded images has been done
Death-all you need is the rawstring message type.
But how do you use the SMTP
Adapter to send emails with embedded images?
I didn't want to cheat and write
A helper class.
I first looked at using the mime/smime encoder Pipeline
Component.
By default the mime encoder uses a mime Content-Type
Multipart/mixed.
So if you have a multipart message with an html
Body part and a single image as a second part, this is what the mime Encoder
Generates:
Mime-version:
1.0
Content-Type: multipart/mixed;
Boundary = "-- = _ nextpart_000000000d_01c79667.1a2eefb0"
Return-path:
Donotreply@acme.com
This is a multi-part message in mime
Format.
---- = _ Nextpart_000000000d_01c79667.1a2eefb0
Content-Type:
Text/html; charset = UTF-8;
Charset = "UTF-8"
Content-transfer-encoding:
Quoted-printable
Content-location:
Http: // localhost/
<HTML>
---- = _ Nextpart_000000000d_01c79667.1a2eefb0
Content-Type:
Image/GIF
Content-transfer-encoding: base64
Content-location:
Http: // localhost/images/logo.gif
Content-ID:
<Http: // localhost/images/logo.gif>
However,
Multipart/mixedIs not how you embed content-you need to use
Multipart/related, To indicate that all the parts in the message are
Related.
(Note: In order to view the output of the SMTP adapter I
Used the iis smtp service, and configured the SMTP adapter to use an SMTP server
OfLocalhost, AndTo addressWhich matched my local domain. This
Will generate EML files in/Inetpub/mailroot/dropWhich you can open
Using Outlook Express (or notepad )).
There's a little known mime Context
Property you can set calledIsmultipartrelated.
If you use this, and
Have all your images as parts to the message, with your HTML part as the body
Part, then the SMTP adapter will send a message which can be viewed in a few
Email clients e.g. Outlook.
If you use this property, this is what the mime
Encoder will output:
Mime-version:
1.0
Content-Type: multipart/related;
Type = "text/html ";
Boundary = "-- = _ nextpart_000000000d_01c79667.1a2eefb0"
Return-path:
Donotreply@acme.com
This is a multi-part message in mime
Format.
---- = _ Nextpart_000000000d_01c79667.1a2eefb0
Content-Type:
Text/html; charset = UTF-8;
Charset = "UTF-8"
Content-transfer-encoding:
Quoted-printable
Content-location:
Http: // localhost/
<HTML>
---- = _ Nextpart_000000000d_01c79667.1a2eefb0
Content-Type:
Image/GIF
Content-transfer-encoding: base64
Content-location:
Http: // localhost/images/logo.gif
Content-ID:
<Http: // localhost/images/logo.gif>
However this doesn' t work
For any web based browsers e.g. Hotmail, Yahoo, squirrelmail, or
Lotus Notes.
Reading the RFC for multipart HTML messages showed me what I was missing:
The Content-Type for the complete message needs to beMultipart/related,
But the first (body) part needs to consist of two parts, and have a Content-Type
OfMultipart/alternative.-That is, the first part is actually another
Multi-part message!
The reason for this is the body part contains a text
Part, and an HTML part-so that browsers which don't understand HTML can still
Display the message.
It appears that a lot of email browsers won't display
Messages unless they are in this format and, in fact, this is what the RFC
Recommends.
Problem is, the mime encoder does not support this (as far
I can make out-there's a promising property called
PartcontenttypesecondaryheaderBut I couldn't get it to work for me, plus
IbasemessagepartDoesn't act as a container for other parts, so it's
Unclear how you 'd represent it in a message anyway ).
So I wrote
Pipeline component which takes an HTML stream as input, parses it and downloads
All the resources, and then does the correct mime encoding.
This is
Output from my component:
Mime-type: 1.0
Content-Type: multipart/related;
Type = "multipart/alternative ";
Boundary = "-- = _ nextpart_000000000d_01c79667.1a2eefb0"
Return-path:
Donotreply@acme.com
This is a multi-part message in mime
Format.
---- = _ Nextpart_000000000d_01c79667.1a2eefb0
Content-Type:
Multipart/alternative;
Boundary = "-- = _ nextpart_000000000e_01c79667.1a2eefb0"
---- = _ Nextpart_000000000e_01c79667.1a2eefb0
Content-Type:
Text/plain;
Charset = "iso-8859-1"
Content-transfer-encoding:
8bit
Plain text version of
Email
---- = _ Nextpart_000000000e_01c79667.1a2eefb0
Content-Type:
Text/html;
Charset = "UTF-8"
Content-transfer-encoding:
Quoted-printable
Content-location:
Http: // localhost/
<HTML>
---- = _ Nextpart_000000000e_01c79667.1a2eefb0 --
---- = _ Nextpart_000000000d_01c79667.1a2eefb0
Content-Type:
Image/GIF
Content-transfer-encoding: base64
Content-location:
Http: // localhost/images/logo.gif
Content-ID:
<Http: // localhost/images/logo.gif>
The next trick was trying
To get the SMTP adapter to accept the output from my component:
In BizTalk,
There are two ways of mime encoding content: simple encoding is already med by
SMTP adapter (e.g. If you don't use the mime encoder); more advanced encoding is
Specified med by the mime encoder.
So obviously the mime encoder sets
Property which indicates that the message is already MIME encoded so the SMTP
Adapter doesn' t need to bother.
If you look at the list of context Properties
Which the mime encoder supports, you see there's one called ismimeencoded.
Seems pretty
Obvious.
Could t that the property doesn' t work.
I had
Add a debug Pipeline component which wocould dump all the context Properties
Attached to a message after the mime encoder had finished with it to find
Answer.
Turns out there's another context property calledMimeencoded
(Note the lack of capitalization), which is in the system namespace (not
Mime namespace) and can only be set from code.
And this is the one that
SMTP adapter looks for. You can set it like this:
Inmsg. Context. Write ("mimeencoded ",
"Http://schemas.microsoft.com/BizTalk/2003/system-properties ",
True );
And now it works: I get email with embedded resources which
Can viewed correctly in all mail browsers (could t Lotus Notes, which
Occasionally doesn't show images-but that's notes for you !)
As
Aside, whenever I write a Pipeline component, I always try and have it work in
Streaming fashion (check out Christof claessenss' great article about this ).
However when I
Reflected over the source of the mime encoder, I noticed that it doesn' t chain
The streams-during the icomponent. Execute () call, the encoder reads the streams
All parts and returns a new message with a single part. So it's not implemented
In a streaming fashion (I. e. You can't chain together all the streams from all
Components ).
What I haven't covered in this post is how to use
Content-IDAndCID:Prefix (in your HTML) to link the embedded
Resources to the parts in your mime message-you can see examples of this in
The RFC.