协同办公

Odoo 邮件组为什么不只是“群发邮箱”:mail.group 的成员、审核和退订链路讲透

Odoo 的 mail.group 看起来像一个邮件列表功能,但官方源码做得远不止“把邮件群发出去”。它同时维护访问模式、成员订阅、审核规则、退订令牌和待审核提醒,是一套完整的邮件协同模型。

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

先说结论

很多人第一次看到 Odoo 的 mail.group,会把它理解成一个“能群发邮件的邮箱列表”。

这不算错,但太浅。

addons/mail_group/models/mail_group.pymail_group_message.py 看,官方其实实现的是一整套邮件协同模型,里面同时包含:

  • 邮件别名入口
  • 成员订阅与退订
  • 访问模式控制
  • 审核队列
  • 发件人白名单 / 黑名单
  • 待审核提醒给 moderator
  • 一键退订链接和 token

一句话说:

mail.group 不是“群发器”,而是“以邮件为载体的半开放协同空间”。


为什么 mail.group 不是简单继承 mail.thread

源码注释里写得很清楚:

  • 它没有直接继承 mail.thread
  • 但又接入了 mail gateway 流程

原因很实际。

如果直接把它做成普通 chatter 记录,很多“邮件列表”语义不好表达,比如:

  • reply-to 维护
  • 列表页脚
  • List-Unsubscribe 头
  • 审核前挂起
  • 同发件人的批量 allow / ban

所以 Odoo 走的是另一条路:

  • mail.message 承载具体邮件消息
  • 再用 mail.group.message 包装出“邮件组上下文”

这说明官方认为邮件组不是普通对象消息流,而是更像一个带规则的讨论列表。


为什么访问模式有 publicmembersgroups

mail.groupaccess_mode 很有代表性:

  • public
  • members
  • groups

这三种模式说明官方不是只考虑“内部团队自由发”,而是在设计不同开放度的邮件协作空间:

public

更像面向更宽范围的开放讨论入口。

members

强调只有已订阅成员才能发。

groups

强调只有指定用户组里的成员才能发。

这意味着 mail.group 从一开始就把“谁能发进来”视为核心规则,而不是事后补丁。


为什么邮件先变成 mail.group.message

message_post() 里,Odoo 的流程是:

  1. 先创建 mail.message
  2. 再创建对应的 mail.group.message
  3. 再根据审核规则决定后续动作

这个设计很妙。

因为它把两层语义拆开了:

mail.message

负责“这是一封消息”

mail.group.message

负责“这封消息在邮件组里处于什么审核状态、属于哪条讨论链”

这样一来,审核、父子消息关系、发件人状态这些邮件组特有语义,就不会硬塞进通用消息模型里。


审核为什么不是一个简单开关

很多人会以为审核就是:

  • 开启后所有邮件先审批
  • 审批通过再发

但源码明显更细:

  • moderation 决定组是否启用审核
  • mail.group.moderation 维护某个邮箱在某个组里的 allow / ban 规则
  • mail.group.message 维护消息当前是 pending_moderationaccepted 还是 rejected

这三层加在一起,才构成完整审核体系。

也就是说,Odoo 的审核不是“总开关”,而是:

  • 组级规则
  • 发件人级规则
  • 消息级状态

三层叠加。


为什么 allow / ban 会影响同一作者的其他待审邮件

mail_group_message.py 里,action_moderate_allow()action_moderate_ban() 都会调用 _get_pending_same_author_same_group()

意思是:

  • 当 moderator 对一个作者做 allow / ban
  • 系统会把同组、同作者、还在 pending 的消息一起处理

这很符合现实邮件列表管理:

  • 你不是只审批这一封
  • 你是在判断“这个发件人以后值不值得信任”

所以 Odoo 的审核思路不是逐封手工劳作,而是逐步沉淀发件人信誉规则。


为什么待审核消息还要主动通知 moderator

_notify_moderators() 非常关键。

很多系统只把待审消息堆在后台列表里,等管理员自己去看。

但 Odoo 会:

  • 定时扫描 pending moderation
  • 对 moderator 发 Inbox / Email 通知

这说明在官方视角里,审核并不是“可有可无的后台管理功能”,而是邮件协同链里必须被及时消费的一环。

否则消息就会卡在中间,协作链断掉。


为什么退订要做 one-click token

源码里有几层退订相关方法:

  • _generate_action_token()
  • _generate_email_access_token()
  • _get_email_unsubscribe_url()

同时发信时还会注入:

  • List-Unsubscribe
  • List-Unsubscribe-Post: List-Unsubscribe=One-Click

这说明 Odoo 对邮件组的理解是成熟的邮件列表,而不是随便发封通知邮件。

也就是说:

一旦你把讨论做成邮件列表,就必须同时把“优雅退出”做完整。

否则这个协作空间很快就会变成打扰源。


为什么群发时还要加列表头、页脚和回帖语义

_notify_members() 里会处理:

  • List-Archive
  • List-Subscribe
  • List-Unsubscribe
  • List-Id
  • List-Post
  • Precedence: list
  • 每个成员专属的 footer

这说明 Odoo 不是把邮件当“通知渠道”而已,而是真的在模拟一套规范邮件列表行为。

这对协同质量非常重要,因为邮件客户端、自动回复规则、退订入口,很多都依赖这些头信息。


这套设计对办公协同有什么启发

1. 邮件讨论空间一定要同时设计入口和退出

订阅容易,退订也必须清晰。

2. 审核要区分“组规则 / 发件人规则 / 单条消息状态”

否则很快会失控。

3. moderator 不是被动管理员,而是消息链中的关键节点

如果不主动提醒,审核就会积压。

4. 邮件列表不是发件功能,而是长期协作空间

所以必须考虑成员、信誉、回帖链和规范头信息。


做相关定制时最容易踩的坑

1. 只做群发,不做订阅与退订机制

结果用户体验会很差。

2. 审核只做布尔字段

后面根本支撑不了不同作者的信誉积累。

3. 不处理 reply-to / List-* headers

邮件线程和客户端行为会乱。

4. 不通知 moderator

待审消息容易积压成死队列。


一句话记忆法

Odoo 的 mail.group 不是简单群发邮箱,而是一套带成员规则、审核队列、信誉沉淀和退订协议的邮件协同空间。

理解这一句,就能看懂为什么官方在这个模块里做了这么多“看似麻烦”的设计。

DISCUSSION

评论区

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