Board index » cppbuilder » TIdAttachment Problem with MIME Encoding

TIdAttachment Problem with MIME Encoding


2006-09-20 07:13:28 PM
cppbuilder84
Hi,
i found a problem sending attachments via my BDS2006/Indy 9 SMTP test-application. If IdMessage1->Encoding is set to: meMIME, the received attachment has got 16 bytes appended, with meUU (UUencoding), everything is ok.
Could this be a problem of my program, or is this a bug?
Can anyone confirm this?
And a second question: I tried to free some memory at the end with
attach1->Free();
but then i get an Exception "EInvalidPointer" at this point.
Why?
Best Regards
Robert
----------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdMessage1->Encoding=meUU; //meMIME has a problem
TIdAttachment *attach1 = new TIdAttachment(IdMessage1->MessageParts, "c:\\attachment.txt" ) ;
attach1->ContentType= "multipart/mixed";
//
IdMessage1->From->Name="SENDERNAME";
IdMessage1->From->Address="SENDERADDRESS";
IdMessage1->Subject="Test BDS2006/Indy9 19.9.06" ;
IdMessage1->Recipients->EMailAddresses=Edit2->Text;
IdMessage1->Body->Add( "Some text...");
//Sending...
IdSMTP1->Host=Edit7->Text;
if (CheckBox1->Checked==true)
{
IdSMTP1->Username=Edit4->Text ;
IdSMTP1->Password=Edit5->Text ;
IdSMTP1->AuthenticationType=atLogin;
}
else IdSMTP1->AuthenticationType=atNone;
IdSMTP1->Connect(4000);
IdSMTP1->Send(IdMessage1);
IdSMTP1->Disconnect();
IdMessage1->Clear();
//attach1->Free();
}
 
 

Re:TIdAttachment Problem with MIME Encoding

I could answer my second question myself, i made a mistake with the last two calls:
...
IdMessage1->Clear();
attach1->Free();
...
I reversed the order of both and it worked.
Regards Robert
 

Re:TIdAttachment Problem with MIME Encoding

"Robert Lieblich" < XXXX@XXXXX.COM >wrote in message
Quote
If IdMessage1->Encoding is set to: meMIME, the received attachment
has got 16 bytes appended, with meUU (UUencoding), everything is ok.
What EXACTLY is being appended? Please be more specific. What does the
actual message data look like?
Quote
I tried to free some memory at the end with attach1->Free();
but then i get an Exception "EInvalidPointer" at this point. Why?
First and foremost, never call Free() directly. Use 'delete' instead.
Second, the TIdMessage owns the attachments, so you do not need to free them
manually. They will be freed automatically when the TIdMessage itself is
cleared or freed. Since you are clearing the TIdMessage before freeing the
TIdAttachment, your pointer to the attachment is invalid by the time you try
to free it. That is why you are getting the exception - the attachment has
already been freed by Indy itself.
Quote
TIdAttachment *attach1 = new TIdAttachment(IdMessage1->MessageParts,
"c:\\attachment.txt" ) ;
Because you are using the MessageParts collection, you should be storing the
message text into the collection as well, not in the TIdMessage::Body.
Quote
attach1->ContentType= "multipart/mixed";
That is the completely wrong ContentType to use. You are attaching a text
file, so you have to use "text/plain" instead. You are not creating your
own multipart containers, so you should not be using the "multipart" type at
all, except at the top level of the TIdMessage.
Try this code instead:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdMessage1->Clear();
IdMessage1->Encoding = meMIME;
TIdText *text1 = new TIdText(IdMessage1->MessageParts, NULL);
text1->Body->Add("Some text...");
text1->ContentType = "text/plain";
TIdAttachment *attach1 = new TIdAttachment(IdMessage1->MessageParts,
"c:\\attachment.txt");
attach1->ContentType = "text/plain";
IdMessage1->From->Name = "SENDERNAME";
IdMessage1->From->Address = "SENDERADDRESS";
IdMessage1->Subject = "Test BDS2006/Indy9 19.9.06" ;
IdMessage1->Recipients->EMailAddresses = Edit2->Text;
IdMessage1->ContentType = "multipart/mixed";
IdSMTP1->Host = Edit7->Text;
if( CheckBox1->Checked )
{
IdSMTP1->Username = Edit4->Text;
IdSMTP1->Password = Edit5->Text;
IdSMTP1->AuthenticationType = atLogin;
}
else
IdSMTP1->AuthenticationType = atNone;
IdSMTP1->Connect(4000);
try
{
IdSMTP1->Send(IdMessage1);
}
__finally {
IdSMTP1->Disconnect();
}
IdMessage1->Clear();
}
Gambit
 

