Don't use CDONTS (even the acronym is a good reminder). Don't use ASPMail.Don't worry about talking to the email server directly. Do it the fastsmooth asynchronous way: drop a file off and let the SMTP server handleit.
That being said, we use this process to handle our emails. Its robust, dern fast, and we send a tonof emails this way.
Working backwards, let's start with a little MIME, shall we?
MIME (Multi-purpose Internet Mail Extensions) is an extension of SMTP(Simple Mail Transfer Protocol), that allows some description of the data tocue the recipient into using the right application to view the contents. Youmay have already dealt with MIME types and not even know it. "text/html"anyone? how about "text/css" ? --Those are MIME types, and tell therecipient (your browser) how to handle the data.
What does knowing MIME do for us? Well, in order to just drop a file off andgo, and expect IIS' SMTP server to send it out, we have to write the file inraw MIME format. It's not that tough, but ya gots to know what goes where.We get to generate our own email headers. On top of that, if we want tosend attachments, we have to play with MIME and know the right way topackage it.
Email process overview:
Because we may have multiple people firing this off, we need toensure we don't step on anyone else:
<%Function GenMIMEName() Randomize ' Initialize random-number generator. RandomNbr = Int((1000000 * Rnd) + 0) RandomNbr = Right("0000000" + RandomNbr, 6) GenMIMEName = Request.ServerVariables("REMOTE_ADDR") & "_" & RandomNbr & ".email"End Function%>
We need to have some specific headers and such, here's what a MIME emaillooks like before its sent out:
Return-Path:<email@example.com>Date: Mon, Aug 28 2000 17:41 -0600To: <firstname.lastname@example.org>From: <email@example.com>Subject: [Friday Freebie] Look, ma no CDONTS!MIME-Version: 1.0Content-Type: text/plain; charset="US-ASCII"Content-transfer-encoding: 7bit
This is the body of the email. I'm the company liability!
So this is pretty straightforward then, right? We gotta worry about acouple things: creating the date in the right format, and making sure wehave at least one blank line after the headers to indicate the start of thebody. To create the date, we need to spit it out in "ddd, dd mmm yyyy hh:nngggg" try this:
<%function GenMIMEDate(byval mydate, byval gggg) ' mydate is already a date type, no error checking here! ' gggg is expected to already be in offset from GMT format, i.e. "-0600" ' we need to return ddd, dd mmm yyyy hh:nn gggg ddd = weekdayname(weekday(mydate),True) mmm = monthname(month(mydate),True) ' make sure we have a leading zero on single digit dates dd = zeropad(day(mydate),2) yyyy = year(mydate) hh = hour(mydate) nn = minute(mydate) GenMIMEDate = ddd &", "& dd &" "& mmm &" "& yyyy &" "& hh &":"& nn &" "& ggggend functionFunction zeropad(byval val, byval ceiling)if len(val)
for i=1 to ceiling-Len(val) val = "0"&val Nextend ifzeropad = valEnd Function%>
I played with dummy proofing the offset, but for now let's just assumethat we already now it, as its not the point of this tip ;)
So here's what I have to generate our headers and email:
<%function GenMIMEHeaders(byval replyto, byval from, byval mto, byval subject)replyto = "<"& replyto &">"from = "<"& from &">"sendto = split(mto,",")for each addr in sendto tolist = "<"& addr &">," & tolistNexttolist = Left(tolist,len(tolist)-1) ' take off the last commaheaders = "Return-Path:"&replyto & vbNewLineheaders = headers & "Date: " & GenMIMEDate(Now,"-0600") & vbNewLineheaders = headers & "To:"& tolist & vbNewLineheaders = headers & "From:"& from & vbNewLineheaders = headers & "Subject: "& subject & vbNewLineheaders = headers & "MIME-Version: 1.0" & vbNewLineheaders = headers & "Content-Type: text/plain; charset=""US-ASCII""" &vbNewLineGenMIMEHeaders = headers & "Content-transfer-encoding: 7bit" & vbNewLine &vbNewLineend function
function GenMIMEEmail(byval from, byval mto, byval subject, byval body)GenMIMEEmail = GenMIMEHeaders(from,from,mto,subject) & bodyend function%>
Notice we're able to take in a comma delimited list of
To: addresses. That
Also notice I've separated creating the headers with attaching the body.This on purpose, because in the next part we're gonnaexpand to include attachments.
Now we gotta write it to a file, in a temporary spot. This is because if wecreate the file in IIS's SMTP Server Pickup directory, it will try to slurpit up before we're done, and that's Bad. Oh yeah, where the hell is thisPickup directory?
\InetPub\MailRoot\Pickup(using the default install namefor the Inet root). Create a directory for the temp spot; we use
Let's write it to file, shall we?
<%Sub WriteEmail(byval email, byval filename)Dim ForAppending,fs,a,logstr' drop the email to a fileForAppending = 8filename = "D:\InetPub\Mailroot\Pickup\tempmail\" & filenameSet fs = CreateObject("Scripting.FileSystemObject")Set a = fs.OpenTextFile(filename, ForAppending, True)a.Write(email)a.CloseSet a = NothingSet fs = NothingEnd Sub%>
Well, so far we gots the email being generated with all the MIME we need(for now), and we're writing it to the file system with no probs. Now wegotta move it to the Pickup directory to actually get it sent. I'll reopenthe WriteEmail subroutine and tweak a few things to get it done:
<%Sub WriteEmail(byval email, byval filename)Dim ForAppending,fs,a,logstr' drop the email to a filetempdir ="tempmail\"pickupdir = "D:\InetPub\Mailroot\Pickup\"ForAppending = 8tempfilename = pickupdir & tempdir & filenameSet fs = CreateObject("Scripting.FileSystemObject")Set a = fs.OpenTextFile(tempfilename, ForAppending, True)a.Write(email)a.CloseSet a = Nothingfs.MoveFile tempfilename, pickupdir & filenameSet fs = NothingEnd Sub%>
Now, let's see the function calls in action:
<%' use _ to use multiple lines in VBScriptemail = genMIMEEmail("firstname.lastname@example.org", _ "email@example.com", _ "[Friday Freebie] Look, ma no CDONTS!", _ "This is the body of the email. I'm the company liability!")WriteEmail email,GenMIMEName%>
Gee, that was simple, wasn't it? In the next installment, we'll add in attachments.