Click here to Skip to main content
13,402,795 members (41,064 online)
Click here to Skip to main content
Add your own
alternative version


21 bookmarked
Posted 1 Nov 2006

Exchange Domain Mail SMTP Sink

, 1 Nov 2006
Rate this:
Please Sign up or sign in to vote.
How to create a domain mail sink for Exchange Server.

Active Directory Users and Computers - notice


A while ago, I started running Microsoft Small Business Server with Microsoft Exchange 2003. I use Outlook with RPC over HTTP, synchronize with Exchange on my Smart Phone, and use OWA. I also host a few domains on my server.

When I signup for a service, I want to give as my e-mail address, so that I can block spam. It’s easy to add SMTP addresses to Active Directory accounts, but I have accounts on a thousand services! Hence the following question: how do I get * routed in Exchange?

If you just want to install this sink, download the binaries and run RegisterSink.cmd. Add to users that should receive all e-mail Run UnregisterSink to uninstall.


These two articles are an excellent start, but I have more than one domain and I want this to be configurable.

What does this code do?

  • Implement IMailTransportSubmission::OnMessageSubmission to catch submitted e-mail messages.
  • Search for an Active Directory user that has an exactly matching mail or proxy address.
  • Search for an Active Directory user that has a matching mail or proxy address.
  • Route e-mail accordingly.
  • Log routing events to the event log.

Implementation Details

Please note that the samples below are stripped of error checking. Please see the actual source code attached.

First, I had to follow the details in Writing Managed Sinks for SMTP and Transport Events and create the managed proxy objects to receive SMTP events.

Code to connect to Active Directory code is widely available. The slightly tricky parts are connecting to the RootDSE and finding the Users node.

// Root DSE and the Users LDAP path
mRootDSE = new DirectoryEntry(
 "LDAP://" + (DomainName.Length > 0 ? DomainName + "/" : string.Empty) +
mUsersLDAPPath = "LDAP://" + 
 (DomainName.Length > 0 ? DomainName + "/" : string.Empty) + 
 "CN=Users," + RootDSE.Properties["defaultNamingContext"].Value;

When an e-mail arrives, it will be potentially re-routed. A new list of recipients must be created.

void IMailTransportSubmission.OnMessageSubmission(
 MailMsg message,
 IMailTransportNotify notify,
 IntPtr context)
 Message Msg = new Message(message);
 RecipsAdd NewRecipients = Msg.AllocNewList();
 bool fReRouted = false;
 foreach (Recip Recipient in Msg.Recips)
     fReRouted |= ReRoute(Recipient, Msg, NewRecipients);
 if (fReRouted)

And the meat of the re-routing:

private bool ReRoute(Recip Recipient, Message Msg, 
                     RecipsAdd NewRecipients)
     ActiveDirectory Directory = new ActiveDirectory();
     string[] SearcherPropertiesToLoad = { "cn", "mail", 
                                     "proxyAddresses" };
     DirectorySearcher Searcher = new DirectorySearcher(
      new DirectoryEntry(Directory.UsersLDAPPath),
      (proxyAddresses=*smtp:@" + 
      Recipient.SMTPAddressDomain.ToLower() + 
      "*)(proxyAddresses=*smtp:" + 
      Recipient.SMTPAddress + "*)))",
     SearchResultCollection SearchResults = Searcher.FindAll();
     if (SearchResults.Count == 0) return false;
     foreach (SearchResult SearchResult in SearchResults)
      foreach (string ProxyAddressProperty in 
       string ProxyAddress = ProxyAddressProperty.ToLower();
       if ("smtp:" + Recipient.SMTPAddress.ToLower() == 
        // there's an address that matches
        // exactly, add him to the re-routing
        // list because there might be other
        // recipients that don't match and
        // will require routing
               Recipient.SMTPAddress, null);
        return false;
     foreach (SearchResult SearchResult in SearchResults)
      foreach (string ProxyAddressProperty in 
       string ProxyAddress = ProxyAddressProperty.ToLower();
       // this is necessary to avoid matching
       // with
       if ("smtp:@" + Recipient.SMTPAddressDomain.ToLower() == 
        string RoutedSMTPAddress = 
        NewRecipients.AddSMTPRecipient(RoutedSMTPAddress, null);
        return true;
     return false;

That's it. This was overall a simple task, and should, frankly, ship with Microsoft Exchange. This code can probably be easily extended to support regular expressions and other fancy things.


  • 10/24/2006: initial release.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Team Leader Application Security Inc.,
United States United States
Daniel Doubrovkine has been in software engineering for twelve years and is currently development manager at Application Security Inc. in New York City. He has been involved in many software ventures, including Xo3 and Vestris Inc, was a development lead at Microsoft Corp. in Redmond, and director of Engineering at Visible Path Corp. in New York City. Daniel also builds and runs a foodie website,

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Amir Mohammad Nasrollahi7-Aug-13 23:12
professionalAmir Mohammad Nasrollahi7-Aug-13 23:12 
QuestionCreate domains is the same? Pin
Felipe.Gonzalez20-Nov-07 14:25
memberFelipe.Gonzalez20-Nov-07 14:25 
AnswerRe: Create domains is the same? Pin
dB.21-Nov-07 3:30
memberdB.21-Nov-07 3:30 
Question?!?!?!?! Pin
Hillai9-May-07 3:06
memberHillai9-May-07 3:06 
What's That ?!
I Open The ZIP File But Nothing Happend !!
Even When I CLickesd On registersink.cmd !Confused | :confused: Confused | :confused: Confused | :confused: Confused | :confused:


AnswerRe: ?!?!?!?! Pin
dB.9-May-07 3:30
memberdB.9-May-07 3:30 
QuestionNewRecipients? Pin
Pletzky7-Nov-06 21:07
memberPletzky7-Nov-06 21:07 
AnswerRe: NewRecipients? Pin
dB.8-Nov-06 3:13
memberdB.8-Nov-06 3:13 
GeneralRe: NewRecipients? Pin
Pletzky8-Nov-06 7:03
memberPletzky8-Nov-06 7:03 
Generalbest solution Pin
mikedepetris6-Nov-06 23:56
membermikedepetris6-Nov-06 23:56 
GeneralRe: best solution Pin
dB.7-Nov-06 3:59
memberdB.7-Nov-06 3:59 
GeneralRe: best solution Pin
meraydin4-Sep-07 11:20
membermeraydin4-Sep-07 11:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1802120.2 | Last Updated 1 Nov 2006
Article Copyright 2006 by dB.
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid