Outlook MailItem:如何区分邮件是传入还是传出?

发布于 2024-08-02 10:49:05 字数 283 浏览 2 评论 0原文

我正在用 C# 编写 VSTO Outlook 插件,我需要区分给定的 MailItem 是传入还是传出(或者两者都不是,例如当它是草稿时)。

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

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

谢谢你的想法:)

I am writing VSTO Outlook addin in C#, and I need to distinguish, whether given MailItem is incoming or outgoing (or neither, when it is for example a draft).

Is there some foolproof way to do this? Best solution I have now would be getting a list of recipients, cc's, and bcc's, loading email adresses from active accounts, and checking if those two lists intersect, but this seems quite fragile to me, and I hope that there is a better solution.

Use case: I'd like to get a relevant date for an email, which could be either ReceivedTime, or SentOn, but to know which one I should use, I beed to know whether a mail was sent or received.

Thank you for ideas :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

热血少△年 2024-08-09 10:49:05

来到这个页面是因为我在 VBA 中遇到了同样的问题。检查父文件夹很麻烦,因为一条消息可能保存在多个文件夹深处(因此您必须迭代多个文件夹),或者用户可能已更改该文件夹。一个极端的例子:已删除邮件文件夹包含传入和传出邮件项目。

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

奇怪的是,像检查邮件是传入还是传出这样看似简单的事情却会让我们犯错!

Came to this page because I was having same issue in VBA. Checking the parent folders is cumbersome, as a message can be held either several folders deep (and therefore you have to iterate up several folders) or the user may have changed the folder. An extreme example: the deleted items folder contains both incoming and outgoing mail items.

I have chosen a similar solution to another person (Adi Kini) above where I check the ReceivedByName (I think he chose ReceivedEntryID). The ReceivedByName property is always Null ("") for a sent message, wherever it currently lays. This method can find a sent item that has been dragged to the inbox!. It seems a fairly reliable method of checking.

It seems odd that such an apparently straightforward thing as checking whether mail is incoming or outgoing can trip us up!

牵你手 2024-08-09 10:49:05

我带着同样的问题来到这里。由于我将明确建议用户将邮件移动到我的用例中的某个文件夹,因此检查 Parent 不会有帮助...

关于 MailItem.Sent:您确定 MailItem.Sent 以这种方式工作吗?我刚刚编写了一个简单的代码来运行我的收件箱和已发送项目,并且几乎所有这些已发送都是 true。我认为这实际上只是表明邮件是否已发送(=不是草稿)...

I came here with the same problem. Since I will explicitly suggest that user moves the mail to some folder in my usecase, checking Parent would not help...

Regarding MailItem.Sent: are you sure that MailItem.Sent works this way? I just wrote a simple code to run through both my Inbox and SentItems and for almost all of them Sent is true. I assume this is really just an indication whether the mail has been sent (= is not draft)...

浮光之海 2024-08-09 10:49:05

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

I resolved this problem by adding a new UserProperty after e-mail was sent. So when I need to check if e-mail was sent I check this property. This works even if e-mail was moved out of Sent folder. Of course, this works only for newly created e-mails, but you may add this property to all e-mails in Sent folder during first start. The only bug is that UserProperties are printed by default, but this can be overridden.

七颜 2024-08-09 10:49:05

这就是我检查邮件类型的方法,即使邮件被移动到任何文件夹,它也能工作。该解决方案使用 Outlook 2007 中提供的 PROPERTY ACCESSOR。下面是代码

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
}

This is how I check mail type and it works even if mail is moved to any folder. This solution uses PROPERTY ACCESSOR which is available in outlook 2007. Below is the code

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
}
千仐 2024-08-09 10:49:05

MailItem.sent 对于传入也是如此。

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

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

MailItem.sent is true for incoming too.

How about checking MailItem.ReceivedByEntryID. But i am sure this will fail (ReceivedByEntryID will be null for mails in inbox) if you say import from outlook express or maybe some other email program

Iterating thru mail accounts/senderemail may help as you said, but its not fool proof (like if you rename the email address)

一曲琵琶半遮面シ 2024-08-09 10:49:05

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

Take a look at the MailItem's .Parent property - examine the folder properties to determine if it is the inbox, outbox, drafts, sent items, etc.

别闹i 2024-08-09 10:49:05

您可以检查它是否位于 Outlook.OlDefaultFolders.olFolderInboxolFolderOutbox 内,然后您应该可以使用其他方法来检查它是否位于这些文件夹中!

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

You can check if it's inside the Outlook.OlDefaultFolders.olFolderInbox or olFolderOutbox, then there should be other methods you can use to check if it's inside either of these folders!

Outlook.Application _application = new Outlook.Application();
Outlook.MAPIFolder folder = _application.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
烟火散人牵绊 2024-08-09 10:49:05

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

For a simple sended/received control by SMTP address, i suggest an address-check approach.
It can be done in this way:

'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
潇烟暮雨 2024-08-09 10:49:05

我反对 SenderName 与 CurrentUser,以区分收件箱或已发送文件夹中的电子邮件。

输入图片此处描述

I contradict SenderName vs CurrentUser, to distinguish between emails in inbox or sent folder.

enter image description here

黎夕旧梦 2024-08-09 10:49:05

您尝试过 MailItem.Sent 属性吗?

传入时为 true,传出时为 false。

Did you try MailItem.Sent property?

Its true for incoming, and false for outgoing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文