Indy IdSMTP and attachments in Thunderbird
Using the latest snapshot of Indy tiburon on D20开发者_如何学JAVA10. A very simple project like:
var
stream: TFileStream; (s is TidSMTP and m is TidMessage)
begin
s.Connect;
Stream := TFileStream.Create('c:\Test.zip', fmOpenRead or fmShareExclusive);
try
with TIdAttachmentMemory.Create(m.MessageParts, Stream) do
begin
ContentType := 'application/x-zip-compressed';
Name := ExtractFilePath('C:\'); //'
FileName := 'Test.zip';
end;
finally
FreeAndNil(Stream);
end;
s.Send(m);
s.Disconnect();
end;
Everything works Ok in Outlook, The bat!, OE, yahoo, etc... but in Thunderbird the attachment is not shown. Looking at the source of the message in Thunderbird, the attachment is there. The only difference I can find between messages send by indy and other clients is that Indy messages have this order:
Content-Type: multipart/mixed; boundary="Z\=_7oeC98yIhktvxiwiDTVyhv9R9gwkwT1"
MIME-Version: 1.0
while any other clients have the order:
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="Z\=_7oeC98yIhktvxiwiDTVyhv9R9gwkwT1"
Don't know if THAT is the source of the problem, but if so: is this a bug on Thunderbird or is this a problem with indy which "malforms" the headers of the messages? Is this order a problem? Does that matter anyway?
The latest version (as today) of Indy has a problem in the headers:
The problem seems to be around the line in the mail header with:
Content-Type: multipart/mixed; boundary="oIROJ8Yu4KsL8BbjOo0fc\=_O7oAqLVq97i"
The "=" inside the boundary identifier is prepended with a "\" (probably to escape it), but in the body of the mail the boundary looks like this:
--oIROJ8Yu4KsL8BbjOo0fc=_O7oAqLVq97i
If you look at the source of Indy, in the file idGlobalProtocols, ReplaceHeaderSubItem calls QuoteString, which is the one that adds the backslash. You could carefully change the logic here and recompile Indy.
RFC 1521 explicitly states:
Messages composed in accordance with this document MUST include such a header field, with the following verbatim text:
MIME-Version: 1.0
And note it is an header field:
Header fields are lines composed of a field name, followed by a colon (":"), followed by a field body, and terminated by CRLF. (rfc 2822)
Thereby if Indy does not set it as an header field it's an Indy bug, IMHO its syntax is invalid, it can't be set in the content-type line (maybe just a missing CRLF?) - and TB just follows the RFC verbatim, while the other know the RFC are often not followed completely and process the document anyay.
You should try something like this: (Note: The code doesn't show you how to send the message, just how to create it. There is another service that sends the emails).
Msg := TIdMessage.Create(nil);
try
{create the message}
Msg.Subject := Subject;
with Msg.Recipients.Add do
begin
Text := EMailAddress;
end;
Msg.From.Address := From;
Msg.From.Name := Copy(From, 1, pos('@', From) - 1);
with Msg.ReplyTo.Add do
begin
Text := From;
end;
with TIdMessageBuilderHtml.Create do
try
{plain text}
PlainText.Text := 'body text'
{html body}
Html.Text := '<html><body><p>' + 'body text' + '</p></body></html>';
{attachments}
for i := 0 to AttachFiles.Count - 1 do
Attachments.Add(AttachFiles.Strings[i]);
FillMessage(Msg);
finally
Free;
end;
{save the message for sending}
Msg.NoEncode := False;
Msg.NoDecode := False;
Msg.SaveToFile(locfilename + TempExt);
finally
Msg.Free;
end;
Answer to Rob Kennedy's comment bellow: I posted this code because for me, this code works with all major mail clients. The code is self explanatory, creates the message with attachments, saves it. I posted a solution that works. I don't have time (I'm at work) to compare the headers or message source of the original code the and the one posted by me to see why mine works. The original poster is free to do it and report back.
精彩评论