{smallsort}

Re:TIdAttachment Problem with MIME Encoding

Hello Remy,
this is the (faulty) test-attachment (the correct end would be: ..Ende!):
TESTMAIL
testmail attachment
______?
<><><>1234567890
Ende! y+l]ƾzwj?
The ?. in the middle are the German "Umlaute".
I figured something out. Your example works, because
you use:
attach1->ContentType = "text/plain";
With attach1->ContentType = "multipart/application";
or "multipart/mixed"
you get the "additional bytes problem" with the .txt-file and
with other, e.g. .pdf-files.
It looks as the problem is caused by the "multipart" phrase.
Even when you use "mime/image" or "mim/image" or just "image" it'ok...
I have not tried "attach1->ContentType = "text/plain"; " before,
because i wanted to attach also binary files (attachment.txt was just one example), but surprisingly these work also with
"text/plain" .
What would be the CORRECT ContentType for binary attachments?
Thank you for your valuable tips, also the free .. delete subject.
Everything would be much easier for the C++ users
like me if there were a few short examples of these components.
If there is something to find in the documentation, ist a
listing of classes, methods, functions and properties, but the more conceptual overview of HOW to use a special component is missing.
Regards Robert
 

Re:TIdAttachment Problem with MIME Encoding

"Robert Lieblich" < XXXX@XXXXX.COM >wrote in message
Quote
this is the (faulty) test-attachment (the correct end would be: ..Ende!):
That is not what I wanted to see. Please show the COMPLETE message data,
including all headers.
Quote
I Your example works, because you use:
attach1->ContentType = "text/plain";
That is what is supposed to be used, because you are attaching a text file.
The ContentType for a particular message part has to match the actual data
inside that part.
Quote
With attach1->ContentType = "multipart/application";
That is not a valid ContentType value. There is no "application" subtype
defined for the "multipart" media type.
Quote
or "multipart/mixed"
"multipart/mixed" is NOT the correct ContentType to use for your
attachment - unless the attachment contains pre-formatted "multipart" data
to begin with, which is likely not what you are actually doing.
Quote
you get the "additional bytes problem" with the .txt-file and
with other, e.g. .pdf-files.
The ContentType alone has no effect whatsoever on Indy's encoders. They
don't care about the ContentType at all. The value is written to the header
inside the message data and then ignored for everything else.
Quote
It looks as the problem is caused by the "multipart" phrase.
Even when you use "mime/image" or "mim/image" or just "image" it'ok...
Those are not valid ContentType values, either.
Quote
I have not tried "attach1->ContentType = "text/plain"; " before
You should have been using that all along. The fact that you don't know how
to use ContentType values properly indicates that you do not understand how
emails actually work in general.
Quote
because i wanted to attach also binary files (attachment.txt was just
one example), but surprisingly these work also with "text/plain" .
For any file, binary or text, you have to use the proper ContentType. For
example, .txt files must use "text/plain", .htm files must use "text/html",
.pdf must use "application/pdf", .zip files must use
"application/x-zip-compressed", etc. So unless you know for sure off the
top of your head what a given file should use, then you should always use
Indy's GetMIMETypeFromFile() function instead, ie:
attach1->ContentType = GetMIMETypeFromFile(attach1->FileName);
GetMIMETypeFromFile() knows the registered types for a whole bunch of known
file extensions, as well as queries the OS for known types as well.
Gambit
 

Re:TIdAttachment Problem with MIME Encoding

Remy Lebeau (TeamB) wrote:
Quote
Indy's GetMIMETypeFromFile() function instead, ie:

attach1->ContentType = GetMIMETypeFromFile(attach1->FileName);
Does it really get it from the file (by opening the file) or just from
looking at the extension of the filename?
Hans.
 

