为什么文本文件的编码从 UTF-8 更改为 ANSI(以及如何解决这个问题)?
Why has the textfile's encoding changed from UTF-8 to ANSI (and how to solve this)?
我正在使用 Indy 从 Android 设备发送一个 .txt 文件作为附件。
当我下载此文件时,.txt 文件的编码已从 UTF-8 更改为 ANSI,并在一行中显示其内容,而不是在一行下方。
那么我做错了什么,如何解决这个问题?
用于发送邮件的功能代码:
Body := TStringList.Create;
IdSMTP := TIdSMTP.Create(nil);
SSLHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(Form1);
IdSMTP.IOHandler:= SSLHandler;
IdSMTP.UseTLS:= utUseExplicitTLS;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.AuthType := satDefault;
IdSMTP.Username := AppData.MailAddrSender;
IdSMTP.Password := Appdata.MailPassword;
IdMessage := TIdMessage.Create(nil);
IdMessage.From.Name := aName;
IdMessage.From.Address := AppData.MailAddrSender;
IdMessage.Subject := 'E-mail subject';
PathString := System.IOUtils.TPath.Combine(System.IOUtils.TPath.GetDocumentsPath, (PathString + 'Log.txt'));
Body.Add('Mail todays log,');
if FileExists(PathString) then
TIdAttachmentFile.Create(IdMessage.MessageParts,PathString);
try
for I := 0 to Body.Count -1 do
IdMessage.Body.Add(Body.Strings[I]);
IdEmailAddressItem := IdMessage.Recipients.Add;
IdEmailAddressItem.Address := AppData.MailAddrReceiver;
try
IdSMTP.Connect;
try
if IdSMTP.Authenticate then
IdSMTP.Send(IdMessage);
finally
IdMessage.Free;
IdSMTP.Disconnect;
end;
except
on E: Exception do
//exception handling here
end;
finally
IdSMTP.Free;
SSLHandler.DisposeOf;
Body.DisposeOf;
end;
感谢您的宝贵时间。
When I download this, the .txt file's encoding has changed from UTF-8 to ANSI
使用TIdAttachmentFile
时,文件的原始字节按原样发送。 Indy 不会更改附件的编码。
TIdAttachmentFile
根据您传递给构造函数的文件名的扩展名默认其 ContentType
属性 值。在本例中,扩展名是 .txt
,因此 ContentType
应该默认为 text/plain
。 text/...
媒体类型有一个与之关联的 charset
属性,但您没有在代码中设置附件的 Charset
属性。否则,收件人将使用默认值 charset
来解释数据(根据 RFC 822 通常为 us-ascii
)。因此,收件人可能正在检测缺少 charset
的 text/plain
媒体类型,并且正在 显示 ASCII/ANSI 中的文件数据,因为它确实不知道数据实际上是 UTF-8 编码的(因为文件是附件,如果将附件保存到新文件,收件人应该 保存 原始字节)。
如果您知道附加的文件是以 UTF-8 编码的事实,您应该明确说明:
if FileExists(PathString) then
begin
Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, PathString);
Attachment.ContentType := 'text/plain';
Attachment.Charset := 'utf-8';
end;
and is displaying it's content in lines next to eachother instead of underneath eachother.
这听起来更像是换行符问题,而不是编码问题。例如,如果 Android 上的原始文件使用 LF
换行符,但收件人只支持 CRLF
换行符。
如果需要,您可以让 Indy 将换行符规范化为 CRLF
。您只需将文件数据加载到 TIdText
而不是 TIdAttachmentFile
,然后确保将 TIdText.ContentDisposition
属性 设置为 attachment
(否则它将默认为 inline
),并设置 TIdText.FileName
,因此数据仍被收件人视为附件:
if FileExists(PathString) then
begin
Attachment := TIdText.Create(IdMessage.MessageParts, nil);
Attachment.Body.LoadFromFile(PathString, TEncoding.UTF8);
Attachment.ContentType := 'text/plain';
Attachment.Charset := 'utf-8';
Attachment.ContentDisposition := 'attachment';
Attachment.FileName := ExtractFileName(PathString);
end;
现在,综上所述,您在使用 Indy 的组件时通常还存在一些其他小的编码问题。我会建议更像这样的东西:
try
IdSMTP := TIdSMTP.Create(nil);
try
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
IdSMTP.IOHandler := SSLHandler;
IdSMTP.UseTLS := utUseExplicitTLS;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.AuthType := satDefault;
IdSMTP.Username := AppData.MailAddrSender;
IdSMTP.Password := Appdata.MailPassword;
IdMessage := TIdMessage.Create(nil);
try
IdMessage.From.Name := aName;
IdMessage.From.Address := AppData.MailAddrSender;
IdMessage.Subject := 'E-mail subject';
IdEmailAddressItem := IdMessage.Recipients.Add;
IdEmailAddressItem.Address := AppData.MailAddrReceiver;
IdMessage.Body.Add('Mail todays log,');
PathString := System.IOUtils.TPath.Combine(System.IOUtils.TPath.GetDocumentsPath, PathString + 'Log.txt');
if FileExists(PathString) then
begin
// or TIdText...
Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, PathString);
Attachment.ContentType := 'text/plain';
Attachment.Charset := 'utf-8';
end;
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
finally
IdMessage.Free;
end;
finally
IdSMTP.Free;
end;
except
on E: Exception do
//exception handling here
end;
我正在使用 Indy 从 Android 设备发送一个 .txt 文件作为附件。
当我下载此文件时,.txt 文件的编码已从 UTF-8 更改为 ANSI,并在一行中显示其内容,而不是在一行下方。
那么我做错了什么,如何解决这个问题?
用于发送邮件的功能代码:
Body := TStringList.Create;
IdSMTP := TIdSMTP.Create(nil);
SSLHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(Form1);
IdSMTP.IOHandler:= SSLHandler;
IdSMTP.UseTLS:= utUseExplicitTLS;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.AuthType := satDefault;
IdSMTP.Username := AppData.MailAddrSender;
IdSMTP.Password := Appdata.MailPassword;
IdMessage := TIdMessage.Create(nil);
IdMessage.From.Name := aName;
IdMessage.From.Address := AppData.MailAddrSender;
IdMessage.Subject := 'E-mail subject';
PathString := System.IOUtils.TPath.Combine(System.IOUtils.TPath.GetDocumentsPath, (PathString + 'Log.txt'));
Body.Add('Mail todays log,');
if FileExists(PathString) then
TIdAttachmentFile.Create(IdMessage.MessageParts,PathString);
try
for I := 0 to Body.Count -1 do
IdMessage.Body.Add(Body.Strings[I]);
IdEmailAddressItem := IdMessage.Recipients.Add;
IdEmailAddressItem.Address := AppData.MailAddrReceiver;
try
IdSMTP.Connect;
try
if IdSMTP.Authenticate then
IdSMTP.Send(IdMessage);
finally
IdMessage.Free;
IdSMTP.Disconnect;
end;
except
on E: Exception do
//exception handling here
end;
finally
IdSMTP.Free;
SSLHandler.DisposeOf;
Body.DisposeOf;
end;
感谢您的宝贵时间。
When I download this, the .txt file's encoding has changed from UTF-8 to ANSI
使用TIdAttachmentFile
时,文件的原始字节按原样发送。 Indy 不会更改附件的编码。
TIdAttachmentFile
根据您传递给构造函数的文件名的扩展名默认其 ContentType
属性 值。在本例中,扩展名是 .txt
,因此 ContentType
应该默认为 text/plain
。 text/...
媒体类型有一个与之关联的 charset
属性,但您没有在代码中设置附件的 Charset
属性。否则,收件人将使用默认值 charset
来解释数据(根据 RFC 822 通常为 us-ascii
)。因此,收件人可能正在检测缺少 charset
的 text/plain
媒体类型,并且正在 显示 ASCII/ANSI 中的文件数据,因为它确实不知道数据实际上是 UTF-8 编码的(因为文件是附件,如果将附件保存到新文件,收件人应该 保存 原始字节)。
如果您知道附加的文件是以 UTF-8 编码的事实,您应该明确说明:
if FileExists(PathString) then
begin
Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, PathString);
Attachment.ContentType := 'text/plain';
Attachment.Charset := 'utf-8';
end;
and is displaying it's content in lines next to eachother instead of underneath eachother.
这听起来更像是换行符问题,而不是编码问题。例如,如果 Android 上的原始文件使用 LF
换行符,但收件人只支持 CRLF
换行符。
如果需要,您可以让 Indy 将换行符规范化为 CRLF
。您只需将文件数据加载到 TIdText
而不是 TIdAttachmentFile
,然后确保将 TIdText.ContentDisposition
属性 设置为 attachment
(否则它将默认为 inline
),并设置 TIdText.FileName
,因此数据仍被收件人视为附件:
if FileExists(PathString) then
begin
Attachment := TIdText.Create(IdMessage.MessageParts, nil);
Attachment.Body.LoadFromFile(PathString, TEncoding.UTF8);
Attachment.ContentType := 'text/plain';
Attachment.Charset := 'utf-8';
Attachment.ContentDisposition := 'attachment';
Attachment.FileName := ExtractFileName(PathString);
end;
现在,综上所述,您在使用 Indy 的组件时通常还存在一些其他小的编码问题。我会建议更像这样的东西:
try
IdSMTP := TIdSMTP.Create(nil);
try
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
IdSMTP.IOHandler := SSLHandler;
IdSMTP.UseTLS := utUseExplicitTLS;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.AuthType := satDefault;
IdSMTP.Username := AppData.MailAddrSender;
IdSMTP.Password := Appdata.MailPassword;
IdMessage := TIdMessage.Create(nil);
try
IdMessage.From.Name := aName;
IdMessage.From.Address := AppData.MailAddrSender;
IdMessage.Subject := 'E-mail subject';
IdEmailAddressItem := IdMessage.Recipients.Add;
IdEmailAddressItem.Address := AppData.MailAddrReceiver;
IdMessage.Body.Add('Mail todays log,');
PathString := System.IOUtils.TPath.Combine(System.IOUtils.TPath.GetDocumentsPath, PathString + 'Log.txt');
if FileExists(PathString) then
begin
// or TIdText...
Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, PathString);
Attachment.ContentType := 'text/plain';
Attachment.Charset := 'utf-8';
end;
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
finally
IdMessage.Free;
end;
finally
IdSMTP.Free;
end;
except
on E: Exception do
//exception handling here
end;