Неправильная строка границы в составном / смешанном сообщении - PullRequest
5 голосов
/ 22 ноября 2011

Я использую Delphi 2006 для создания и отправки сообщения электронной почты с вложением в приложение только для личного использования.Я отправляю сообщение с экземпляром TIdSMTP, а затем также помещаю копию в определенную папку IMAP с экземпляром TIdIMAP4.Все это очень хорошо работает с версией Indy 10, распространяемой вместе с BDS2006, с одним исключением: в заголовке письма всегда указывается неправильное время.

Я решил исправить это, если смогу, и после поискарешение, которое казалось наиболее разумным, чтобы получить последний снимок Indy 10 и использовать его.

Это помещает правильное время в заголовок письма, но есть новая проблема.Строка границы теперь отличается в заголовке сообщения, которое добавляется в папку IMAP, чем в теле письма!(Обратите внимание, что сообщение, отправленное через SMTP, является правильным.)

Это релевантная информация заголовка из более старой версии Indy 10:

Content-Type: multipart/mixed; boundary="XNlC6OyS4QSiHY2U=_jsXyps6TR34pFNsh"
MIME-Version: 1.0
Date: Tue, 22 Nov 2011 09:11:58 +0000

A test of the BDS2006-bundled version of Indy

--XNlC6OyS4QSiHY2U=_jsXyps6TR34pFNsh
Content-Type: application/octet-stream;
        name="20111122.xls"

И это тот же заголовокинформация из Indy 10.5.8 (снимок 10_4702, который я установил вчера):

Content-Type: multipart/mixed; boundary="CDbEncbFvL7RZdOJ3DOIRoRBs=_nBsbZms"
MIME-Version: 1.0
Date: Tue, 22 Nov 2011 07:33:46 -0600

investigating more deeply, why does the boundary indicator change?

--h=_WzGWJei29fng7SqdPpDh1nkJxJZhiGc
Content-Type: application/octet-stream;
    name="20111122.xls"

Штамп времени установлен, но теперь строка границы неверна.В результате в сообщении, которое добавляется в мою папку IMAP, вообще ничего не появляется.

Вот соответствующий код, который создает сообщение электронной почты и вложение, отправляет его и помещает копию вПапка IMAP:

  FTheMsg.Date := Now;  // FTheMsg is a component dropped onto the form
  FTheMsg.Recipients.EMailAddresses := edMailTo.Text;
  FTheMsg.ClearBody;
  FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' +
              FormatDateTime('mm/dd/yy', FEndDate);
  FTheMsg.Body.Assign(FMemo.Lines);

  // create the attachment
  TIdAttachmentFile.Create(FTheMsg.MessageParts, fileName);

  // send the mail!
  FSmtp.Host := FSMTPHost;  // values set up elsewhere, FSmtp is a component on the form
  FImap.Host := FIMAPHost;  // FImap is also a component on the form

  FSmtp.Connect;
  try
    FSmtp.Send(FTheMsg);
    FImap.Connect;
    try
      if (not FImap.AppendMsg('Sent Items', FTheMsg, FTheMsg.LastGeneratedHeaders, [mfSeen]))     then
        StatusBar1.Panels[4].Text := 'Failed append msg';
    finally
      FImap.Disconnect;
    end;
  finally
    FSmtp.Disconnect;
  end;

Как я уже говорил, отправляемая электронная почта в порядке и отображается правильно.Но тот, который добавлен в мою папку IMAP (в FImap.AppendMsg () выше), неверен.Я пытался отследить код, чтобы увидеть, где он может идти не так, но, честно говоря, я недостаточно знаком с Indy и различными протоколами электронной почты / RFC, чтобы определить, что происходит не так.Все, что я могу сказать, это то, что старая версия сохраняет сообщение во временный файл, прежде чем добавить его в папку, а более новая версия сохраняет его в поток памяти.Очевидно, что в этом что-то другое, но я в настоящее время слишком невежественен, чтобы определить что.

Есть ли простой способ исправить проблему с отметкой времени в старой версии?Если это так, это было бы хорошо для моего использования, так как все остальное кажется правильным.Если нет, что еще мне нужно сделать, чтобы исправить проблему, показанную здесь, с неверной строкой границы?

(Поскольку это приложение строго для моего собственного использования, я могу жить с неправильной датой, если у меня естьв, но не с «пустой» копией в моей папке «Отправленные».)

