Sending Email Via an External SMTP Server Using CDO

by John Peterson


Introduction

I’m not sure how much interest there is in this, but it’s one
of those things I always meant to do and never did… until now.

I was spurred on to actually do it by an innocent email from a newbie asking
"Where do I specify the SMTP server when sending an email via CDO?" As
most of you probably know, the most common config with CDO for 2000
or CDONTS (NT 4) is to not specify an external SMTP server and to use the
local Microsoft SMTP server to send the messages.
Most third-party components, on the other hand, expect there to be an
external SMTP server specified. This distinction has always sort of
bugged me.

I always figured you could send messages via a seperate SMTP
server via CDO, but I had never tried it. The only thing I had
ever looked into was the "Smart Host" setting at the
local SMTP server level which will forward all mail to another
SMTP server via the local SMTP service. There’s not much info
floating around about this, but it does work as it’s supposed
to and has been useful on occasion.

The problem with that solution is that you still need to have the local
SMTP server installed, configured, and running. It’s not a biggie,
but if you configure it wrong or a bug is found you could find
yourself with an open relay and be used to spam everyone on the internet!
Using one outgoing SMTP server for your entire web farm/department/corporation/whatever
makes administering and ensuring it’s secure much easier.

I set out to find out how to use CDO (as opposed to a 3rd party component)
and still specify an external SMTP server to handle the emailing.
I didn’t do an exhastive search, but
after checking a half-dozen of my favorite ASP sites, a half-dozen of my
ASP books, and searching the web via Altavista and Google,
I couldn’t find anyone covering this. I’m not saying no one has ever
written about this, but I couldn’t find it.
(If you find anything outside the MSDN docs relating to this topic
let me know
and I’ll link to it.)

Having no luck in the ASP community, I rolled up my sleeves,
dove into the documentation, booted up another test server to
relay through, and started writing and trying some code.
Come to find out it’s pretty easy once you figure out all the
constants.

The Process

Here’s the process I went through to arrive at the code listed below.
I’m including it so that if you need to find any information that I haven’t
included you’ll at least know where to start looking.

Web Sites

There are tons of great ASP-related websites out there, but for something
like this (a simple question that should have a simple answer and that
you can assume hundreds of people have asked at one time or another) I tend
to look to for a FAQ (Frequently Asked Questions) list. There are two
good ASP FAQ sites that I know of… http://www.aspfaq.com/ and
http://www.aspfaqs.com/. Both are normally good about covering this type
of thing, but I couldn’t find any info about this topic
(at least as of the date of this article – when I was looking).
That being said, if you have a question that might be covered in a FAQ,
I highly recommend you check them out before posting your question to a
newsgroup or discussion list. You’ll get an answer much faster, it’ll
probably be of higher quaility, and you’ll help keep the noise down on the
newsgroups and lists so that people can get more complex questions
answered quicker. Basically everyone wins!

Books and Search Engines

I then checked the books on my shelf. Over the years I’ve accumulated
quite a library of ASP-related books, but apparently none about CDO.
Personally I find books
have their place, but technology-related books become outdated so fast that
it’s hard to keep up and since CDO isn’t really part of ASP and is a so called
"related technology", none of them cover much more then the basic
send an email script.

Okay so scratch the books… to the web! Well I got tons of results ranging
from
hosting companies to development shops. Mixed in were plenty of good
resources for sending an email via ASP, but we already knew how to do that!
I spent some time trying to refine my search using some booleans, but
never really got anything useful.

Microsoft

Finally I gave in and decided that I had to go to Microsoft for the info
I wanted. In a perfect (or even slightly sane) world, you’d think
that the source for the software you’re trying to use would be the
first place you should look. Well anyone who’s been developing with
Microsoft products for a while knows that this just isn’t the case…
especially for ASP. It’s getting a lot better with ASP.NET, but
still…

For an interesting and pertinent example of what I’m talking about:
next time you get a chance, take
a look at the ASP.NET QuickStart that ships with the .NET Framework.
In the top navigation bar they have a link titled "How Do I…"
that leads to a great page full of sample scripts. This page has
hundreds of samples on topics from how to generate and compare a hash value
for use in cryptograpy to how to call a function exported from an
unmanaged DLL so that .NET can interoperate with legacy apps. Now I’m
not saying these aren’t worthy topics, but nowhere on this page is there
any mention of how to send an email!

