Ty Anderson

Working with Outlook mail items: how to create, delete, access & enumerate

Mail items are the featured player of Outlook… email! Sure, contacts and appointments are regulars but email receives the most attention. We are addicted to the stuff. I bet you check on the toilet don’t you. That’s gross.

Anyway, as an Outlook plug-in developer, you need to know the basics. In football it’s called blocking and tackling. In Outlook development, we can call it working with Outlook email items.

In the Outlook object model, an email is known as a MailItem. Today, I’ll cover the blocking and tackling with email:

Life is short and the day is long. Let’s get to it.

Note. I’m assuming you know how to create an ADX COM Add-in project in Visual Studio using Add-in Express for Office and .net. If not, look back at a few recent blog posts. We explain how to do this all the time.

How to access & enumerate mail items

Emails reside in Outlook folders. The folder hierarchy is different per user but how you access & enumerate email items is always the same. This sample shows how to access the default inbox folder and do some manipulating o’ the emails.

Friend Sub EnumerateInboxEmails()
    Dim inbox As Outlook.Folder = Nothing
 
    Dim ns As Outlook._NameSpace = OutlookApp.Session
    inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
 
    Dim mailItems As Outlook.Items = inbox.Items
 
    For i As Integer = 1 To mailItems.Count
        Dim outlookItem As Object = mailItems(i)
        Dim mailItem As Outlook._MailItem = _
            TryCast(outlookItem, Outlook._MailItem
        If mailItem IsNot Nothing Then
            Console.WriteLine(mailItem.Subject)
        End If
        'Release COM Objects!
        Marshal.ReleaseComObject(outlookItem)
    Next
 
    'Release COM Objects!
    If mailItems IsNot Nothing Then Marshal.ReleaseComObject(mailItems)
    If ns IsNot Nothing Then Marshal.ReleaseComObject(ns)
    If inbox IsNot Nothing Then Marshal.ReleaseComObject(inbox)
End Sub

It all begins by grabbing the default inbox folder. Next we grab the items within the inbox and loop through them. Granted, this is where the sample gets a bit lame but I bet you have some ideas that could make this exciting. Something like looping through all the emails and saving them to a CSV file? I don’t know… it’s up to you.

The last bit, I release all the COM objects I created. This is a best practice for all Office add-in development, not just for when you work with emails.

How to create and send a mail item

Creating an email with code is easy. Writing a coherent and grammatically correct email via code is not. That is something best left to users. Here, I have two samples. The first shows how to create an email and display it.

Friend Sub CreateMailItem()
    Dim email As Outlook._MailItem
    email = OutlookApp.CreateItem(Outlook.OlItemType.olMailItem)
    email.Subject = "My Automated Email"
    email.Display(True)
 
    'Release!
    If email IsNot Nothing Then Marshal.ReleaseComObject(email)
End Sub

The idea is you automate the creation of an email, automate it a bit by inserting a subject line, then display it so the use can finalize it and send it.

But what if you want to automate it and send it… the user be damned? They’ll probably mess it up anyway with grammatical errors. In this scenario, you want to borrow heavily from this sample code:

Friend Sub CreateAndSendEmail(recipientName As String)
    Dim email As Outlook._MailItem
    Dim recipients As Outlook.Recipients
    Dim recipient As Outlook.Recipient
 
    email = OutlookApp.CreateItem(Outlook.OlItemType.olMailItem)
    email.Subject = "Another automated email"
    email.Body = "Hi there...want to order take out for lunch?"
 
    recipients = email.Recipients
 
    recipient = recipients.Add(recipientName)
    recipient.Type = Outlook.OlMailRecipientType.olTo
    recipient.Resolve()
 
    If recipient.Resolved Then
        email.Send()
    Else
        MessageBox.Show("You do not have an email address for " & recipientName & ".", _
            "Recipient not found", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End If
 
    'Release them COM Objects!
    If Not IsNothing(recipients) Then Marshal.ReleaseComObject(recipients)
    If Not IsNothing(recipient) Then Marshal.ReleaseComObject(recipient)
    If Not IsNothing(email) Then Marshal.ReleaseComObject(email)
End Sub

What we do here is:

  • create the email
  • fill some important properties like Subject, Body, and Recipients
  • resolve the recipient email address
  • send the sucker!

Of course, we also clean up after ourselves too. Mom would be proud… if she knew anything about Outlook development that is.

How to delete/remove a mail item

The only thing more fun than creating stuff is destroying it. It can be cathartic. Out with the old, in with the new, etc. Here, in the following sample, you will see how to delete a single email item that resides in either an Outlook Explorer or Inspector window.

Friend Sub DeleteMailItem(ByVal InspectorOrExplorer As Object)
    Dim mailItem As Outlook._MailItem = Nothing
    Dim selection As Outlook.Selection = Nothing
    Dim item As Object = Nothing
    If TypeOf InspectorOrExplorer Is Outlook._Explorer Then
        Try
            'Explorer.Selection fires an exception for a top-level folder 
            selection = CType(InspectorOrExplorer, Outlook._Explorer).Selection
            item = selection.Item(1)
            If TypeOf item Is Outlook._MailItem Then
                mailItem = CType(item, Outlook._MailItem)
                mailItem.Delete()
            End If
            Marshal.ReleaseComObject(item)
        Catch
        Finally
            If selection IsNot Nothing Then Marshal.ReleaseComObject(selection)
        End Try
    ElseIf TypeOf InspectorOrExplorer Is Outlook._Inspector Then
        Try
            item = CType(InspectorOrExplorer, Outlook._Inspector).CurrentItem
            mailItem = TryCast(item, Outlook._MailItem)
            If mailItem IsNot Nothing Then
                mailItem.Delete()
            End If
            Marshal.ReleaseComObject(item)
        Catch
        End Try
    End If
End Sub

Microsoft made it tricky by giving Outlook two types of windows… but I like it. It’s a challenge. In the sample above, you see the Selection object. This object contains the mail item currently selected by the user. We check the type of window and branch accordingly.

For Explorers, the code grabs first selected item. If the user selected more than one mail item… too bad… we only delete one today. For Inspectors, we don’t use the Selection object. We use the Inspector’s CurrentItem property to get to the MailItem. We then delete it.

Okay, deleting one email is fine-and-dandy. But sometimes I like to delete everything… especially after vacation. This sample doesn’t delete everything. Instead, it deletes all emails residing in the active folder that have a low priority.

Friend Sub DeleteMailItems(matchCriteria As String)
    'Lets assume the current folder of hte Explorer
    'Examples of MatchCriteria could be......
    '[Importance] = low
    '[DateReceived] = today()
    '[UnRead] = true
    'etc.

    Dim explorer As Outlook._Explorer
    Dim folder As Outlook.Folder
    Dim folderItems As Outlook.Items
    Dim filteredItems As Outlook.Items
 
    explorer = OutlookApp.ActiveExplorer
    folder = explorer.CurrentFolder
    If folder.DefaultItemType = Outlook.OlItemType.olMailItem Then
        folderItems = folder.Items
        filteredItems = folderItems.Restrict(matchCriteria)
 
        For i As Integer = 1 To filteredItems.Count
            Dim outlookItem As Object = filteredItems(i)
            Dim mail As Outlook._MailItem
            mail = TryCast(outlookItem, Outlook._MailItem)
            If mail IsNot Nothing Then
                mail.Delete()
            End If
            'Relase COM Objects!
            Marshal.ReleaseComObject(outlookItem)
        Next
 
        'Relase COM Objects!
        Marshal.ReleaseComObject(filteredItems)
        Marshal.ReleaseComObject(folderItems)
    End If
 
    'Relase COM Objects!
    Marshal.ReleaseComObject(folder)
    Marshal.ReleaseComObject(explorer)
End Sub

The code grabs a reference to the ActiveExplorer‘s folder object and ensures we are dealing with emails. Then, we use the Restrict method to filter based off of a search string (I included samples in the code). Then, the code rummages around via a Loop and removes them.

How to attach files to an email

If you automate Outlook emails, you will, at some point, want to attach a file to the email. All you need to do is grab the email and add an attachment to its Attachments collection.

Friend Sub AttachFileToEmail(mailItem As Outlook._MailItem, filePath As String)
    Dim attachments As Outlook.Attachments
 
    attachments = mailItem.Attachments
    attachments.Add(filePath, Outlook.OlAttachmentType.olByValue)
    Marshal.ReleaseComObject(attachments)
End Sub

You will, of course, need to know the file path for the file you want to attach.

How to save and delete all attachments in the inbox

Sometimes, you have 100s or 1000s of emails in a folder. These emails will have attachments that take up space. Here is a code sample that will clear some space by saving the attachments to a Windows folder and removing them from Outlook.

Friend Sub SaveAllAttachmentsInInbox(savePath As String)
    Dim ns As Outlook._NameSpace = Nothing
    Dim inbox As Outlook.Folder = Nothing
    ns = OutlookApp.Session
    inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
 
    Dim mailItems As Outlook.Items
    Dim attachmentItems As Outlook.Items
 
    mailItems = inbox.Items
    attachmentItems = mailItems.Restrict("[HasAttachment] = True")
 
    For i As Integer = 1 To attachmentItems.Count
        Dim outlookItem As Object = attachmentItems(i)
        Dim mailItem As Outlook._MailItem
        mailItem = TryCast(outlookItem, Outlook._MailItem)
        If mailItem IsNot Nothing Them
            Dim attachments As Outlook.Attachments = mailItem.Attachments
 
            While attachments.Count > 0
                Dim attach As Outlook.Attachment = Nothing
                attach = attachments(1)
                attach.SaveAsFile(savePath & "\" & attach.FileName)
                attach.Delete()
                Marshal.ReleaseComObject(attach)
            End While
 
            Marshal.ReleaseComObject(attachments)
 
            mailItem.Save()
        End If
 
        Marshal.ReleaseComObject(outlookItem)
    Next
 
    'Release the COM
    Marshal.ReleaseComObject(attachmentItems)
    Marshal.ReleaseComObject(mailItems)
    Marshal.ReleaseComObject(ns)
    Marshal.ReleaseComObject(inbox)
End Sub

Once again, I use the Restrict method to filter items before I process them. This strategy saves a few cycles. After I have a collection of mail items with attachments, I save each attachment to a file path and delete them from their parent email. Lastly, and this is important, I call MailItem’s Save method. If I don’t do that, the attachment will remain in Outlook.

Useful events

We have a few articles already that cover how to work with Outlook Item events. I’ll refer you to them if you want to dig deeper. Here, I want to point a few Outlook events that might prove useful when coding against Outlook emails.

To use these events, you need to add an ADXOutlookEvents object to the AddinModule.

NewMail and NewMailEx

These two events are similar for various reasons:

a) their names

b) what they do

c) their usefulness

