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.