Outlook VBA— Some MailItem Properties return value

2020-04-30 16:15发布

问题:

EDIT: New info: I just now realised that, while the return of Mailitem.Body is "", the actual value is "Application-defined or object-defined error" . I'm not entirely sure what that means, but I do know it shows up in multiple fields-- I included a screen shot below.

I am having an issue where certain properties will return the correct value, and others will not. I have an example email, where I have an email with subject "Subject", the message is "Body", the sender email address is "email@address.com", and the date sent is 12 June 2013.

When I run the following code:

    Dim ComputerName As String
    Dim ErrorState As String
For Each MailItem In InboxItems
        ComputerName = MailItem.Subject
        'ErrorState = MailItem.Body
        ErrorState = MailBody(MailItem)
        strDate = GetDate(MailItem.SentOn)
        SenderEmail = MailItem.SenderEmailAddress
        If strDate = DateToday And SenderEmail = "email@address.com" Then
            Computers(a, 0) = ComputerName
            Computers(a, 1) = ErrorState
            a = a + 1
        End If
        Debug.Print MailItem.Subject
        Debug.Print MailItem.Body
    Next MailItem

What I get is ComputerName = "Subject", ErrorState = "", SenderEmail = "", and strDate = "2013/6/12" (which is the proper format in this case). Why would this return proper values for two of the Mailitem properties, but not for two of the others? This is a very strange problem, and I would appreciate any help you all might be able to give!

I will add more of the context for the code here:

    Set objOutlook = CreateObject("Outlook.Application", "localhost")
    Set objNamespace = objOutlook.GetNamespace("MAPI")
    Set Inbox = GetFolder("email@address.org/inbox")
    Set InboxItems = Inbox.Items
    InboxItems.SetColumns ("SentOn")

GetFolder is a function to get the mailbox by folder path. I have to do this because I am not using the default inbox in outlook.

I also tried using the MailBody Function proposed below, in case the body were in an HTML or RTF format. Unfortunately, it proved that the body was normal, and MailItem.Body should have retrieved it, and it still is not working. MailItem.Body returns "", even though I know that the email has a body. The body is just the number 1, and that is what I should be getting.

Also, I should note that the sender of the email is the same as the recipient; in other words, the email was sent from one email address to itself. I don't know if this could make a difference, but I figured that I would put it out there just in case.

回答1:

Multiple Item Types

First, there is no guarantee that all items in the Inbox.Items collection are of type MailItem. Inboxes also contain AppointmentItem, MeetingItem, and other *Item type objects. Not all of these item types have the same properties populated. To ensure you do not get a type mismatch error, declare your iterator variable as a generic Object and only assign it to a strongly-typed MailItem variable if it is of the correct type:

Dim oInbox    As Outlook.Folder
Dim oItem     As Object
Dim oMailItem As MailItem

Set oInbox = ActiveExplorer.Session.DefaultStore.GetRootFolder().Folders("Inbox")
For Each oItem In oInbox.Items
    If TypeOf oItem Is MailItem Then
        Set oMailItem = oItem
        ' Do stuff
    Else
        Debug.Print "Skipping " & TypeName(oItem)
    End If
Next

Optional properties

Second, there is no gaurantee that all properties of an object will be populated. If a mail item was never sent, it will have no sender address, and certainly it is possible to have an email with no body. A good way to get familiar with which properties are available and what they contain is to use the Locals window (View > Locals Window in the VBA IDE). Here's a screen shot of the above code paused in the loop, with some of the properties of the oMailItem object expanded:

Body vs. HTMLBody

MailItem objects have three body properties: Body, HTMLBody, and RTFBody. Usually only one of them is populated. Which one depends on the format of the email. You can check the BodyFormat property to find which one is applicable to the current item. Using that, here's a generalized way to get the raw body of a MailItem, no matter what the format:

Public Function MailBody(ByVal MailItem As MailItem) As String
    Select Case MailItem.BodyFormat
        Case OlBodyFormat.olFormatPlain, OlBodyFormat.olFormatUnspecified
            MailBody = MailItem.Body
        Case OlBodyFormat.olFormatHTML
            MailBody = MailItem.HTMLBody
        Case OlBodyFormat.olFormatRichText
            MailBody = MailItem.RTFBody
    End Select
End Function