电脑报精华 · 2000 年 · 2000wl073

ASP环境下邮件列表功能的实现

ASP环境下邮件列表功能的实现

邮件列表(Mailing List)是当前最受欢迎的网络服务之一。本文通过一个示例系统的建设,介绍在ASP环境下邮件列表功能的实现方法。
一、系统概貌
整个应用系统可以分为两个部分,即面向最终用户的功能和面向管理任务的功能。面向最终用户的功能主要包括:提供输入界面让用户输入个人信息(用户名字和EMail地址等)并将其注册到“客户登记簿”,提供“取消订阅邮件列表”功能。
管理员访问管理界面之前应通过简单的安全检查。成功进入管理界面之后,管理员需要执行的操作包括查看、编辑和删除用户记录,编辑邮件以及发送邮件给所有订阅者。
向订阅者发送邮件需要用一个服务器部件来完成。在本实现中我们将使用ServerObjects的ASPMail 3.0。据该公司网站介绍,在所有商业或免费的类似产品中,ASPMail在ASP环境下的应用最为广泛,包括Microsoft、Intel、HP在内的许多公司均使用ASPMail,从它的Web网站可以下载试用版本。试用版本的ASPMail将在由它所发送的每个邮件末尾加上版权声明。当然,也可以选用其它类似的服务器部件,包括JMail以及NT 服务器(Service Pack 4)提供的CDONTS.NewMail对象。下面我们简单介绍这两个部件的使用,你可以按照这里的介绍替换本文实现中的ASPMail。
CDONTS只有在NT服务器上才是可用的。而ASPMail除了NT服务器、工作站之外还可以用于Win9x。CDONTS是Collaboration Data Objects for NT Server的缩写,邮件的发送任务可以用它的NewMail对象完成。和ASPMail以及JMail不同,NewMail对象不要求指定SMTP服务器信息,它总是假定邮件是通过本地机器上安装的邮件服务发送的。
发送一个简单的纯文本邮件的VBScript代码如下:

 ' 创建NewMail对象实例
 Set mail = Server.CreateObject("CDONTS.New- Mail")
 ' 设置收件人,发件人等信息
 mail.From = "[email protected]"
 mail.To = "[email protected]"
 ' 邮件内容
 mail.Body = "邮件内容."
 ' 发送邮件
 mail.Send
 Set mail = Nothing

JMail是完全免费的,由Dimac开发。用它来发送邮件的代码为:
 ' 创建对象
 Set JMail = Server.CreateObject("JMail.SMTP-Mail")
 ' 指定邮件服务器
 JMail.ServerAddress = "mail.mydomain.com"
 ' 发件人,收件人,主题
 JMail.Sender = "[email protected]"
 Jmail.AddRecipientEx "Guest0", "[email protected]"
 JMail.Subject = "邮件主题"
 ' 邮件内容
 JMail.Body = "邮件内容"
 ' 发送邮件
 JMail.Execute

我们用Access数据库guestbook.mdb来存储用户信息。该数据库只含一个表Guests。Guests表的字段名称及其类型如下表:

每个用户记录都需要一个唯一标识,因此我们将这里的Guest_ID字段定义为自动编号类型。将Mail_List字段设为是/否类型使得我们可以快速和方便地检查用户是否要求加入邮件列表。Sign_Date字段保存的是用户注册日期,请将其缺省值设置为Now()。所有其它字段的含义均可从其名字看出。
二、面向用户的功能
为最终用户提供的功能主要由一个HTML文件和两个ASP文件提供,它们负责接受用户的订阅申请以及退出邮件列表申请。
用户的个人信息在图1所示的登记表单中输入,其实现文件是homepage.htm。当用户提交表单,系统对用户输入数据进行必要的验证,然后把它们保存到数据库并提示注册成功信息。这部分功能可以在signbook.asp文件找到,下面的代码用于将用户输入数据保存到数据库:

  ' 如果用户输入数据验证通过则将它保存到数据库
  if blnValid = True then
  ' 在数据库中插入新记录
  strSQL_Insert = "INSERT INTO Guests ( Guest_Name, Guest_Email, " & _
" Mail_List, Guest_Comment )" & _
" VALUES ('" & strName & "', '" & strEmail & _
"', '" & blnMailList & "', '" & strComments & "');"
  Set oConn=Server.CreateObject("ADODB.Connection")
  oConn.Open strDSNPath
  On error resume next
  oConn.Execute strSQL_Insert
  oConn.Close
  Set oConn = Nothing
  ' 记录插入是否成功
  if err.number < > 0 then
  ' 出现错误
  strValid = …数据库操作错误提示信息,略…
  else
  '记录插入成功
  strValid = …注册成功提示信息,略…
  end if 'err.number < > 0
  else '用户输入数据错误
  strValid = ...用户输入数据错误提示,略...
  end if 'blnValid = True
