User guide

Version 0.94 BETA
Scott Landry

Doc History:
July 7, 2011 – Renamed Agent; fixed eventlog crash & install code; updated build & docs for 2010
Jan 19, 2012 - Fixed some doc typos.
Jan 25, 2012 - Formating fixes and alternate install instructions provided
Apr 10, 2012 - Added binary download for those with only 2010 SP2 binaries
Jun 5, 2012 - Added step to build instructions


In Exchange 2003, there was an ability to select an outbound SMTP connector based on the sender’s from address.  This was essentially controlled by establishing connector restrictions.  Additionally, there was the ability to use transport routing event sinks for modifying the Exchange routing behavior. This functionality was considered for Exchange 2007 RTM, but it was not known how widely used the feature was and so the short story is that the functionality was not included.  However, after the impact was better known, the functionality of being able to control a route with Transport Agents was brought back to the product in SP1.  Today you can accomplish with an Agent the same thing that you could accomplish with routing restrictions in Exchange 2003 and then some. There may be a future date when this functionality is included into the Exchange product, however, many requirements exist today which require the functionality.

In an effort to prevent Exchange administrators from having to write and maintain code, the RoutingRuleAgent project has been started on CodePlex, Microsoft’s open source community. The project is freeware, open source, but is not supported by Microsoft. You will need to rely on community support for this functionality. If this is not possible in order to meet business needs, you should consider other options.

The goal of RoutingRuleAgent is to provide the largest array of functional possibilities available while keeping the code as simple as possible, resulting in a flexible solution that performs well without having to customize the source code and build customized versions. That is, the goal is that for most administrators, the binaries can be downloaded, installed, and used without ever having to compile and build a customized version.   The way this is accomplished is by building on the Transport Rules engine and RFC standard X-headers.

Common Scenarios

The main scenario that is missed from Exchange 2003 is the ability to route outbound SMTP messages to a specific SMTP smart host. This is highly useful if you have one set of users that has different archival or scanning requirements and the systems used for this activity do not integrate directly into Exchange Server. Another possibility is that you have a secondary SMTP domain that needs to use a specific smart host before passing to the Internet.

<insert diagram>

How it works

Again, the design goal for RoutingRuleAgent was to make sure that it offered flexibility. Rather that force an administrator to decide between using groups or using SMTP domains, the RoutingRuleAgent simply adds on to the Transport Rules feature already in Exchange. Simply install the agent, and then create rules to act on messages with any Transport Rule conditions. For the Action, you will stamp a header, X-MS-Exchange-Organization-RoutingRuleDomain, which will tell the RoutingRuleAgent to act on the message.

Because Transport Rules execute after routing decisions are typically made by the Transport engine, there is a RoutingRuleAgent must force messages with the header (X-MS-Exchange-Organization-RoutingRuleDomain) to be resubmitted through the pipeline so that the new routing decisions can be made. This will only happen the first time a message is processed by RoutingRuleAgent and results in a DEFER event in the message tracking log. In order to prevent the message from continuing to be resubmitted through the pipeline and looping, an additional header is added, X-MS-Exchange-Organization-RoutingRuleCompleted. Both headers remain on internal messages, but will be stripped automatically by the header firewall when leaving the Exchange organization.


1. Download the RoutingRuleAgent.dll. Make sure to grab the version for the Service Pack level of your Exchange server.  If not, you will need to build it using Visual Studio.  See instructions for building the binary below.

It is suggested to copy it to the following location:

 \Program Files\Microsoft\Exchange Server\v14\Transport Roles\Agents\RoutingRule

While this specific location is not required, it is suggested because it is the tested location. You can of course update and customize the path for your specific installation. Only the single binary is required.


2. Navigate to the following location (or equivalent based on your .NET installation):


Run the following command from either local cmd.exe or local Powershell:

InstallUtil.exe “\Program Files\Microsoft\Exchange Server\v14\Transport Roles\Agents\RoutingRule\RoutingRuleAgent.dll"

