An Exchange Transport Agent allows you to either add new name properties, change the value or remove existing properties.

If you choose to log data in a log file or write events to the event log, you should be aware of the fact that the Exchange Transport service runs under the Network Service account. In order for the Transport service to be able to write data in the log file you need to grant the Network Service account write permissions on the file. Also, for logging events in the application event log, I recommend creating the new Event Source manually in the Windows registry as the Network Service account has access permissions to the Applications event log only and searching for the source in the other event logs will generate an error.

 

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.IO;
   6: using Microsoft.Exchange.Data.Transport;
   7: using Microsoft.Exchange.Data.Transport.Email;
   8: using Microsoft.Exchange.Data.Transport.Routing;
   9: using Microsoft.Exchange.Data.Mime;
  10: using Microsoft.Exchange.Data.Common;
  11: using Microsoft.Exchange.Data.ContentTypes.Tnef;
  12:  
  13: namespace MyRoutingAgent
  14: {
  15:     public sealed class MyRoutingAgentFactory : RoutingAgentFactory
  16:     {
  17:         public override RoutingAgent CreateAgent(SmtpServer server)
  18:         {
  19:             return new MyRoutingAgent();
  20:         }
  21:     }
  22:  
  23:     public class MyRoutingAgent : RoutingAgent
  24:     {
  25:         public const string LOG_FILE_PATH = @"C:\MyRoutingAgent\MyRoutingAgent.log";
  26:  
  27:         public MyRoutingAgent()
  28:         {
  29:             base.OnRoutedMessage += new RoutedMessageEventHandler(MyRoutingAgentClass_OnRoutedMessage);
  30:         }
  31:  
  32:         void MyRoutingAgentClass_OnRoutedMessage(RoutedMessageEventSource source, QueuedMessageEventArgs e)
  33:         {
  34:             if (e.MailItem.Message.Subject.Contains("[TEST]"))
  35:             {
  36:                 LogMessage("OnRoutedMessage", e.MailItem, "Processing message sent to " + e.MailItem.Message.Subject + ".");
  37:                 ProcessMailItem(e.MailItem);
  38:             }
  39:         }
  40:         void ProcessMailItem(MailItem item)
  41:         {
  42:             try
  43:             {
  44:                 MimePart tnefPart = item.Message.TnefPart;
  45:                 if (tnefPart != null)
  46:                 {
  47:                     TnefReader reader = new TnefReader(tnefPart.GetContentReadStream());
  48:                     TnefWriter writer = new TnefWriter(
  49:                         tnefPart.GetContentWriteStream(tnefPart.ContentTransferEncoding),
  50:                         reader.AttachmentKey);
  51:                     while (reader.ReadNextAttribute())
  52:                     {
  53:                         if (reader.AttributeTag == TnefAttributeTag.MapiProperties)
  54:                         {
  55:                             writer.StartAttribute(TnefAttributeTag.MapiProperties, TnefAttributeLevel.Message);
  56:                             while (reader.PropertyReader.ReadNextProperty())
  57:                             {
  58:                                 if (reader.PropertyReader.IsNamedProperty)
  59:                                 {
  60:                                     int tag;
  61:                                     unchecked
  62:                                     {
  63:                                         // The first four bytes of the tag is must be at least 0x8000 
  64:                                         // when setting a named property, the second determines the type. 
  65:                                         // http://www.cdolive.com/cdo10.htm
  66:                                         tag = (int)0x8000001E;
  67:                                     }
  68:  
  69:                                     Guid PS_PUBLIC_STRINGS = new Guid("00020329-0000-0000-C000-000000000046");
  70:                                     switch (reader.PropertyReader.PropertyNameId.Name)
  71:                                     {
  72:                                         case "MyNamedProperty1":
  73:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
  74:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty1");
  75:                                             writer.WritePropertyValue("");
  76:                                             break;
  77:                                         case "MyNamedProperty2":
  78:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
  79:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty2");
  80:                                             writer.WritePropertyValue("");
  81:                                             break;
  82:                                         case "MyNamedProperty3":
  83:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
  84:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty3");
  85:                                             writer.WritePropertyValue("");
  86:                                             break;
  87:                                         case "MyNamedProperty4":
  88:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
  89:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty4");
  90:                                             writer.WritePropertyValue("");
  91:                                             break;
  92:                                         case "MyNamedProperty5":
  93:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
  94:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty5");
  95:                                             writer.WritePropertyValue("");
  96:                                             break;
  97:                                         case "MyNamedProperty6":
  98:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
  99:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty6");
 100:                                             writer.WritePropertyValue("");
 101:                                             break;
 102:                                         case "MyNamedProperty7":
 103:                                             // You can either choose to change the value of the property or just skip the property(remove it from the message) if you remove all two next lines of code
 104:                                             writer.StartProperty(new TnefPropertyTag(tag), PS_PUBLIC_STRINGS, "MyNamedProperty7");
 105:                                             writer.WritePropertyValue("");
 106:                                             break;
 107:                                         default:
 108:                                             writer.WriteProperty(reader.PropertyReader);
 109:                                             break;
 110:                                     }
 111:                                 }
 112:                                 else
 113:                                 {
 114:                                     writer.WriteProperty(reader.PropertyReader);
 115:                                 }
 116:                             }
 117:                         }
 118:                         else
 119:                         {
 120:                             writer.WriteAttribute(reader);
 121:                         }
 122:                     }
 123:                     if (null != writer)
 124:                     {
 125:                         writer.Close();
 126:                     }
 127:                 }
 128:                 else
 129:                 {
 130:  
 131:                 }
 132:             }
 133:             catch (Exception ex)
 134:             {
 135:                 // Logging exception raised by the code above
 136:                 LogEvents(ex.Message + ". Stack Trace: " + ex.StackTrace, EventLogEntryType.Error);
 137:             }
 138:  
 139:         }
 140:  
 141:         private void LogMessage(string eventName, MailItem item, string message)
 142:         {
 143:             TextWriter tw = System.IO.File.AppendText(LOG_FILE_PATH);
 144:             tw.WriteLine(DateTime.Now.Ticks + "\t" + eventName + " - " + item.Message.Subject + " - " + message);
 145:             tw.Close();
 146:         }
 147:     }
 148: }