android - 为什么文本文件的编码从 UTF-8 更改为 ANSI(以及如何解决这个问题)?

标签 android text-files email-attachments indy10 delphi-xe8

我正在使用 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/plaintext/... 媒体类型有一个与之关联的 charset 属性,但您没有在代码中设置附件的 Charset 属性。否则,收件人将使用默认的 charset 来解释数据(通常是 us-ascii 根据 RFC 822)。因此,很可能收件人正在检测缺少 charsettext/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;

关于android - 为什么文本文件的编码从 UTF-8 更改为 ANSI(以及如何解决这个问题)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30778960/

相关文章:

Android 相机按钮半按监听器

android - 键映射错误,仅适用于我的应用

c - 从 txt 文件中读取数据并在终端中获得被拒绝的权限

php - 有没有更好的方法来处理一个 300,000 行的文本文件数据并将其插入 MySQL?

android - 在 Android 的电子邮件附件中显示零字节 pdf 文件

c# - 是否可以使用 MailKit 修改/附加邮件而无需下载整个邮件?

Android:Hilt 未使用模块,这可能是应用程序崩溃而不显示任何信息的原因

android - 在eclipse pulsar上开始android开发

java - 将大字符串写入文本文件?

Python Sendgrid 发送带有 PDF 附件的电子邮件