这些代码实现了面向最终用户的第一个功能:将个人信息注册到登记簿并将用户加入到邮件列表。
每一个从邮件列表接收邮件的用户可以在邮件的最后发现一个链接(类如http://www.mycompany.com/unsubscribe.asp),以及用户ID和邮件帐号的提示。单击这个链接可以访问取消订阅的unsubscribe.asp页面,其界面如图2所示。当用户提供了正确的EMail地址和ID号,unsubscribe. asp中的脚本修改该用户注册记录的Mail_List标记,从而使得系统不再向该用户发送邮件。下面是这部分功能的实现代码:

 < %
 if Request.ServerVariables("REQUEST_METHOD") = "POST" then
 iGuestID = Request.Form("txtID")
 sGuestEmail = Request.Form("txtEmail")
 if iGuestID < > "" and sGuestEmail < > "" then
 '在数据库中更新用户记录
 strSQL_UnSubs = "UPDATE Guests SET Guests.Mail_List=" & 0 & _
 " WHERE Guests. Guest_ID=" & iGuestID & _
 " AND Guests.Guest _Email='" & sGuestEmail & "';"
 Set oConn = Server.CreateObject("ADODB.Connection")
 oConn.Open strDSNPath
 oConn.Execute strSQL_UnSubs, iUpdates
 on error resume next
 oConn.Close
 Set oConn = Nothing
 if err.number < > 0 then
 sError = ...SQL语句执行失败提示信息, 略...
 else
 if iUpdates < > 0 then
 sError = ...取消订阅成功提示信息,略...
 else
 sError = ...不能找到数据库记录提示信息,略...
 end if 'iUpdates < > 0
 end if 'err.number < > 0
 else
 Response.Redirect("homepage.htm")
 end if 'iGuestID < > ""
 end if 'REQUEST_METHOD = "POST"
 %>
执行SQL命令时提供的iUpdates变量反映了该SQL语句所影响的记录数。如果该值为0,即可假定用户没有正确地输入ID或EMail地址。上述代码实现了面向用户的第二个功能,接下来我们要实现的是登记簿的管理功能。
三、用户注册记录管理
在访问管理页面之前必须经过身份验证。本实现中我们用图3所示的secure.htm页面供管理员输入身份识别码,若用户输入值非空则用Cookies来保存它。执行管理任务的页面是admin.asp,每当用户试图访问这个页面,下面的代码将检查这个Cookies与用户身份识别码(这里是123456)是否匹配,如匹配失败则将该用户重定向到输入身份识别码的secure.htm页面。

 < %
strPW1 = Request.Form("txtPW")
 if strPW1 < > "" then
Response.Cookies("PassWord") = strPW1
 end if 'strPW1 < > ""
 strPW2 = Request.Cookies("PassWord")
 If strPW2 < > "123456" Then
Response.Redirect("secure.htm")
 End if 'strPW2 < > "123456"
 %>
一旦管理员的身份验证通过,他们能够通过Admin.asp执行的操作包括:
*查看Guests表中的所有记录
*向所有邮件列表中的用户发送邮件
管理页面admin.asp如图4所示。显示Guests表的记录时先从数据库提取这些记录,然后使用一个For Each ... Next结构遍历记录集的字段集合,提取字段名字并设置表格的表头。在这个页面中我们不再显示Guest_ID字段,但每个用户记录的前面都加上了一个“删除”和“编辑”功能的链接。用户名字字段Guest_Name与邮件字段Guest_Email被转换为mailto链接,单击名字可以单独向该用户发送邮件。其它要格式化的字段还包括是否发送邮件(Mail_List)以及用户留言(Guest_Comment)。生成表头的代码为:

 ' 从数据库选取记录
 strSQL_Select = "SELECT Guests.Guest_ID, Guests.Guest_Email, " & _
" Guests.Guest_Name, Guests.Mail_List, " & _
" Guests.Guest_Comment, Guests.Sign_Date " & _
" FROM Guests ORDER BY Guests.Guest_Name; "
 Set oConn=Server.CreateObject("ADODB.Connection")
 oConn.Open strDSNPath
 Set rsGbook = oConn.Execute(strSQL_Select)
 if rsGbook.BOF = True and rsGbook.EOF = True then
...数据库空提示,略...
else
rsGbook.MoveFirst
%>
  < table BORDER="0" cellpadding="5" cellspacing="2" align="center">
 < tr>
  < % for each Head in rsGbook.Fields
  if Head.Name = "Guest_ID" then %>
..."删除"与"编辑"表头,略...
  < % else %>
 < td VALIGN="middle" align="center">< font face=Arial size=2>
  < % select case Head.Name
 case "Guest_Name"
 Response.Write "名字"
 case "Mail_List"
 Response.Write "邮件列表"
 case "Guest_Comment"
 Response.Write "留言"
 end select
  %>
  < /font>< HR>< /td>
 < % end if 'Head.Name = "Guest_ID"
 next %>
< /tr>
为在表格的其余位置显示用户注册记录,我们用两个嵌套的循环遍历所有记录的所有字段,即在一个Do While ...循环里面嵌入一个For Each ... Next 循环。数据的格式化工作放在For Each ... Next循环内。其实现代码类如:

 < % Do While Not rsGbook.EOF %>
< tr>
 < % For Each Field in rsGbook.Fields
 if Field.Name = "Guest_ID" then %>
< td VALIGN="middle" ALIGN="center">
...删除功能的链接,略...
< /td>
< td VALIGN="middle" ALIGN="center">
...编辑功能的链接,略...
< /td>
 < % else %>
< td VALIGN="middle" align="center">
 < % if isNull(Field) then
Response.Write " "
else
 if Field.Name = "Guest_Name" then
 Response.Write ...用户名字的mailto链接,略...
 elseif Field.Name = "Mail_List" then
...输出"是"或"否",略...
 elseif Field.Name = "Guest_Comment" then
...输出用户留言,略...
 end if 'Field.Name
end if 'isNull(Field)%>
 < /td>
 < % end if 'Field.Name = "Guest_ID"
Next
rsGbook.MoveNext %>
< /tr>
 < % loop %>
 < /table>
现在我们已经把数据库记录显示在表格中了。单击表格中的图形链接可以访问edit_record.asp和delete_record.asp,这两个文件分别提供记录的编辑和删除功能。首先我们来看看删除功能的实现:

 < %
 iGuestID = Request.Querystring("ID")
 if iGuestID < > "" then
 '从数据库删除由ID标识的记录
 strSQL_Delete="DELETE FROM Guests"& _
"WHERE Guest_ID="& iGuestID
 Set oConn = Server.CreateObject("ADODB.Connection")
 oConn.Open strDSNPath
 on error resume next
 oConn.Execute strSQL_Delete
 oConn.Close
 Set oConn = Nothing
 if err.number < > 0 then
 Response.Redirect("admin.asp?Error_Del=True")
 else
 Response.Redirect("admin.asp?Error_Del=False")
 end if
 else
 Response.Redirect("admin.asp")
 end if 'iGuestID < > ""
 %>
上述代码与unsubscribe.asp中的代码非常相似,实际上两者完成的任务也很类似。这里的ID是必须的,它标识了要求删除的记录。实际的删除任务通过DELETE SQL命令完成。
更新记录页面edit_ record.asp所用的代码稍微复杂一点,其界面如图5所示。这里要用到两个SQL语句:第一个SQL SELECT语句从数据库选取需要编辑的记录;第二个SQL UPDATE语句将管理员编辑结果保存到数据库。这里我们不再具体分析实现过程,请参见本文所附代码及其注释。

四、邮件的编辑及发送
最后要实现的功能是邮件的编辑和发送。这部分功能由Email_List.asp文件提供,其界面如图6所示。接下来我们就来分析这个文件。

Email_List.asp的内部工作过程和edit_record.asp很类似。管理员在表单中写作邮件并提交它,系统将选择所有Mail_List字段值为“是”的记录,然后将新邮件的拷贝发送给这些记录中的Guest_Mail地址。
每一次发送邮件我们都重新创建mailer对象,发送完成后关闭它。这一点非常重要,这是由于我们需要修改邮件的正文,加入取消订阅邮件列表的URL和ID号。
if Request.ServerVariables("REQUEST_METHOD") = "POST" then
 strSubject = Request.Form("txtSubject")
 strBody = Request.Form("txtBody")
 strFrom = Request.Form("txtFrom")
 ' 从数据库选取收件人记录
 strSQL_SelectEmail = "SELECT Guests.Guest_ID, Guests.Guest_Email " & _
 " FROM Guests WHERE ((Guests.Mail_List)=-1);"
 Set oConn = Server.CreateObject("ADODB.Connection")
 oConn.Open strDSNPath
 Set rsMail = oConn.Execute(strSQL_SelectEmail)
 if rsMail.BOF = True and rsMail.EOF = True then
...数据库为空提示,略...
else
rsMail.MoveFirst
Do While Not rsMail.EOF
' 创建对象
Set Mailer = Server.CreateObject("SMTPsvg.Mailer")
' 填写其它邮件标题信息
Mailer.FromName = strFrom
Mailer.FromAddress = strEmailFrom
Mailer.RemoteHost = strHost
Mailer.Subject = strSubject
Mailer.BodyText = ...设置邮件内容,略...
strTo = rsMail.Fields("Guest_Email").Value
If strTo < > "" then
Mailer.Recipient = strTo
if Mailer.SendMail then
  ...发送成功提示,略...
  else
  ...发送失败提示,略...
end if 'Mailer.SendMail
end if 'strTo < > ""
rsMail.MoveNext
Set Mailer = Nothing
Loop
 end if 'rsMail.BOF = True and rsMail.EOF = True
 rsMail.Close
 Set rsMail = Nothing
 oConn.Close
 Set oConn = Nothing
 end if 'REQUEST_METHOD = "POST"
这里需要注意的是,我们将变量strHost的值赋给ASPMail的实例对象的RemoteHost属性。因此,必须保证strHost的值是一个合适的邮件服务器名字(如mail.mydomain.com)。
(仙人掌工作室)