And even if you do happen to stumble upon what you’re looking for,
you better print out a hard copy… there’s a good chance it’ll be moved
or removed the next time you go to look at it.

 

Visual Basic

It’s really nice that VBScript and VB are so similar sometimes. I knew VB had a
way of looking up constants. I fired off VB, created a new project, added a reference
to CDO for Windows 2000, and ran the Object Browser and copied the constants I needed
into my script file. Not the neatest way to do it, but it got the job done and
did it without knowing that the UUID for the CDO for Windows 2000 Type Library
is CD000000-8B95-11D1-82DB-00C04FB1625D.

The type library should also get you the constants for any errors CDO throws your way,
but I tend to find it just as easy to look them up in the VB Object Browser… either
way will get you a better explanation then some random error number.

Anyway… without any further ado…

The Code

You can probably do this via CDONTS, but I assume most of us are
on Win 2000 by now so the code below uses CDO for 2000. I’ll try and get
a CDONTS version up soon… I’m having some trouble finding an NT 4 server
to test it on.

<%
Const cdoSendUsingMethod        = _
	"http://schemas.microsoft.com/cdo/configuration/sendusing"

Const cdoSendUsingPort          = 2
Const cdoSMTPServer             = _
	"http://schemas.microsoft.com/cdo/configuration/smtpserver"
Const cdoSMTPServerPort         = _
	"http://schemas.microsoft.com/cdo/configuration/smtpserverport"
Const cdoSMTPConnectionTimeout  = _
	"http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout"

Const cdoSMTPAuthenticate       = _
	"http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"
Const cdoBasic                  = 1
Const cdoSendUserName           = _
	"http://schemas.microsoft.com/cdo/configuration/sendusername"
Const cdoSendPassword           = _
	"http://schemas.microsoft.com/cdo/configuration/sendpassword"

Dim objConfig  ' As CDO.Configuration
Dim objMessage ' As CDO.Message
Dim Fields     ' As ADODB.Fields

' Get a handle on the config object and it's fields
Set objConfig = Server.CreateObject("CDO.Configuration")
Set Fields = objConfig.Fields

' Set config fields we care about
With Fields
	.Item(cdoSendUsingMethod)       = cdoSendUsingPort
	.Item(cdoSMTPServer)            = "smtp_server_name"

	.Item(cdoSMTPServerPort)        = 25
	.Item(cdoSMTPConnectionTimeout) = 10
	.Item(cdoSMTPAuthenticate)      = cdoBasic
	.Item(cdoSendUserName)          = "username"
	.Item(cdoSendPassword)          = "password"

	.Update
End With

Set objMessage = Server.CreateObject("CDO.Message")


Set objMessage.Configuration = objConfig

With objMessage
	.To       = "Display Name <email_address>"
	.From     = "Display Name <email_address>"
	.Subject  = "SMTP Relay Test"

	.TextBody = "SMTP Relay Test Sent @ " & Now()
	.Send
End With

Set Fields = Nothing
Set objMessage = Nothing

Set objConfig = Nothing
%>

To use it you’ll need to edit the smtp server name, the username and password
if you’re authenticating, and the to and from email addresses.

Bad News For NT4 Users:

I did some more research and found some info that makes it look like
doing this via CDO for NTS isn’t going to happen.
Microsoft has a page
in the CDO for NTS documentation that compares CDO for NTS and CDO 1.2.1
(the two CDO libraries available on NT4). It appears that while the
CDO for NTS library doesn’t support "remote server access",
CDO 1.2.1 doesn’t support "SMTP access". As a result, accessing
a remote server via SMTP would seem to be impossible if you want to use
either CDO library on NT4.

However, all is not lost. As I mentioned earlier, it is still possible
to send email via CDO and use an external SMTP server by using the
"Smart Host" setting at the local SMTP server level. This
does mean the local SMTP service will need to be running, but it does
allow you to set SMTP permissions and settings in one place. As far
as I can tell, it’s either "Smart Host" or a 3rd party or
custom component if you’re still on NT4. Sorry guys.

Related Links

Two of our readers each independently informed me that Microsoft has a
KnowledgeBase article which addresses this topic:

Thanks go out to both Marsha Glassner and Cameron Frasnelly for finding
the article and letting us know about it.

More by Author

Must Read