a while back we migrated our email-to-fax to an external company called myfax. we had an internal faxing service that had given us all sorts of problems, hence the move. one nice thing about the internal faxing service was that you could send an email to 1234567890@domain.fax, and because of a send connector in exchange 2007 it redirected it to the fax server.
so when we moved over to myfax, i wanted to keep the same functionality in place so that users could send things to 1234567890@domain.fax, but then have exchange rewrite the email and change domain.fax to myfax’s domain name. sounds simple enough, right?
unfortunately, if you are running exchange in a small environment and its the only exchange server, you can’t do this. the only way to do this using exchange was to implement a second exchange server, an edge server. now, i like the idea of the edge server. i would like to implement an edge server. but at our size and our budget, it wasn’t a very practical option.
i did get some advice that i could use a product like exclaimer to do rewrites (looked nice, and it could do it). but, back to the numbers, and at the cost of exclaimer, i was almost better off just getting an edge server.
since neither an edge server or exclaimer was an option, i googled a bit and found some things that got me going in the right direction. in the end, i wrote (for the record, wrote = copied and modified someone else’s code with some help) a dll for exchange that does the header rewrite functionality for us.
heres what i had to do:
- download and install microsoft visual studio c# 2008 express edition
- start a new project in c# express (use the class library template)
- add a reference to the following dll’s (both located on your exchange server @ C:\Program Files\Microsoft\Exchange Server\Public
- Microsoft.Exchange.Data.Transport
- Microsoft.Exchange.Data.Common

- point to the dll’s (either point directly to the exchange server using an UNC path, or copy them locally)

- now that the dll’s are referenced, copy and paste the following code (replace what was in the original .cs file, don’t append to it).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
| using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;
using Microsoft.Exchange.Data.Mime;
using Microsoft.Exchange.Data.Transport;
using Microsoft.Exchange.Data.Transport.Email;
using Microsoft.Exchange.Data.Transport.Routing;
namespace Samples.Agents.MyRoutingAgent
{
public class MyRoutingAgentFactory : RoutingAgentFactory
{
public override RoutingAgent CreateAgent(SmtpServer server)
{
return new MyRoutingAgent();
}
}
public class MyRoutingAgent : RoutingAgent
{
public MyRoutingAgent()
{
base.OnSubmittedMessage += new SubmittedMessageEventHandler(MyRoutingAgent_OnSubmittedMessage);
}
void MyRoutingAgent_OnSubmittedMessage(SubmittedMessageEventSource source, QueuedMessageEventArgs e)
{
Regex regex_fax = new Regex("(\\d+@)domain.fax", RegexOptions.IgnoreCase);
//Alter the P1 headers.The P1 address is used for routing.
for (int intCounter = e.MailItem.Recipients.Count - 1; intCounter >= 0; intCounter--)
{
if (e.MailItem.Recipients[intCounter].Address.IsValid)
{
# region email_header_p1_block
//Save the whole email address and local part of the address to strings
string strEmailAddress = e.MailItem.Recipients[intCounter].Address.LocalPart + "@" + e.MailItem.Recipients[intCounter].Address.DomainPart;
string strLocalPart = e.MailItem.Recipients[intCounter].Address.LocalPart;
//Match using the created regex agains the saved email address string
Match match_domain_fax = regex_fax.Match(strEmailAddress);
//If the match is successful, move on, otherwise exit
if (match_domain_fax.Success)
{
//The match is successful, remove the old address
e.MailItem.Recipients.Remove(e.MailItem.Recipients[intCounter]);
e.MailItem.Recipients.Add(new RoutingAddress(strLocalPart + "@faxing_domain.com"));
#endregion
}
}
}
//Alter the P2 headers so that the mail displays the correct recipient display Name
EmailRecipientCollection erToRecipientCollection;
erToRecipientCollection = e.MailItem.Message.To;
foreach (EmailRecipient rec in erToRecipientCollection)
{
Match match_domain_fax = regex_fax.Match(rec.SmtpAddress);
if (match_domain_fax.Success)
{
string xname = regex_fax.Replace(rec.SmtpAddress, "$1faxing_domain.com");
rec.DisplayName = xname;
rec.SmtpAddress = xname;
}
}
}
}
} |
- build the project. after its built, you should have a dll @ c:\documents and settings\user.name\my documents\visual studio 2008\projects\project_name\project_name\bin\release\project_name.dll (this is on xp sp3)
- copy your new dll to a folder on the exchange server (lets use c:\routing_agent)
- open up a powershell prompt and run the following commands
- net stop msexchangetransport # to stop the exchange transport service
- install-transportagent -name “routing_agent_v1″ -assemblypath C:\routing_agent\project_name.dll -transportagentfactory samples.agents.myroutingagent.myroutingagentfactory
- enable-transportagent -identity “routing_agent_v1″
- get-transportagent -identity “routing_agent_v1″
- net start msexchangetransport
thats it, you should now have a working routing agent on a non-edge exchange server that can do header rewrites.
references:
90% of this code was taken from: http://blogs.msdn.com/akashb/archive/2009/02/24/how-to-rewrite-the-to-address-in-transport-agents-on-a-hub-server.aspx
http://gsexdev.blogspot.com/2009/01/from-address-rewriting-in-transport.html
http://msdn.microsoft.com/en-us/library/aa579185.aspx