【问题标题】:RDOMail.Recipients Doesn't Contain BCC Address for Received UserRDOMail.Recipients 不包含接收用户的密件抄送地址
【发布时间】:2020-11-05 22:38:04
【问题描述】:

我正在处理代码库中的一个问题,我们希望提取 Outlook 收到的电子邮件的所有收件人。我知道如果收件人在密件抄送行,那封电子邮件的收件人不知道这些收件人,但如果 在密件抄送行上,您确实知道(它在电子邮件标题中)。所以我有一个看起来像这样的消息:

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。它不应该返回它知道的任何密件抄送地址吗?

示例代码(可能是一些语法错误,因为我正在简化实时代码):

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. 这让我相信我也可以将 Recipients 集合用于读取操作。

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

已更新解决方案

我最终使用了 Eugene 的答案,并将其与查看收到的电子邮件的 SMTP BCC 标头结合起来。仍然有一些情况(您在 BCC 标头上的内部电子邮件在 On-Prem Exchange 环境中可能根本不包含 SMTP 标头),但在这一点上,我认为它非常完整。所以对于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;
}

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

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

【问题讨论】:

    标签: c# outlook mapi outlook-redemption


    【解决方案1】:

    Outlook 对象模型(以及扩展 MAPI)在 Recipients 集合中不提供任何信息。在这种情况下,Count 属性返回 0。在扩展 MAPI 的情况下,IMessage::GetRecipientTable 方法返回一个空表。以下是 MSDN 的声明:

    IMessage::GetRecipientTable 方法返回一个指向邮件收件人表的指针,其中包含有关邮件所有收件人的信息。每个收件人都有一行。

    因此,兑换库中没有问题。

    根据我对收到的示例电子邮件进行的研究,该示例电子邮件在 Internet 标头中包含以下内容:

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

    在 OOM 的情况下,您可以使用 MailItem.ReceivedByName 属性返回一个字符串,该字符串表示邮件的真正收件人的显示名称。

    对于扩展 MAPI(Redemption 是此 API 的包装),您可以使用 PidTagReceivedRepresentingSmtpAddress 属性,该属性包含由接收邮箱所有者表示的用户的 SMTP 电子邮件地址。 DASL 属性名称是http://schemas.microsoft.com/mapi/proptag/0x5D08001F

    【讨论】:

      【解决方案2】:

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

      通常,当通过 SMTP 发送邮件时,服务器不会查看 MIME 标头以找出收件人。收件人由RCPT TO SMTP 命令确定。并且没有电子邮件客户端在传出消息中指定密件抄送标头 - 这将是一个错误。

      【讨论】:

      • 但如果您是密件抄送收件人,则您中。我的问题不是表明我在哪里打印了 SMTP 对话,并且您可以在标题中看到我自己的地址吗?
      • 密件抄送收件人将在您的“已发送邮件”文件夹中,但绝不会在您收件箱中收到的邮件中。
      猜你喜欢
      • 2018-04-07
      • 2015-01-23
      • 2013-08-15
      • 2013-10-08
      • 2018-07-14
      • 1970-01-01
      • 2011-11-20
      • 2021-12-15
      • 2017-01-03
      相关资源
      最近更新 更多