网站邮件的异步发送

网站使用免费的Jmail进行邮件发送,当某一个操作直接与邮件发送动作关联时,会造成2~5s左右的延迟,实际使用体验不佳。因此对于邮件采用异步发送方案才是更好的选择。

一、改造步骤

1、在数据库中新增[mails]表,注意增加一项sender用于记录邮件发送人(之前是通过直接识别当前用户确定发件人,异步的话就必须留下发件人信息了)。

2、在公用文件中定义savemail函数,用于将邮件的相关信息直接存储进[mails]表。注意,邮件的body需要先使用HTMLEncode()函数进行处理,否则insert into [mails]时会出错。实际发邮件之前,再用HTMLDecode()函数还原。

3、修改mailfunction,修改发件人的获取来自sender。

4、将所有相关sendmail操作,替换为savemail操作。

5、增加mailcron页面,用于检查[mails]表并将它们全部发送出去。发完的邮件即刻从[mails]表格中删除。

6、新增系统任务计划,建议5~10分钟执行一次,程序使用powershell.exe,参数为:

-Command "& {Invoke-WebRequest -Uri 'mailcron_page_url'}"

7、可以创建一个showmails页面来监控当前[mails]表格中的待发邮件情况。

二、注意事项

1、格式化问题

之前对网页端的富文本编辑器输入的内容进行格式化使用的HTMLEncode函数和HTMLDecode函数,也处理了<br>标签。对于邮件功能而言,mailbody不涉及到用户输入,因此无需处理<br>,否则<br>被替换为vbCrlf后,在邮件正文中并不会被正确处理。

一种解决方法是设置一个专门的HTMLDecodeMail函数,让它不处理<br>。但实践证明,这样做,有一定概率HTML代码仍然会被破坏,导致一些格式化的语句不能正确显示。

更可靠的方式是,使用参数化的查询方式。定义一个ADODB.Command:

Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
‘用?占位符代表了字符串变量1
.CommandText = "insert into [table] (column1,column2) values (?,'"&变量2&"')"
'指定命令类型为文本命令
.CommandType = 1
‘201表示长文本,1表示这是一个输入的参数,65530表示最大长度,第一行匹配第一个?
.Parameters.Append .CreateParameter("param1", 201, 1, 65530, s_body)
.Execute
End With
set cmd=nothing

具体一些常量的定义参见adovbs.inc。

这样一来,就可以顺利将s_body写入数据库,并且后续邮件操作中也无需再对内容编码/解码。

2、邮件头Reply-To的有效性问题

实践证明,JMail组件4.5版本,支持通过JMail.ReplyTo方法设置x-header中的“reply-to”参数。但必须注意,不是所有的邮件客户端都支持这个参数,例如“QQ邮箱”的安卓客户端就不支持。Samsung 电子邮箱客户端、Gmail客户端,以及Foxmail桌面程序,都支持。

因此即使设置了Reply-To,邮件中可能还是要给出提醒。