Delphi 多部分/混合消息中的边界字符串不正确

Delphi 多部分/混合消息中的边界字符串不正确,delphi,indy10,Delphi,Indy10,我正在使用Delphi2006在一个仅供个人使用的应用程序中创建并发送一封带有附件的电子邮件。我用一个tidstp实例发送消息,然后用一个TIdIMAP4实例将一个副本放入一个特定的IMAP文件夹中。这一切都与BDS2006发布的Indy 10版本配合得非常好,但有一个例外:电子邮件标题中的时间总是不正确的 如果可以的话,我决定修复这个问题,在寻找解决方案之后,获得最新的Indy 10快照并使用它似乎是最合理的 这会将正确的时间放入电子邮件标题中,但出现了一个新问题。现在,添加到IMAP文件夹的

我正在使用Delphi2006在一个仅供个人使用的应用程序中创建并发送一封带有附件的电子邮件。我用一个tidstp实例发送消息,然后用一个TIdIMAP4实例将一个副本放入一个特定的IMAP文件夹中。这一切都与BDS2006发布的Indy 10版本配合得非常好,但有一个例外:电子邮件标题中的时间总是不正确的

如果可以的话,我决定修复这个问题,在寻找解决方案之后,获得最新的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)中的标题信息相同:

时间戳是固定的,但现在边界字符串不正确。结果是,添加到我的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时间,这样至少可以让消息在接收方端包含正确的时间。我并不特别关心这个修复,但它确实起到了作用。]

当存在附件时,不要使用
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; 
或:

现在,尽管如此,它很可能仍然无法以任何方式正常工作
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
属性中,请调用
tidmtp.Send()
TIdIMAP4.AppendMsg()
TIdMessage.NoEncode
属性设置为True,以便
TIdMessage.Headers
TIdMessage.Body
按原样发送

我知道,这违背了
TIdIMAP4.AppendMsg()
comments/docs的要求
AppendMsg()
目前根本不考虑MIME,因此它无法确保标头和正文中的MIME边界相互匹配。我会试着找一个解决办法。对于Indy 11,Indy的整个MIME处理系统将被重新设计,因此我将确保可以保留边界和/或指定自定义边界,以便
AppendMsg()
可以更好地匹配主体边界和标题边界


IMAP4通常是一个非常棘手的协议。

嗯,这有一定的影响,但不完全是我想要的。我创建了一个内存流,设置FTheMsg.NoEncode:=False,将消息保存到流中,重置FTheMsg.NoEncode:=True并重新加载消息,然后使用tidmtp.Send()和TIdIMAP4.AppendMsg()发送消息,并将NIL作为“AdditionalHeaders”参数传递。结果是,我没有得到任何附件,也没有文字可见的消息!这是使用NoEncode=False保存后的完整消息,然后使用NoEncode=True
code
Subject:Glucose Readings 11/07/11-11/20/11重新加载至:philip。jurgenson@pejurgenson.net内容类型:多部分/混合;boundary=“D9uTCLury1wVu8hlPEcf=\u 0afpyB9eNLrK”MIME版本:1.0日期:2011年11月22日星期二15:00:10-0600这是一个MIME格式的多部分消息。如果NoEncode=False,则保存的消息将显示为完整。抱歉,我误读了有关设置NoEncode的部分-我读取了I
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;