Indy. Проблема с кодировкой в теле письма

Шамиль Фаридович
Дата: 16.06.2009 12:58:30
Здравствуйте!
Пишу отправитель почты на D7, используя TidSMTP из Indy 9.
Проблемы с русскими буквами в заголовке и отправителе удалось решить с помощью
function TfmMain.ConvertToWIN1251(instr:string):string;
begin
  result:='=?'+'Windows-1251'+'?B?'+IdEncoderMIME1.Encode(instr)+'?=';
end;
Но осталась другая - с MS Outlook. Когда отправляешь письмо без вложения, то все приходит нормально. Однако если письмо с аттачем, то снова абракадабра вместо русских букв. Причем в других почтовиках, например веб от Яндекс и Рамблер, а также The Bat такой проблемы нет. Впрочем если рассмотреть код входящих писем, то можно найти перед самим телом письма можно найти
Content-Transfer-Encoding: 7bit
Наверное здесь и кроется решение.
Но как изменить это значение? Изменения значения idMessage1.ContentTransferEncoding ни к чему не приводят.
P.S. IdCoderHeader.pas, idGlobal.pas правил и переустанвливал Indy - не помогло вообще, без функции ConvertToWIN1251 даже заголовки приходили кракозяброй.
Зайцев Фёдор
Дата: 16.06.2009 13:02:41
ЕМНИП, аутпук любит когда заголовок и тело письма кодированы одинаково
Шамиль Фаридович
Дата: 16.06.2009 13:22:16
Что вы имеете в виду?
Так выглядит приходящее письмо
Return-Path: <my@mail.ru>
Received: from [10.8.2.21] (HELO mx21.rambler.ru)
  by mail79.rambler.ru (CommuniGate Pro SMTP 4.2.10)
  with ESMTP id 48920832 for my2@mail.ru; Tue, 16 Jun 2009 10:23:15 +0400
Received: from ***
	by mx21.rambler.ru (Postfix) with ESMTP id 82C8AD8583A
	for < my2@mail.ru >; Tue, 16 Jun 2009 10:23:14 +0400 (MSD)
Received: ***
  ***
  with ESMTP id 1860306; Tue, 16 Jun 2009 10:23:27 +0400
From: =?windows-1251?B?z/Du4/Dg7OzgIOPu6+7x7uLg7ej/?= <my@mail.ru>
Subject: =?windows-1251?B?0eXq8uXsIO73?=
To: my2@mail.ru, my3@mail.ru, my4@mail.ru
Content-Type: multipart/mixed;
 boundary="=_NextPart_2rfkindysadvnqw3nerasdf";
	charset="windows-1251"
MIME-Version: 1.0
Date: Tue, 16 Jun 2009 10:22:24 +0400
X-Priority: 3
X-Library: Indy 9.00.10
Message-ID: <auto-000001860306@narat.ru>

This is a multi-part message in MIME format

--=_NextPart_2rfkindysadvnqw3nerasdf
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Test
Проверка русских букв
123 русские буквы english
парам

--=_NextPart_2rfkindysadvnqw3nerasdf
Content-Type: application/octet-stream;
        name="Программирование.xls"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
        filename="Программирование.xls"

0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAAJQAAAAAAAAAA
....
--=_NextPart_2rfkindysadvnqw3nerasdf--
Офф
Дата: 16.06.2009 13:27:06
Шамиль Фаридович,

Вы случайно не в РОССЕЛЬХОЗБАНКЕ работаете?
Шамиль Фаридович
Дата: 16.06.2009 14:34:23
Надеюсь там работают программисты получше меня - те, что не бьются 3 сутки головой о... Indy!
Bator
Дата: 16.06.2009 17:20:14
1. взять последнюю версию 9ки.
2. код создания письма в студию.

и видится мне, что пишется не в тело письма, а во вложение

Content-Type: text/plain
Content-Transfer-Encoding: 7bit