Both occur when Outlook receives email.

NewMail executes when one or more new mail items hit the Outlook inbox. It’s a real stinker in terms of usefulness because it doesn’t tell you which items arrived… just that some items arrived. It’s a lot like when one of my kids calls my name and then forgets what they were going to tell me.

NewMailEx also occurs when one more mail items hit the inbox. But, this even provides us with a comma-delimited string. This string contains the EntryIDs of all items received since the last time NewMailEx executed. It’s obvious you want to ignore NewMail and utilize NewMailEx

Private Sub adxOutlookEvents_NewMailEx(sender As Object, _
    entryIDCollection As String) Handles adxOutlookEvents.NewMailEx
 
    Dim ns As Outlook._NameSpace = Nothing
    Dim mailItem As Outlook._MailItem = Nothing
    Dim entryIDs As String()
 
    Try
        ns = OutlookApp.Session
        entryIDs = entryIDCollection.Split(",")
 
        For i = 0 To entryIDs.Length - 1
            Dim outlookItem As Object
            outlookItem = ns.GetItemFromID(entryIDs(i))
            mailItem = TryCast(outlookItem, Outlook._MailItem)
            If mailItem IsNot Nothing Then
                mailItem.Display()
            End If
 
            Marshal.ReleaseComObject(outlookItem)
        Next
 
        Marshal.ReleaseComObject(ns)
    Catch
    End Try
