Sep 182011
 

in the time that i have been in IT (almost 6 years) i have become very proficient at hacking together code to do what i need. from vb scripts to do simple network administration to customizing some python to send over an exploit, i have found a way to make it work.

what i miss and don’t know is how to do is code correctly. in my search for learning how to code proper i ran across some great courses from stanford university and thought i would share.

i was looking for entry level classes that started at square one and these classes fit the bill perfectly. whats even better is that not only the video, but the homework assignments, handouts, and files are all available free of charge.

so far i have watched almost 4 of the classes and can say i have already learned some things, looking forward to the next 70+ classes ;)

here are the classes with links:

titleurllanguageitunes link
cs106a - programming methodologyhttp://www.stanford.edu/class/cs106a/javahttp://itunes.apple.com/us/itunes-u/programming-methodology/id384232896
cs106b - programming abstractionshttp://www.stanford.edu/class/cs106b/c++http://itunes.apple.com/us/itunes-u/programming-abstractions/id384232917
cs107 - programming paradigmshttp://www.stanford.edu/class/cs107/c++http://itunes.apple.com/us/itunes-u/programming-paradigms/id384233005

note: for the record, i am not really a fan of itunes (and you can get these classes on youtube as well), but being able to download all the classes to my hard drive with a single mouse click was compelling enough for me to do it through itunes.

Mar 042010
 

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:

  1. download and install microsoft visual studio c# 2008 express edition
  2. start a new project in c# express (use the class library template)
  3. add a reference to the following dll’s (both located on your exchange server @ C:\Program Files\Microsoft\Exchange Server\Public
    1. Microsoft.Exchange.Data.Transport
    2. Microsoft.Exchange.Data.Common
    3. point to the dll’s (either point directly to the exchange server using an UNC path, or copy them locally)
  4. 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;
                    }
                }
            }
        }
    }
  5. 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)
  6. copy your new dll to a folder on the exchange server (lets use c:\routing_agent)
  7. open up a powershell prompt and run the following commands
    1. net stop msexchangetransport # to stop the exchange transport service
    2. install-transportagent -name “routing_agent_v1″ -assemblypath C:\routing_agent\project_name.dll -transportagentfactory samples.agents.myroutingagent.myroutingagentfactory
    3. enable-transportagent -identity “routing_agent_v1″
    4. get-transportagent -identity “routing_agent_v1″
    5. 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