How to control routing from your own routing agent

With the release of Microsoft Exchange Server 2007 Service Pack 1 you can programmatically override the default routing for message recipients on a per-recipient basis. This can be done by using the SetRoutingOverride method on the recipient for which you want to override the default routing.

Let's assume that you have an Exchange 2007 server with just one send connector "Internet Connector"" using DNS for the address space *. With this configuration all messages leaving the organization will use this connector. Let's further assume that you want to route messages from certain senders to a smarthost instead of using DNS. This can be done as follows:

- Create an additional send connector "Smarthost Connector" pointing to the smarthost
- Specify a non-existing domain (e.g. nexthopdomain.com) as address space of the new connector
- Write, install and enable a routing agent which registers for the OnResolvedMessage event and overwrites the default routing for the recipient.

The sample agent of this article shows you how to route messages from administrator@contoso.com over the new connector, the routing for all other sender's won't be changed. 

1.) Create a C# project (dll/library type) 

2.) Copy the following DLLs from the C:\Program Files\Microsoft\Exchange Server\Public directory of an Exchange 2007 server to the debug directory of your new C# project:
     a. Microsoft.Exchange.Data.Common.dll
     b. Microsoft.Exchange.Data.Transport.dll

3.) Add references to the two DLLs to the C# project using the Visual Studio solution explorer

4.) Add the following code to your project:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Exchange.Data.Transport;
using Microsoft.Exchange.Data.Transport.Email;
using Microsoft.Exchange.Data.Transport.Smtp;
using Microsoft.Exchange.Data.Transport.Routing;
using Microsoft.Exchange.Data.Common;

namespace RoutingAgentOverride
{
    public class SampleRoutingAgentFactory : RoutingAgentFactory
    {
        public override RoutingAgent CreateAgent(SmtpServer server)
        {
            RoutingAgent myAgent = new ownRoutingAgent();

            return myAgent;
        }
    }
}
public class ownRoutingAgent : RoutingAgent
{
    public ownRoutingAgent()
    {
        //subscribe to different events
        base.OnResolvedMessage += new ResolvedMessageEventHandler(ownRoutingAgent_OnResolvedMessage);
    }

    void ownRoutingAgent_OnResolvedMessage(ResolvedMessageEventSource source, QueuedMessageEventArgs e)
    {
        try
        {
            // For testing purposes we do not only check the sender address but the subject line as well
            // If the subject contains the substring "REDIR" then the default routing is overwritten.
            //
            // Instead of hard-coding the sender you could also perform an LDAP-query, read the information
            // from a text file, etc.
            //
            if (e.MailItem.FromAddress.ToString() == "administrator@contoso.com"
                && e.MailItem.Message.Subject.Contains("REDIR"))
            {

                // Here we set the address space we want to use for the next hop. Note that this doesn't change the recipient address.
                // Setting the routing domain to "nexthopdomain.com" only means that the routing engine chooses a suitable connector
                // for nexthopdomain.com instead of using the recpient's domain.

                RoutingDomain myRoutingOverride = new RoutingDomain("nexthopdomain.com"); 
                                                                                         
                foreach (EnvelopeRecipient recp in e.MailItem.Recipients)
                {
                    recp.SetRoutingOverride(myRoutingOverride);

                }

            }
        }

        catch // (Exception except)
        {

        }
    }

}

5.) Compile the DLL

6.) Copy the DLL to the HT server

7.) Install the transport agent using the Exchange Management Shell:
     Install-TransportAgent "OwnTestAgent" -TransportAgentFactory "RoutingAgentOverride.SampleRoutingAgentFactory" -AssemblyPath "Path to DLL"

8.) Enable the transport agent using the Exchange Management Shell:
     Enable-TransportAgent "OwnTestAgent"

9.) IMPORTANT: Exit Powershell
10. IMPORTANT: Restart the MSExchangeTransport service

11.) Verify that the agent was successfully enabled / registered by running Get-Transportagent

Tips:

  • To live debug the dll you need to attach to edgetransport.exe.
  • To recompile after a change
    • detach from edgetransport
    • stop the transport service (otherwise Visual studio won't be able to overwrite the file)
      (only if you registered the dll from the \debug folder)
  • Sometimes messages remain in the outbox until the mail submission service is restarted