7bit для win1251 как-то мало будет
Шамиль Фаридович
Дата: 17.06.2009 15:48:15
Про 7bit я сообщил в начале поста, в этом и направлении копал.
Порывшись по инету, увидел совет использовать TidText.Body вместо TidMessage.Body, так как у TidText есть свойство CharSet(правда не моей версии Indy 9 - поэтому пришлось скачать Indy 10.0.76 c www.indyproject.org. В них тоже нужно было кое-что подправить, а именно в модуле
IdGlobalProtocols.pas в функции IdGetDefaultCharSet поменять строку
LANG_RUSSIAN: Result := idcsKOI8_R;
на
LANG_RUSSIAN: Result := idcsWINDOWS_1251;
и перекомпилировать.
Если кто-то последует моим стопам и воспользуется автоматической установкой Indy 10 в IDE, и при компиляции будет выскакивать ошибка, мол такой модуль был скомпилирован в другой версии, то это означает, что вы не полностью удалили старую версию Indy. Есть 2 пути:
1. Зайти в Environment Options->Library path и поднять папку с библиотекой новой версии Indy (у меня она называлась LibD7) выше папки $(DELPHI)\Lib
2. В ручную удалить из папки $(DELPHI)\Lib все старые dcu'шки, более новые версии которых есть в библиотеке новой версии (мне в этом очень помог FAR manager и команда "Сравнение папок"
Первый путь проще, но второй имхо правильнее.

А это получившийся код:
procedure TfmMain.btSendMailClick(Sender: TObject);
 var Msg: TIdMessage;
      idtTextPart: TIdText;
begin
 Msg:=TIdMessage.Create(Self);
 with Msg do
 begin
  CharSet:='windows-1251';
  Subject:='тема сообщения';
  Recipients.EMailAddresses:='адрес1@mail.ru,адрес2@mail.ru,адрес3@mail.ru';
  From.Address:='Email отправителя';          //указываем автора письма
  From.Name:='Имя отправителя';

  idtTextPart := TIdText.Create(Msg.MessageParts, nil);
  idtTextPart.ContentType := 'text/plain';
  idtTextPart.CharSet := 'windows-1251';
  idtTextPart.Body:=memo1.Lines;

  TIdAttachmentFile.Create(Msg.MessageParts, 'C:\File1.txt');
  TIdAttachmentFile.Create(Msg.MessageParts, 'C:\File2.xls');
  TIdAttachmentFile.Create(Msg.MessageParts, 'C:\File3.doc');
 end;

 with IdSMTP1 do
 begin
   Host:='***';
   Username:='***';
   Password:='***'; 
   Connect;
   if Connected then IdSMTP1.Send(Msg);
 end;
 idtTextPart.Free;
 Msg.Free;
 IdSMTP1.Disconnect;
 showmessage('Сообщение доставлено!');
end;
Альт
Дата: 17.06.2009 21:48:29
Шамиль Фаридович, а в поиске?
stokito
Дата: 24.03.2010 14:42:16
Я только что поборол проблему, но за корректность не ручаюсь. Время нет разобраться лучше.
Причём в TODO к этому файлу прописано:
2001-Jul-11 Hadi Hariri
TODO: Make checks for encoding and content-type later on.
TODO: Merge Encoding and AttachmentEncoding
TODO: Make encoding plugable
TODO: Clean up ISO header coding
Тоесть проблема уже с 2001 года :(


Побороть можно изменив файл IdMessage.
Причём в TODO к этому файлу прописано:
2001-Jul-11 Hadi Hariri
TODO: Make checks for encoding and content-type later on.
TODO: Merge Encoding and AttachmentEncoding
TODO: Make encoding plugable
TODO: Clean up ISO header coding
Тоесть проблема уже с 2001 года :(
В функции GenerateHeader заменить ISOCharSet на CharSet.

      Values['From'] := EncodeAddressItem(From, HeaderEncoding, TransferHeader, CharSet); {do not localize}
      Values['Subject'] := EncodeHeader(Subject, [], HeaderEncoding, TransferHeader, CharSet); {do not localize}
      Values['Subject'] := EncodeHeader(Subject, [], HeaderEncoding, TransferHeader, CharSet); {do not localize}
      Values['To'] := EncodeAddress(Recipients, HeaderEncoding, TransferHeader, CharSet); {do not localize}
      Values['Cc'] := EncodeAddress(CCList, HeaderEncoding, TransferHeader, CharSet); {do not localize}
      ....
      Values['Reply-To'] := EncodeAddress(ReplyTo, HeaderEncoding, TransferHeader, CharSet); {do not localize}
      Values['Organization'] := EncodeHeader(Organization, [], HeaderEncoding, TransferHeader, CharSet); {do not localize}
      Values['Disposition-Notification-To'] := EncodeAddressItem(ReceiptRecipient, {do not localize}
        HeaderEncoding, TransferHeader, CharSet);