协同办公

Odoo 离岗自动回复为什么不会无限乱飞:`out_of_office` 消息类型、4 天限流与责任人补发链路讲透

Odoo 的离岗自动回复不是简单把一段请假文案群发出去。源码里它被做成独立 `message_type`,只在特定消息类型上触发,还会补入负责人和父消息作者,并对同一往来设置 4 天去重窗口。

协同办公
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 4 阅读

先说结论

很多系统一做离岗自动回复,就容易把自己做成“自动回信风暴制造机”。

Odoo 在这件事上其实相当克制。

mail_thread.py 的源码看,离岗自动回复不是普通 comment,也不是泛泛的 auto comment,而是被单独设计成:

  • 特定触发条件;
  • 独立 message_type='out_of_office'
  • 只对合适的作者与内部收件人关系生效;
  • 同一往来 4 天内不重复轰炸;
  • 还会把负责人和父消息作者这种“功能上应该回应的人”纳进补发判断。

一句话说:

Odoo 的离岗自动回复,本质上是通知链路里的一个节制型补偿机制,而不是无脑自动回信。


主要看哪里

核心源码在:

  • addons/mail/models/mail_thread.py
  • addons/mail/models/res_users.py
  • addons/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_office
  • mail.message 中的 message_type = 'out_of_office'

第一步:不是所有消息都会触发离岗自动回复

源码一进 _notify_thread_with_out_of_office() 就先做筛选。

它要求:

  • 当前记录必须是有效线程,不是 transient;
  • message_type 只能是 commentemail

也就是说:

  • 普通系统通知不触发;
  • 乱七八糟的自动消息不触发;
  • 只有真正像“有人给你发了协作内容”的消息,才考虑要不要回离岗说明。

这个判断很关键。

因为离岗回复的目的不是给系统动作配旁白,而是告诉真实沟通发起者:

“你找的人暂时不在。”


第二步: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

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。