Delphi Indy9 and Indy10 Attachment Technique Plaintext+Html+Image+
HTML Messages
A question that is asked frequently is:
How do you send HTML messages with Indy?
How you set up the TIdMessage component depends on what exactly you want the message to actually contain:
1) if you don’t want to add any attachments, and you don’t want to include a plain-text alternative for readers who don’t support HTML, then simply place the HTML code into the TIdMessage.Body property and set the TIdMessage.ContentType property to text/html.
2) if you do want to add attachments, or to include a plain-text alternative, then you need to ignore the TIdMessage.Body property altogether and use the TIdMessage.MessageParts collection instead. How you do that depends on which version of Indy you are using.
Indy 9
You instantiate two TIdText instances – the first containing the plain-text content and its ContentType property set to text/plain, and the second containing the HTML code and its ContentType property set to text/html.
The TIdMessage.ContentType property should be set to multipart/alternative, unless attachments are added, in which case the ContentType property should be either multipart/mixed or multipart/related, depending on whether the attachments are used with the HTML or not. To add attachments, instantiate TIdAttachment instead of TIdText. If the attachments are images or sounds that are being used by the HTML, then you also set the TIdAttachment.ContentID property to unique values that the HTML can reference via the “cid” protocol. For example, if the ContentID property of an image attachment is “image1” then the HTML needs to use “cid:image1” as the “src” attribute for any <img> element that displays that image attachment.
Unfortunately, Indy 9 does not handle the plaintext+html+images scenerio as well as it should. Indy 10 handles it better…
Indy 10
You do the same things as above, except that you use TIdAttachmentFile or TIdAttachmentMemory instead of TIdAttachment, and there are extra steps involved to set up the TIdText and TIdAttachmentFile/Memory instances properly.
Every message part has a ParentPart property that is set to -1 by default. This is an index to the part that is the PARENT of the current part. This is for nesting parts underneath each other, where -1 means that a part is not nested another another part but is instead located at the top-level of the message. Because of this nesting support, you end up with a variety of different setups depending on what exactly you want to send:
Plain-text and HTML and no attachments
Add two TIdText instances to the TIdMessage.MessageParts collection, as described above. Leave the ParentPart properties set to -1.
Set the TIdMessage.ContentType property to multipart/alternative.
You end up with the following TIdMessage layout:
TIdMessage (multipart/alternative) { TIdText (text/plain), ParentPart -1 TIdText (text/html), ParentPart -1 }
Here is a code snippet:
with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'plain text goes here'; ContentType := 'text/plain'; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'HTML goes here'; ContentType := 'text/html'; end; IdMessage1.ContentType := 'multipart/alternative';
HTML and non-related attachments and no plain-text
Non-related attachments are attachments that the user can click on and save out of the message. The message content does not refer to the attachments for any purpose.
Add a TIdText instance for the HTML content, and add TIdAttachmentFile/Memory instances for the attachments. Leave the ParentPart properties set to -1.
Set the TIdMessage.ContentType property to multipart/mixed.
You end up with the following TIdMessage layout:
TIdMessage (multipart/mixed) { TIdText (text/html), ParentPart -1 TIdAttachment (whatever), ParentPart -1 TIdAttachment (whatever), ParentPart -1 and so on... }
Here is a code snippet:
with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'HTML goes here'; ContentType := 'text/html'; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image1.jpg') do begin ContentType := 'image/jpeg'; FileName := 'image1.jpg'; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image2.jpg') do begin ContentType := 'image/jpeg'; FileName := 'image2.jpg'; end; IdMessage1.ContentType := 'multipart/mixed';
HTML and related attachments and no plain-text
Related attachments are grouped together with the HTML part so that the HTML content can reference them when needed. In order for HTML to reference any attachments, the HTML part and all of the related attachments need to be placed into a multipart/related section together so that they can find each other. The ContentType of the section must always have a type attribute that is set to the ContentType of the first nested child part. Each attachment also needs to have its ContentID property assigned to a unique value within the group. The HTML code can then use the “cid” protocol when referencing an attachment in the “src” attribute of any <img>, <sound>, and other such elements. For example, if an image has a ContentID of “image1” then the HTML code can refer to it as <img src=”cid:image1″>. The particular ContentID values are arbitrary and what they are does not matter just as long as they are each unique.
Add a TIdText instance for the HTML content. Leave the ParentPart properties set to -1.
Add TIdAttachmentFile/Memory instances for the attachments. Leave the ParentPart properties set to -1, and set the ContentID properties as desired.
Set the TIdMessage.ContentType property to multipart/related; type=”text/html”.
You end up with the following TIdMessage layout:
TIdMessage (multipart/related; type="text/html") { TIdText (text/html), ParentPart -1 TIdAttachment (image/*) ParentPart -1, ContentID 12345 TIdAttachment (image/*) ParentPart -1, ContentID 56789 and so on... }
Here is a code snippet:
with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'HTML goes here'; ContentType := 'text/html'; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image1.jpg') do begin ContentID := '12345'; ContentType := 'image/jpeg'; FileName := 'image1.jpg'; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image2.jpg') do begin ContentID := '56789'; ContentType := 'image/jpeg'; FileName := 'image2.jpg'; end; IdMessage1.ContentType := 'multipart/related; type="text/html"';
Plain-text and HTML and attachments
The layout depends on whether you are including HTML-related attachments or not, as follows:
HTML-related attachments only
Add a blank TIdText with its ContentType property set to multipart/alternative. Leave the ParentPart property set to -1.
Add TIdText instances for the plain-text and HTML contents. Set the ParentPart properties to the index of the ‘multipart/alternative’ part.
Add TIdAttachmentFile/Memory instances for the attachments. Leave the ParentPart properties set to -1, and set the ContentID properties as desired.
Set the TIdMessage.ContentType to multipart/related; type=”multipart/alternative”.
You end up with the following TIdMessage layout:
TIdMessage (multipart/related; type="multipart/alternative") { TIdText (multipart/alternative), ParentPart -1 { TIdText (text/plain), ParentPart 0 TIdText (text/html), ParentPart 0 } TIdAttachment (image/*) ParentPart -1, ContentID 12345 TIdAttachment (image/*) ParentPart -1, ContentID 56789 and so on... }
Here is a code snippet:
with TIdText.Create(IdMessage1.MessageParts, nil) do begin ContentType := 'multipart/alternative'; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'plain textgoes here'; ContentType := 'text/plain'; ParentPart := 0; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'HTML goes here'; ContentType := 'text/html'; ParentPart := 0; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image1.jpg') do begin ContentID := '12345'; ContentType := 'image/jpeg'; FileName := 'image1.jpg'; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image2.jpg') do begin ContentID := '56789'; ContentType := 'image/jpeg'; FileName := 'image2.jpg'; end; IdMessage1.ContentType := 'multipart/related; type="multipart/alternative"';
Non-related attachments only
Add a blank TIdText with its ContentType property set to multipart/alternative. Leave the ParentPart property set to -1.
Add TIdText instances for the plain-text and HTML contents. Set the ParentPart properties to the index of the multipart/altrnative part.
Add TIdAttachmentFile/Memory instances for the attachments. Leave the ParentPart properties set to -1, and leave the ContentID properties empty.
Set the TIdMessage.ContentType property to multipart/mixed.
You end up with the following TIdMessage layout:
TIdMessage (multipart/mixed) { TIdText (multipart/alternative), ParentPart -1 { TIdText (text/plain), ParentPart 0 TIdText (text/html), ParentPart 0 } TIdAttachment (whatever) ParentPart -1 TIdAttachment (whatever) ParentPart -1 and so on... }
Here is a code snippet:
with TIdText.Create(IdMessage1.MessageParts, nil) do begin ContentType := 'multipart/alternative'; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'plain textgoes here'; ContentType := 'text/plain'; ParentPart := 0; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'HTML goes here'; ContentType := 'text/html'; ParentPart := 0; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\archive.zip') do begin ContentType := 'application/x-zip-compressed'; FileName := 'archive.zip'; end; IdMessage1.ContentType := 'multipart/mixed';
Related and non-related attachments
You need to combine the two layouts above. You end up with the following TIdMessage layout:
TIdMessage (multipart/mixed) { TIdText (multipart/related; type="multipart/alternative"), ParentPart -1 { TIdText (multipart/alternative), ParentPart 0 { TIdText (text/plain), ParentPart 1 TIdText (text/html), ParentPart 1 } TIdAttachment (image/*) ParentPart 0, ContentID 12345 TIdAttachment (image/*) ParentPart 0, ContentID 56789 and so on... } TIdAttachment (whatever) ParentPart -1 TIdAttachment (whatever) ParentPart -1 and so on... }
Here is a code snippet:
with TIdText.Create(IdMessage1.MessageParts, nil) do begin ContentType := 'multipart/related; type="multipart/alternative"'; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin ContentType := 'multipart/alternative'; ParentPart := 0; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'plain textgoes here'; ContentType := 'text/plain'; ParentPart := 1; end; with TIdText.Create(IdMessage1.MessageParts, nil) do begin Body.Text := 'HTML goes here'; ContentType := 'text/html'; ParentPart := 1; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image1.jpg') do begin ContentID := '12345'; ContentType := 'image/jpeg'; FileName := 'image1.jpg'; ParentPart := 0; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\image2.jpg') do begin ContentID := '56789'; ContentType := 'image/jpeg'; FileName := 'image2.jpg'; ParentPart := 0; end; with TIdAttachmentFile.Create(IdMessage1.MessageParts, 'c:\folder\archive.zip') do begin ContentType := 'application/x-zip-compressed'; FileName := 'archive.zip'; end; IdMessage1.ContentType := 'multipart/mixed';
POST YOUR COMMENTS
You must be logged in to post a comment.