Indy SMTP服务器 - 如何检测CC& BCC收件人?

时间:2014-08-29 21:09:38

标签: delphi smtp indy10

我正在尝试使用Delphi帮助,Indy示例和Google开发SMTP中继服务器。

我刚刚开始并有一个虚拟SMTP客户端,它将测试消息发送到SMTP服务器,稍后将对其进行处理并使用SMTP中继转发它。

在服务器上,我为每位收件人收到一个OnRcpt(我使用一个To,一个CC和一个Bcc进行测试。

当我处理To并将CC转换为AMsg时,我也会在OnMsgReceive中看到AMsgTStringStream收件人(适当地加前缀)使用To:CC:),但我看不到BCC

问题:如何判断哪些地址为ToCCBCC


这是一些非常简单的代码。我正在设置断点&检查收到的参数,试图看看是什么东西

procedure TEmailMonitorMainForm.IdSMTPServerMsgReceive(ASender: TIdSMTPServerContext;
  AMsg: TStream; var VAction: TIdDataReply);
var
  LMsg : TIdMessage;
begin
  LMsg := TIdMessage.Create(Nil);
  LMsg.LoadFromStream(AMsg);
  LMsg.Free();   // breakpoint here  examine   Lmsg
end;         // IdSMTPServerMsgReceive()

[更新]当我发送,然后<message>.BCCList.Count = 1,但是当我收到时,它是0,而收到的CClist.Count是1,应该是。

1 个答案:

答案 0 :(得分:3)

  

在服务器上,我为每个收件人收到一个OnRcpt(我用一个To,一个CC和一个Bcc进行测试)。

SMTP协议不区分ToCCBCC收件人。这是电子邮件格式的工件,通过其To:Cc:标头(没有Bcc:标头,但TIdMessage.SaveToFile()创建了一个,因此TIdMessage.LoadFromFile()可以重新设置加载它)。当SMTP客户端向SMTP服务器发送电子邮件时,客户端会确定目标收件人并在服务器的单独RCPT TO命令中指定每个收件人(这是允许BCC工作的 - 但没有电子邮件本身中的Bcc:标头,但服务器为每个RCPT TO收件人提供了Bcc命令。 RCPT TO地址是TIdSMTPServer.OnRcptTo事件中指定的值,并在TIdSMTPServerContext.RCPTList属性中收集。这些地址由SMTP客户端明确请求,并且是您应该将电子邮件发送到的唯一地址(而不是电子邮件标头中指定的收件人)。

  

当我处理OnMsgReceive并将AMsg转换为TStringStream(适当地以To:和CC :)作为前缀时,我也看到AMsg中的To和CC收件人,但我没有看到BCC那里。

就SMTP服务器而言,实际的电子邮件本身只是任意数据。它旨在按原样交付给每个请求的收件人。这就是为什么电子邮件数据在TStream事件中以TIdSMTPServer.OnMsgReceive的形式提供的原因,以及为什么Indy 10中的TIdSMTPServer不会像在Indy中那样提供基于TIdMessage的事件9及更早。

如果电子邮件采用RFC 822/2822/5322格式(通常是这种格式),则会有To:Cc:个标头。接收/加载此类电子邮件到TIdMessage时,这些标头分别用于填写TIdMessage.RecipientsTIdMessage.CCList属性。但由于通常没有Bcc:标题(除非从TIdMessage.SaveToFile()创建的文件加载电子邮件),TIdMessage.BCCList将不会被填写。

  

如何判断哪些地址是To,CC和BCC?

由于SMTP协议本身不区分不同的收件人类型,因此区分它们的唯一方法是解析电子邮件,查看其To:Cc:标头。 TIdSMTPServerContext.RCPTList属性中不属于这两个标头之一的任何地址都必须是Bcc收件人。但是,无法保证TIdSMTPServerContext.RCPTList属性中的其他地址始终与To:Cc:标头匹配(尽管它们通常会匹配),因为从技术上讲,SMTP客户端可以发送任何原始它想要的数据和SMTP将按原样提供它,而不关心它实际包含的内容。

  

这里有一些非常简单的代码。

请勿使用TIdMessage.LoadFromStream()来解析TStream事件提供的TIdSMTPServer.OnMsgReceive对象!它并不总是正常工作。在Embarcadero和AToZed论坛中已经多次详细讨论了技术原因,例如this discussion。您需要暂时使用以下解决方法。这个问题将在Indy 11中解决:

procedure TEmailMonitorMainForm.IdSMTPServerMsgReceive(ASender: TIdSMTPServerContext; AMsg: TStream; var VAction: TIdDataReply);
var
  LMsg : TIdMessage;
  LClient: TIdMessageClient;
  LIO: TIdIOHandlerStreamMsg;
begin
  LMsg := TIdMessage.Create(Nil);
  try
    //LMsg.LoadFromStream(AMsg);    
    LClient := TIdMessageClient.Create;
    try
      LIO := TIdIOHandlerStreamMsg.Create(LClient, AMsg);
      LIO.FreeStreams := False;
      LIO.EscapeLines := True;
      LIO.Open;
      LClient.IOHandler := LIO;
      LClient.ProcessMessage(LMsg, False);
    finally
      LClient.Free;
    end;
    // now you can use LMsg as needed...
  finally
    LMsg.Free;
  end;
end;
相关问题