VBA – Retrieve an Outlook Message/Item

I was answering a question to my post VBA – Extract Outlook E-mail Messages where Tom asked a straightforward question

OK so using your code I can store email properties, contents etc.

 

Now I want to be able to instruct Outlook to open one of the emails whose properties I have stored in my Access database. By ‘open’ I mean the equivalent of double-clicking the email in an Outlook folder.

 

Using your code ‘ For Each oPrp In .ItemProperties’ I wrote all of the 90 property/value pairs to a table. There are ‘oPrp.Name’s like ConversationIndex, EntryID, ConversationID which I suspect can be used to reference the exact email in Outlook. But how?

Once again, I thought I’d share my reply and code so it can benefit everyone.

The key to pretty much anything Outlook related is the EntryId property. This property uniquely identifies each item in Outlook: Mail items, Appointment items, … So as long as you grab this piece of information and store it, you can then retrieve the item at a later point in time (assuming the item isn’t deleted or otherwise modified so a new EntryId is generated).

So the question then becomes:

How can I retrieve a specific Outlook EntryId Item?

You might be tempted to loop through a folder’s items, or use a Restrict search, but luckily for us, Outlook has the GetItemFromID method designed expressly for this very purpose!

Thus, we can then put togther a very simple function, such as

'---------------------------------------------------------------------------------------
' Procedure : Outlook_OpenEmail
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Locate and open an Item based on its EntryId
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sEntryId - The EntryId of the Outlook Item to locate and display to the user
'
' Usage:
' ~~~~~~
' Outlook_OpenEmail "000000004829439D8D28C14BAA8D1C72F0D28EA6E4552500"
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2019-08-19              Initial Release (Blog help)
'---------------------------------------------------------------------------------------
Function Outlook_OpenEmail(ByVal sEntryId As String)
'REF: https://docs.microsoft.com/en-us/office/vba/api/outlook.namespace.getitemfromid
'    #Const EarlyBind = 1 'Use Early Binding
    #Const EarlyBind = 0    'Use Late Binding
    #If EarlyBind Then
        Dim oOutlook          As Outlook.Application
        Dim oOutlookMsg       As Outlook.MailItem
    #Else
        Dim oOutlook          As Object
        Dim oOutlookMsg       As Object
    #End If

    On Error Resume Next
    Set oOutlook = GetObject(, "Outlook.Application")        'Bind to existing instance of Outlook
    If Err.Number <> 0 Then        'Could not get instance, so create a new one
        Err.Clear
        Set oOutlook = CreateObject("Outlook.Application")
    End If
    On Error GoTo Error_Handler

    Set oNameSpace = oOutlook.GetNamespace("MAPI")
    'Find the item, if not found it generates a -2147221233 error
    Set oOutlookMsg = oNameSpace.GetItemFromID(sEntryId) 
    'Open/Display the item to the user
    oOutlookMsg.Display 

Error_Handler_Exit:
    On Error Resume Next
    If Not oOutlookMsg Is Nothing Then Set oOutlookMsg = Nothing
    If Not oOutlook Is Nothing Then Set oOutlook = Nothing
    Exit Function

Error_Handler:
    If Err.Number = "287" Then
        MsgBox "You clicked No to the Outlook security warning. " & _
               "Rerun the procedure and click Yes to access e-mail " & _
               "addresses to send your message. For more information, " & _
               "see the document at http://www.microsoft.com/office" & _
               "/previous/outlook/downloads/security.asp."
    ElseIf Err.Number = -2147221233 Then
        MsgBox "Outlook item not found.", vbInformation + vbOKOnly
    Else
        MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
               "Error Number: " & Err.Number & vbCrLf & _
               "Error Source: Outlook_OpenEmail" & vbCrLf & _
               "Error Description: " & Err.Description & _
               Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
               , vbOKOnly + vbCritical, "An Error has Occurred!"
    End If
    Resume Error_Handler_Exit
End Function

One last precision. I entitled my function …OpenEmail, but it is not limited/restricted to e-mails in reality. It truly should be entitled …OpenItem as it can be used to open any Outlook item (e-mail, appointment, task, …) as long as you supply a valid EntryId.

Important
The EntryId can change! You read that right. The EntryId will change if the message is moved to a different folder, … so it is unique and dependable as long as you don’t touch the item! Otherwise you may need to perform more generalized search to find what you are looking for in which case you may like to review:

7 responses on “VBA – Retrieve an Outlook Message/Item

    1. Daniel Pineault Post author

      In the function header I give an example

      Outlook_OpenEmail "000000004829439D8D28C14BAA8D1C72F0D28EA6E4552500"

      Or, the version I prefer myself

      Call Outlook_OpenEmail("000000004829439D8D28C14BAA8D1C72F0D28EA6E4552500")

      Or say you stored the values in a table field

      Call Outlook_OpenEmail(rs![OutlookEntryId])
  1. Mario

    L’ho provata e mi restituisce “Outlook item not found.”
    Il messaggio che cerco però è presente nella cartella outlook posta inviata
    come parametro EntryID gli passo la stringa che identifica il messaggio che ho salvato in una tabella in fase di creazione del messaggio eseguendo .save

    Quale potrebbe essere il motivo per cui non trova il messaggio? forse il codice EntryID assegnato in fase di creazione cambia quando il messaggio viene spostato in posta inviata? se cosi fosse come potrei risalire al nuovo EntryID?

  2. Mario

    English translation of my message:

    I tried it and it returns “Outlook item not found.”
    However, the message I am looking for is present in the Outlook Sent folder
    as the EntryID parameter I pass the string that identifies the message that I saved in a table when creating the message by executing .save

    What could be the reason why he can’t find the message? maybe the EntryID code assigned during creation changes when the message is moved to sent mail? if so how could I trace the new EntryID?

    1. Daniel Pineault Post author

      The EntryId can change if, for instance if the item is moved. It’s a real pain and something I’ve never understood the reason for. So sometimes it may be better to locate an item by date/time, subject, sender, recipient(s), …