C# Outlook邮件项目:如何区分邮件是传入的还是传出的?

C# Outlook邮件项目:如何区分邮件是传入的还是传出的?,c#,outlook,vsto,mailitem,C#,Outlook,Vsto,Mailitem,我正在用C#向Outlook加载项编写VST,我需要区分给定的邮件项是传入的还是传出的(或者两者都不是,例如,当它是草稿时) 有什么万无一失的方法吗?我现在拥有的最好的解决方案是获取收件人、抄送人和密件抄送人的列表,从活动帐户加载电子邮件地址,并检查这两个列表是否相交,但这对我来说似乎很脆弱,我希望有更好的解决方案 用例:我想获得一封电子邮件的相关日期,可以是ReceivedTime,也可以是SentOn,但要知道我应该使用哪一个日期,我需要知道是否发送或接收了一封邮件 感谢您的建议:)查看邮件

我正在用C#向Outlook加载项编写VST,我需要区分给定的邮件项是传入的还是传出的(或者两者都不是,例如,当它是草稿时)

有什么万无一失的方法吗?我现在拥有的最好的解决方案是获取收件人、抄送人和密件抄送人的列表,从活动帐户加载电子邮件地址,并检查这两个列表是否相交,但这对我来说似乎很脆弱,我希望有更好的解决方案

用例:我想获得一封电子邮件的相关日期,可以是ReceivedTime,也可以是SentOn,但要知道我应该使用哪一个日期,我需要知道是否发送或接收了一封邮件


感谢您的建议:)

查看邮件项目的.Parent属性-检查文件夹属性以确定它是否是收件箱、发件箱、草稿、已发送邮件等。

您是否尝试了MailItem.sent属性


传入为true,传出为false。

我带着同样的问题来到这里。因为我将明确建议用户将邮件移动到我的用例中的某个文件夹中,所以检查父项将不会有帮助


关于MailItem.Sent:您确定MailItem.Sent是这样工作的吗?我只是写了一个简单的代码来运行我的收件箱和sentitem,几乎所有发送的都是真的。我假设这实际上只是指示邮件是否已发送(=不是草稿).

MailItem.sent对于传入邮件也是如此

检查MailItem.ReceivedByEntryID怎么样。但我确信,如果您说从outlook express或其他电子邮件程序导入,则此操作将失败(对于收件箱中的邮件,ReceivedByEntryID将为空)


正如您所说,通过邮件帐户/senderemail进行迭代可能会有所帮助,但这并不是万无一失的(比如重命名电子邮件地址)

您可以检查它是否在
Outlook.OlDefaultFolders.olFolderInbox
olFolderOutbox
中,然后应该有其他方法可以用来检查它是否在这些文件夹中

Outlook.Application _application = new Outlook.Application();
Outlook.MAPIFolder folder = _application.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

我通过在电子邮件发送后添加一个新的UserProperty解决了这个问题。因此,当我需要检查电子邮件是否已发送时,我会检查此属性。即使电子邮件已从“已发送”文件夹中移出,也可以使用此功能。当然,这只适用于新创建的电子邮件,但您可以在第一次启动时将此属性添加到Sent文件夹中的所有电子邮件中。唯一的错误是默认情况下会打印UserProperties,但这是可以的。

这是我检查邮件类型的方式,即使邮件移动到任何文件夹,它也会工作。此解决方案使用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
}

来到本页是因为我在VBA中遇到了相同的问题。检查父文件夹很麻烦,因为一封邮件可能存放在多个文件夹中(因此您必须遍历多个文件夹),或者用户可能更改了文件夹。一个极端的例子:deleted items文件夹包含传入和传出邮件

我已经为上面的另一个人(Adi Kini)选择了一个类似的解决方案,在这里我检查了ReceivedByName(我想他选择了ReceivedEntryID)。已发送消息的ReceivedByName属性始终为Null(“”),无论其当前位于何处。此方法可以找到已拖到收件箱的已发送项目!。这似乎是一种相当可靠的检查方法


奇怪的是,像检查邮件是收到还是发出这样一件看似简单的事情会让我们绊倒

对于通过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

但是,如果用户(或邮件过滤规则)已经将邮件移动到某个通用文件夹(例如,项目XYZ的文件夹),同时包含传入和传出的电子邮件,该怎么办?在这种情况下,传入/传出将是特定于电子邮件的属性,而不是特定于文件夹的属性。好主意,但我没有想到:)。这是一个很好的问题。我没有一个上帝的答案。你必须检查所有的收件人,抄送等,还是你可以只看发件人?如果帐户所有者没有发送它,那么它是传入的。不是所有收到的邮件都已经发送了吗?我认为这对已移动到另一个文件夹(例如带有过滤器)的已发送/已接收邮件不起作用-是吗?不,请看David的回答这是一个非常重要的解决方案,但可能只有一个在这里可以起作用。然而,插件必须一直运行——否则我们会收到一封未标记的电子邮件——并且必须在第一次启动时运行。我们将无法标记已移动到其他文件夹的已发送电子邮件。也许可以扫描所有邮件,查看收件人是否是用户的电子邮件地址之一,但这可能需要在大型exchange/IMAP帐户上花费数小时…谢谢!这可能适用于大多数用户,因为我不认为许多企业用户会从Outlook Expres导入他们的电子邮件(即使他们这样做了,大多数有用的操作仍然只涉及Outlook接收的最新邮件)。请注意,如果邮件项目由指定了地址的公用文件夹接收,则
ReceivedByName
ReceivedEntryID
都不会有值。适用于exchange邮件帐户,但不适用于imap/smtp-使用ol 2016测试