先说结论
很多系统一做离岗自动回复,就容易把自己做成“自动回信风暴制造机”。
Odoo 在这件事上其实相当克制。
从 mail_thread.py 的源码看,离岗自动回复不是普通 comment,也不是泛泛的 auto comment,而是被单独设计成:
- 特定触发条件;
- 独立
message_type='out_of_office'; - 只对合适的作者与内部收件人关系生效;
- 同一往来 4 天内不重复轰炸;
- 还会把负责人和父消息作者这种“功能上应该回应的人”纳进补发判断。
一句话说:
Odoo 的离岗自动回复,本质上是通知链路里的一个节制型补偿机制,而不是无脑自动回信。
主要看哪里
核心源码在:
addons/mail/models/mail_thread.pyaddons/mail/models/res_users.pyaddons/mail/models/mail_message.py
关键点包括:
_notify_thread_with_out_of_office()_notify_thread_with_out_of_office_get_additional_users()res.users上的is_out_of_officemail.message中的message_type = 'out_of_office'
第一步:不是所有消息都会触发离岗自动回复
源码一进 _notify_thread_with_out_of_office() 就先做筛选。
它要求:
- 当前记录必须是有效线程,不是 transient;
message_type只能是comment或email。
也就是说:
- 普通系统通知不触发;
- 乱七八糟的自动消息不触发;
- 只有真正像“有人给你发了协作内容”的消息,才考虑要不要回离岗说明。
这个判断很关键。
因为离岗回复的目的不是给系统动作配旁白,而是告诉真实沟通发起者:
“你找的人暂时不在。”
第二步:Odoo 区分“真正要被回复的作者”
源码里不会简单拿 author_id 就开回。
它会先做:
_message_compute_real_author(...)
如果拿不到 partner,再退回 email_from。
这说明 Odoo 的目标不是“有作者字段就回”,而是尽量识别:
- 这是一个真实合作方;
- 或至少是一个真实外部邮箱;
- 总之得有可被答复的对象。
如果既没有有效 partner,也没有可回的邮箱,离岗回复就不会发。
这避免了很多对空对象、对系统地址、对内部匿名流程的无效回信。
第三步:为什么负责人和父消息作者也可能被纳入
这是这段源码里最容易被忽视,但也最体现协同理解的一部分。
_notify_thread_with_out_of_office_get_additional_users() 会额外补两类人:
1. 记录负责人 user_id
如果当前模型有 user_id,而且负责人不是当前消息作者本人,Odoo 会把负责人也纳入 OOO 检查集合。
2. 父消息作者
如果这次消息是回复链的一部分,而且父消息作者:
- 不在当前直接收件人里;
- 不是当前外部作者本人;
- 不是 portal/share 用户;
那也会被纳入。
这背后传达的协作逻辑很清楚:
真正需要向外部说明“我现在不在”的,不一定只是被直接点名的人,也可能是这条协作链路里的责任人或上一个内部应答人。
这和单纯“谁在 To 里就谁回”相比,成熟很多。
第四步:为什么要单独用 message_type='out_of_office'
Odoo 没把离岗回复塞进普通 comment 或 auto_comment,而是专门定义了:
out_of_office
源码注释还说明了原因:
- 更容易识别;
- 更容易避免重复;
- 不和别的自动消息混在一起。
这是一个非常值得学习的建模习惯。
如果你把所有自动回复都塞进同一种消息类型,后面做:
- 去重;
- 检索;
- 展示差异;
- 统计;
- 再通知过滤
都会非常痛苦。
Odoo 选择给离岗回复一个独立身份,本质上是在保护后续维护性。
第五步:为什么 4 天内只回一次
源码里会查过去 4 天内已经发过的 out_of_office 消息:
- 作者是不是这些离岗用户;
- 收件对象是不是当前这位真实作者或其邮箱;
- 时间是否在
-4d范围内。
如果匹配上,就不再重复回。
这意味着 Odoo 很清楚离岗回复最大的产品风险是什么:
- 不是“发不出去”;
- 而是“发太多”。
4 天窗口的意义在于:
- 外部发件人第一次来信时能得到解释;
- 同一轮往来不会被每封消息都回一次;
- 系统能避免把请假说明变成噪音来源。
第六步:回复体也不是硬编码死文案
Odoo 会用 QWeb 模板:
mail.message_notification_out_of_office
渲染这些内容:
- 用户配置的离岗说明
out_of_office_message - 被回复的原正文
replied_body - 用户签名
signature
所以它不是只发一句“我不在”。
而是给对方一个尽量完整、又仍然可控的上下文化答复。
这也是为什么离岗回复仍然属于协同体验,而不只是系统设置页里的小功能。
开发里最容易误解的点
误解一:离岗回复就是发给所有通知收件人
不是。
Odoo 只会针对“真实作者”这侧去回复,同时判断哪些内部用户需要代表自己表达离岗状态。
误解二:自动回复越及时越好
如果没有去重窗口,及时就会变成骚扰。
误解三:负责人不在收件人里,就不需要管
源码恰恰相反:负责人虽然不一定直接被点名,但在业务上经常是应该回应的人,所以 Odoo 会补入判断。
一句话记住
Odoo 的离岗自动回复不是邮件礼貌功能,而是一个被严格收口的协同补偿机制:
只在合适的消息上触发,只回复真正的外部作者,只让应该负责的内部人表达离岗,并且用独立消息类型和 4 天窗口控制噪音。
如果你在做客服、项目、售后、任务流的协同二开,这套边界非常值得直接借鉴。
DISCUSSION
评论区