我正在尝试使用 Delphi 帮助、Indy 示例和 Google 开发 SMTP 中继服务器。
我刚刚开始,有一个虚拟 SMTP 客户端,它将测试消息发送到 SMTP 服务器,该服务器稍后将处理它并使用 SMTP 中继转发它。
在服务器上,我收到一个 OnRcpt
对于每个收件人(我使用一个 To
、一个 CC
和一个 Bcc
进行测试)。
我还看到了 To
和CC
AMsg
中的收件人当我处理OnMsgReceive
时并转换AMsg
到 TStringStream
(适本地以 To:
和 CC:
为前缀),但我没有看到 BCC
那里。
问题:如何判断哪些地址是 To
, CC
和BCC
?
这是一些非常简单的代码。我正在设置断点并检查收到的参数以尝试查看发生了什么
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,这是应该的。
最佳答案
At the server, I receive one OnRcpt for each recipient (I test with one To, one CC and one Bcc).
SMTP 协议(protocol)不区分收件人
、CC
和BCC
收件人。这是电子邮件格式的产物,通过其 To:
和 Cc:
header (没有 Bcc:
header ,尽管 TIdMessage .SaveToFile()
创建一个,以便 TIdMessage.LoadFromFile()
可以重新加载它)。当 SMTP 客户端将电子邮件发送到 SMTP 服务器时,客户端会确定预期的收件人,并在发送给服务器的单独的 RCPT TO 命令中指定每个收件人(这就是允许 BCC 的原因) > 工作 - 电子邮件本身没有 Bcc:
header ,但服务器会为每个 Bcc
收件人提供一个 RCPT TO
命令) 。 RCPT TO
地址是在 TIdSMTPServer.OnRcptTo
事件中指定的值,并收集在 TIdSMTPServerContext.RCPTList
属性中。这些地址是 SMTP 客户端明确请求的,并且是您应该将电子邮件发送到的唯一地址(而不是电子邮件 header 中指定的收件人)。
I also see the To and CC recipients in AMsg when I handle OnMsgReceive and convert AMsg to a TStringStream (suitably prefixed with To: and CC:), but I don't see the BCC there.
对于 SMTP 服务器而言,实际的电子邮件本身只是任意数据。它应按原样交付给每个请求的收件人。这就是为什么电子邮件数据在 TIdSMTPServer.OnMsgReceive
事件中作为 TStream
提供,以及为什么 Indy 10 中的 TIdSMTPServer
不提供 基于 TIdMessage
的事件,就像 Indy 9 及更早版本中所做的那样。
如果电子邮件位于 RFC 822/2822/5322格式(通常是这样),它将具有 To:
和 Cc:
header 。将此类电子邮件接收/加载到 TIdMessage
中时,这些 header 分别用于填充 TIdMessage.Recipients
和 TIdMessage.CCList
属性。但由于通常没有 Bcc:
header (除非电子邮件是从 TIdMessage.SaveToFile()
创建的文件加载的),因此 TIdMessage.BCCList
不会被填写。
how do I tell which addresses were To, CC and BCC?
由于 SMTP 协议(protocol)本身不区分不同的收件人类型,因此区分它们的唯一方法是解析电子邮件,查看其 To:
和 Cc:
header 。 TIdSMTPServerContext.RCPTList
属性中不属于这两个 header 之一的任何地址都必须是Bcc
收件人。但是,不能保证 TIdSMTPServerContext.RCPTList
属性中的其他地址始终与 To:
和 Cc:
header 匹配(尽管它们通常会),因为从技术上讲,SMTP 客户端可以发送它想要的任何原始数据,并且 SMTP 会按原样传送它,而不关心它实际包含的内容。
Here's some exceedingly simple code.
不要使用TIdMessage.LoadFromStream()
来解析TIdSMTPServer.OnMsgReceive
提供的TStream
对象事件!它并不总是能正常工作。技术原因已在 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;
关于delphi - Indy SMTP 服务器 - 如何检测 CC 和 BCC 收件人?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25576292/