This documentation is archived and is not being maintained.

A Look at a Transport Agent: The Message Statistics Sample

EWS Managed API

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

Topic Last Modified: 2007-07-23

By Ray Dixon, Programming Writer

Transport agents enable you to access a great deal of information about messages that travel through the Edge Transport and Hub Transport servers. In this article, I will take a look at the Message Statistics sample transport agent.

The Message Statistics sample agent examines and records aggregate information about messages submitted to the Edge Transport server. The agent records the following information across all messages:

  • Total number of P1 recipients
  • Total number of P2 To: recipients
  • Total number of P2 Cc: recipients
  • Total number of P2 Bcc: recipients
  • Root content types
  • Subject character sets
  • MAPI message classes
  • Total number of system messages
  • Total number of interpersonal messages
  • Total number of clear signed messages
  • Total number of encrypted messages
  • Total number of opaque signed messages
  • Total number of messages with no message security
  • Total number of Calendar messages
  • Total number of non-MIME messages with attachments
  • Total number of Multipurpose Internet Mail Extensions (MIME) messages
  • Total number of Transport Neutral Encapsulation Format (TNEF) messages
  • Message body character sets
  • Message body encodings
  • Message body formats, including:
  • Total number of HTML body formats
  • Total number of enriched body formats
  • Total number of RTF body formats
  • Total number of text body formats
  • Total number of messages where body format is none
  • Information about attachments, including:
  • Total number of inline attachments
  • Total number of OLE attachments
  • Attachment file name extensions
  • Depth of embedded messages
  • File name character sets
  • Total number of root-level attachments
  • Attachment content headers

The agent keeps this information in memory and writes it to an XML file when the transport service stops and each time the Timer object fires. The timer is set to a default interval of ten hours. Each time the agent writes the information to disk, it creates a new XML file, and uses a GUID for the file name.

Now that you know what the Message Statistics sample agent does, let's take a look at it. Before you read further, be sure to download the sample from the Microsoft Download Center. This sample is written in C# and requires an Edge Transport server.

The Message Statistics sample includes four files, listed in the following table.

File Description


A Microsoft® Windows® PowerShell script that installs and enables the agent.


The C# source code for the agent.


The Microsoft Visual Studio® project file.


A Windows PowerShell script that uninstalls the agent.

Open the project in Microsoft Visual Studio® .NET 2005 and look at the code in MessageStatistics.cs. Let's look through the agent one piece at a time.

First, find the public class named MessageStatisticsFactory (line 28). This class contains the CreateAgent method and a Timer object. The CreateAgent method simply returns a new instance of the MessageStatsAgent class, which is the actual transport agent. The Timer object, named timer, calls the MessageStatsAgent.WriteToXML method (more on that later) every ten hours. This lets the agent perform writing operations in bulk, rather than each time it processes a message.

Also in the MessageStatisticsFactory class is an override of the AgentFactory.Close method. This override disposes of the Timer object and calls the MessageStatsAgent.WriteToXML method to make sure the agent saves any unwritten statistics before it closes.

Now, find the definition for the MessageStatsAgent class (line 59). This class contains the more interesting code. At the beginning of the class definition, you see several static variables. The agent uses these variables to keep track of the overall statistics between calls to the MessageStatsAgent.WriteToXML method.

The MessageStatsAgent() constructor defines the event that the agent will listen to, in this case the OnEndOfData event, and the handler for that event, which is the EndOfDataHandler method. The constructor also uses reflection to determine the path to the agent's location, so the agent can use it later when writing to the log.

Next, you see the definition for the EndOfDataHandler method. This method gets called every time the server receives a message. The EndOfDataHandler method basically consists of a call to the GetMessageData method and, if an exception occurs, a call to the WriteExceptionToXML method. The WriteExceptionToXML method writes to an XML log file information about any exception that occurs when the agent calls the GetMessageData event handler. This is where the fun begins.

When you look inside the GetMessageData event handler, you see a lot of calls to the UpdateDictionary method. This method simply updates the dictionary objects the agent uses to keep track of the various statistics it logs. From an agent perspective, the interesting part is in the code that gets the information to put in the dictionary objects. Look through that code and you can see how to access different types of information about the message, such as the message type (system, interpersonal, and so on.), the recipients (To, Cc, and Bcc), whether the message is signed or encrypted, the MAPI message class, the Multipurpose Internet Mail Extensions (MIME) or Transport Neutral Encapsulation Format (TNEF) content, attachments, and more.

OK, watching a build isn't very exciting, but you do need to build the agent in order to use it. Using Visual Studio .NET 2005, build the MessageStatistics project in Debug mode. It should run without error, and it should produce a file named MessageStatistics.dll in the .\bin\debug folder of the project.

With the project files on the Edge Transport server role, open the Exchange Management Shell and navigate to the folder that contains the MessageStatistics.csproj file. Execute the install.ps1 script. This installs and enables the Message Statistics Sample agent on the Edge Transport server role. Be sure to close the Exchange Management Shell prompt after you install the agent so the management shell doesn't keep a reference to the assembly.

To disable and uninstall the agent, execute the uninstall.ps1 script.

To try out the Message Statistics sample, send a few messages through the Simple Mail Transfer Protocol (SMTP) server that is running the agent. After that, you can either wait ten hours (the default setting on the Timer object) or restart the MSExchangeTransport service to get the agent to write to an XML log file. The agent creates a folder named logs in its installation folder, in which it writes the XML log files. The default location for this folder is C:\Program Files\Microsoft\Exchange Server\TransportRoles\Agents\SmtpAgents\MessageStatistics\Log. Open an XML file in that folder to view the statistics the agent saved about the messages you sent.

The Message Statistics Sample agent demonstrates a lot of the cool things you can do with an agent. Play around with the sample and try different things. Try changing the interval during which the Timer object waits between writing to the log files. Perhaps change the WriteToXML method to write to a database instead of files. Add some logic that looks for and acts on specific types or combinations of information about the messages. Envision taking the ideas presented in this sample to another level in your application.