Many Web sites either have or are adding email functionality. You can use email for many tasks, such as notifying customers of order status, responding to requests for information, and notifying people of a service or support question.
One issue you face in using email in your site is your ISP. ISPs each provide a different email package for their clients. Some ISPs provide more than one. But you or your Web developer must learn the package your ISP supports. Even if you're an administrator, it's important for you to understand how software developers create such applications. This month, I show you how to use one of the most popular email packages-Dimac w3 Jmail-with Active Server Pages (ASP). You can also use the code and technologies in this article to automate email on your site.
Installing and Running Jmail
Jmail is a free Microsoft COM component that you can use to send email. To install this component on local or test systems, download it from http://www.dimac.net. When you've completed the download, execute jmail.exe to install the component. The executable installs the jmail.dll in the \winnt\system\w3jmail directory. You can use Jmail with any application that can execute a COM object.
No uninstall option exists for Jmail. If you need to remove the application, make sure you clean up the Registry first by executing
regsvr32 "C:\winnt\system32\w3Jmail\jmail.dll" /u
(Use extreme caution when making changes to the Registry.) After you install Jmail, I suggest that you look on the Dimac Web site (http://www.dimac.com) for an example script so that you can test Jmail. (Dimac provides a series of example scripts from simple to fairly sophisticated.) Copy the code from a simple example to the clipboard, and paste it into a file named Jmail1.asp. Save Jmail1.asp in a virtual directory that supports the execution of ASP scripts.
Next, modify the file, as Listing 1 shows. Let's walk through the code to see how Jmail works. The first line of importance instantiates the Jmail object.
Set Jmail = Server.CreateObject("Jmail.SMTPMail")
After this code, you can use Jmail's properties and methods to interact with the Jmail object. The first task is to let Jmail know the name of your SMTP server. Use the ServerAddress property to set the server name.
Jmail.ServerAddress = "SMTPserver"
Next, let Jmail know the email address of the message sender.
Jmail.Sender = "[email protected]"
Jmail uses the Sender property to set the From line in the message. (The From address is the email address the user can reply to by clicking Reply on the message.)
Use the Subject property to set the Subject line of the message.
Jmail.Subject = "Mail test..."
Use Jmail's AddRecipient method to add the email addresses to which the message is going. Notice that the following code doesn't use the assignment operator (=) between AddRecipient and the email address, which is a clue that you're using a method and not simply setting a property like the last bit of code did.
Jmail.AddRecipient "[email protected]" Jmail.AddRecipient "[email protected]"
Next, set the Body text of the message.
Jmail.Body = "This is a test from 32X Tech"
Use the Priority property to change the message's priority. The priority values appear in Table 1.
Jmail.Priority = 1
The next line adds the mail header by pulling the server IP address using the REMOTE_ADDR server variable.
Jmail.AddHeader "Originating-IP", Request.ServerVariables("REMOTE_ADDR")
Use the Execute method to send the mail message.
These changes are for a simple mail message using Jmail. As soon as anyone views the page in a browser, Jmail sends the email automatically. The only requirements are that your SMTP server name and email addresses be valid and Jmail reside on the Web server.
Sometimes, you need to create email based on email addresses from a database. For example, let's say you have an extranet that provides support for your customers and vendors. You'll likely have a database of key contacts for these companies, including their email addresses. If you do, you can publish a special email message to those companies at any time by using ActiveX Data Objects (ADO) to pull the data from the database, then use Jmail or another mail component to generate the email messages. The second example, which Listings 2 and 3 show, does just that.
Instead of mixing HTML and script, MailDB.asp is a structured code (i.e., a code that is complete with subroutines and functions that perform logical tasks) that provides email support. You can use this script anytime you need to use data-driven email in your application. Let's start with the code in Listing 2. The second line of this code performs a very important task: the Option Explicit statement causes VBScript to only allow the use of variables that you have explicitly defined.
If you use Option Explicit, then the script will not execute unless you define every variable like this:
Some people say that using Option Explicit, which forces explicit declaration of all variables, is a hassle and unnecessary. I think it's vital. If you don't use Option Explicit and you type Jnail instead of Jmail, you might spend hours trying to find out why the code doesn't logically work before you discover that you've used an n instead of an m. Use Option Explicit, and that problem won't occur.
The Jmail variable. Because the Jmail variable must be global to the entire script, define the variable at the start of the script. You use this variable, which contains the reference to the Jmail component, in two different procedures. If you declare the variable in only one of the procedures, the variable will be local to that procedure and won't be available to the other procedure.
The InitMail procedure. The InitMail procedure contains all the startup code for Jmail. Placing the code in a procedure isolates it so that it's used only once per execution of the script. Therefore, the code runs more efficiently because the startup code is executed only once per mail session. The InitMail procedure is also handy because it localizes all the startup functions.
The SendMail procedure. The SendMail procedure sends an email message. This procedure is easy to use because it takes all the data it needs for sending an email message as parameters when it executes, then it generates the email message. Notice that SendMail takes only one recipient. You can use the AddRecipient method repeatedly to add many recipients to a message, but this method puts all of those recipients in the message's To list. What happens when you want to send mail to a lot of people, but you don't want anyone on the list to get the email address of anyone else on the list? For this reason, you want to use only one recipient per message instead of AddRecipient.
The code after the SendMail procedure interacts with HTML and ADO. First, the script declares the variables.
Dim oRS, sDSN, sBody, sSubject, iPriority, sTo
Then, the script uses InitMail to set up Jmail.
The script uses the ASP Request object to extract the contents of the variables from the HTML form used to feed MailDB.asp. Listing 3 shows the code for the form. When the following three lines of code execute, the local variables will contain the values you enter in the browser.
sSubject = request("txtSubject") sBody = request("txtBody") iPriority = request("lstPriority")
As an alternative, you can feed the subject and body information from a database or file instead of entering it with a browser. The choices are almost limitless. (Later in this article, I look at some alternatives for entering the body text.)
The following line creates an instance of the ADO Recordset object.
Set oRS = server.CreateObject("adodb.recordset")
Set the sDSN variable to the connect string for the database server. You must change this code to work with your server. The Data Source attribute specifies the server name, and the Catalog attribute specifies the database.
sDSN = "Provider=SQLOLEDB.1;Persist Security Info=False; & User ID=sa;Initial _ Catalog=MyCompany;"Data Source=DATASERVER;"
The next line opens the ADO Recordset. You must change this line to properly define the DSN for your database. This code pulls data from the MailList table.
oRS.Open "Select * from MailList", sDSN
The Do...Loop statement does all the work. The loop goes through the Recordset one record at a time. For each record, the loop sets the sTo variable to the email address from the database, then SendMail executes to send the email message.
Do While Not oRS.EOF sTo = oRS ("EmailAddress") . . . SendMail sSubject, sTo, sBody, iPriority oRS.MoveNext Loop
Finally, the code closes the Recordset, sets the oRS and Jmail variables to nothing, and redirects the User to the MailGenerator page.
oRS.Close Set oRS = nothing Set Jmail = nothing Response.Redirect "MailGenerator.htm" %>
Adding Other Features
So far, you've seen how to create a simple script that generates an email message and how to create an ASP script that generates email. Now, let's take a look at other features that you might want to add to your mail.
Attachments. At times, you might want to send attachments with a mail message. Maybe you're generating a special promotion or have some other type of document that must go with the mail message. The syntax for attaching documents is straightforward. You simply use the AddAttachment method and specify the path to the file you want to attach. For example, the following line attaches the dec99promo.doc file.
Jmail.AddAttachment "N:\promotions\dec99promo.doc "
If you're going to use attachments or files with Jmail or other components, you must make sure that the user account accessing the files has the proper security access. For example, if your site is using Anonymous security, then you must make sure the IUSR_machinename account (or the account you changed it to) has the appropriate access to read the target files, which might be even more interesting if the files are on a network drive, as in the example just given (i.e., N:). If you let users input the filename, the security issue becomes more complex because users might specify files that are anywhere on the network or even on their local workstations.
AppendBodyFromFile. You can use the AppendBodyFromFile method to load an email message's body with text from a file. The method appends the text to the body but doesn't replace text already there, which lets you use AppendBodyFromFile to add just a footer to the body. The syntax is
Adding Error Handling
I recommend that you add error handling to your application to make sure that emails go out when you intend them to. Jmail sends mail through an SMTP server, which results in nondeliverable mail being either trapped by the SMTP server or routed to the ServerAddress address. Error handling is also necessary to make an application robust. Error handling in ASP limits you to a rudimentary error-handling method. You use the On Error Resume Next statement to turn on error handling in VBScript.
On Error Resume Next
When this statement executes in a script, runtime errors won't stop the script's execution and generate error messages in the browser. Instead, the script continues executing after the error. Thus, you must use the proper error-handling techniques to make sure you catch and fix any errors.
One technique you can use with most objects in VBScript/ASP code is the VBScript Err object. The Err object has properties that you set when a runtime error occurs. You typically check the status of the Err object by inserting an If...Then...Else statement in your code.
If Err <> 0 Then
If the Err.Number property is not 0, the If statement code executes and handles the error. Number is the default property of the Err object, so you don't need to explicitly specify Number when you want to access it.
You can access the description of an error message by checking the Description property of the Err object. The entire If...Then...Else statement to check for errors might look like
If Err <> 0 Then Response.Write "An error occurred. <br>" Response.Write "Error: " & err.number & "<br>" Response.Write "Error: " & err.description & "<br>" End If
Checking for errors immediately after you execute a section of code is important. If you don't, you might check the Error object and find an error that occurred earlier in the code. For example, you could put an If...Then...Else statement to check for errors after the Do...Loop statement in Listing 2. But what happens if the error occurs somewhere within the Jmail code or within the ADO code?
Another consideration arises when you use a component such as Jmail on the Web: Jmail includes its own error properties. The Jmail error properties are
- Jmail.ErrorCode-returns the error code as an integer
- Jmail.ErrorMessage-returns a description of the error
- Jmail.ErrorSource-returns the source of the error if you set the Silent property to true
Listing 4 shows JmailError.asp. This code uses the Jmail error properties to output a message in the browser if any errors occur. I adapted this code from an error-handing example ("Error trapping in w3 Jmail") on the Dimac Web site. (Although the code on the Web site demonstrates how to use the Jmail error-handling properties, it doesn't work.) Listing 4 illustrates several interesting points about error handling in Jmail.
Silent. You can put Jmail into Silent mode with the code
Jmail.Silent = true
Silent mode causes Jmail not to issue any runtime error messages, but lets Jmail use the error messages. If you look closely at the Execute line, you can see how the If...Then...Else statement is checking the return value of Execute. If Execute doesn't return true, the error-handling code executes. This approach is nice because it lets your code trap the error and handle it programmatically. A script such as MailDB.asp needs to use Silent mode to trap errors.
Logging. You can turn on Logging, which causes Jmail to log the results of its various operations, with the statement
Jmail.Logging = true
Logging is useful because you can retrieve information from the log and determine the operations that occurred. The log is actually read in Listing 4 as part of the error handler in the If...Then...Else statement.
Modifying Your Code
What happens if you move your Web site to a new ISP and that ISP uses a different email package? If you've taken the time to carefully isolate the email code that appears in Listing 2, then all you need to do is change a few lines of code. If you're using the Microsoft Windows NT 4.0 Option Pack, the only change you really need to make to the code is to change the address of the SMTP server. Then your application will work fine with the new component. Most email components use a similar interface, which makes moving between different components fairly easy.
A lot of email options for ASP exist-Jmail is but one. Other components, such as ServerObject's AspMail (http://www.serverobjects.com) and NextWord's ActiveMail (formerly ActiveMail) (http://www.nextword.com/clearviewprod.htm), offer comparable features. In fact, one ISP I used had installed AspMail. I converted my application to Jmail by simply changing one procedure. You can find these components by searching the Internet for Internet mail components or ASP components. Most of the techniques in this article work with any email package, which makes it easy to modify the techniques for that program or component.