Re:TIdAttachment Problem with MIME Encoding

"Hans Galema" < XXXX@XXXXX.COM >wrote in message
Quote
Does it really get it from the file (by opening the file)
No, it does not open the file at all.
Quote
or just from looking at the extension of the filename?
Yes. It looks up the file extension in its list of known extensions, which
is a mixture of values that are hard-coded, with a list of values that are
pulled from the OS's registered types.
Gambit
 

Re:TIdAttachment Problem with MIME Encoding

Hi Remy,
Quote
That is not what I wanted to see. Please show the COMPLETE message data,
including all headers.
I don't think that this is neccessary.
Quote
The ContentType alone has no effect whatsoever on Indy's encoders. They
don't care about the ContentType at all. The value is written to the
header
inside the message data and then ignored for everything else.
That is a good hint. That means, the encoding in Indy should correct, the
additional bytes are added
from the receiving mailserver (because I was using the wrong ContentType,
ok).
Quote
For any file, binary or text, you have to use the proper ContentType. For
example, .txt files must use "text/plain", .htm files must use
"text/html",
.pdf must use "application/pdf", .zip files must use
"application/x-zip-compressed", etc. So unless you know for sure off the
top of your head what a given file should use, then you should always use
Indy's GetMIMETypeFromFile() function instead, ie:
That's not bad, but actually, as Hans noted, it does not care about the file
itself.
And, sometimes I want to send binary files with a .txt extension(why not? If
it's just for me..).
But I did some tests and all that I really want is to send any attachment
unchanged (in
a binary mode). So, with "image/jpg" or "application/x-zip-compressed" I
could send all attachments I tried so far unchanged, and no additional
bytes.
And, could it be bad to transfer even a plain text attachment in this mode?
By the way, when you put the text message in a text-attachment like that:
...
TIdText *text1 = new TIdText(IdMessage1->MessageParts, NULL);
text1->Body->Add("Some text...");
text1->ContentType = "text/plain";
...
and not in the IdMessage1->Body, it's not possible to use UUEncoding (Indy
gives an errormessage that only a simple textmessage plus attachment are
allowed in UU-mode) .
And, in MIME mode, this text is ignored at the receiving mailserver (or the
mailclient?), at least
at our company Exchangeserver 2003 and the one from web.de (which is
according to the MIME
standard as far as I understand). But in the form: text message in the
messagebody and
other files as attachements, it works also well.
Best regards Robert
 

Re:TIdAttachment Problem with MIME Encoding

