Отправка письма через TIdSMTP и TIdMessage
От: lsv  
Дата: 22.10.09 11:40
Оценка:
Отправляю письмо с помощью TIdSMTP и TIdMessage, работаю с Indy10 в CodeGear C++Builder.
  IdSMTP = new TIdSMTP(NULL);
  IdSMTP->AuthType = satDefault;
...
  Msg = new TIdMessage(NULL);
  Msg->ContentType = L"text/plain; charset=koi8-r";
  Msg->IsEncoded = true;
  Msg->Encoding = meMIME;
  Msg->ContentTransferEncoding = L"8bit";
  Msg->Body->Text = L"Тело сообщения";
...
  IdSMTP->Connect();
  IdSMTP->Send(Msg);

Когда письмо приходит то оно состоит из знаков вопроса
???? ?????????
В чем может быть проблема, что еще надо включить или поменять, а то уже мозг сломал?
Re: Отправка письма через TIdSMTP и TIdMessage
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 22.10.09 12:27
Оценка:
Здравствуйте, lsv, Вы писали:

lsv>Отправляю письмо с помощью TIdSMTP и TIdMessage, работаю с Indy10 в CodeGear C++Builder.

lsv>
lsv>  IdSMTP = new TIdSMTP(NULL);
lsv>  IdSMTP->AuthType = satDefault;
lsv>...
lsv>  Msg = new TIdMessage(NULL);
  Msg->>ContentType = L"text/plain; charset=koi8-r";
  Msg->>IsEncoded = true;
  Msg->>Encoding = meMIME;
  Msg->>ContentTransferEncoding = L"8bit";
  Msg->>Body->Text = L"Тело сообщения";
lsv>...
lsv>  IdSMTP->Connect();
lsv>  IdSMTP->Send(Msg);
lsv>

lsv>Когда письмо приходит то оно состоит из знаков вопроса
lsv>???? ?????????
lsv>В чем может быть проблема, что еще надо включить или поменять, а то уже мозг сломал?

Когда-то похожее я находил на Delphi Kingdom — там часто возникают вопросы по Indy. Вот привожу код:


uses IdMessage,
    IdAttachmentFile,
    IdText,
    IdSMTP,
    IdPOP3,
    IdCoderHeader,
...

Procedure TMailer.LInitializeISO(Sender: TObject; var VTransferHeader: TTransfer;
                           var VHeaderEncoding: Char; var VCharSet: string);
begin
  VTransferHeader:=bit8;
  VHeaderEncoding:='B';
  VCharSet:='Windows-1251';
end;

function TMailer.SendMail(const Host,Password,Username: String;
                          const Recipients:  array of String;
                          const FromAdres,Subject: String;
                          const MessageText:  String;
                          const Attachments: array of String): boolean; 

var EMsg: TIdMessage;
    IdSMTP1: TIdSMTP;
    EText: TIdText;
    i: integer;
begin
  result := false;
  IdSMTP1 := TIdSMTP.Create(nil);
  IdSMTP1.Host:= Host;
  IdSMTP1.Password:= Password;
  IdSMTP1.Username:= Username;

  EMsg := TIdMessage.Create(IdSMTP1);
  EMsg.OnInitializeISO := Self.LInitializeISO;

  try
    EMsg.CharSet := 'Windows-1251';
    EMsg.Subject := Subject;
    EMsg.ContentTransferEncoding  := '8bit';

    EText := TIdText.Create(EMsg.MessageParts); 

    EText.Body.Text :=
              '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'+
              '<html><head>'+
                              '<meta http-equiv="content-type" content="text/html; charset=Windows-1251">'+
                              '<title>Тра-ля-ля </title></head>'+
              '<body bgcolor="#ffffff">'+
              MessageText + '</body></html>';

    EText.ContentType := 'text/html';
    EText.CharSet := 'Windows-1251';
    EText.ContentTransfer := '8bit';
    for i := 0 to high(Recipients) do 
        EMsg.Recipients.Add.Address :=Recipients[i];
    EMsg.From.Address := FromAdres;
    EMsg.Body.Clear;
    EMsg.Date := now;
    for i := 0 to high(Attachments) do
      if FileExists(Trim(Attachments[i])) then 
         TIdAttachmentFile.Create(EMsg.MessageParts, Attachments[i]);
    EMsg.AfterConstruction;

    IdSMTP1.Connect;
    if IdSMTP1.Connected
      then
        try
          IdSMTP1.Send(EMsg);
          result := true;
        except
        end;
    finally
      IdSMTP1.Disconnect;
      EMsg.Free;
    end;
end;



Кстати, а для koi8-r можно попробовать еще такое:

Procedure TMailer.LInitializeISO(Sender: TObject; var VTransferHeader: TTransfer;
                           var VHeaderEncoding: Char; var VCharSet: string);
begin
  VTransferHeader:=bit7;
  VHeaderEncoding:='Q';
  VCharSet:='koi8-r';
end;
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re: Отправка письма через TIdSMTP и TIdMessage
От: Аноним  
Дата: 22.10.09 13:17
Оценка:
Здравствуйте, lsv, Вы писали:

