private void DumpMapiProperties(IMessage inMsg, MailMessage outMsg) { String header, body; //Get the original transport headers, and parse them out String xportHdrs = MapiUtils.GetStringProperty(inMsg, Tags.PR_TRANSPORT_MESSAGE_HEADERS); if (xportHdrs == null) { return; } //Each header line consists of the header, whitespace, colon, whitespace, value Regex hdrLineRex = new Regex(@" (?# Match single- and multi-line SMTP headers ) (?<header> (?# The header element... ) [a-z0-9\-]+ (?# consists of letters, numbers, or hyphens.) ) (?# the header is followed by...) \s*:\s* (?# ...optional whitespace, a colon, additional optional whitespace...) (?<value> (?# ...and the value of the header, which is ...) .*? (?# ...any character, possibly spanning multiple lines...) ) (?=\r\n\S|\n\S|\z)(?# ...delimited by the start of another line w/ non-whitespace, or the end of the string) ", RegexOptions.IgnoreCase | //Obviously, case-insensitive RegexOptions.Multiline | //Need to match potentially multi-line SMTP headers RegexOptions.Singleline | //and . matches newlines as well RegexOptions.IgnorePatternWhitespace //Ignore the pattern whitespace included for readability ); foreach (Match match in hdrLineRex.Matches(xportHdrs)) { if (match.Success) { header = match.Groups["header"].Value; body = match.Groups["value"].Value; //If this header isn't one of the built-in ones that will be generated automatically //by OpenSmtp.net if (header.ToLower() != "to" && header.ToLower() != "from" && header.ToLower() != "reply-to" && header.ToLower() != "date" && header.ToLower() != "subject" && header.ToLower() != "cc" && header.ToLower() != "bcc" && header.ToLower() != "mime-version" && header.ToLower() != "content-type" && header.ToLower() != "content-transfer-encoding") { //OpenSmtp isn't smart enough to recognize multi-line header values, and wants to //quoted-printable them because of the CR/LF control chars. So, straighten multi-line values out body = Regex.Replace(body, @"\r\n\s+|\n\s+", " "); outMsg.AddCustomHeader(header, body); } } } //Now dump all of the MAPI properties as X- headers just in case they're needed Tags[] propIds; inMsg.GetPropList(0, out propIds); foreach (Tags propId in propIds) { //Skip properties that are too big or redundant if (propId == Tags.ptagBody || propId == Tags.ptagBodyHtml || propId == Tags.ptagHtml || propId == Tags.PR_BODY || propId == Tags.PR_BODY_HTML || propId == Tags.PR_RTF_COMPRESSED || propId == Tags.PR_TRANSPORT_MESSAGE_HEADERS) { continue; } header = String.Format("X-{0}", propId); try { Value val = MapiUtils.GetProperty(inMsg, propId); if (val is MapiBinary) { //Binary values aren't good for much continue; } if (val == null) { body = "<null>"; } else { body = val.ToString(); //Cannot have line breaks in SMTP headers, so if there are any, escape them body = body.Replace("\n", @"\n"); body = body.Replace("\r", @"\r"); body = body.Replace("\t", @"\t"); } outMsg.AddCustomHeader(header, body); } catch (MapiException e) { outMsg.AddCustomHeader("X-Exception", String.Format("Error getting property: {0}", e.Message)); } } }