简体   繁体   中英

Accessing the ‘Body’ of an Outlook email from Excel VBA

The following code stopped working after upgrading from Office 2010 on W7 to Office 365 on W10.

Sub readbodytest()

    Dim OL As Outlook.Application
    Dim DIB As Outlook.Folder
    Dim i As Object 'Outlook.ReportItem
    Dim Filter As String

    Set OL = CreateObject("Outlook.Application")
    Set DIB = OL.Session.GetDefaultFolder(olFolderInbox)

    Const PR_SENT_REPRESENTING_EMAIL_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x0065001E"
    Filter = "@SQL=" & _
        """" & PR_SENT_REPRESENTING_EMAIL_ADDRESS & """ ci_phrasematch 'mailer-daemon' OR " & _
        """" & PR_SENT_REPRESENTING_EMAIL_ADDRESS & """ ci_phrasematch 'postmaster' OR " & _
        "urn:schemas:httpmail:subject ci_phrasematch 'undeliverable' OR " & _
        "urn:schemas:httpmail:subject ci_phrasematch 'returned'"
    For Each i In DIB.Items.Restrict(Filter)
        Debug.Print i.Body '<< Code fails here
    Next

    Set i = Nothing
    Set DIB = Nothing
    Set OL = Nothing
End Sub

It returns a runtime error -2147467259 “Method 'Body' of object '_MailItem' failed”

The code will work when run directly in outlook VBA, but not when run externally.

The purpose of the code was to do a bulk review of returned mail items, match information in the Body of the email to a record on a database, and update the database to record the failure.

Looking to see if anyone has any suggestions before I just re-write the code to run in reverse (eg from Outlook VBA to the database; instead of the database trying to retrieve it from Outlook)

It makes sense to use the Logon method of the Application class which logs the user on to MAPI, obtaining a MAPI session. Here is what MSDN says:

Use the Logon method only to log on to a specific profile when Outlook is not already running. This is because only one Outlook process can run at a time, and that Outlook process uses only one profile and supports only one MAPI session. When users start Outlook a second time, that instance of Outlook runs within the same Outlook process, does not create a new process, and uses the same profile.

If Outlook is not running and you only want to start Outlook with the default profile, do not use the Logon method. A better alternative is shown in the following code example, InitializeMAPI: first, instantiate the Outlook Application object, then reference a default folder such as the Inbox. This has the side effect of initializing MAPI to use the default profile and to make the object model fully functional.

Second, I'd suggest checking the item type before accessing any properties. Not all items may contain such properties.

Another possible pitfall and most probably that is a security issue when dealing with the Outlook object model. When you try to access any sensitive property Outlook may trigger a security issue (it may be an error in the code or UI guard/prompt). "Security" in this context refers to the so-called "object model guard" that triggers security prompts and blocks access to certain features in an effort to prevent malicious programs from harvesting email addresses from Outlook data and using Outlook to propagate viruses and spam. You can use the following ways to bridge the gap:

  1. The Security Manager for Outlook component allows to turn prompts off/on at runtime.

  2. Use the low-level code which doesn't generate security prompts. Or any other third-party wrappers around that API (for example, Redemption).

  3. Deploy a group policy to avoid security prompts.

  4. Running an up-to-date antivirus software.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM