Get email Headers from an Outlook MailItem

While working on a VSTO add-in for Microsoft Outlook, I came across the need to access the headers of an email, to parse out X-CustomProperty tags that were put in by an application that sent the emails. However, I couldn’t find a Headers property in the Outlook object model, so below is an attempt to create one.

The Regex used is courtesy of John Gietzen’s answer on this stackoverflow question.

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Office.Interop.Outlook;

public static class MailItemExtensions
{
    private const string HeaderRegex =
        @"^(?<header_key>[-A-Za-z0-9]+)(?<seperator>:[ \t]*)" +
            "(?<header_value>([^\r\n]|\r\n[ \t]+)*)(?<terminator>\r\n)";
    private const string TransportMessageHeadersSchema =
        "http://schemas.microsoft.com/mapi/proptag/0x007D001E";

    public static string[] Headers(this MailItem mailItem, string name)
    {
        var headers = mailItem.HeaderLookup();
        if (headers.Contains(name))
            return headers[name].ToArray();
        return new string[0];
    }

    public static ILookup<string, string> HeaderLookup(this MailItem mailItem)
    {
        var headerString = mailItem.HeaderString();
        var headerMatches = Regex.Matches
            (headerString, HeaderRegex, RegexOptions.Multiline).Cast<Match>();
        return headerMatches.ToLookup(
            h => h.Groups["header_key"].Value,
            h => h.Groups["header_value"].Value);
    }

    public static string HeaderString(this MailItem mailItem)
    {
        return (string)mailItem.PropertyAccessor
            .GetProperty(TransportMessageHeadersSchema);
    }
}

Sample usage:

string[] preparedByArray = mailItem.Headers("X-PreparedBy");
string preparedBy;
if (preparedByArray.Length == 1)
    preparedBy = preparedByArray[0];
else 
    preparedBy = "";

string allHeaders = mailItem.HeaderString();

Edit 2011/08/05:
Thanks to Rob for the heads-up. I updated the code to return a Lookup instead of a Dictionary – this handles the case of multiple headers with the same name.

This entry was posted in Technology and tagged , , , , , , . Bookmark the permalink. Trackbacks are closed, but you can post a comment.

4 Comments

  1. Rob K
    Posted 2011/08/05 at 4:30 am | Permalink

    Very nice! It probably would’ve taken me a week of digging around in MSDN (accompanied by much cursing) to figure this out on my own, so big thanks to you (and google =).

    However, my attempt to utilize it is throwing
    “ArgumentException was unhandled by user code”
    “An item with the same key has already been added.”
    on line 25, the ToDictionary() call.

    I suspect it’s because the email I’m testing on has THREE “Received:” headers, which isn’t unusual at all.

    Since my immediate need is merely to check for the presence of a particular header in a MailItem, the HeaderString() method is usable. But I figured you might want an early heads-up in case someone needs the additional lookup functionality.

    (I’d normally try to provide some helpful suggestions or patch it, but I’m a C# noob and I don’t even know what the “=>” operator does =)

  2. Posted 2011/08/05 at 11:03 am | Permalink

    Thanks Rob, I updated the post with code that should work with multiple headers.

  3. Charles
    Posted 2011/10/17 at 4:40 pm | Permalink

    Hi,

    Can we use the same approach to add custom headers to out bound messages?
    I’m trying to build and OutlookAddin that will enable me add a custom header for any mail i send from my outlook.

    Thanks

  4. Posted 2012/11/01 at 7:27 pm | Permalink

    Brilliant. Time and pain saver. Thank you.

Post a Comment

Your email is never published nor shared. Required fields are marked *

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*
*

Time limit is exhausted. Please reload the CAPTCHA.