Teaser: Sending Email from a Script

I'm going to be blogging about how to write a scripting engine in the CLR. As a teaser, let me show you what I can do with the scripter I've already ginned up. There's not a whole lot of effort expended in creating this scripter, and it has some warts -- some really big ones, which I won't hide, but it already can do quite a lot of things.

(define fwdir "c:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/")

That just defines a global variable (or symbol), “fwdir“, whose value is the path in the string literal.

(define syslib (load-assembly (string-append fwdir "system.dll")))

That defines a global symbol, “syslib“, whose value is the result of calling “load-assembly” on the string concatenation of (the value of) “fwdir', which we already defined, and the string literal “system.dll.“  The blue strings are part of the IEEE 1178 standard language; the red ones are my extensions for scripting in the CLR. “load-assembly“ just returns an object of type “Assembly“, which we use in the Reflection API in various ways.

(define maildll (string-append fwdir "system.web.dll"))

You should be getting the idea by now...

(define maillib (load-assembly maildll))

Ditto... let's do something new:

(define email (new maildll "System.Web.Mail.MailMessage"))

That creates a new instance of the type “System.Web.Mail.MailMessage” in the assembly “maildll” and assigns the instance to the symbol “email“.

(invoke email "set_Body" "Test Body")

That invokes the “set_Body“ method on the object “email“ with the argument “Test Body“. “set_Body“ is actually the “set“ branch of the property “Body“; Reflection exposes this as an ordinary method named “set_Body“ and my invoke routine just makes a really straightforward call to Reflection's Invoke. If we had written that line of code in C# instead of the scripter, it would look like email.Body = "TestBody";

(invoke email "set_Subject" "Test Subject")

(invoke email "set_From" "few@boar.com")

(invoke email "set_To" "brianbec@exchange.nowhere.com")

Those are just some more property “set“s. Let's get an email server and send the message!

(define server-ip (invoke-static syslib "System.Net.Dns" "Resolve" "df-keekyoo"))

That assigns to the symbol “server-ip“ the result of invoking the static method “System.Net.Dns.Resolve“ in the assembly syslib for the exchange server “df-keekyoo“. The “invoke-static“ procedure requires us to separate the namespace of the target routine, namely “System.Net.Dns“, from the name of the target routine, namely “Resolve“. Sorry about that.

(define address (vector-ref (invoke server-ip "get_AddressList") 0))

Invoking the method “get_AddressList“, which, of course, is really the “get“ branch of the property “AddressList“, on the “server-ip“ object returned in the prior call to “System.Net.Dns.Resolve“ results in an array of addresses. We access the 0-th component of the array via the IEEE-standard routine “vector-ref“ to get the stuff we need for the next call. It all just works... nice.

(invoke-static maillib "System.Web.Mail.SmtpMail" "set_SmtpServer"
   
(invoke address "ToString"))

In an inner call, we invoke the .NET-standard “ToString“ method on the “address“ object to get the argument for a call of the static routine “System.Web.Mail.SmtpMail.set_SmtpServer“ in the “maillib“ assembly. This call is for side-effect, so we discard its return value.

(invoke-static maillib "System.Web.Mail.SmtpMail" "Send" email)

Finally, we send the email object.  Boom!  We're done.  Slick, eh?

Published Tuesday, February 17, 2004 4:51 PM by brianbec

Filed under:

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)