Outlook Address Book – complete guide for developers
I bet if we surveyed most users of Outlook (the non-developer kind of users) and asked them why Outlook exists, they’d respond by saying, “email”. They’d be correct of course. But they wouldn’t be fully correct. Email is front and center but Outlook wouldn’t be anything without Contacts.
Almost everything you do in Outlook involves a contact. Email, appointments, address book all involve contacts (aka people… people you know). Tasks are more of a personal thing but you can assign them to others so lay off! Tasks involve people too even if the only “people” is you.
Because contacts are important, knowing how to use them in your Outlook solutions is a key skill. Today, you and I will cover Outlook’s address book… complete with VB.NET code samples and just enough explaining.
- What is the Outlook Address Book
- Address Book code samples
- How to access the Outlook Address Book
- How to enumerate folders & new Outlook address book entries
- How to enumerate items & edit contact items
- How to remove an address book item
- How to move a ContactItem to another folder
- How to forward a business card
- Display an address book entry (aka a Contact)
- Set a reminder to contact a Contact
- Responding to Items collection event
- Take action before moving an address book item
What is the Outlook Address Book
Out-of-the-box, Outlook’is address book is the default contacts folder that resides in a user’s Outlook folder structure. In a typical Outlook installation, there is a single contacts folder and feeds the TO, CC, BCC fields in the Outlook email form. In any form that supports assigning a contact to it, the default address book feeds it as well.
When the user clicks an address field like the TO, the address book dialog form displays. Here you will see the contacts listed in your contacts folder. If connected to Exchange or other directory providers, these address books will also display contacts available via the LDAP directory.
Today, we are not concerned with the LDAP directory. We are dealing only with the default Outlook address book. And according to the Outlook object model, that directory is the contacts directory… as you will soon see in the code samples.
Address Book code samples
From here until I stop typing, we’ll take a brisk walk through code samples worth stealing for your own purposes. I’ll start at the beginning and see where it goes.
How to access the Outlook Address Book
To gain a reference to the default address book, you need to reference the default contacts folder.
Private Function GetDefaultAddressBook() As Outlook.MAPIFolder Dim ns As Outlook._NameSpace = Me.OutlookApp.GetNamespace("MAPI") If ns IsNot Nothing Then Try Return ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts) Finally Marshal.ReleaseComObject(ns) End Try End If Return Nothing End Function
This task is trivial as the GetDefaultAddressBook function shows. You don’t need to make a function like I did as you can always call the GetDefaultFolder function via the OutlookApp.Session object. I made this function so I can use it in subsequent code samples and make them pithy.
How to enumerate folders & new Outlook address book entries
It stands to reason you will want to enumerate objects within the default address book. The EnumerateAddressBookFolders procedure shows how. What it does is add a new contact to each folder as it does its enumerating.
Private Sub EnumerateAddressBookFolders() Dim ab As Outlook.MAPIFolder = GetDefaultAddressBook() Dim fldrs As Outlook.Folders = ab.Folders For i = 1 To fldrs.Count Dim folder As Outlook.MAPIFolder = fldrs(i) Dim folderItems As Outlook._Items = folder.Items Dim contact As Outlook.ContactItem = _ folderItems.Add(Outlook.OlItemType.olContactItem) With contact .FirstName = "John" .LastName = "Doe" .Email1Address = "john.doe@interweb.com" .PrimaryTelephoneNumber = "+12125551212" .Save() End With Marshal.ReleaseComObject(contact) Marshal.ReleaseComObject(folderItems) Marshal.ReleaseComObject(folder) Next Marshal.ReleaseComObject(fldrs) Marshal.ReleaseComObject(ab) End Sub
I know the sample is generic but it serves my purposes here to illustrate how to rummage around the folders and how to add a new contact. Just be sure to save that new contact or he (or she) will never really exist.
How to enumerate items & edit contact items
With a folder in-hand, you will run across scenarios that require you to look inside that folder’s items and edit those items. The EnumerateABItems procedure edits each item in the default Outlook address book and adds a note to it.
Private Sub EnumerateABItems() Dim ab As Outlook.MAPIFolder = GetDefaultAddressBook() Dim abItems As Outlook._Items = ab.Items For i = 1 To abItems.Count Dim objItem As Object = abItems(i) Dim con As Outlook._ContactItem = TryCast(objItem, Outlook._ContactItem) If con IsNot Nothing Then con.Body = con.Body & vbCrLf & "Enumerated: " & Now.Date con.Save() End If Marshal.ReleaseComObject(objItem) Next Marshal.ReleaseComObject(abItems) Marshal.ReleaseComObject(ab) End Sub
It’s nothing major but I hope you see the main points. When enumerating, don’t use a FOR… EACH loop as they are bad for business in Outlook development. Instead, FOR… NEXT along with the item count. Next, access each item and change properties as you see fit. Oh… be sure to save it too.
How to remove an address book item
Here is a simple strategy for deleting a contact in the Outlook address book. In this sample, the code loops through the default address book items in search a specific email address (John Doe). If found, the code deletes that contact.
Private Sub DeleteJohnDoe(email As String) Dim ab As Outlook.MAPIFolder = GetDefaultAddressBook() Dim abItems As Outlook._Items = ab.Items For i = abItems.Count To 1 Step -1 Dim objItem As Object = abItems(i) Dim contact As Outlook._ContactItem = TryCast(objItem, Outlook._ContactItem) If contact IsNot Nothing Then If contact.Email1Address = email Then contact.Delete() End If Marshal.ReleaseComObject(objItem) Next Marshal.ReleaseComObject(abItems) Marshal.ReleaseComObject(ab) End Sub
How to move a ContactItem to another folder
Sometimes, you might need to move a contact to different Outlook folder. This is easy.
Private Sub MoveContact(ByRef contact As Outlook._ContactItem, _ ByRef folder As Outlook.MAPIFolder) contact.Move(folder) End Sub
The MoveContact procedure accepts a contact and a folder as parameters. Which is all you need. You need a contact so you call its Move function. When calling the Move function, you need to pass the target folder object and voila! Contact moved.
How to forward a business card
I think this method is underexposed and underappreciated. This sample code accepts an email address as a search string. If a contact exists with the email, the code creates a new email and inserts the contacts business card within it.
Private Sub ForwardContact(contactEmail As String) Dim contacts As Outlook.MAPIFolder = GetDefaultAddressBook() Dim contactsItems As Outlook._Items = contacts.Items Dim query As String = "[Email1Address]='" & contactEmail & "'" query = query & " OR [Email2Address]='" & contactEmail & "'" query = query & " OR [Email3Address]='" & contactEmail & "'" Dim person As Outlook._ContactItem = contactsItems.Find(query) If Not person Is Nothing Then person.ForwardAsBusinessCard() Marshal.ReleaseComObject(person) End If Marshal.ReleaseComObject(contactsItems) Marshal.ReleaseComObject(contacts) End Sub
Display an address book entry (aka a Contact)
This sample is similar to the one just above. It takes the passed email string to build a search query. The Find method then uses the query to execute the search.
Private Sub FindAndDisplayContact(contactEmail As String) Dim contacts As Outlook.MAPIFolder = GetDefaultAddressBook() Dim contactsItems As Outlook._Items = contacts.Items Dim query As String = "[Email1Address]='" & contactEmail & "'" query = query & " OR [Email2Address]='" & contactEmail & "'" query = query & " OR [Email3Address]='" & contactEmail & "'" Dim person As Outlook._ContactItem = contactsItems.Find(query) If Not person Is Nothing Then person.Display() Marshal.ReleaseComObject(person) End If Marshal.ReleaseComObject(contactsItems) Marshal.ReleaseComObject(contacts) End Sub
If a matching contact is found, the code displays it for user’s perusal.
Set a reminder to contact a Contact
Sometimes you want to remind yourself to call someone in your Outlook address book. This code does finds a contact and the sets a task reminder for that contact.
Private Sub MarkContactasTask(contactEmail As String) Dim contacts As Outlook.MAPIFolder = GetDefaultAddressBook() Dim contactsItems As Outlook._Items = contacts.Items Dim query As String = "[Email1Address]='" & contactEmail & "'" query = query & " OR [Email2Address]='" & contactEmail & "'" query = query & " OR [Email3Address]='" & contactEmail & "'" Dim person As Outlook._ContactItem = contactsItems.Find(query) If Not person Is Nothing Then person.MarkAsTask(Outlook.OlMarkInterval.olMarkThisWeek) person.Save() Marshal.ReleaseComObject(person) End If Marshal.ReleaseComObject(contactsItems) Marshal.ReleaseComObject(contacts) End Sub
This code sets the reminder for this week. You might want to set it to something else.
Responding to Items collection event
You watch all items in an address book and take action when contacts are created, edited, or removed. To make this happen, you need to add an OutlookItemsEvent class. You can do this by using the Visual Studio to click Project > Add New Item. In the Add New Item dialog windows, find the Add-in Express Items on the left-hand side.
Expand it select Outlook. Now, select the Outlook Items Events Class and click Add. You will now have a new class names OutlookItemsEventsClass1. This is where we will add the code for the items events.
This edit is easy because we already had the folder setup from the previous example. And were ready to go with the address book items. Let’s take a quick look at ProcessItemAdd, ProceeItemChange, and ProcessItemRemove.
Public Overrides Sub ProcessItemAdd(Item As Object) Dim contact As Outlook._ContactItem = TryCast(Item, Outlook._ContactItem) If contact IsNot Nothing Then contact.Body = contact.Body & vbNewLine & "Added on: " & Now.Date() contact.Save() End If End Sub Public Overrides Sub ProcessItemChange(Item As Object) Dim contact As Outlook._ContactItem = TryCast(Item, Outlook._ContactItem) If contact IsNot Nothing Then contact.Body = contact.Body & vbNewLine & "Last Edited on: " & Now.Date() End If End Sub Public Overrides Sub ProcessItemRemove() MsgBox("Contact deleted.", MsgBoxStyle.OkOnly) End Sub
ProcessItemAdd and ProcessItemChange are similar because they both pass an Item object. Item is the address book item that is being added or changed. Thus, in these two samples, access Item, cast it is a ContactItem, and edit its Body property.
The ProcessItemRemove event does not include the Item object. Thus, you can’t take any last minute action on that contact that is dying. But you can respond to the event according to your requirements. Mine were fairly benign.
Take action before moving an address book item
This sample piggy-backs off the previous sample. But instead of the times, we want to monitor a folder and take action before a user moves an item. To do this, you respond to the ProcessBeforeItemMove event in the OutlookItemsEventsClass1 class.
Public Overrides Sub ProcessBeforeItemMove(item As Object, moveTo As Object, _ e As AddinExpress.MSO.ADXCancelEventArgs) Dim contact As Outlook._ContactItem = TryCast(item, Outlook._ContactItem) If contact IsNot Nothing Then Dim query As String = "[Email1Address]= '" & contact.Email1Address & "'" If moveTo IsNot Nothing Then Dim moveToItems As Outlook._Items = moveTo.Items Dim alreadyThere As Outlook._ContactItem = moveToItems.Find(query) If alreadyThere Is Nothing Then contact.Body = contact.Body & vbCrLf & vbCrLf & "Moved on " & Now.Date() contact.Save() Else Marshal.ReleaseComObject(alreadyThere) End If Marshal.ReleaseComObject(moveToItems) End If End If End Sub
And, I know, the sample is nothing special. Here, the code only changes the body of the contact item currently in-transit. But, I think you get the idea.
To wrap-up the add-in, we need to edit the AddinInitialize event:
Friend FolderItemEvents As OutlookItemsEventsClass1 = Nothing Private Sub AddinModule_AddinInitialize(sender As Object, e As EventArgs) _ Handles MyBase.AddinInitialize FolderItemEvents = New OutlookItemsEventsClass1(Me) FolderItemEvents.ConnectTo(ADXOlDefaultFolders.olFolderContacts, True) End Sub
Notice too the need for the class-level FolderItemEvents object.
And the AddinBeginShutdown event:
Private Sub AddinModule_AddinBeginShutdown(sender As Object, e As EventArgs) _ Handles Me.AddinBeginShutdown If FolderItemEvents IsNot Nothing Then FolderItemEvents.RemoveConnection() FolderItemEvents = Nothing End If End Sub
These two events create and remove the connection to the OutlookItemsEventsClass1 (by storing it in the FolderItemEvents object.
***
That’s it and that’s all but we have more samples in the queue. Stay tuned.
Available downloads:
These code samples were created using Add-in Express for Office and .net:
4 Comments
Shouldn’t you count backwards through the contacts in DeleteJohnDoe? Otherwise, when you delete the contact, won’t the value of abItems.Count change and throw an out-of-bounds exception?
Hi Alan,
You are correct. Here is the corrected procedure:
Private Sub DeleteJohnDoe(email As String)
Dim ab As Outlook.MAPIFolder = GetDefaultAddressBook()
Dim abItems As Outlook._Items = ab.Items
For i = abItems.Count To 1 Step -1
Dim objItem As Object = abItems(i)
Dim contact As Outlook._ContactItem = TryCast(objItem, Outlook._ContactItem)
If contact IsNot Nothing Then
If contact.Email1Address = email Then contact.Delete()
End If
Marshal.ReleaseComObject(objItem)
Next
Marshal.ReleaseComObject(abItems)
Marshal.ReleaseComObject(ab)
End Sub
Question I have a 4 mails box in my outlook and I want to scan contacts in each (1 by 1). What function I can use to do that
Thanks a lot
Hello Marc,
Get message stores in your Outlook. For each store get the Contacts folder in that store. Then scan the folder as shown above.
Reference:
https://docs.microsoft.com/en-us/office/vba/api/outlook.namespace.stores
https://docs.microsoft.com/en-us/office/vba/api/outlook.stores
https://docs.microsoft.com/en-us/office/vba/api/outlook.store.getdefaultfolder