2015-06-11 15 views
1

Я отправляю файл .txt в виде вложения с устройства Android с помощью Indy.Почему кодировка текстового файла изменилась с UTF-8 на ANSI (и как решить эту проблему)?

Когда я загружаю это, кодировка файла .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; 

Спасибо за ваше время.

ответ

1

При загрузке этого кодирования файла .txt изменился с UTF-8 в ANSI

При использовании TIdAttachmentFile, исходные байты файла передаются как есть. Indy не изменяет кодировку прикрепленного файла.

TIdAttachmentFile присваивает свой ContentType значение свойства, основанное на расширении имени файла, которое вы передаете конструктору. В этом случае расширение составляет .txt, поэтому значение ContentType должно соответствовать text/plain. Тип носителя text/... имеет связанный с ним атрибут charset, но вы не устанавливаете свойство Charset вложения в свой код. Без этого получатель будет интерпретировать данные, используя вместо этого по умолчанию charset (обычно us-ascii на RFC 822). Поэтому вполне вероятно, что получатель обнаруживает тип медиафайла 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 linebreaks, но получатель поддерживает только CRLF linebreaks.

Если вы хотите, вы можете 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; 
+0

Я, наконец, получил это, чтобы работать, спасибо вам за подробный ответ и предложение по кодированию! –