Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Не сохраняет вложения на русском


Автор: Rodeon 6.6.2010, 04:05
Здравствуйте!
Почту всю принимала программа, пока вложенный файл в одном из писем не был на русском языке!
Большая часть кода отсюда http://forum.vingrad.ru/forum/topic-84672/view-all.html
Проверяю при помощи:
Код

MainForm.Memo.Lines.Add(attach.FileName)

Файлы аттача на английском пишутся и сохраняються нормально, на русском в memo не заносится имя файла (такое ощущение что отобразить не может, пустую строку заносит) и файл сам тоже не сохраняеться.
Я так понимаю надо скорее всего конвертировать имена файлов, которые на русском, только с какой кодировки и в какую!?
Спасибо заранее за ответ!

Автор: Rodeon 6.6.2010, 14:21
Отвечаю сам себе!
Так как имя файла получаю вида =?koi8-r?Q?=F0=D2=C9=CC_=CB_=C4=CF=C7=CF=D7_=EB=F2=F3_2010=C7.xls?= или =?koi8-r?B?0NLFxNPUwdfMxc7JxSDOwSDQ0sHL1MnL1SDX1M/Sz8UuZG9j?= или =?UTF-8?B?0KDQtdGG0LXQvdC30LjRjyDQrtC60LguZG9j?=
через if pos>0 и case ищу строку ?koi8-r?Q? или ?koi8-r?B?
первый случай текст koi8-r Quoted-Printable для него использую сперва:
Код

s:=IdDecoderQuotedPrintable.DecodeString(attach_name);

из комплекта indy, а потом
Код

const
Koi: array[0..66] of Char = (
'T', '¨', '¸', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ',
'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð',
'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú',
'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä',
'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î',
'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø',
'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
Win: array[0..66] of Char = (
'¸', '¨', 'T', 'þ', 'à', 'á', 'ö', 'ä', 'å', 'ô',
'ã', 'õ', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï',
'ÿ', 'ð', 'ñ', 'ò', 'ó', 'æ', 'â', 'ü', 'û', 'ç',
'ø', 'ý', 'ù', '÷', 'ú', 'Þ', 'À', 'Á', 'Ö', 'Ä',
'Å', 'Ô', 'Ã', 'Õ', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í',
'Î', 'Ï', 'ß', 'Ð', 'Ñ', 'Ò', 'Ó', 'Æ', 'Â', 'Ü',
'Û', 'Ç', 'Ø', 'Ý', 'Ù', '×', 'Ú');


function KoiToWin(Str: string): string;
var
  i, j, index: Integer;
begin
  Result := '';

  for i := 1 to Length(Str) do
  begin
    index := -1;
    for j := Low(Win) to High(Win) do
      if Koi[j] = Str[i] then
      begin
        index := j;
        Break;
      end;

    if index = -1 then
      Result := Result + Str[i]
    else
      Result := Result + Win[index];
  end;
end;

Нашел на форуме, автору спасибо!

Во втором случае, если ?koi8-r?B? т.е. koi8-r base64
сперва использую
Код

function Decode64(s: string): string;
var dm: TIdDecoderMIME;
begin
  result := s;
  dm := TIdDecoderMIME.Create(nil);
  try
    result := dm.DecodeString(s);
  finally
    dm.Free;
  end;
end;

а потом снова функцию KoiToWin описанную чуть выше.
изполученых имен файлов удаляю =?koi8-r?Q? или =?koi8-r?B? и в конце 2 символа а именно ?=, все получил имя файла, с которым теперь можно сохранять.

По поводу =?UTF-8?B?, сначала натравливаю функцию Decode64, а потом стандартную Utf8toansi - на выходе имя файла на русском.
Удаляю символы спереди и сзади и сохраняю вложение.
Ура. Пока все работает.

Автор: Rodeon 6.6.2010, 15:25
Очередная проблемма возникла когда вложенние имеет длинное имя, типа
=?koi8-r?B?0M/Mz9bFzsnFIM/CIM/Sx8HOydrBw8nJIMkg0NLPx9LBzc3BINDSwQ==?= =?koi8-r?B?y9TJy8kg5+31IPXQ0sHXzMXOycUuZG9j?=
т.е. имя состоит из двух частей!
фиг знает как убрать это ограничение!?
Пока что делаю так! Маленько переделал код Snowy http://forum.vingrad.ru/forum/topic-84672/view-all.html
Код

procedure ProcessAttach(att: TIdAttachment);
var
  Path: string;
  FName:string;
  Temp1,Temp2:string;
begin
  Fname:=att.FileName;
  Form1.Memo1.Lines.Add(Fname);
  if pos('==?= =?koi8-r?B?',Fname)>0 then
  Begin
    Delete(Fname,1,11);
    Delete(Fname,length(Fname)-1,2);
    Temp1 := Copy(Fname,1,pos('==?= =?koi8-r?B?',Fname)+1);
    Temp2:=TIdDecoderMIME.DecodeString(Temp1);
    Temp1 := Copy(Fname,pos('==?= =?koi8-r?B?',Fname)+16,length(Fname)-pos('==?= =?koi8-r?B?',Fname)+1);
    Fname:=Temp2+TIdDecoderMIME.DecodeString(Temp1);
    Fname:=KoiToWin(Fname);
  End;
  if pos('koi8-r?Q',Fname)>0 then
  Begin
    Delete(Fname,1,11);
    Delete(Fname,length(Fname)-1,2);
    Fname:=Form1.IdDecoderQuotedPrintable.DecodeString(Fname);
    Fname:=KoiToWin(Fname);
    Form1.Memo1.Lines.Add(Fname);
  end;
  if pos('koi8-r?B',Fname)>0 then
  Begin
    Delete(Fname,1,11);
    Delete(Fname,length(Fname)-1,2);
    Fname:=TIdDecoderMIME.DecodeString(Fname);
    Fname:=KoiToWin(Fname);
    Form1.Memo1.Lines.Add(Fname);
  end;
  if pos('UTF-8?B',Fname)>0 then
  Begin
    Delete(Fname,1,10);
    Delete(Fname,length(Fname)-1,2);
    Fname:=TIdDecoderMIME.DecodeString(Fname);
    Fname:=UTF8ToAnsi(Fname);
    Form1.Memo1.Lines.Add(Fname);
  end;
  Path := globalpath + '\'+pop.Username+'\'+'Attach';
  ForceDirectories(Path);
  Path := Path + '\' + Fname;
  try
    if FileExists(Path) then DeleteFile(Path);
    att.SaveToFile(Path);
    sl.Add('Attach: ' + Fname);
  except
    ShowMessage('Не удается сохранить файл');
  end;
end;

Если есть какие соображения как убрать это ограничение, буду рад!

Автор: Rodeon 7.6.2010, 01:04
Утомил меня Indy своими ошибками(uneven size in decodetostream,
range check error,
max line length exceeded и т.д.)
Причем зависимость появления ошибок так установить и не удалось.
Перепробовал за 1.5 дня около 10 компонентов для работы с почтой, остановился на  SakEmail components
так как даже в демо по работе с почтой есть все что мне нужно было, поддержка руского языка в прикрепленных файлах, прогрессбар общий и для каждого письма в отдельности.
Осталось доделать пример и можно пользоваться!
Если кому надо, то компонент прикрепил!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)