I'm using Delphi 7 and Indy 10.0.52.
Here is the code that is generating the IdMessage:
procedure TEmailBuilder.BuildHTMLAndEmbedded(AMessage: TIdMessage);
var
j : Integer;
begin
AMessage.ContentType := 'multipart/alternative';
// Create plain text part
with TIdText.Create(AMessage.MessageParts, FTextMessage) do
ContentType := 'text/plain';
// create part to hold html and attachments
with TIdText.Create(AMessage.MessageParts) do
ContentType := 'multipart/related';
with TIdText.Create(AMessage.MessageParts, FBody) do
begin
ContentType := 'text/html';
ParentPart := 1;
end;
// Create embedded attachments
for j := 0 to FEmbeddedAttach.Count - 1 do
begin
with TIdAttachmentFile.Create(AMessage.MessageParts,
FEmbeddedAttach[j]) do
begin
ContentType := GetMimeTypeFromFile(FEmbeddedAttach[j]);
ParentPart := 1;
end; // with
end;
end;
The email that is sent looks like this:
Subject: testing testing!
To: t...@uil.net
Content-Type: multipart/alternative;
boundary="KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbv"
MIME-Version: 1.0
Sender: Tim Sullivan <t...@uil.net>
Organization: Questek Systems, Inc.
Date: Mon, 20 Jun 2005 15:53:32 -0400
This is a multi-part message in MIME format
--KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbv
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable
This is an HTML message, and requires an HTML-enabled mail client to r=
ead it.
--KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbv
Content-Type: multipart/related;
boundary="KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbvS"
--KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbvS
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable
<html>
<body>
<p>
This is test with images.
</p>
<p>
<img src="cid:barker2.gif" align="left"
alt="" />
</p>
</body>
</html>
--KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbvS
xContent-Type: image/gif;
name="barker2.gif"
xContent-Transfer-Encoding: base64
xContent-Disposition: attachment;
filename="barker2.gif"
[bunch of encoded stuff removed - x put in front of some headers because the
Borland news server rejected the message :-)]
--KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbvS--
--KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbv--
Thanks in advance for any assistance. I'm quite sure I've got something
moronically wrong here, but I've just been beating my head against a wall
for a day now.
--
Tim Sullivan
Unlimited Intelligence Limited
http://www.uil.net
> I'm pretty sure I've got this all set up correctly, but for some
> reason the email, when it arrives, is visually empty - no text
> part, no html message, nothing.
You likely did not set the message up properly in the first place.
> The content of the email is clearly coming through, since I see
> it downloading the 160K or so that the message is supposed to
> be.
That does not mean that the content itself is well-formed.
> with TIdAttachmentFile.Create(AMessage.MessageParts,
> FEmbeddedAttach[j]) do
> begin
> ContentType := GetMimeTypeFromFile(FEmbeddedAttach[j]);
> ParentPart := 1;
> end; // with
You did not set the ContentID property for each attachment. That is the ID
that the HTML uses when referring to the attachments.
> Content-Type: multipart/alternative;
> boundary="KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbv"
Is the boundary really not indented? It needs to be if it is not already.
Gambit
Thanks for your help with this. Your other posts on this topic have gotten
me as far as I am without breaking down and crying. :-)
> You likely did not set the message up properly in the first place.
That is entirely possible, however I'm pretty sure the code is as per other
responses in this newsgroup.
>> Content-Type: multipart/alternative;
>> boundary="KywwqE3vN7MgA56La1Y1xP8=_MxVKriNbv"
>
> Is the boundary really not indented? It needs to be if it is not already.
The boundary is not indented. However, this is all being generated by the
TIdMessage.SaveToStream method, since I'm writing the built IdMessage into a
database blob.
Is there a way to force it to indent? Or should I be looking at changing
Indy code?
> You did not set the ContentID property for each attachment. That is the
> ID
> that the HTML uses when referring to the attachments.
Thanks! I've made that change, but it still hasn't remedied the problem -
the emails are coming in blank.
Any further thoughts?
I should modify this statement: it looks like it's on 2 lines in the post I
made, but it's actually on the same line as the Content-Type.
> The boundary is not indented. However, this is all being generated
> by the TIdMessage.SaveToStream method, since I'm writing the
> built IdMessage into a database blob.
If that were the case, then there should have been indenting. Indy always
outputs the boundary declaration indented, as per the MIME specs. Unless
the boundary is on the same line as the ContentType, which is ok as well.
But if the boundary is on its own line with no indenting, then it is treated
as its own separate header value, which is wrong. It must be part of the
ContentType header.
> I've made that change, but it still hasn't remedied the problem - the
> emails are coming in blank.
When I run your earlier email data through OE, after making sure the header
values were indented properly and no other changes to the data otherwise,
everything appears fine (minus a missing image, of course, since you
stripped it out).
> Any further thoughts?
The ContentDisposition of each related attachment should probably be
'inline', though that is not required.
Gambit
It seems that it's something to do with the validity of the HTML I'm
sending. Once I've got this all worked out, I'll post the source so that
anyone doing something similar to this can be pointed to it.
Thanks for the assistance.
From posts in this newsgroup, the format should be:
TIdMessage (multipart/mixed)
{
TIdText (multipart/alternative) ParentPart -1
{
TIdText (text/plain), ParentPart 0
TIdText (multipart/related), ParentPart 0
{
TIdText (text/html), ParentPart 2
TIdAttachmentFile (image/*) ParentPart 2
}
}
TIdAttachmentFile (whatever), ParentPart -1
}
The code I'm using for this is:
procedure TEmailBuilder.BuildHTMLAndAttachmentsAndEmbedded(AMessage:
TIdMessage);
var
j: Integer;
begin
AMessage.ContentType := 'multipart/mixed';
// create overall group
with TIdText.Create(AMessage.MessageParts) do
ContentType := 'multipart/alternative';
// Create plain text part
with TIdText.Create(AMessage.MessageParts, FTextMessage) do
begin
ContentType := 'text/plain';
ParentPart := 0;
end;
// create part to hold html and attachments
with TIdText.Create(AMessage.MessageParts) do
begin
ContentType := 'multipart/related';
ParentPart := 0;
end;
with TIdText.Create(AMessage.MessageParts, FBody) do
begin
ContentType := 'text/html';
ParentPart := 2;
end;
// Create embedded attachments
for j := 0 to FEmbeddedAttach.Count - 1 do
begin
with TIdAttachmentFile.Create(AMessage.MessageParts,
FEmbeddedAttach[j]) do
begin
ContentType := GetMimeTypeFromFile(FEmbeddedAttach[j]);
ContentID := GetCIDByImagePath(FEmbeddedAttach[j], false);
ContentDisposition := 'inline';
ParentPart := 2;
end;
end;
// Create the attachment parts
for j := 0 to FFileAttach.Count - 1 do
begin
with TIdAttachmentFile.Create(AMessage.MessageParts, FFileAttach[j])
do
ContentType := GetMimeTypeFromFile(FFileAttach[j]);
end;
end;
I've attached the created stream from the TIdMessage to
borland.public.attachments. It also looks right to my mildly-trained eye.
I can't wait to put this to bed. :-)
> I've attached the created stream from the TIdMessage to
> borland.public.attachments. It also looks right to my
> mildly-trained eye.
The email works fine in my OE as-is without any changes. I see an HTML page
with an embeeded image and an attached image, as expected.
Gambit
Gah. So why doesn't it show in Outlook 2003? This makes no sense.
I'm sure it's not Indy, I'm just curious why things seem to work sometimes
and not others.
> Gah. So why doesn't it show in Outlook 2003? This makes no sense.
Works fine in Outlook 2003. I see the text and an image plus two attached
files.
But: The "Sender:" tag in the header is definitely wrong. It must be
"From:".
How did you mail this message (or open in Outlook)?
I had to telnet to my SMTP and paste the complete shebang in the DATA
phase...
SpamAssassin complained about HTML mail without corresponding plain text
part. (I understand this is a style problem, not a technical issue, but
maybe Outlook's spam filter gets triggered...?)
--
Ben
Thanks for taking a look at things.
> Works fine in Outlook 2003. I see the text and an image plus two attached
> files.
*kills self*
I've figured it out, though it took awhile. A friend noticed that the parts
were not what he expected.
The layout suggested in other messages was:
multipart/mixed
multipart/alternative
text/plain
multipart/related
text/html
image/jpeg (embedded image)
application/zip (or whatever the attachment is)
He pointed me to a Zend site
(http://www.zend.com/zend/spotlight/sendmimeemailpart3.php#Heading5) which
had this layout:
multipart/mixed
multipart/related
multipart/alternative
text/plain
text/html
image/jpeg (the inline)
application/zip (the attach)
... I rearranged things to that spec, and it worked!
Thanks Remy and Ben for your help. I'll post my code tomorrow once it's less
embarassing. Hopefully it'll help other people who are doing similar things.
:-)
> I'm just curious why things seem to work sometimes and not others.
Because Microsoft doesn't like to follow established standards that the rest
of the world follows. Microsoft likes to do its own thing whenever it can.
Gambit
Well, it didn't work for Thunderbird either, so evidently it's a conspiracy.
:-)
Problem has been solved, code has been posted.
> > Because Microsoft doesn't like to follow established standards that
> > the rest
> > of the world follows. Microsoft likes to do its own thing whenever
> > it can.
>
> Well, it didn't work for Thunderbird either, so evidently it's a
> conspiracy. :-)
It is actually an MS screw-up: Outlook Express and certain Outlook
versions implement the protocols differently, some won't read the
other's emails properly.
Ciaran