Если потребуется дополнительная информация, я с удовольствием предоставлю все, что смогу.

[РедактироватьЯ включил что-то вроде клуджа в МОЙ код, используя более старую версию Indy.Я просто устанавливаю дату / время сообщения на время UTC / GMT перед его отправкой, и это, по крайней мере, позволяет сообщению содержать правильное время на конце получателя.Меня это не особо волнует, но оно помогает.]

1 Ответ

5 голосов
/ 22 ноября 2011

Не используйте свойство TIdMessage.Body для хранения текста, когда вложение присутствует.Вместо этого поместите текст в объект TIdText.Еще лучше, используйте классы TIdMessageBuilder..., такие как TIdMessageBuilderPlain, чтобы подготовить для вас тело TIdMessage.

Попробуйте:

FTheMsg.Clear; 
FTheMsg.Date := Now;  // FTheMsg is a component dropped onto the form 
FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + FormatDateTime('mm/dd/yy', FEndDate); 
FTheMsg.ContentType := 'multipart/mixed'; 

TIdText.Create(FTheMsg.MessageParts, FMemo.Lines).ContentType := 'text/plain';
TIdAttachmentFile.Create(FTheMsg.MessageParts, fileName); 

FSmtp.Connect; 
try 
  FSmtp.Send(FTheMsg); 
  FImap.Connect; 
  try 
    if (not FImap.AppendMsg('Sent Items', FTheMsg, nil, [mfSeen])) then 
      StatusBar1.Panels[4].Text := 'Failed append msg'; 
  finally 
    FImap.Disconnect; 
  end; 
finally 
  FSmtp.Disconnect; 
end; 

Или:

FTheMsg.Clear; 
FTheMsg.Date := Now;  // FTheMsg is a component dropped onto the form 
FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + FormatDateTime('mm/dd/yy', FEndDate); 

with TIdMessageBuilderPlain.Create do
try
  PlainText.Assign(FMemo.Lines);
  Attachments.Add(fileName); 
  FillMessage(FTheMsg);
finally
  Free;
end;

FSmtp.Connect; 
try 
  FSmtp.Send(FTheMsg); 
  FImap.Connect; 
  try 
    if (not FImap.AppendMsg('Sent Items', FTheMsg, nil, [mfSeen])) then 
      StatusBar1.Panels[4].Text := 'Failed append msg'; 
  finally 
    FImap.Disconnect; 
  end; 
finally 
  FSmtp.Disconnect; 
end; 

Теперь, с учетом сказанного, вполне вероятно, что он все равно не будет работать правильно в любом случае.TIdIMAP4.AppendMsg() вызывает TIdMessage.SaveToStream() внутренне, что обновляет содержимое электронной почты свежим (и, таким образом, изменяет границу, используемую в теле).Если вы передадите ранее существовавший TIdMessage.LastGeneratedHeaders или позволите TIdIMAP4.AppendMsg() захватить текущий TIdMessage.Headers, они будут не синхронизированы с новой границей, которую генерирует TIdMessage.SaveToStream().

Чтобы убедиться, что оба SMTPи IMAP4 синхронизированы, им нужно получать одни и те же данные.Попробуйте сначала вызвать TIdMessage.SaveToStream() вручную, установив для свойства TIdMessage.NoEncode значение False, затем установите для свойства TIdMessage.NoDecode значение True и вызовите TIdMessage.LoadFromStream(), чтобы перезагрузить сохраненные данные как есть в свойства TIdMessage.Headers и TIdMessage.Body,затем вызовите TIdSMTP.Send() и TIdIMAP4.AppendMsg() со свойством TIdMessage.NoEncode, установленным в True, чтобы TIdMessage.Headers и TIdMessage.Body отправлялись как есть.

Я знаю, это идет вразрез с тем, что TIdIMAP4.AppendMsg()комментарии / документы говорят делать.AppendMsg() в настоящее время вообще не учитывает MIME, поэтому не гарантирует, что границы MIME в заголовке и теле соответствуют друг другу.Я постараюсь проверить исправление для этого.Для Indy 11 вся система обработки MIME в Indy будет переработана, поэтому я позабочусь о том, чтобы можно было сохранить границы и / или указать пользовательские границы, чтобы AppendMsg() лучше соответствовал границе тела и границе заголовка..

IMAP4 - очень сложный протокол для работы в целом.

...