End Sub

This code sample takes the comma-delimited string, splits it, and loops through its values. It then calls the GetItemFromID function that is found in the Session object (which is actually an Outlook Namespace object… ugh). GetItemFromID retrieves the mail item and then the code opens it. If there are lots of emails, this will annoy the user… a sure sign you have developed a solid Outlook add-in.

ItemSend

Anytime the user sends an email is a great time to mess with it. I’ve been tempted to write and install Outlook add-ins on my friends’ PCs that help them with their email sending. I have not succumbed to this temptation and have instead opted for productive things like the code sample below.

Private Sub adxOutlookEvents_ItemSend(sender As Object, _
    e As ADXOlItemSendEventArgs) Handles adxOutlookEvents.ItemSend
 
    Dim mailItem As Outlook._MailItem
 
    mailItem = TryCast(e.Item, Outlook._MailItem)
    If mailItem IsNot Nothing Then
        mailItem.Body = "I LOVE YOU!!!"
        mailItem.Save()
    End If
End Sub

The trick here is to use ADXOlItemSendEventArgs object (e) to get to the mail item that is “sending”. Then, you make someone’s day by changing the Body of the email. Just think through how this strategy could be used to make the world a better place.

For more information about this event, please see How to handle the Outlook ItemSend event: C# and VB.NET examples.