This step is required to setup application event logging.  It is required, but only needs to be done once.  If you are having troubles getting this to work, you will need to simply manually create the following Registry key:


3. Open the local Microsoft Exchange Management Shell (Powershell) and run the following command:

Install-TransportAgent -Name "Routing Rule Agent" -TransportAgentFactory RoutingRuleAgent.RoutingRuleFactory -AssemblyPath "C:\Program Files\Microsoft\Exchange Server\V14\TransportRoles\agents\RoutingRule\RoutingRuleAgent.dll"


4. You will then need to verify the order:


Verify that the Routing Rule Agent is lower priority than “Transport Rule Agent”.


5. You will then need to enable the agent:

Get-TransportAgent "Routing Rule Agent" | Enable-TransportAgent


6. Exit the shell and restart the “Microsoft Exchange Transport Service.”


First, you’ll need to think about how you want your outbound routing. For the purposes of our example, consider the following two send connectors:

Name                        AddressSpaces                SmartHosts
----                        -------------                ----------
Internet                    {SMTP:*;1}                   {[]}
Override                    {SMTP:override.local;1}      {[]}

The simplest case that you might want is for messages from one user to be routed specifically to the host []. Here’s how to accomplish that.

First, create a new Transport Rule. The conditions for that rule might look something like this (TODO: screenshots):

 1. New Transport Rule.  Set conditions (e.g. from User & sent to users Outside the organization)

It is important to note that in the above screenshot, not only are we limiting which senders are going to be rerouted, but we’re also limiting the scope to (recipient) users outside the organization. By default, the Transport Rule will execute against all messages, even internal messages. It is not generally suggested to override the route of internal mail by sending it to another server. The reasons are threefold:

  • Internal messages contain properties and formatting that is not understood by servers outside of the organization; scanning and archiving these internal messages would make limited sense because they would not be understood by other servers.
  • Internal messages have special properties that can only be passed between authenticated connections between Exchange servers. If the trust is broken, then the properties are firewalled and this can cause issues ranging from false positives with junk mail, duplicated journal reports, transmission of unsecured messages to unsecured systems, etc.
  •  If your environment has multiple hub transport hops, the current version of RoutingRuleAgent will only work predictably with external recipients because it must execute each time there is a message that meets the criteria, unlike normal Transport Rules which only execute once. There may be workarounds for this issue, but they are not suggested at this time.

You can control whatever conditions you’d like.   Please note that in Exchange 2007, Hub Transport rules do limit what you can do with the Senders or Recipients. For this reason, in Exchange 2007, you cannot create a Hub rule for only senders in your organization with the domain, nor can you limit the rule to only execute against messages sent to a specific domain. This functionality is available in Edge Server or in the upcoming Exchange 2010 release.

Next, we need to tell the RoutingRuleAgent to execute and where to reroute the message:

 2. Actions -> set header with value -> "X-MS-Exchange-Organization-RoutingRuleDomain" with "override.local".

As you can see, we’re telling the RoutingRuleAgent to reroute the message to the destination “override.local”, which is the SMTP domain matching the connector we configured earlier. The net result is that the message will go to [] as long as the RoutingRuleAgent is installed on all servers in the path to that send connector.

That’s it. Create as many rules as you like and in any order that you would like. Transport Rules are smart enough to fork the message – so if you have a large number of recipients that match different rules or no rule at all, each set of recipients will be routed accordingly.


With the following regkey, you can easily set the logging levels 0-7.




Known Issues

  • Currently, this agent is tested only on Exchange 2010 SP1. Basic testing only.
  • Exchange 2007 Hub Transport Rules do not contain conditions for pattern matching or matching a specific SMTP domain in the envelope recipient or from field. You will need to specify individual users or groups or install the RoutingRuleAgent on an Edge server. Exchange 2010 adds these conditions.
  •  The first execution of the agent against a message will result in a DEFER event in the message tracking log. This is by design.
  •  X-MS-Exchange-Organization-RoutingRuleCompleted headers will not persist on messages after they leave the Exchange organization. This is to prevent two organizations both with the RoutingRuleAgent from having issues.
  •  It is possible to only install the RoutingRuleAgent on your outbound servers, limiting the impact should it malfunction, or limiting how many servers the manual installation is performed against. However, if those servers are in different AD sites, you could create looping situations if you’re not careful (as servers without the agent will make different routing decisions than those with the agent), so it is advisable to install the agent uniformly throughout the organization. Alternately, you can install it only on Edge servers. The rules can still execute either on Edge or Hub servers.

