Monday, May 23, 2005

Poking around in SMTP

A few years back, I had seen a mailer engine that spit out email messages in EML format. I found this engine to be extremely helpful because I could turn off the SMTP service, run the mailer-engine, and then manually inspect the messages in Outlook Express. If the messages were fine, I re-enabled the SMTP service.

At the time, it was clear that the engine was leveraging the CDO.Message object's ability to persist to a file.

Recently, I wondered if this was possible using the .net framework, but was dissapointed to find out that the System.Web.Mail.SMTPServer object only exposed the method "Send".

Enter Reflector.

The SMTPServer implementation is very interesting. Reflection shows that there are three internal classes:

  • CdoSysHelper
  • CdoNtHelper
  • LateBoundAccessHelper

As it turns out, the SMTPServer object acts as a proxy between the legacy COM objects, "CDO.Message" and "CDONTS.NewMail" -- it detects which environment you are using, then delegates the sending of the message to the "Send" method to the appropriate COM object.

What's equally interesting, is that the .net framework doesn't use COM Interop to talk to the COM objects. Instead, it uses the LateBoundAccessHelper to instantiate the COM object by it's ProgId, and then manually sets its properties and methods using Late Binding.

To stream my messages out into EML format I suppose I could use COM Interop to the CDO library, but that would mean I would have to package the interop wrapper (and its dependencies) with my assembly.

I'll have to take a look at extracting this code using a Reflector add-in, and extending the class to save to a file instead of sending directly. It'll be interesting if I can do this without adding an Interop wrapper to CDO. I wonder if there'll be any performance drawbacks in this approach...

yet another side-project...

submit to reddit