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.
hi
would you explain how this cod can be called?
thanks
In the function header I give an example
Or, the version I prefer myself
Call Outlook_OpenEmail("000000004829439D8D28C14BAA8D1C72F0D28EA6E4552500")Or say you stored the values in a table field
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?
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?
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), …
Thanks for the reply,
I used the restist method to find the message I’m interested in by looking for a unique code inside the object.
source
https://learn.microsoft.com/en-us/office/vba/api/outlook.items.restrict
Yes, that’s how I probably would have approached the issue as well. I wrote a post on that a couple years ago: VBA – Search Outlook Emails/Items. Once you understand the basics it is a very powerful technique.