Notes这套老伙计,平时安安静静没人夸,可真到了给全公司发通知、给几百个客户推版本更新、给各个部门同步报表的时候,大家又都会齐刷刷想起它。我前前后后处理过不少“邮件群发”的活儿,也看过太多种翻车方式:一封邮件塞四五百个地址然后被服务器拒收、群发出去一半人收到乱码、发完领导问“为什么有人说没收到”……这些坑单独拎出来都不大,叠在一起就足够让人怀疑人生。
之所以想“再谈”一次,是因为之前那篇更多讲的是基本操作,真到了复杂场景里,还有不少细节没被说透。这篇我不会再从“什么是Notes”讲起,直接按实际操作过的路径来:怎么选群发方式、发送前要清哪些地址底子、内部通知型群发怎么设置选项、大批量定制内容怎么写代理、群发之后的退信和“静默失败”到底怎么定位。如果你手头正好在维护跑Notes的单位邮件系统,下面这些内容大概率能替你省下几个小时的排查时间。
1. 先把Notes群发的路径选明白
不少刚接触Notes的人,以为“群发”就是新建便笺,然后往收件人栏里塞一堆地址。这么干在小范围应急时没问题,但一旦数量上到几十上百,或者内容必须因人而异,这条路就走不通了。我的习惯是先按场景把群发路径定下来,再动手。
用得最多的有三条路:
- 直接新建便笺,手工填多个收件人或拖入群组。适合五十人以内、内容完全相同、发送频率低的通知类邮件。优点是没有学习成本,缺点是收件人地址一旦出错,退信只能一封封看。
- 通过通讯录群组批量发送。适合常态化通知,比如部门公告、周报同步、节假日提醒。把固定名单维护成群组后,每次新建便笺拖一个组名进去就行。上到一两百人没有问题,是Notes群发最舒服的形态。
- 用代理(Agent)或脚本逐封生成并发送邮件。适合几百上千人、内容带定制字段、或者收件人名单来自业务数据的场景。它最灵活,也最需要谨慎,写错了容易产生批量事故。
这三条路之间并不是非此即彼。我做方案时会先问一句:这份名单是稳定的还是每次都在变?内容是统一的还是因人而异?
名单稳定、内容统一,优先维护通讯录群组;名单来自Excel或业务库、内容每个人不同,就上代理;临时三五封,手工最省事。表格看一眼就清楚:
| 场景 | 推荐路径 | 上限参考 | 风险点 |
|---|---|---|---|
| 临时通知、小范围同步 | 手工便笺多收件人 | 约50人以内 | 地址填错不易发现 |
| 固定名单、常态更新 | 通讯录群组 | 500人以内问题不大 | 群组维护不及时 |
| 千人级、内容差异化 | 代理逐封发送 | 取决于服务器限额 | 脚本错误、触发网关限制 |
选路径这件事,本质上是把“发送动作”和“名单管理”分开。手工便笺的问题是名单和发送绑在一起,每次都要重新敲地址;群组把名单沉淀下来,发送只是一个拖拽动作;代理则是把名单从文件流转成邮件流,适合自动化。想明白了这一点,就不会再纠结“该不该用群组”或者“要不要写代理”了。
2. 群发前先把“地址底子”清理干净
很多人群发出问题,根本原因不在发送过程,而在地址本身。Notes环境里的地址有两副面孔,必须分清。
一类是Notes内部层级地址,长这样:CN=张三/OU=部门/O=单位。这是Domino目录里人员文档的标识,Notes路由器靠它把邮件送到内部数据库。另一类是Internet地址,就是常见的zhangsan@example.com。给外部用户发信,Domino最终会走SMTP协议,用的就是这种地址。
问题出在混合场景。比如一个群组里既有内部员工,又有外部合作伙伴的邮箱地址。你新建便笺时如果格式没设对,外部用户可能收到一串乱码,或者对方根本看不懂信封上的内容。我自己处理过一个典型的“格式灾难”:某次群发把纯Notes格式直接发给了外部邮箱,外部客户收到的正文变成了一堆带=号的编码文本,看起来就像被加密了。
所以群发之前,我会先去“文件 → 首选项 → 邮件”里把发送格式确认一遍。如果群里既有内部地址又有外部地址,最稳妥的选择是“多格式”,让Domino按收件人类型自动决定用Notes富文本格式还是MIME格式。切忌为了省事把所有邮件强制设为纯Notes格式,否则外部收件人大概率吃亏。
除了格式,还有三个检查项目我几乎每次都做:
- 群组成员里有没有已离职或已停用的账号。这种地址发出去,轻则退信,重则被他人代收或误投。
- 外部地址拼写是否准确。群组里混入一个写错的域名,整组发送就会带着一封退信回来,还可能因为太久没维护导致批量错误。
- 有没有把“仅供管理使用”的群组拿来发信。这种组在普通用户的通讯录里可能看不到,或者选了就报错。
第三点值得多说一句。Notes群组文档里有个属性叫“仅供管理使用”,勾选后普通用户在邮件地址选择器里就找不到这个组了。很多管理员建组时顺手勾上,之后自己忘记,还以为是通讯录不同步。遇到“群组明明存在却选不到”时,先去检查这个开关。
地址底子的另一层含义是“别名和显示名”。Domino目录里的人名可以很长,比如张三/部门/单位,直接在便笺收件人栏输入时容易敲错层级路径。通用的做法是建一个专用分发组,把规范地址沉淀在组里,发信时只拖组名。这样既不用记复杂地址,也能在群发的“源头”上减少地址错误。
3. 内部通知型群发的完整操作流程
先设定一个最常见的实操场景:要给全公司几个部门的人发一份“系统升级维护通知”,名单大约一百多人,内容相同,附带一个PDF附件。这种任务用通讯录群组完成是最顺的。
打开Notes客户端后,第一步不是新建便笺,而是先在通讯录里确认可用的群组。如果是公司通讯录里已有的组,直接双击它,看看成员列表是否干净。我见过太多人跳过这一步,结果发完才发现组里还躺着几个离职员工。地址是这次的“面粉”,面粉有问题,后面无论怎么操作都白搭。
确认群组没问题后,点击“新建便笺”,在收件人区域输入或拖入组名。Notes会保留组名而不展开每个成员,这正是想要的形态——不仅界面干净,发送时地址解析也由服务器统一处理。
接下来是很多人忽略的“发送选项”。新建便笺后,在发送工具条上找到“发送选项”按钮,重点设置三项:
- 送达报告:选“仅失败时通知”。一百多人的群发如果每封都回执,收件箱会瞬间被几十封系统邮件淹没;“仅失败时通知”能在异常时第一时间暴露问题。
- 收件人不可见:建议勾上。Notes里这个选项可以让当前便笺的收件人列表对其他收件人隐藏,也就是邮件里不展示完整名单。群发内部邮件时,这不仅是礼貌,也是在保护名单结构,防止收到的人把几百个邮箱地址转发出去。
- 优先级:普通通知用“普通”或“低”。站内普通邮件路由消耗时间不会太长,没必要把每封推送邮件都标成高优先级,那样反倒容易在高峰期和其他重要邮件抢队列。
这三项设置好后,再把附件拖进便笺。注意附件大小这一关:Domino服务器在路由器和SMTP层面都有消息大小限制,具体阈值由管理员在服务器配置文档里定义,常见的是10MB到50MB之间。群发场景里,一个10MB的PDF发十个人就是100MB的投递压力,如果收件人中还有外部地址,对方服务器也可能拒收超大邮件。
遇到大附件时,我的处理顺序是:先在单位内网共享盘或文件服务里放一份,邮件正文写清下载路径和访问权限,再附上链接。这比硬塞附件更靠谱,外部收件人也不会因为邮箱已满或附件超限导致整封邮件被弹回。
全部设置完成后,发送前再审核一遍收件人区域和主题行。主题行里别用太多感叹号,也别出现“1888”“免费”这类外部邮箱系统很容易拦下的词,内部Notes路由虽然不受影响,但万一有人设置转发规则转到外部邮箱,就可能触发垃圾邮件过滤。
发送动作本身很快,真正容易被忽略的是“已发送”归档。Notes会默认把发出去的邮件保存在“已发送”文件夹,但群发使用了不可见选项后,已发送文件夹里显示的仍然只是组名,并不会保存完整展开名单。如果需要留痕,最好把这次用到的群组成员列表快照导出一份存档,避免日后“到底发给谁了”变成了悬案。
4. 大批量定制内容:用代理逐封发送
另一种高频需求是名单几百上千、且每个人的内容不完全相同。举个例子:要给一批用户发账号变更通知,邮件正文里必须有各自的用户名和临时密码。这种需求没法用群组一封搞定,因为内容不同;也没法手工一封封发,因为量太大。
正解是写一个LotusScript代理,遍历数据文档,逐封创建邮件并发送。这里我从头讲一下实现思路。
先准备数据源。最简单的方式是在Notes数据库里建一个视图,每条文档对应一个人,文档里至少有三个字段:收件人地址、主题、正文内容。正文内容可以是拼接好的字符串,也可以把用户名、临时密码分别存在字段里,由代理动态拼接。
然后新建一个代理,触发机制选择“对已选文档运行”或者“从操作菜单运行”,语言选择LotusScript。核心流程是这样的:
Sub Initialize Dim session As New NotesSession Dim db As NotesDatabase Dim vw As NotesView Dim doc As NotesDocument Dim mail As NotesDocument Dim rt As NotesRichTextItem Dim recipient As String Dim subject As String Dim body As String Set db = session.CurrentDatabase Set vw = db.GetView("待发名单") Set doc = vw.GetFirstDocument Do While Not (doc Is Nothing) recipient = doc.GetItemValue("Recipient")(0) subject = doc.GetItemValue("Subject")(0) body = doc.GetItemValue("Body")(0) Set mail = db.CreateDocument mail.Form = "Memo" Call mail.ReplaceItemValue("SendTo", recipient) Call mail.ReplaceItemValue("Subject", subject) Set rt = New NotesRichTextItem(mail, "Body") Call rt.AppendText(body) Call mail.Send(False) Set doc = vw.GetNextDocument(doc) Loop End Sub这段代码有几个关键点在真实项目里必须补充完善。
第一,发送后要把源文档标记为“已发送”。最简单的做法是在源文档里加一个字段,比如SentFlag,发送成功后ReplaceItemValue("SentFlag", "1")并保存。这样代理中断重跑时,已经发过的记录可以跳过,不会对同一人连发两封。
第二,错误处理不能少。几百封邮件按顺序发送,中间任何一封因为地址无效或者服务器超时抛出错误,整个代理就会停在那一封上。实际做法是在Send操作外面包一层On Error GoTo或者用Resume Next处理错误,把失败记录先标注出来,全部跑完后集中查看。
第三,数量大到一定程度时不能一封接一封快速循环。有些单位的Domino服务器或者前置邮件网关会限制单用户单位时间内的发信量,比如每小时最多100封。直接在循环里狂奔,前面200封发得很顺利,第201封就被网关拒了。稳妥的做法是分批次或者加延时。比如在循环里数到50封后,让代理暂停几分钟再继续,既能稳住服务器,也会减少被外部反垃圾系统盯上的概率。
第四,发送前一定要把地址类型想清楚。如果列表中有外部用户,SendTo里可以直接写完整Internet地址,Domino会在路由时自动识别。但如果这个地址同时也存在于Domino目录中(比如同一人是内部员工又有外部邮箱字段),服务器可能优先匹配Notes内部地址。这时候要根据需求决定是发内部件还是外部件,必要时在地址前加标记或在收件人文档里调整Internet地址路由策略。
用代理群发真正考验的其实不是代码,而是数据质量。代码再健壮,拿到一份有三分之一空地址的名单也是白搭。我每次写这类代理,都会让用户先把Excel名单导入Notes,然后在视图中做一次“无效地址筛选”,把明显缺前缀、空字段、重复项先过滤掉,再真正跑发送。
5. 群发之后的那些“静默失败”
邮件点下“发送”按钮,不代表任务结束了。Notes的投递机制是异步的:客户端把邮件投递到Domino路由队列,服务器根据收件人类型分别走内部路由或外发SMTP。这个链条上任何一环出问题,都可能让群发变成“部分成功”。
第一批要关注的是送达报告。发送时如果在“发送选项”里选了“仅失败时通知”,那么任何一封投递失败时,Notes都会生成一个投递失败报告(Delivery Failure Report)。这份报告通常包含三样信息:失败的收件人地址、失败原因、失败阶段。常见的原因如下:
| 报错形态 | 大概率原因 | 处理建议 |
|---|---|---|
| 收件人不存在、名称无法解析 | 地址拼错、人员已停用 | 检查名单并修正 |
| 邮箱已满、超过限额 | 对方邮箱容量不够 | 联系对方清理或改用其他通道 |
| 路由失败、无法投递到目标域 | 外部域名错误或网关未启用 | 检查域名拼写及外发网关状态 |
| 消息过大、超过传输限制 | 附件太大或服务器限额调低 | 压缩、拆分或换链接 |
| 对方服务器拒收、被反垃圾拦截 | SPF/DKIM配置缺失或内容特征明显 | 联系管理员检查发信服务器配置 |
第二类问题更隐蔽:送达报告没有报错,但对方表示没收到。这通常不是Notes主动投递失败,而是外部邮箱服务把邮件当垃圾邮件拦下了。Domino作为发信服务器,对外发信时依赖单位的邮件域信誉。如果单位域名的SPF记录没有把Domino服务器的出口IP加进去,对方反垃圾系统很容易以“发件人域不可信”为由拒收。这个时候只能通过IT管理员去补SPF/TXT记录,或者在DNS层面做DKIM签名配置。
我在排查外部群发进垃圾箱时,先要的就是这类云邮箱的拒信或“垃圾邮件”标记样本。从邮件原始头里可以看到认证结果,比如spf=fail或dkim=none,据此判断是服务器信任问题还是内容问题。如果是信任问题,发多频繁都会进垃圾箱,和文字写得好不好没关系。
第三种失败是群组内部的“一人患病,全组吃药”。群发时收件人栏放的是组名,但发送后某个成员地址无效,投递失败报告里会把这个成员的具体地址标出来,其他成员不受影响。风险在于大量错误地址同时堆积时,服务器可能对整条消息产生延迟。有一次处理某单位群发,组里混入了几十个早已停用的旧账号,结果整组邮件的投递时间从几秒拉长到几十分钟,后来清理名单才恢复正常。
还有个经常会问到的功能:邮件发出去了还能不能撤回?Notes有撤回机制,但适用范围很有限。只有收件人尚未读且邮件还在服务器邮箱文件中时,撤回通知才可能生效;一旦对方已经打开邮件,或者你发的是外部互联网地址,撤回基本是摆设。所以群发之前认真检查名单,远比发完之后想办法“后悔”要实际得多。
群发后的“静默失败”是最磨人的情况,原因不外乎几个:DNS解析、服务器认证、地址失效。这些在发送成功界面里根本看不出来,只能靠收尾复核。我的做法是群发后半小时内登录Domino管理员控制台,观察邮件路由队列和退信统计。队列里积压大量消息,说明服务器或网关存在瓶颈;退信统计异常上升,则需要立刻定位问题组成员和外部域。
6. 我的Notes群发检查习惯
最后说几句我的个人习惯,算不上什么标准流程,但是踩过几次坑之后总结出来的,实用性很强。
第一,群发前固定跑三件套。给真实的大名单发送之前,先用自己邮箱试发一次,确认正文、附件、收件人字段都正常;再从大名单里抽出两三个小范围样本地址,确认对方能正常收到;最后确认数量级和自己要发送的批次规划一致。这三步看起来花时间,但能拦截掉八成以上的低级事故。
第二,专门维护“分发组”,不临时凑名单。我经手过的单位里,最稳定的群发方案往往不是技术人员发明的,而是某个部门助理持续维护的一份几十行Excel。把这份Excel导入Notes,做成一个专用分发组,每次发送前更新一次成员,比每次临时在便笺里粘贴地址可靠太多。分发组单独放在一个固定的通讯录位置,命名带前缀,比如分发-全员通知,避免和日常业务组混在一起。
第三,退信不删,归档到一个文件夹里。Notes可以通过“工具 → 规则”建立一条规则,把主题包含“Delivery Failure”或“投递失败”的邮件自动移入“退信归档”文件夹。每个季度集中看一次,就能发现哪些地址需要清理。不要小看这个动作,它在我看来是Notes群发里最好用的“防火墙”。
Notes群发这件事,真正难的一直不是“发出去”这个动作,而是发之前对名单、地址、服务器限额有数,发之后对退信和垃圾箱问题有排查路径。把这些环节捋顺,群发就只是一次普通的鼠标点击而已。