Feedback has forums for support and feedback. Please let us know if you find limitations not covered in this document so that it can be updated accordingly.

Please let us know if you're using the Agent!


<Insert MS-PL here.>

Building the Binary

These instructions should be optional except possibly when a new Service Pack release causes new Exchange Transport DLLs to be released.

Download the Class1.css file from this site & copy both Microsoft.Exchange.Data.Common.dll & Microsoft.Exchange.Data.Transport.dll from your Exchange server.  You will need these three files on your Visual Studio workstation.

1. Install Visual Studio on your workstation.  Express should be sufficent, although you may not be able to use source control and check-in additions to the project.

2. Create a new "Class Library" project using C#.  Call it "RoutingRuleAgent".

3. Copy the class1.css content that you downloaded into the class file created.

4. On the "solution explorer" pane (right side), you will need to Add->Reference and choose the two Exchange binaries you have copied from your Exchange server.  You will also need to add a reference to System.Configuration.Install.

5. Right-click on the project node in "solution explorer".  Project will be the level right under solution.  Choose "properties".  Make sure that the .NET framework target version says 3.5.

6. Select the "release" configuration (vs. Debug) and build the DLL.  You will grab the DLL from the release bin folder and copy that to your Exchange server.

7. Resume following the rest of the directions.  Enjoy!

Last edited Jun 5, 2012 at 6:43 PM by Ironic77, version 9


TMice Sep 1, 2012 at 1:23 PM 

It works great on my Exchange 2010 server. I use external SMTP for sending emails and POP3 connectors to take emails from that server to mine Exchange server. And experience one issue. If I receive NDR message or vacation autoreply, POP3 connectors cannot download those message due to invalid header fields.

Error message in Event Log (Event ID: 207):
One or more (1) e-mail messages in the POP3 mailbox account 'user@My-SMTP-SERVER' on the POP3 server 'My-SMTP-SERVER' have invalid header fields. Because of this, the messages cannot be delivered to the Exchange Server mailbox 'user@My-SMTP-SERVER' in Windows Small Business Server. The messages are still on the POP3 server. To resolve this issue, connect to the POP3 mailbox account, and then manually retrieve or delete the messages.

I can download those messages by POP3 outlook. But it is not a solution.

Have anybody experienced this? I would appreciate the help because I want to connect one more domain to my Exchange server.

charlesgate_86 Jun 21, 2012 at 6:35 AM 
Thank you so much.

I've tested in my lab and it worked as per the requirement :)

Ironic77 Jun 5, 2012 at 6:44 PM 
Although some servers check PTR records, they don't need to match the domain you're sending on behalf of. The PTR record just needs to resolve to A record which then resolves to the IP so everything checks out in both directions.

JD001 Apr 21, 2012 at 3:11 AM 
I'll give this a shot in a few weeks when I move a client from a POP service provider to his new Exchange server (SBS11). They host two public domains, and the from fields are frequently changed to match. The biggest sticking point is the fact that I need two reverse DNS PTR records, because there are so many mail servers/spam services out there that will never accept messages without a valid reverse record. In an ideal world, I'd create two Exchange send connectors, map domain A to the first and domain B to the second, assign each send connector a unique private IP address and NAT the SMTP traffic to two unique public IPs. Then I could assign a reverse record for both domains using unique public IP addresses.

I have a strong suspicion I'll have to use a smart host for one of the domains using the routingruleagent. Bummer, you'd think Microsoft's latest mail server would have this kind of capability builtin.