I was browsing the Internet recently and found a company that sells Outlook add-ins for various purposes (I won't mention the company). What a shame, because a few lines of VBA code could save dozens or hundreds of dollars that might be otherwise spent on frivolous add-ins that remind you if you forgot an attachment, or automatically BCC someone, or something similar. As long as you're OK with giving up a pretty UI (with the company's logo plastered on it, of course) and are willing to get into the trenches and debug your own code.
This is the first post in a series on how to Save Money In Outlook by writing your own code (or just cutting and pasting what you find here
). But isn't that what this site is all about anyway?
Automatically Add Contacts on Outgoing Messages
Do you want to automatically add recipients as contacts, whenever you send an email?
The following VBA event handler will automatically add outgoing recipient email addresses as contacts in your Contacts folder (if they don't already exist there). It can be customized to add only the people you reply to (Replies), or only the people you send to (New Messages). It can be customized to include CC/BCC recipients as well.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
' automatically add outgoing recipient to default Contacts folder
' assumes one recipient, otherwise it adds the first recipient only
' assumes that recipient is listed in "Firstname Lastname" format
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim contactItm As Outlook.ContactItem
' only act on mailitems
If Not IsMail(Item) Then GoTo ProgramExit
' check if recipient is a contact
Set Msg = Item
If Not IsExistingContact(Msg.To) Then
' add contact
Set contactItm = GetOutlookApp.CreateItem(olContactItem)
With contactItm
.FullName = Msg.To
.Email1Address = Msg.Recipients.Item(1).Address
.Close olSave
End With
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.number & " - " & Err.Description
Resume ProgramExit
End Sub
Function IsExistingContact(name As String) As Boolean
Dim itm As Object
Dim Itms As Outlook.Items
Dim firstName As String
Dim lastName As String
' search for the name
Set Itms = GetItems(GetNS(GetOutlookApp), olFolderContacts)
' parse the name
If InStr(name, " ") = 0 Then
Set itm = Itms.Find("[FullName] =" & Chr(34) & name & Chr(34))
Else
firstName = Left$(name, InStr(name, " ") - 1)
lastName = Right$(name, Len(name) - InStrRev(name, " "))
Set itm = Itms.Find("[FirstName] =" & Chr(34) & firstName & Chr(34) & _
" And [LastName] = " & Chr(34) & lastName & Chr(34))
End If
IsExistingContact = (Not itm Is Nothing)
End Function
Function IsMail(itm As Object) As Boolean
IsMail = (TypeName(itm) = "MailItem")
End Function
Function GetOutlookApp() As Outlook.Application
' returns native Outlook.Application object
Set GetOutlookApp = Outlook.Application
End Function
Function GetNS(ByRef app As Outlook.Application) As Outlook.NameSpace
' returns native NameSpace Object
Set GetNS = app.GetNamespace("MAPI")
End Function
Function GetItems(olNS As Outlook.NameSpace, _
folder As OlDefaultFolders) As Outlook.Items
' returns Items collection for specified default folder
Set GetItems = olNS.GetDefaultFolder(folder).Items
End Function
To check if a contact already exists, we use the Find Method on the Items Collection for the default Contacts folder. If the contact does not exist, our object reference will point to Nothing.
Create Contacts from emails in a folder
I think this could be a blog post on its own. In addition to adding contacts automatically from outgoing messages, we can also imagine a scenario where we need to do this for emails in a folder. The following VBA code will loop through all emails in a folder (either the default Inbox, or a folder of your choosing) and check if the recipient (or sender) is already in your Contacts folder. If not, they're added as a contact (name and email address only).
Sub LoopThroughFolderAddContacts()
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim MsgRecips As Outlook.Recipients
Dim MsgRecip As Outlook.Recipient
Dim emailItm As Outlook.MailItem
Dim Itms As Outlook.Items
Dim contactItm As Outlook.ContactItem
' loop through default Inbox
Set Itms = GetItems(GetNS(GetOutlookApp), olFolderInbox)
' or to pick your folder:
' Set Itms = GetNS(GetOutlookApp).PickFolder.Items
' loop through each email
For Each emailItm In Itms
Set Msg = emailItm
' loop through each recipient and sender in email
Set MsgRecips = Msg.Recipients
For Each MsgRecip In MsgRecips
If Not IsExistingContact(MsgRecip.name) Then
' add contact
Set contactItm = GetOutlookApp.CreateItem(olContactItem)
With contactItm
.FullName = MsgRecip.name
.Email1Address = MsgRecip.Address
.Close olSave
End With
End If
Next MsgRecip
' add msg sender as well?
If Not IsExistingContact(Msg.SenderName) Then
' add sender as contact
Set contactItm = GetOutlookApp.CreateItem(olContactItem)
With contactItm
.FullName = Msg.SenderName
.Email1Address = Msg.SenderEmailAddress
.Close olSave
End With
End If
Next emailItm
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub





Hi JP
Thanks for the interesting and valuable code that you release. In trying to use the above routine to add the message sender from each item in a folder I get an error. The IsExistingContact function fails for me if the 'name' argument does not contain a space character eg a single word sender name.
Thanks
Matt
I'll update the code in the post, thanks!
I am new to VBA, but am intrigued by what can be accomplished. You seem to be very adept at writing this code and I was wondering if you could help with something I had in mind. I want to create and save in my Drafts folder an email message with subject and body. In the body of the message, I would have a field that looked like this {name}. I then want to be able to launch a new mail message, be presented with a list of draft emails from a dropdown list that I can choose. Once I choose the draft email, a pop entry request for a name will be presented. After I enter the name I wish to use, the subject and body gets inserted into my current message and the {name} field is replaced with the name I entered when asked. Assume the To: field is already populated.
This is kind of an adhoc mail-merge capability. It would be nice if this was presented in the form of a Ribon, but just having a sub I can call would be ok as well.
Thanks in advance for any help you can provide.
I'd love to help but I'm afraid I don't understand your workflow. What you describe sounds very awkward. If you explain your goal, maybe I can provide a solution better suited to meet that goal.
I occasionally get pdf documents from another source, which contains an email address. When I click on that email address, it pops up a new blank mail message. Once that new blank mail message is open, I would like to run a macro that will pick from a list of draft emails that I have previously saved to use as the body and subject and ask me for a name to use in the Body of the email, replacing only a field labeled "{name}".
I found and use an excel mail-merge VBA program that works fine, but you have to copy and past emails into a sheet and you have to copy and paste the draft mail subject line into the sheet as well. The sheet works fine when you have several addresses to mail to, but I usually get these in 1 or two at a time.
I would like to have this ad-hoc, mail-merge type functionality run from within outlook VBA. I think the way to address this would be to use a form of some sort, populate the form dropdown box with a list of all the draft mail messages that are located in the drafts folder. The form would also have an entry box for a name to use that would then search for {name} in the draft body and replace it with the name entered into the name field and then all that information would become part of the currently open new mail message that I was working on.
I've seen forms used before, but don't have a great deal of background on them.