Discussion:
Ecoded attachments to a TidMessage
(too old to reply)
Richard Bibby
2006-11-01 19:52:31 UTC
Permalink
Hej,

I have an application that reads a file and then sends it as an attachement
on an TidMessage. This works fine and I can send (to mysef), received and
view the attached file.

Then I decided that I must encrypt the file before I attach it. So I used
the .Net System.Security.Cryptography assembly to encrypt it.

When you look at the encypted file it has lots of "strange" characters i.e.
characters with coding above the normal a-z.

When I send the file to myself, and then look at it after I have recieved it
I see that the characters have changed. Consequently I can not decrypt it.

I don't know why this is happening but I susppect that it must have
something to do with local or character coding.

Anyone any ideas how i can solve this?

What is the difference between a binary file (such as a progam as an
attachement) and my text file? Am I attaching it incorrectly?

/Richard
Remy Lebeau (TeamB)
2006-11-01 22:45:47 UTC
Permalink
Post by Richard Bibby
When you look at the encypted file it has lots of "strange"
characters i.e. characters with coding above the normal a-z.
You likely did not tell TIdMessage to apply any encoding to the attachment,
so it sent the data in its original binary format. You should always set
the TIdAttachment.ContentTransfer property.
Post by Richard Bibby
When I send the file to myself, and then look at it after I have recieved it
I see that the characters have changed. Consequently I can not decrypt it.
Then the data is likely being altered by the email system. Not all systems
can handle 8-bit binary data. That is why 7-bit encoding schemes like
base64 and quoted-printable exist in the first place.
Post by Richard Bibby
What is the difference between a binary file (such as a progam as an
attachement) and my text file?
Text is just a 7-bit subset of 8-bit binary. But in the early days of the
Internet, email systems only supported 7-bit data. Many still do. Which is
why 8-bit data usually has to be transmitted using a 7-bit encoding scheme.
There are standards in place to add 8-bit support to email protocols, but
many servers have not caught up yet.
Post by Richard Bibby
Am I attaching it incorrectly?
Since you did not show any code, there is no way to answer that.


Gambit
Remy Lebeau (TeamB)
2006-11-02 08:20:24 UTC
Permalink
how do I take a MemoryStream and add it as base64 encoded
binary attachement to my TIdmessage.
Which version of Indy are you using? If Indy 9 or earlier, then you cannot.
Only Indy 10 has that capability.
<snip>

If you are using Indy 10, then that is exactly what you need to do.
I guess I need to encode the Attachment first to Base64?
No. Indy does that automatically.


Gambit
Richard Bibby
2006-11-02 15:04:21 UTC
Permalink
Hej,

I am sure I am using indy 10 (is there a way of checking appart from
directory names?)

So what you are saying is that if I use Indy 10, and the code I included in
my previous post, it should all work?

Does the recieving mail client decode the Base64?

/Thanks
Post by Remy Lebeau (TeamB)
how do I take a MemoryStream and add it as base64 encoded
binary attachement to my TIdmessage.
Which version of Indy are you using? If Indy 9 or earlier, then you cannot.
Only Indy 10 has that capability.
<snip>
If you are using Indy 10, then that is exactly what you need to do.
I guess I need to encode the Attachment first to Base64?
No. Indy does that automatically.
Gambit
Remy Lebeau (TeamB)
2006-11-02 17:49:07 UTC
Permalink
Post by Richard Bibby
I am sure I am using indy 10 (is there a way of checking appart
from directory names?)
Right click on any Indy component in the form designer.
Post by Richard Bibby
So what you are saying is that if I use Indy 10, and the code I
included in my previous post, it should all work?
Yes, provided that you are setting up the rest of the TIdMessage properly.
Please show your actual code
Post by Richard Bibby
Does the recieving mail client decode the Base64?
Yes.


Gambit
Richard Bibby
2006-11-02 23:08:04 UTC
Permalink
Hej,

I am using indy 10.

The problem is I have the text:

"This is one line of data that has been sent. The end."

which is encrypted to:
þE?YôE!¡/}áùûÔfÝS.f.ÇÐUePzM~aô1Ûv#],gŒœ¬A!

