RDOMail.Recipients 不包含已接收用户的 BCC 地址

RDOMail.Recipients Doesn't Contain BCC Address for Received User

我正在处理我们代码库中的一个问题,我们想要提取 Outlook 收到的电子邮件的所有收件人。我知道如果收件人在密件抄送线上,则该电子邮件的收件人不知道这些收件人,但如果在密件抄送线上,你确实知道(它在电子邮件 headers)。所以我有一条看起来像这样的消息:

From: FirstName LastName<name1@host1.tld>
Date: Thu, 16 Jul 2020 09:48:10 +0100
Message-ID: <CAE+EE4GS7RtDKgPGOUbTFQ3=7i9+QiKB++1cx7qqLd_09PRZFg@mail.gmail.com>
Subject: Testing
To: undisclosed-recipients:;
Bcc: name2@host2.tld
Content-Type: multipart/alternative; 

使用 Redemption RDOMail.Recipients,我希望它有一个项目,并且它将是 name2@host2.tld(因为这是我所掌握的关于这封电子邮件收件人的所有信息)。当我实际遍历收件人时,我得到的计数为 0。它不应该 return 它知道的任何密件抄送地址吗?

示例代码(可能是一些语法错误,因为我只是简单地使用实时代码):

public IEnumerable<string> GetRecipients(RDOMail mailItem)
{
  var recipients = mailItem.Recipients;
  for (var i = 0; i < recipients.Count; i++) // never enters as Count == 0
  {
    var recipient = recipients[i];
    var smtpAddress = GetSmtpAddress(recipient);
    yield return smtpAddress;
  }
}

RDOMail 有密件抄送属性,但收到的邮件也是空白。 documentation 确实注意到:This property contains the display names only. The Recipients collection should be used to modify the BCC recipients. 这让我相信我也可以使用收件人 collection 进行读取操作。

是的,我意识到我可能能够假设如果当前地址不在 TO 或 CC 行,它在 BCC 行。但这不适用于共享邮箱......或者更确切地说,我必须进行大量挖掘才能了解收到的邮件来自何处才能做出正确的假设。

更新了解决方案

我最终使用了 Eugene 的回答,并将其与查看 SMTP BCC header 以获取收到的电子邮件相结合。仍然存在一些情况(您在 BCC header 上的内部电子邮件在 On-Prem Exchange 环境中可能根本不包含 SMTP header),但在这一点上,我认为它非常完整。所以我仍然使用上面的代码 GetRecipients(RDOMail mailItem),但是在我这样做之后,我还调用:

一些常量

public const string PR_TRANSPORT_MESSAGE_HEADERS = "http://schemas.microsoft.com/mapi/proptag/0x007D001F"
public const string PID_TAG_RECEIVED_REPRESENTING_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x5D08001F"

测试收件人是否在密件抄送中

private bool IsReceiverInBcc(RDOMail mailItem)
{
  if (mailItem == null) return false;
  
  var receiver = ConvertReceiverToContact(mailItem);
  var messageHeaders = mailItem.Fields(Consts(PR_TRANSPORT_MESSAGE_HEADERS)?.ToString();
  
  if (!string.IsNullOrWhiteSpace(messageHeaders)
  {
    var bccHeaderRegex = new Regex($"{Environment.NewLine}Bcc: .*{Environment.NewLine}", RegexOptions.IgnoreCase);
    
    foreach (Match headerMatch in bccHeaderRegex.Matches(messageHeaders))
    {
      if (headerMatch?.Value?.IndexOf(receiver.address, CompareOptions.IgnoreCase) >= 0
      {
        return true;
      }
    }
  }
  
  return false;
}

从密件抄送中提取当前用户header

private EmailContact ConvertReceiverToContact(RDOMail mailItem)
{
  var contact = new EmailContact
  {
    Address = mailItem.Fields(Consts.PID_TAG_RECEIVED_REPRESENTING_SMTP_ADDRESS),
    Name = mailItem.ReceivedByName
  };
  
  return contact;
}

Outlook object 模型(以及扩展 MAPI)在 Recipients collection 中不提供任何信息。本场景中的 Count 属性 returns 0。在扩展 MAPI 的情况下,IMessage::GetRecipientTable 方法 returns 一个空的 table。以下是 MSDN 的内容:

The IMessage::GetRecipientTable method returns a pointer to the message's recipient table, which includes information about all of the recipients for the message. There is one row for every recipient.

因此,Redemption 库中没有任何问题。

根据我对在互联网上收到的包含以下内容的示例电子邮件进行的研究header:

To: undisclosed-recipients:;
Bcc: eugene@somedomain.com

在 OOM 的情况下,您可以使用 MailItem.ReceivedByName 属性 其中 returns 表示邮件消息真实收件人显示名称的字符串。

在扩展 MAPI 的情况下(兑换是围绕此 API 的包装),您可以使用包含 SMTP 电子邮件地址的 PidTagReceivedRepresentingSmtpAddress 属性接收邮箱所有者代表的用户。 DASL 属性 名称是 http://schemas.microsoft.com/mapi/proptag/0x5D08001F

不,即使是 BCC 收件人也不会出现在 BCC 中 header。您可以在以 MIME 格式保存时生成 BCC header,但它不会出现在从 POP3 或 IMAP4 服务器接收的邮件中。

通常,当通过 SMTP 发送邮件时,服务器不会查看 MIME headers 来确定收件人。收件人由 RCPT TO SMTP 命令确定。并且没有电子邮件客户端在外发邮件中指定 BCC header - 这将是一个错误。