IBM Notes:创建按用户输入日期发送邮件的定时代理
实现按指定日期定时发送邮件的方案
针对你的需求,我们需要把「立即发送邮件」的逻辑拆成两部分:存储待发送任务和定时触发发送。下面是具体的实现步骤和代码修改:
一、修改原按钮代码:创建待发送任务文档
原来的按钮是直接发送邮件,现在我们改成创建一个专门的「待发送邮件任务」文档,把邮件的关键信息(收件人、主题、正文、发送日期)都存进去,留给后面的定时代理处理。
假设你的表单上已经添加了一个日期字段SendDate(让用户选择要发送的日期时间),修改后的按钮代码如下:
Sub Click(Source As Button) Dim incharge As String Dim Session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase Dim ws As New NotesUIWorkspace Dim uidoc As NotesUIDocument Dim doc As NotesDocument Dim varValues As Variant Dim varCC As Variant Set uidoc = ws.currentDocument Set doc = uidoc.Document ' 获取用户输入的发送日期 Dim sendDateTime As NotesDateTime Set sendDateTime = doc.GetItemValue("SendDate")(0) If sendDateTime Is Nothing Then Msgbox "请选择要发送的日期时间!", MB_EXCLAMATION Exit Sub End If varCC = "(the CC address)" varValues = doc.GetItemValue( "incharge" ) ' 把员工信息整理成数组,简化循环逻辑 Dim employeeList As Variant employeeList = Array( _ Array("Employee 1", "Employee 1 Address", "Message"), _ Array("Employee 2", "Employee 2 Address", "Message"), _ Array("Employee 3", "Employee 3 Address", "Message"), _ Array("Employee 4", "Employee 4 Address", "Message"), _ Array("Employee 5", "Employee 5 Address", "Message"), _ Array("Employee 6", "Employee 6 Address", "Message") _ ) Dim empInfo As Variant For Each empInfo In employeeList Dim empName As String, empAddr As String, empMsg As String empName = empInfo(0) empAddr = empInfo(1) empMsg = empInfo(2) If Not Isnull( Arraygetindex( varValues, empName ) ) Then ' 创建待发送任务文档 Dim pendingDoc As NotesDocument Set pendingDoc = db.CreateDocument pendingDoc.Form = "PendingEmail" ' 需要先创建这个表单 pendingDoc.SendTo = empAddr pendingDoc.CopyTo = varCC pendingDoc.Subject = "(subject)" pendingDoc.Body = empMsg pendingDoc.Principal = "(the sender address)" pendingDoc.SendDate = sendDateTime ' 存储计划发送的时间 pendingDoc.Status = "Pending" ' 标记为待发送状态 Call pendingDoc.Save(True, False) End If Next Msgbox "定时发送任务已创建,将在指定时间发送邮件!", MB_INFORMATION End Sub
关键准备工作:
你需要先在数据库中创建一个名为PendingEmail的表单,包含以下字段:
SendDate(日期时间型):存储计划发送的时间Status(文本型):标记任务状态(Pending表示待发送,Completed表示已发送)SendTo(文本/姓名型):收件人地址CopyTo(文本/姓名型):抄送地址Subject(文本型):邮件主题Body(富文本/文本型):邮件正文Principal(文本型):发件人地址
二、创建定时触发的代理:执行发送任务
接下来创建一个定时代理,让它定期扫描数据库中的PendingEmail文档,当到达指定发送时间时,执行邮件发送操作。
代理设置步骤:
- 在Notes Designer中打开目标数据库,新建代理
- 代理类型选择「LotusScript」
- 触发方式选择「定时运行」,比如设置为「每天」或者「每小时」运行一次(根据你的需求调整频率)
- 目标可以选择「所有文档」,或者后续通过视图筛选更高效
代理代码:
Sub Initialize Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase ' 获取当前服务器时间 Dim currentTime As NotesDateTime Set currentTime = New NotesDateTime(Now) ' 查询所有待发送的任务文档 ' 建议后续创建一个专用视图(选择公式:SELECT Form="PendingEmail" & Status="Pending"),用视图查询效率更高 Dim collection As NotesDocumentCollection Set collection = db.Search({Form="PendingEmail" & Status="Pending" & SendDate <= @Now}, Nothing, 0) Dim doc As NotesDocument Set doc = collection.GetFirstDocument() While Not doc Is Nothing Dim sendDate As NotesDateTime Set sendDate = doc.GetItemValue("SendDate")(0) ' 判断是否到达发送时间(考虑可能的时间差) If sendDate.TimeDifference(currentTime) <= 0 Then ' 创建邮件文档并发送 Dim email As NotesDocument Set email = db.CreateDocument email.Form = "Memo" ' 使用标准邮件表单 email.Principal = doc.Principal(0) email.Subject = doc.Subject(0) email.CopyTo = doc.CopyTo email.SendTo = doc.SendTo email.Body = doc.Body ' 发送邮件(False表示不保存已发送邮件到发件箱) On Error Resume Next Call email.Send(False) If Err = 0 Then ' 发送成功,标记任务为已完成 doc.Status = "Completed" doc.SentTime = currentTime Call doc.Save(True, False) Else ' 发送失败,记录错误信息方便排查 doc.ErrorMsg = Err & ": " & Error$ Call doc.Save(True, False) End If On Error GoTo 0 End If Set doc = collection.GetNextDocument(doc) Wend End Sub
优化建议:
- 优先创建专用视图:创建一个视图展示待发送任务,选择公式为
SELECT Form="PendingEmail" & Status="Pending",并按SendDate排序,代理通过视图查询会比用Search方法效率更高。 - 时区处理:如果用户和服务器不在同一时区,需要确保
SendDate存储的是服务器时区的时间,或者在代码中做时区转换。 - 失败重试:可以给发送失败的任务添加重试逻辑,比如标记为
Failed,后续代理再次尝试发送。
内容的提问来源于stack exchange,提问作者Jamie