I then send it as an attachment using the code below. When I open and look
at it in Outlook I get the following:
?E?Y?E!?/}??????S?f???UeP?M??a?1?v#]?g???A!

As you can see the normal characters have survived, but the others have been
replaced by  indicating they are not printable. Naturally it does not
decode.

The code is:

Mail := TidMessage.Create ( nil );
try

//Add the subject and body we received.
Result := co_CannotAddSubjAndBody ;
Mail.Subject := Subject ;
Mail.Body.Text := MessageBody ;

// Add the 'sender'.
Result := co_CannotReadConnectMSEmail ;
Mail.From.Address := ReadConfiguration(co_ConnectMSEmailAddress );

// Now add the recipients we recieved as the Addressees.
Result := co_CannotCreateRecipList ;
Mail.Recipients.EMailAddresses := Addressees[0] ;
for i := 1 to High( Addressees ) do
Mail.Recipients.EMailAddresses := Mail.Recipients.EMailAddresses
+ ',' + Addressees[i] ;

// If there are any CC's then add them now.
if High(CopyTo) > -1 then
begin
Result := co_CannotCreateCCList ;
Mail.CCList.EMailAddresses := CopyTo[0] ;
for i := 1 to High( CopyTo ) do
Mail.CCList.EMailAddresses := Mail.CCList.EMailAddresses + ','
+ CopyTo[i] ;
end ;

Result := co_CannotAddAttachments ;
// Now add any attachements.
for I := 0 to High( Attachments ) do
begin

// This next bit of code is written to show me that the file is
as I expected it.
FS := FileStream.Create(
'C:\Inetpub\wwwroot\ConnectMS\bin\Attachment.log', FileMode.Create );

FS.Write(Attachments[0], 0,40 );
FS.Flush ;
fs.Close ;
// End of text code.

with TIdAttachmentMemory.Create( Mail.MessageParts,
Attachments[i] ) do
begin
FileName := 'Your datab64.txt' ;
ContentTransfer := 'base64';
ContentID := 'SingleAttachment';
end;

end ;

// So now try to connect to the server.
Result := co_UnabledToConnectToSMTPServer ;
SMTP.Connect ;

// And now try to send the email message.
Result := co_UnabledToSendMail ;
SMTP.Send(Mail);

/ Richard
Post by Remy Lebeau (TeamB)
Post by Richard Bibby
I am sure I am using indy 10 (is there a way of checking appart
from directory names?)
Right click on any Indy component in the form designer.
Post by Richard Bibby
So what you are saying is that if I use Indy 10, and the code I
included in my previous post, it should all work?
Yes, provided that you are setting up the rest of the TIdMessage properly.
Please show your actual code
Post by Richard Bibby
Does the recieving mail client decode the Base64?
Yes.
Gambit
Remy Lebeau (TeamB)
2006-11-02 23:39:57 UTC
Permalink
What exactly are you having a problem with?
Post by Richard Bibby
"This is one line of data that has been sent. The end."
þE?YôE!¡/}áùûÔfÝS.f.ÇÐUePzM~aô1Ûv#],gŒœ¬A!
As it should be, because that is what you are telling TIdMessage to do.
Post by Richard Bibby
I then send it as an attachment using the code below. When I open and look
?E?Y?E!?/}??????S?f???UeP?M??a?1?v#]?g???A!
As you can see, the non-ASCII characters are being stripped out, probably
because they were outside the valid range of ASCII characters. You did not
tell TIdMessage to encode the attachment properly.
Post by Richard Bibby
Mail.Body.Text := MessageBody ;
When using attachments, you need to put the body text into a TIdText within
the MessageParts instead.
Post by Richard Bibby
Mail.Recipients.EMailAddresses := Addressees[0] ;
for i := 1 to High( Addressees ) do
Mail.Recipients.EMailAddresses :=
Mail.Recipients.EMailAddresses
Post by Richard Bibby
+ ',' + Addressees[i] ;
It would be easier to use the Add() method instead:

for i := 0 to High( Addressees ) do
Mail.Recipients.Add.Address := Addressees[i] ;
Post by Richard Bibby
Mail.CCList.EMailAddresses := CopyTo[0] ;
for i := 1 to High( CopyTo ) do
Mail.CCList.EMailAddresses := Mail.CCList.EMailAddresses + ','
+ CopyTo[i] ;
Same here:

for i := 0 to High( CopyTo ) do
Mail.CCList.Add.Address := CopyTo[i] ;
Post by Richard Bibby
FS.Write(Attachments[0], 0,40 );
I assume you meant Attachments[i] instead? Also, you are overwriting the
log for each attachment, so only the last attachment will have a log
present.
Post by Richard Bibby
ContentID := 'SingleAttachment'
Get rid of that. You did not set up the message for 'multipart/related'
content, so the ContentID is useless, and will confuse TIdMessage anyway.
In fact, I don't see you setting the TIdMessage.ContentType or
TIdAttachmentMemory.ContentType properties at all. What EXACTLY do you want
the email to look like? What EXACTLY does TIdMessage actually generate?
Please show the raw email data, including all headers.


Gambit
Richard Bibby
2006-11-03 10:08:19 UTC
Permalink
Hej Remy,

I can see that I have not explained this to you very well!

What I have trying to do is take some text, encrypt it with the .Net
encryption platform, then attach it to a message and send it.

The reason I am encrypting the data is because I am sedning sensitive
patient information in the email attachmement.

The reciever of the email will dycrypt the attachment with another program I
have written.

Hope this is clear now.

What I find is happening is that the attachment I am sending does not look
like what I am get back.

The text:

"This is one line of data that has been sent. The end."

is encrypted by .Net encryption to to:
þE?YôE!¡/}áùûÔfÝS.f.ÇÐUePzM~aô1Ûv#],gŒœ¬A!

So this is not just 7 bit ascii...

I then attach it to the email (using TMemoryAttachment).

When I later recieve the email and open the attachment it looks like this:
?E?Y?E!?/}??????S?f???UeP?M??a?1?v#]?g???A!

So as you can see I must be doing something wrong because between adding it,
sending it, recieving it and opening it.... it somehow gets changed.

The code I use is in a previous post.

Thanks for any help you can give me.
Post by Remy Lebeau (TeamB)
What exactly are you having a problem with?
Post by Richard Bibby
"This is one line of data that has been sent. The end."
þE?YôE!¡/}áùûÔfÝS.f.ÇÐUePzM~aô1Ûv#],gŒœ¬A!
As it should be, because that is what you are telling TIdMessage to do.
Post by Richard Bibby
I then send it as an attachment using the code below. When I open and
look
Post by Richard Bibby
?E?Y?E!?/}??????S?f???UeP?M??a?1?v#]?g???A!
As you can see, the non-ASCII characters are being stripped out, probably
because they were outside the valid range of ASCII characters. You did not
tell TIdMessage to encode the attachment properly.
Post by Richard Bibby
Mail.Body.Text := MessageBody ;
When using attachments, you need to put the body text into a TIdText within
the MessageParts instead.
Post by Richard Bibby
Mail.Recipients.EMailAddresses := Addressees[0] ;
for i := 1 to High( Addressees ) do
Mail.Recipients.EMailAddresses :=
Mail.Recipients.EMailAddresses
Post by Richard Bibby
+ ',' + Addressees[i] ;
for i := 0 to High( Addressees ) do
Mail.Recipients.Add.Address := Addressees[i] ;
Post by Richard Bibby
Mail.CCList.EMailAddresses := CopyTo[0] ;
for i := 1 to High( CopyTo ) do
Mail.CCList.EMailAddresses := Mail.CCList.EMailAddresses +
','
Post by Richard Bibby
+ CopyTo[i] ;
for i := 0 to High( CopyTo ) do
Mail.CCList.Add.Address := CopyTo[i] ;
Post by Richard Bibby
FS.Write(Attachments[0], 0,40 );
I assume you meant Attachments[i] instead? Also, you are overwriting the
log for each attachment, so only the last attachment will have a log
present.
Post by Richard Bibby
ContentID := 'SingleAttachment'
Get rid of that. You did not set up the message for 'multipart/related'
content, so the ContentID is useless, and will confuse TIdMessage anyway.
In fact, I don't see you setting the TIdMessage.ContentType or
TIdAttachmentMemory.ContentType properties at all. What EXACTLY do you want
the email to look like? What EXACTLY does TIdMessage actually generate?
Please show the raw email data, including all headers.
Gambit
Remy Lebeau (TeamB)
2006-11-03 11:05:04 UTC
Permalink
Post by Richard Bibby
What I have trying to do is take some text, encrypt it with
the .Net encryption platform, then attach it to a message and send it.
The encrypted data is 8-bit binary, but you are trying to store it as 7-bit
text in the TIdAttachmentMemory. That is why you are losing bytes. You are
using TIdAttachmentMemory's Text-based constructor when you need to use its
binary constructor, or its DataStream property, instead of storing the data
as text. For example:

with TIdAttachmentMemory.Create(Mail.MessageParts) do
begin
DataStream.Write(YourEncryptedBytesHere, 0, NumberOfBytesHere);
FileName := 'Your data.txt';
ContentTransfer := 'base64';
ContentType := 'application/octet-stream';
end;
Post by Richard Bibby
What I find is happening is that the attachment I am sending does
not look like what I am get back.
That is because you are passing it to Indy as 7-bit text instead of 8-bit
binary to begin with.


Gambit
Richard Bibby
2006-11-04 12:22:23 UTC
Permalink
That fix it thanks.
Post by Remy Lebeau (TeamB)
Post by Richard Bibby
What I have trying to do is take some text, encrypt it with
the .Net encryption platform, then attach it to a message and send it.
The encrypted data is 8-bit binary, but you are trying to store it as 7-bit
text in the TIdAttachmentMemory. That is why you are losing bytes. You are
using TIdAttachmentMemory's Text-based constructor when you need to use its
binary constructor, or its DataStream property, instead of storing the data
with TIdAttachmentMemory.Create(Mail.MessageParts) do
begin
DataStream.Write(YourEncryptedBytesHere, 0, NumberOfBytesHere);
FileName := 'Your data.txt';
ContentTransfer := 'base64';
ContentType := 'application/octet-stream';
end;
Post by Richard Bibby
What I find is happening is that the attachment I am sending does
not look like what I am get back.
That is because you are passing it to Indy as 7-bit text instead of 8-bit
binary to begin with.
Gambit
Richard Bibby
2006-11-02 08:18:52 UTC
Permalink
Hej,

Thanks for the reply. You confirm what I suspected.

So the next question is how do I take a MemoryStream and add it as base64
encoded binary attachement to my TIdmessage.

I have search Indy, and the internet, but only seem to find examples that
add text fles.

My latest attempt is as follows:

with TIdAttachmentMemory.Create( Mail.MessageParts,
Attachments[i] ) do
begin
FileName := 'Your data.txt' ;
ContentTransfer := 'base64';
ContentID := 'SingleAttachment';
end;

but I guess I need to encode the Attachment first to Base64?

/Richard
Post by Remy Lebeau (TeamB)
Post by Richard Bibby
When you look at the encypted file it has lots of "strange"
characters i.e. characters with coding above the normal a-z.
You likely did not tell TIdMessage to apply any encoding to the attachment,
so it sent the data in its original binary format. You should always set
the TIdAttachment.ContentTransfer property.
Post by Richard Bibby
When I send the file to myself, and then look at it after I have recieved
it
Post by Richard Bibby
I see that the characters have changed. Consequently I can not decrypt it.
Then the data is likely being altered by the email system. Not all systems
can handle 8-bit binary data. That is why 7-bit encoding schemes like
base64 and quoted-printable exist in the first place.
Post by Richard Bibby
What is the difference between a binary file (such as a progam as an
attachement) and my text file?
Text is just a 7-bit subset of 8-bit binary. But in the early days of the
Internet, email systems only supported 7-bit data. Many still do. Which is
why 8-bit data usually has to be transmitted using a 7-bit encoding scheme.
There are standards in place to add 8-bit support to email protocols, but
many servers have not caught up yet.
Post by Richard Bibby
Am I attaching it incorrectly?
Since you did not show any code, there is no way to answer that.
Gambit
Loading...