Processing Incoming E-mails with Macros

Last reviewed on October 18, 2013

The Rules Wizard is great for a lot of things when automatically processing incoming e-mails. However, when there’s that one certain thing that you can’t do with it, you can always be the Wizard yourself and write your own rules with VBA. However, one of the greatest challenges for developers programming with Outlook is learning how to effectively hook into application events. While it is relatively easy to gain access to objects on the fly, it is not entirely obvious where, when or how these objects should be managed. If Outlook automation was anything like most object models, it would be very straightforward.
Imagine this “fantasy” code:

Sub WorkWithNewMail()

Dim objOutlook As Outlook.Application
Dim objAllNewMail As Outlook.Items
Dim objMyEmail As Outlook.MailItem
Set objOutlook = New Outlook.Application
Set objAllNewMail = objOutlook.NewMail
For Each objMyEmail In objAllNewMail
'Do something with every e-mail received
Next

Next

End Sub

Wouldn’t this make things easier! Unfortunately, there is no magical NewMail collection. You have to build it, and hook into it at the proper time. What is essential is instantiating the necessary objects when Outlook starts. To begin, open the Visual Basic Editor (ALT+F11) and open the ThisOutlookSession module from the Project Explorer window. The first code that we need to add are module level variables that we’ll declare in the general declarations section of the module at the top:

Option Explicit
Private objNS As Outlook.NameSpace
Private WithEvents objNewMailItems As Outlook.Items

The most important object in this example is objNewMailItems, as we’ll soon see. The “WithEvents” statement means we are declaring this object in a way that will allow us to access not only the properties of that object, but also the events that the object exposes.

Now, we have to hook these variables up. The ThisOutlookSession module is special compared to the regular modules that you usually insert into a VBA project in Outlook – it has a “built-in” Application object variable already declared. This way you don’t have to add a “Private WithEvents objApp As Outlook.Application” line or something similar in the general declarations section of the module. With that in mind, add this procedure:

Private Sub Application_Startup()

Dim objMyInbox As Outlook.MAPIFolder

Set objNS = Application.GetNamespace("MAPI")
Set objMyInbox = objNS.GetDefaultFolder(olFolderInbox)
Set objNewMailItems = objMyInbox.Items
Set objMyInbox = Nothing
End Sub

This is essentially where it all begins. As the name of the Application_Startup event indicates, this loads when Outlook launches and is essential to ensure that we gain access to e-mails delivered to the Inbox. This is done by hooking up an event aware procedure tied to the Items collection that we retrieve from the MAPIFolder object we set from the Inbox folder. The event where all the processing on incoming e-mails occurs will be here:

Private Sub objNewMailItems_ItemAdd(ByVal Item As Object)

Dim objEmail As Outlook.MailItem
'Ensure we are only working with e-mail items
If Item.Class<> OlItemType.olMailItem Then Exit Sub

Debug.Print "Message subject: " & objEmail.Subject
Debug.Print "Message sender: " & objEmail.SenderName &" (" & objEmail.SenderEmailAddress & ")";
Set objEmail = Nothing
End Sub

And that’s really all there is to it! The Item object is checked to ensure that it is a MailItem object before we work with it any further.

Once it is validated, we can work with all the properties and methods of the MailItem object to do whatever we want with it. Just printing out the subject line and sender information to the Debug window like the example above is pretty boring, but there are all kinds of possibilities using code to work with e-mails in ways that the Rules Wizard can’t handle:

- write e-mail info to a database
- automatically save attachments to the file system
- lookup the sender’s Contact item and start a Word mail merge using their mailing address
- parse the message body for line items to be added to a spreadsheet

Those are just a few examples, but as long as whatever you want to do has an Object Model it can be done – you don’t just have to automate Outlook or other Office applications.

There are a few caveats to mention though. If a large number of items are added to a folder at that same time, the ItemAdd event may not fire.

This is documented in this KB article:
OL2002: ItemAdd Event Doesn’t Run in Some Scenarios

However, you can get around this if you use Outlook 2003. The NewMailEx event provides a list of all the unique EntryID values for e-mails that were delivered during the last Send/Receive cycle. These values can be used to retrieve each e-mail individually as in the ItemAdd event by using the NameSpace GetItemFromID method.

Private Sub Application_NewMailEx(ByVal EntryIDCollection As
String)
Dim objEmail As Outlook.MailItem
Dim strIDs() As String
Dim intX As Integer
strIDs = Split(EntryIDCollection, ",")
For intX = 0 To UBound(strIDs)
Set objEmail = objNS.GetItemFromID(strIDs(intX))
Debug.Print "Message subject: " & objEmail.Subject
Debug.Print "Message sender:" & objEmail.SenderName &" (" & objEmail.SenderEmailAddress & ")"
Next
Set objEmail = Nothing
End Sub

Note: The Outlook 2003 VBA help file seems to indicate that NewMailEx only works with Exchange Server mailboxes. This is not true – try it and see with POP or IMAP accounts.

Finally, don’t expect this code to process e-mails the way server-side based rules do. Outlook of course has to be running for your code rules to work. For requirements where e-mail needs to be processed 24/7, see the Exchange SDK for information on building Event Sinks that run on the server.

To take this example further, there may be situations where you need to interact with e-mails that are opened rather than received. This involves a different approach and is explained in this article: Getting a Handle on Your E-mails with VBA

How to Use VBA

Copy and paste the code from this page into your ThisOutlookSession project. To do this, click within the code, Select All using Ctrl+A, Ctrl+C to copy.

In Outlook, press Alt+F11 to open the VBA editor and expand Microsoft Outlook Objects then double click on ThisOutlookSession to open it in the editing pane and Ctrl+P to paste the code.

For more detailed instructions and screenshots, see How to use Outlook’s VBA Editor

Written by

Eric Legault
An Outlook developer MVP since 2003, Eric has completed several dozen projects using the Outlook/Exchange/SharePoint platforms, from COM Add-Ins to custom Forms, desktop applications and Windows Service applications. When not working, Eric keeps busy building relationships with technical communities via social media and by contributing to online support forums, writing technical articles and editing technical books and speaking at conferences around the world on Outlook and Office development. Eric Legault+

If the Post Coment button disappears, press your Tab key.