????? — означают, что кто-то не смог конвертировать Unicode в заданную кодовую страницу ANSI.

На мой взгляд — кодировка письма koi8r, а в тело пишется уникод. А перекодировать кто будет?
Re[2]: Отправка письма через TIdSMTP и TIdMessage
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 22.10.09 15:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>????? — означают, что кто-то не смог конвертировать Unicode в заданную кодовую страницу ANSI.


А>На мой взгляд — кодировка письма koi8r, а в тело пишется уникод. А перекодировать кто будет?


Если бы топик стартер указал еще и версию Билдера — было бы вообще чудесно.
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re: Отправка письма через TIdSMTP и TIdMessage
От: lsv  
Дата: 25.10.09 11:53
Оценка:
DarkMaster, спасибо за помощь, известный код, его я тоже сразу попробовал, вот как в простейшем виде он получился на Си:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TIdSMTP *IdSMTP = new TIdSMTP(NULL);
TIdMessage *Msg = new TIdMessage(IdSMTP);
  Msg->OnInitializeISO = MsgInitializeISO;
  Msg->CharSet = L"Windows-1251";
  Msg->Subject = L"Тестовое письмо";
  Msg->ContentTransferEncoding = L"8bit";

TIdText *EText = new TIdText(Msg->MessageParts, NULL);
  EText->Body->Text = L"Тело сообщения";
  EText->ContentType = L"text/plain";
  EText->CharSet = L"Windows-1251";
  EText->ContentTransfer = L"8bit";

  Msg->From->Name = L"Тестер";
  Msg->Body->Clear();
  Msg->AfterConstruction();
...
  IdSMTP->Connect();
  IdSMTP->Send(Msg);
  IdSMTP->Disconnect();
...
}
void __fastcall TForm1::MsgInitializeISO(wchar_t &VHeaderEncoding, UnicodeString &VCharSet)
{
//  VTransferHeader:=bit8;   // в Си такого параметра нет
  VHeaderEncoding = L'B';
  VCharSet = L"Windows-1251";
}

Результат оказался плачевным, весь текст одни знаки вопроса ???? ????????? Могу предположить, что данный код очень старый и был сделан еще под Indy9.

Как я понял, здесь мало кто разберается в почте, поэтому не буду мучать здешних обитателей.
Поковырявшись в исходниках Indy10, мне удалось обнаружить, что весь секрет кроется в простой строчке, используя которую мы получим нормальное письмо
  Msg->ContentTransferEncoding = L"base64";

Вот образец кода, отправляющего правильное письмо
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TIdSMTP *IdSMTP = new TIdSMTP(NULL);
TIdMessage *Msg = new TIdMessage(IdSMTP);
  Msg->Subject = WinToWin1251Q(L"Тестовое письмо");  // WinToWin1251Q - самописная
  Msg->ContentTransferEncoding = L"base64";          // вот она, чудо строчка

  Msg->From->Name = WinToWin1251Q(L"Тестер");
  Msg->ContentType = L"text/plain; charset=windows-1251";
  Msg->Body->Add(L"Тело сообщения");
...
  IdSMTP->Connect();
  IdSMTP->Send(Msg);
  IdSMTP->Disconnect();
...
}
UnicodeString __fastcall WinToWin1251Q(UnicodeString Str)
{
UnicodeString strTo;
  strTo.sprintf(L"=?windows-1251?Q?");
AnsiString sss = Str;
  for(int i=1; i<=sss.Length(); i++)
  {
byte a = sss[i];
    if (a == ' ') a = '_';
    strTo.cat_printf((a<128) ? L"%c" : L"=%.2X", a);
  }
  strTo.cat_printf(L"?=");
  return strTo;
}
Re[2]: Отправка письма через TIdSMTP и TIdMessage
От: Аноним  
Дата: 22.01.10 11:45
Оценка:
Здравствуйте, lsv, Вы писали:

lsv>Как я понял, здесь мало кто разберается в почте, поэтому не буду мучать здешних обитателей.

lsv>Поковырявшись в исходниках Indy10, мне удалось обнаружить, что весь секрет кроется в простой строчке, используя которую мы получим нормальное письмо
lsv>[ccode]
Msg->>ContentTransferEncoding = L"base64";
Не могу сейчас точно сказать про версию Indy, но в свое время тоже случалось встретится с похожей проблемой.
На сколько я помню указание кодировки никак не влияло на кодировку отображения письма. Лечилось указанием
ContentType = L"text/plain, Windows-1251";

Как-то так.

Правда это не решало проблему с русскими символами в теме письма.

Более правильный вариант преобразовывать в юникод тему, имя отправителя и текст письма.
Re[2]: Отправка письма через TIdSMTP и TIdMessage
От: Аноним  
Дата: 29.01.10 18:18
Оценка:
Здравствуйте, lsv, Вы писали: .....

Ну наконец-то. Перерыл пол интернета по этому поводу.
Спасибо за предоставленный код, получилось разобраться!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.