【问题标题】:Why has the textfile's encoding changed from UTF-8 to ANSI (and how to solve this)?为什么文本文件的编码从 UTF-8 更改为 ANSI(以及如何解决这个问题)?
【发布时间】:2015-06-11 11:01:36
【问题描述】:

我正在使用 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;

感谢您的宝贵时间。

【问题讨论】:

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


    【解决方案1】:

    当我下载此文件时,.txt 文件的编码已从 UTF-8 更改为 ANSI

    使用TIdAttachmentFile 时,文件的原始字节按原样发送。 Indy 不会更改附件的编码。

    TIdAttachmentFile 默认其ContentType 属性值基于您传递给构造函数的文件名的扩展名。在这种情况下,扩展名是.txt,所以ContentType 应该默认为text/plain。 text/... 媒体类型具有与之关联的 charset 属性,但您没有在代码中设置附件的 Charset 属性。否则,接收者将使用默认的 charset 来解释数据(通常为 RFC 822 的 us-ascii)。因此,接收者很可能正在检测 text/plain 缺少 charset 的媒体类型,并且以 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;
    

    并在彼此相邻的行中显示其内容,而不是在彼此下方。

    这听起来更像是换行问题而不是编码问题。例如,如果Android上的原始文件使用LF换行符,但收件人只支持CRLF换行符。

    如果需要,可以让 Indy 将换行符标准化为 CRLF。您只需将文件数据加载到TIdText 而不是TIdAttachmentFile,然后确保将TIdText.ContentDisposition 属性设置为attachment(否则将默认为inline),然后设置@987654343 @,因此数据仍然被收件人视为附件:

    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;
    

    【讨论】:

    • 我终于开始工作了,非常感谢您详细的回答和编码建议!
    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 2014-02-17
    相关资源
    最近更新 更多