"Robert Lieblich" < XXXX@XXXXX.COM >wrote in message
Quote
I don't think that this is neccessary.
I wanted to see whether your message is malformed in general. If it is,
then you are going to have other problems.
Quote
That's not bad, but actually, as Hans noted, it does not care about
the file itself.
Indy does not care about the actual file. But the ContentType must match
what the actual data is, or else the receiver will not be able to interpret
the data properly.
Quote
And, sometimes I want to send binary files with a .txt
extension (why not? If it's just for me..).
You should not be sending binary data as text (unless the binary is textual
in nature, of course). In any case, the ContentType must match the actual
file content that is being encoded inside the message.
Quote
But I did some tests and all that I really want is to send any
attachment unchanged (in a binary mode).
Which is easy to accomplish, using TIdAttachment. But the ContentType must
still match the type of data being attached.
Quote
So, with "image/jpg" or "application/x-zip-compressed" I could
send all attachments I tried so far unchanged, and no additional
bytes.
Those are specific ContentTypes for specific data formats. You should not
be using them to send arbitrary binary data. If you really want to do that,
then you have to use "application/octet-stream" instead (which is what Indy
defaults to for uknown types).
Quote
And, could it be bad to transfer even a plain text attachment
in this mode?
No. That will work fine. Text is just binary limited to a smaller range of
byte values, afterall.
Quote
By the way, when you put the text message in a text-attachment like that:
...
TIdText *text1 = new TIdText(IdMessage1->MessageParts, NULL);
text1->Body->Add("Some text...");
text1->ContentType = "text/plain";
...
and not in the IdMessage1->Body, it's not possible to use UUEncoding
Yes, it is. Simply set the TIdMessage::Encoding property to meUU, which in
turn sets the AttachmentEncoding property to "UUE".
Quote
Indy gives an errormessage that only a simple textmessage plus
attachment are allowed in UU-mode
Then you are likely using an old version.
Quote
And, in MIME mode, this text is ignored at the receiving mailserver
(or the mailclient?)
Only if the message is malformed to begin with, or the receiver is buggy.
Gambit
 

Re:TIdAttachment Problem with MIME Encoding

Hi Remy,
Quote
If you really want to do that,
then you have to use "application/octet-stream" instead (which is what Indy
defaults to for uknown types).

That's perfect for me!
Quote
>By the way, when you put the text message in a text-attachment like that:
>...
>TIdText *text1 = new TIdText(IdMessage1->MessageParts, NULL);
>text1->Body->Add("Some text...");
>text1->ContentType = "text/plain";
>...
>and not in the IdMessage1->Body, it's not possible to use UUEncoding

Yes, it is. Simply set the TIdMessage::Encoding property to meUU, which in
turn sets the AttachmentEncoding property to "UUE".

>Indy gives an errormessage that only a simple textmessage plus
>attachment are allowed in UU-mode

Then you are likely using an old version.

The one delivered with my BDS2006, the info says: 9.0.50.
I have attached the code here, maybe you want to check
yourself. With my BDS/Indy I get the mentioned exception,
so I succeeded only when the part with text1 is commented.
With IdMessage1->Encoding = meMIME it's working(but text1 ignored).
------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdMessage1->Clear();
IdMessage1->Encoding = meUU;
TIdText *text1 = new TIdText(IdMessage1->MessageParts, NULL);
text1->Body->Add("Some text 2. ...");
text1->ContentType = "text/plain";
IdMessage1->Body->Add("Some text...");
IdMessage1->ContentType = "text/plain";
TIdAttachment *attach1 = new TIdAttachment(IdMessage1->MessageParts,
"c:\\attachment.zip");
attach1->ContentType = "application/octet-stream";
TIdAttachment *attach2 = new TIdAttachment(IdMessage1->MessageParts,
"c:\\attachment.txt");
attach2->ContentType = "application/octet-stream";
TIdAttachment *attach3 = new TIdAttachment(IdMessage1->MessageParts,
"c:\\attachment.pdf");
attach3->ContentType = "application/octet-stream";
IdMessage1->From->Name = "SENDERNAME";
IdMessage1->From->Address = "SENDERADDRESS";
IdMessage1->Subject = "Test BDS2006/Indy9.0.50 22.9.06" ;
IdMessage1->Recipients->EMailAddresses = Edit2->Text;
IdMessage1->ContentType = "multipart/mixed";
IdMessage1->SaveToFile("c:\\msg.txt",false) ;
IdSMTP1->Host = Edit7->Text;
if( CheckBox1->Checked )
{
IdSMTP1->Username = Edit4->Text;
IdSMTP1->Password = Edit5->Text;
IdSMTP1->AuthenticationType = atLogin;
}
else
IdSMTP1->AuthenticationType = atNone;
IdSMTP1->Connect(4000);
try
{
IdSMTP1->Send(IdMessage1);
}
__finally {
IdSMTP1->Disconnect();
}
IdMessage1->Clear();
}
---------------------------------------------------------
Quote
>And, in MIME mode, this text is ignored at the receiving mailserver
>(or the mailclient?)

Only if the message is malformed to begin with, or the receiver is buggy.

