我正在用 C# 编写 VSTO Outlook 插件,我需要区分给定的 MailItem 是传入还是传出(或者两者都不是,例如草稿时)。
有什么万无一失的方法吗?我现在拥有的最佳解决方案是获取收件人、抄送和密件抄送列表,从活动帐户加载电子邮件地址,并检查这两个列表是否相交,但这对我来说似乎很脆弱,我希望有更好的解决方案.
用例:我想获得一封电子邮件的相关日期,可以是 ReceivedTime 或 SentOn,但要知道我应该使用哪个日期,我需要知道邮件是已发送还是已接收。
谢谢你的想法:)
来到这个页面是因为我在 VBA 中遇到了同样的问题。检查父文件夹很麻烦,因为消息可以保存在多个文件夹深处(因此您必须迭代多个文件夹)或者用户可能已经更改了文件夹。一个极端的例子:deleted items 文件夹包含传入和传出的邮件项目。
我选择了与上面另一个人(Adi Kini)类似的解决方案,我在上面检查了 ReceivedByName(我认为他选择了 ReceivedEntryID)。对于已发送的消息,ReceivedByName 属性始终为 Null (""),无论它当前位于何处。此方法可以找到已被拖到收件箱的已发送邮件!这似乎是一种相当可靠的检查方法。
奇怪的是,像检查邮件是传入还是传出这样一个看似简单的事情却能把我们绊倒!
我带着同样的问题来到这里。由于我会明确建议用户将邮件移动到我的用例中的某个文件夹,因此检查 Parent 将无济于事......
关于 MailItem.Sent:您确定 MailItem.Sent 以这种方式工作吗?我刚刚编写了一个简单的代码来运行我的收件箱和 SentItems,几乎所有的 Sent 都是真的。我认为这实际上只是表明邮件是否已发送(= 不是草稿)...
这就是我检查邮件类型的方式,即使将邮件移动到任何文件夹也能正常工作。此解决方案使用 Outlook 2007 中提供的属性访问器。下面是代码
string PR_MAIL_HEADER_TAG = "http://schemas.microsoft.com/mapi/proptag/0x007D001E";
Outlook.PropertyAccessor oPropAccessor = mItemProp.PropertyAccessor;
string strHeader = (string)oPropAccessor.GetProperty(PR_MAIL_HEADER_TAG);
if (strHeader == "")
{
// MAIL IS OF TYPE SENTBOX
}
else
{
// MAIL IS OF TYPE INBOX
}
我通过在发送电子邮件后添加新的 UserProperty 解决了这个问题。因此,当我需要检查是否发送了电子邮件时,我会检查此属性。即使将电子邮件移出“已发送”文件夹,此操作也有效。当然,这仅适用于新创建的电子邮件,但您可以在首次启动时将此属性添加到已发送文件夹中的所有电子邮件。唯一的错误是默认情况下会打印 UserProperties,但这可以被覆盖。
MailItem.sent 也适用于传入。
检查 MailItem.ReceivedByEntryID 怎么样。但我确信如果您说从 Outlook Express 或其他电子邮件程序导入,这将失败(对于收件箱中的邮件,ReceivedByEntryID 将为空)
正如您所说,通过邮件帐户/发件人电子邮件进行迭代可能会有所帮助,但它不是万无一失的(例如,如果您重命名电子邮件地址)
您可以检查它是否在Outlook.OlDefaultFolders.olFolderInboxor内olFolderOutbox,然后应该有其他方法可以用来检查它是否在这些文件夹中!
Outlook.Application _application = new Outlook.Application();
Outlook.MAPIFolder folder = _application.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
查看 MailItem 的 .Parent 属性 - 检查文件夹属性以确定它是否是收件箱、发件箱、草稿、已发送邮件等。
对于通过 SMTP 地址进行的简单发送/接收控制,我建议使用地址检查方法。可以通过以下方式完成:
'Get mail address sender
Dim mailSender As String = GetSenderSMTPAddress(outMailItem)
'Get current user mail address
Dim mailUser As String = OutlookMail2DocScriba.GetUserSMTPAddress(oNameSpace.CurrentUser.AddressEntry)
'If sender and current user matches is a sended mail, otherwise received
If String.Compare(mailSender, mailUser, True) = 0 Then
Return "Sended"
Else
Return "Received"
End If
Public Shared Function GetSenderSMTPAddress(ByVal mail As Outlook.MailItem) As String
'http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.oladdresslisttype.aspx
If mail Is Nothing Then
Throw New ArgumentNullException()
End If
If mail.SenderEmailType = "EX" Then
Dim sender As Outlook.AddressEntry = Nothing
Try
sender = mail.Sender
Catch ex As Exception
'Se non è stato in grado di reperire il sender (Outlook 2007),
'ignoro l'eccezione e procedo.
End Try
If sender IsNot Nothing Then
Return GetUserSMTPAddress(sender)
Else
Return Nothing
End If
Else
Return mail.SenderEmailAddress
End If
End Function
Public Shared Function GetUserSMTPAddress(ByVal sender As Outlook.AddressEntry) As String
'Now we have an AddressEntry representing the Sender
'http://msdn.microsoft.com/en-us/library/office/ff868214(v=office.15).aspx
Const EXCHANGE_USER_ADDRESS_ENTRY As Int32 = 0
Const EXCHANGE_REMOTE_USER_ADDRESS_ENTRY As Int32 = 5
Dim PR_SMTP_ADDRESS As String = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
If sender.AddressEntryUserType = EXCHANGE_USER_ADDRESS_ENTRY OrElse _
sender.AddressEntryUserType = EXCHANGE_REMOTE_USER_ADDRESS_ENTRY Then
'Use the ExchangeUser object PrimarySMTPAddress
Dim exchUser As Object = sender.GetExchangeUser()
If exchUser IsNot Nothing Then
Return exchUser.PrimarySmtpAddress
Else
Return Nothing
End If
Else
Return TryCast(sender.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS), String)
End If
End Function
您是否尝试过 MailItem.Sent 属性?
传入为真,传出为假。