***

I think this is an appropriate place to end this discussion of working with Outlook emails. These samples will get you started. After you master them, you can keep reading our technical blog as well as our forums to learn more.

Available downloads:

This sample Outlook add-in was developed using Add-in Express for Office and .net:

Outlook Mail Items example (VB.NET)

Outlook 2013 add-in development in Visual Studio 2012 for beginners

11 Comments

  • https://secure.gravatar.com/avatar/2235e7c3e0991673f381250b10057600?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Mesfin Gebrai says:

    Under NewMailEx – the “..word of caution” alludes that Outlook rules are executed prior to the event itself. Can you please confirm that or advise if this is a result of add-in express or the Outlook event itself? From what I understand, the event fires prior to any other actions in outlook, including rules..
    Thanks.

  • https://secure.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Mesfin,

    You are right, the NewMailEx event fires when an item is still in the Inbox folder, before a rule is processed. We have removed “A word of caution” paragraph from the post. Thank you for pointing this out!

  • https://secure.gravatar.com/avatar/404a649d217fd95344b7dbf47d2d2a55?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Mark says:

    Hi there

    This would have been a lovely example, but it does not work in VS 2010…

    Any chance you have a working sample for VS 2010?

    Thanks

    –Mark

  • https://secure.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Mark,

    Thank you for pointing us to the issue. I have just modified the sample project, please download the updated version.

  • https://secure.gravatar.com/avatar/6caa9a50b8f52a910297cd1d06bc1939?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Amit says:

    I have VS.NET 2005, I want to handle the MailItem Save/SaveAs event, How can i capture it?
    I have used mailitem write event, But it does not work.

  • https://secure.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Amit,

    You can use the Write event of the MailItem object for such task. This event occurs when a mail item is saved, either explicitly (for example, using the Save or SaveAs methods) or implicitly (for example, in response to a prompt when closing the item’s inspector).

    Also, you can use ADXRibbonCommand component (with IdMso=FileSaveAs) to intercept clicking on the Save As ribbon button.

  • https://secure.gravatar.com/avatar/574e858bb00b16722bb57e6eaefe24f4?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ravi Cherukuri says:

    Hi,

    I want C# code for delete all mail items from outlook\\Inbox\\Test(My FOlder).

    My code is below

    for (int k = 1; k <= Attach.Count; k++)
    {
    Attachitem = (Microsoft.Office.Interop.Outlook.Attachment)Attach[k];
    Attachitem.SaveAsFile(downloadPath + Attachitem.FileName);
    Console.WriteLine(Attachitem.FileName + " is saved");
    mail.Delete();
    }

    by using above code : example i am having 4 mail items in my outlook folder while coming to the above loop downloading and deleting only 2 mails.

    FOR OTHER ITEMS I NEED TO RUN MY CODE AGAIN AND AGAIN.

    Request you to help in this one.

  • https://secure.gravatar.com/avatar/29957f26ad2d8ba527fd9cc8cfa7b2e0?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Andrei Smolin (Add-in Express Team) says:

    Hello Ravi,

    You need to loop through the folder items in the reverse order: for (int k = Attach.Count; k >= 1; k–)

  • https://secure.gravatar.com/avatar/574e858bb00b16722bb57e6eaefe24f4?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ravi says:

    Super Working fine Anderi..

    for (int k = Attach.Count; k >= 1; –k)

  • https://secure.gravatar.com/avatar/4ff9e6f63504d2dc4121a5468b20b640?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Jurko Gospodneti? says:

    One minor nitpick – when you add an attachment in the `AttachFileToEmail()` example, the result is simply ignored even though it is a COM object reference by itself and should thus be explicitly releases as well. Otherwise we’re leaving releasing that Attachment COM object reference up to the .NET GC.

  • https://secure.gravatar.com/avatar/29957f26ad2d8ba527fd9cc8cfa7b2e0?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Andrei Smolin (Add-in Express Team) says:

    Hello Jurko,

    You are correct! Thank you!

Post a comment

Have any questions? Ask us right now!