TIdAttachment - получение правильного имени файла вложения - без информации о кодировке utf-8 - PullRequest
0 голосов
/ 15 апреля 2020

В моем проекте я пытаюсь извлечь вложения из файлов .eml.

При нормальных условиях (кодировка ISO) это работает. Но в особых обстоятельствах он дал мне неправильное имя файла для вложения.

Вот как выглядит MessagePart в моем примере:

------=_Part_315_1401515384.1585891801067
Content-Type: application/octet-stream; 
    name="=?UTF-8?Q?Report=5F2020-3=5FCustomerA with some spaces in between.csv?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment; 
    filename="=?UTF-8?Q?Report=5F2020-3=5FCustomerA with some spaces in between.csv?="

UGFydG5lcjtNYW5kYW50ZW5uYW1lO05hbWU7RmlybWE7U3RyYd9lO1Bvc3RsZWl0emFobDtPcnQ7
TGFuZDtQcm9kdWt0bGluaWU7S3VuZGVuc3RhdHVzO0RhdHVtIFJlZ2lzdHJpZXJ1bmc7QmVnaW5u
IEthdWY7S/xuZGlndW5nIGf8bHRpZyBhYjtBbnphaGwgQmVudXR6ZXI7QW56YWhsIE1vYmlsZSBz
eW5jO05ldHRvIFJlY2hudW5nc2JldHJhZyBpbiBFdXJvO1Byb3Zpc2lvbnNzdHVmZTtQcm92aXNp
b25zYW50ZWlsIGluIEV1cm8NCg==
------=_Part_315_1401515384.1585891801067--

Пока что ничего впечатляющего. Но по какой-то причине я не получаю правильное имя файла из этого вложения.

Вот мой код для получения имени файла этого файла и сохранения его во временную папку:

function foo(MyMail: TIdMessage; SavePathWithoutBackSlash : string): boolean;
var
 i : Integer;
 lfilename: string;
begin
  for i := 0 to Pred(MyMail.MessageParts.Count) do
    begin
      if (MyMail.MessageParts.Items[i] is TIdAttachmentFile) then
      begin
        lFilename := TIdAttachmentFile(MyMail.MessageParts.Items[i]).FileName;
        TIdAttachmentFile(MyMail.MessageParts.Items[i]).SaveToFile(SavePathWithoutBackSlash + '\' + lFilename);
      end;
    end;
  end; 
end;

Я много пробовал с кодировками, но, похоже, ничто не оказывает влияния.

Я ожидаю, что строка выглядит так: path/Report_2020-3_CustomerA.csv

Что я получаю: path/=?UTF-8?Q?Report=5F2020-3=5FCustomerA.csv?=

Как правильно сохранить вложение?

1 Ответ

0 голосов
/ 15 апреля 2020

Танки к @olivier Я нашел решение этой проблемы. Это комбинация из 2 проблем.

Первая проблема:

TIdAttachmentFile(MyMail.MessageParts.Items[i]).FileName

не возвращает =?UTF-8?Q? возвращает =_UTF-8_Q_ Поэтому я изменил значение на

TIdAttachmentFile(MyMail.MessageParts.Items[i]).Name

-

Вторая проблема:

В соответствии с RFC2047 пробел не допускается между =?...?=. Таким образом, DecodeHeader оставит строку без изменений. Мой код теперь работает и выглядит следующим образом:

Uses 
  ...IdAttachmentFile, IdMessage, IdCoderHeader...  

function foo(MyMail: TIdMessage; SavePathWithoutBackSlash : string): boolean;
    var
     i : Integer;
     lfilename: string;
    begin
      for i := 0 to Pred(MyMail.MessageParts.Count) do
        begin
          if (MyMail.MessageParts.Items[i] is TIdAttachmentFile) then
          begin
            lFilename := TIdAttachmentFile(MyMail.MessageParts.Items[i]).Name;
            if pos('=?UTF-8?Q?',uppercase(lfilename)) > 0 then
            begin
              lfilename:=StringReplace(lFilename,' ','=20',[rfReplaceAll,rfIgnoreCase]);
            end;
            lFileName:= DecodeHeader(lFileName);
            TIdAttachmentFile(MyMail.MessageParts.Items[i]).SaveToFile(SavePathWithoutBackSlash + '\' + lFilename);
          end;
        end;
      end; 
    end;

= 20 - правильная запись для пробелов в UTF-8 с цитируемой для печати

...