No, the text is not generated by Indy, take a look at the
output done with IdMessage1->SaveToFile().
There is no reference for: text1->Body->Add("Some
text 2. ..."); in the file.
This output is visible: IdMessage1->Body->Add("Some text...");
-----------------------------------------------------
From: "SENDERNAME" <SENDERADDRESS>
Subject: Test BDS2006/Indy9.0.50 22.9.06
To: XXXX@XXXXX.COM
Content-Type: multipart/mixed; boundary="=_MoreStuf_2zzz1234sadvnqw3nerasdf"
MIME-Version: 1.0
Date: Fri, 22 Sep 2006 11:56:57 +0200
This is a multi-part message in MIME format
--=_MoreStuf_2zzz1234sadvnqw3nerasdf
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Some text...
--=_MoreStuf_2zzz1234sadvnqw3nerasdf
Content-Type: application/octet-stream;
name="attachment.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attachment.zip"
UEsDBBQAAAAIAH1yKi7fikQuOA0AAABEAAATAAAATm90ZWJvb2tzX01pZXRlLnhsc+1cDXBcVRU+
...
AABOb3RlYm9va3NfTWlldGUueGxzUEsFBgAAAAABAAEAQQAAAGkNAAAAAA==
--=_MoreStuf_2zzz1234sadvnqw3nerasdf
Content-Type: application/octet-stream;
name="attachment.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attachment.txt"
VEVTVE1BSUwNCg0KdGVzdG1haWwgYXR0YWNobWVudA0K5Pb8X19f319fX8TW3A0KPD48Pjw+MTIz
NDU2Nzg5MA0KRW5kZSE=
--=_MoreStuf_2zzz1234sadvnqw3nerasdf
Content-Type: application/octet-stream;
name="attachment.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="attachment.pdf"
JVBERi0xLjMKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIvRmlsdGVyIC9GbGF0ZURlY29k
...)
4EBhlLw08SkooL+/J0f1WEFY4EBhlLw08SldCj4+CnN0YXJ0eHJlZgozMjAxNQolJUVPRgo=
--=_MoreStuf_2zzz1234sadvnqw3nerasdf--
.
Regards Robert
 

Re:TIdAttachment Problem with MIME Encoding

Robert Lieblich wrote:
Quote
IdMessage1->SaveToFile("c:\\msg.txt",false) ;
Probably you know already that you could change that to
IdMessage1->SaveToFile("c:\\msg.eml",false);
You can then doubleclick on the filename and it will open
in the default mailreader for .eml.
Hans.
 

Re:TIdAttachment Problem with MIME Encoding

Remy Lebeau (TeamB) wrote:
Quote
... But the ContentType must match
what the actual data is, or else the receiver will not be able to interpret
the data properly.
That looks strange to me. The receiver can just look at the type
of encoding, then decode it. Then determine the filename and
save it under that name.
The same can be done with the file that is produced with
IdMessage->SaveToFile ( FileName );
What I understand of it (just started yesterday with TIdMessage
and TIdSMPT) that content like in that file is sent bij TIdSMPT.
Hans.
 

Re:TIdAttachment Problem with MIME Encoding

Remy Lebeau (TeamB) wrote:
Quote
The ContentType alone has no effect whatsoever on Indy's encoders. They
don't care about the ContentType at all. The value is written to the header
inside the message data and then ignored for everything else.
You mean the ContentType of TIdMessage here? (As every TIdText has its
own ContentType).
I can not confirm that.
Whatever I put as type Indy will neglect it and determine the type itself.
What I think is a good idea, because why should the use bother with a type?
So I do not put a value in.
I do not put in values for encoding either and was able
to send mails of the following types:
-text only
-text+html
-text+attachments
-text+html+attachments
-text+(html+graphic)
-text+(html+graphic)+attachments
For the latter: If I compose such an email with thunderbird i get:
Content-Type: multipart/mixed;
boundary="------------050109080305000709040803"
With Indy:
Content-Type: multipart/related; type="multipart/alternative";
boundary="=_MoreStuf_...
And the structure of the mail is diferent.
The nice thing is that thunderbird. and also OE displaying
the eml, don't care.
It seems that they just look at 'Content-ID' and theron
promote an attachment to inlinegraphic.
Hans.
Hans.
 

Re:TIdAttachment Problem with MIME Encoding

Hans Galema wrote:
Quote
I can not confirm that.
Using Turbo C++ and Indy9
Hans.
 

Re:TIdAttachment Problem with MIME Encoding

"Hans Galema" < XXXX@XXXXX.COM >wrote in message
Quote
That looks strange to me. The receiver can just look at the type
of encoding, then decode it. Then determine the filename and
save it under that name.
Sure, if the reciever does not care what the actual contents are, and saves
the data straight to the hard drive as-is without any further processing.
But that is not always the case.
Gambit