ruoyi-vue-pro 开发指南 ruoyi-vue-pro 开发指南
  • 萌新必读
  • 后端手册
  • 中间件手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
  • 运维手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
微服务版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读
  • 后端手册
  • 中间件手册
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
  • 运维手册
  • 前端手册 Vue 3.x
  • 前端手册 Vben 5.x
  • 前端手册 Vue 2.x
  • 前端手册 Admin Uniapp
  • 工作流手册
  • 大屏手册
  • 支付手册
  • 会员手册
  • 商城手册
  • ERP 手册
  • CRM 手册
  • MES 手册
  • WMS 手册
  • HRM 手册
  • FMS 手册
  • PMS 手册
  • OA 手册
  • IM 即时通讯手册
  • AI 大模型手册
  • IoT 物联网手册
  • 公众号手册
  • 系统手册
视频教程
  • Vue3 + element-plus (opens new window)
  • Vue3 + vben5(ant-design-vue、element-plus) (opens new window)
  • Vue2 + element-ui (opens new window)
微服务版 (opens new window)
作者博客 (opens new window)
GitHub (opens new window)
  • 萌新必读

    • 简介
    • 交流群
    • 视频教程
    • 功能列表
    • 快速启动(后端项目)
    • 快速启动(前端项目)
    • 接口文档
    • 技术选型
    • 项目结构
    • 代码热加载
    • 一键改包
    • 迁移模块(适合新项目)
    • 删除功能(以租户为例)
    • 表结构变更(版本升级)
    • 国产信创数据库(DM 达梦、大金、OpenGauss、瀚高)
    • 如何去除 Redis 缓存
    • 内网穿透
    • 面试题、简历模版、简历优化
    • 项目外包
  • 后端手册

    • 新建模块
    • 代码生成【单表】(新增功能)
    • 代码生成【主子表】
    • 代码生成(树表)
    • 代码生成(移动端)
    • 功能权限
    • 数据权限
    • 用户体系
    • 三方登录
    • OAuth 2.0(SSO 单点登录)
    • SaaS 多租户【字段隔离】
    • SaaS 多租户【数据库隔离】
    • WebSocket 实时通信
    • 异常处理(错误码)
    • 参数校验、时间传参
    • 分页实现
    • VO 对象转换、数据翻译
    • 文件存储(上传下载)
    • Excel 导入导出
    • 操作日志、访问日志、异常日志
    • MyBatis 数据库
    • MyBatis 联表&分页查询
    • 多数据源(读写分离)、事务
    • Redis 缓存
    • 本地缓存
    • 异步任务
    • 分布式锁
    • 幂等性(防重复提交)
    • 请求限流(RateLimiter)
    • HTTP 接口签名(防篡改)
    • HTTP 接口加解密
    • 单元测试
    • 验证码
    • 工具类 Util
    • 配置管理
    • 数据库文档
  • 中间件手册

    • 定时任务
    • 消息队列(内存)
    • 消息队列(Redis)
    • 消息队列(RocketMQ)
    • 消息队列(RabbitMQ)
    • 消息队列(Kafka)
    • 限流熔断
  • 工作流手册

    • 工作流演示
    • 功能开启
    • 工作流(达梦适配)
    • 审批接入(流程表单)
    • 审批接入(业务表单)
    • 流程设计器(BPMN)
    • 流程设计器(钉钉、飞书)
    • 选择审批人、发起人自选
    • 会签、或签、依次审批
    • 流程发起、取消、重新发起
    • 审批通过、不通过、驳回
    • 审批加签、减签
    • 审批转办、委派、抄送
    • 执行监听器、任务监听器
    • 流程表达式
    • 流程审批通知
    • 移动端审批
  • 大屏手册

    • 报表设计器
    • 大屏设计器
  • 支付手册

    • 功能开启
    • 支付宝支付接入
    • 微信公众号支付接入
    • 微信小程序支付接入
    • 支付宝、微信退款接入
    • 支付宝转账接入
    • 微信转账接入
    • 钱包充值、支付、退款
    • 模拟支付、退款
    • 移动端支付管理
  • 会员手册

    • 功能开启
    • 微信公众号登录
    • 微信小程序登录
    • 微信小程序订阅消息
    • 微信小程序码
    • 会员用户、标签、分组
    • 会员等级、积分、签到
    • 移动端会员管理
  • 商城手册

    • 商城演示
    • 功能开启
    • 商城装修
    • 在线客服
    • 【商品】商品分类
    • 【商品】商品属性
    • 【商品】商品 SPU 与 SKU
    • 【商品】商品评价
    • 【交易】购物车
    • 【交易】交易订单
    • 【交易】售后退款
    • 【交易】快递发货
    • 【交易】门店自提
    • 【交易】分销返佣
    • 【营销】优惠劵
    • 【营销】积分商城
    • 【营销】拼团活动
    • 【营销】秒杀活动
    • 【营销】砍价活动
    • 【营销】满减送活动
    • 【营销】限时折扣
    • 【营销】内容管理
    • 【统计】会员、商品、交易统计
    • 移动端商城管理
  • ERP手册

    • ERP 演示
    • 功能开启
    • 【产品】产品信息、分类、单位
    • 【库存】产品库存、库存明细
    • 【库存】其它入库、其它出库
    • 【库存】库存调拨、库存盘点
    • 【采购】采购订单、入库、退货
    • 【销售】销售订单、出库、退货
    • 【财务】采购付款、销售收款
    • 移动端 ERP
  • CRM手册

    • CRM 演示
    • 功能开启
    • 【线索】线索管理
    • 【客户】客户管理、公海客户
    • 【商机】商机管理、商机状态
    • 【合同】合同管理、合同提醒
    • 【回款】回款管理、回款计划
    • 【产品】产品管理、产品分类
    • 【通用】数据权限
    • 【通用】跟进记录、待办事项
    • 移动端 CRM
  • AI大模型手册

    • AI 大模型演示
    • 功能开启
    • AI 聊天对话
    • AI 绘画创作
    • AI 知识库(RAG)
    • AI 音乐创作
    • AI 写作助手
    • AI 思维导图
    • AI 工具(function calling)
    • AI 工作流
    • Dify 工作流
    • FastGPT 工作流
    • Coze 智能体
    • 推理模式(thinking)
    • 联网搜索
    • MCP Client 客户端
    • MCP Server 服务端
    • 【模型接入】Claude
    • 【模型接入】OpenAI
    • 【模型接入】通义千问
    • 【模型接入】DeepSeek
    • 【模型接入】字节豆包
    • 【模型接入】腾讯混元
    • 【模型接入】硅基流动
    • 【模型接入】MiniMax
    • 【模型接入】月之暗面
    • 【模型接入】百川智能
    • 【模型接入】文心一言
    • 【模型接入】LLAMA
    • 【模型接入】智谱 GLM
    • 【模型接入】讯飞星火
    • 【模型接入】微软 OpenAI
    • 【模型接入】谷歌 Gemini
    • 【模型接入】Stable Diffusion
    • 【模型接入】Midjourney
    • 【模型接入】Suno
    • 【模型接入】Grok
    • 【模型接入】阶跃星辰
    • 移动端 AI 大模型
  • IoT物联网手册

    • 功能开启
    • 产品管理
    • 设备管理
    • 物模型配置
    • 设备网关与子设备
    • 设备动态注册
    • 设备接入(概述)
    • 设备接入(HTTP 协议)
    • 设备接入(MQTT 协议)
    • 设备接入(EMQX 协议)
    • 设备接入(TCP 协议)
    • 设备接入(UDP 协议)
    • 设备接入(WebSocket 协议)
    • 设备接入(CoAP 协议)
    • 设备接入(Modbus Client 模式)
    • 设备接入(Modbus Server 模式)
    • 设备接入(自定义协议)
    • 场景联动
    • 数据流转
    • 告警配置
    • OTA 固件升级
    • 移动端 IoT 物联网
  • MES手册

    • MES 演示
    • 功能开启
    • 【基础】物料产品、分类、计量单位
    • 【基础】客户管理、供应商管理
    • 【基础】车间设置、工作站设置
    • 【基础】编码规则
    • 【生产】工序设置、工艺流程
    • 【生产】生产工单
    • 【生产】生产排产、工序流转卡
    • 【生产】生产报工
    • 【生产】安灯配置、安灯呼叫
    • 【生产】工作记录
    • 【仓库】仓库与库区库位、条码赋码、SN码
    • 【仓库】批次管理、库存现有量、库存事务
    • 【仓库】到货通知、采购入库、采购退货
    • 【仓库】生产领料、生产退料、物料消耗
    • 【仓库】产品产出、产品入库
    • 【仓库】发货通知、销售出库、销售退货
    • 【仓库】外协发料、外协入库
    • 【仓库】其他入库、其他出库
    • 【仓库】调拨单、装箱管理
    • 【仓库】库存盘点
    • 【质量】检测项设置、常见缺陷
    • 【质量】质检方案
    • 【质量】来料检验(IQC)
    • 【质量】过程检验(IPQC)
    • 【质量】出货检验(OQC)
    • 【质量】退货检验(RQC)
    • 【质量】待检任务、检验结果、缺陷记录
    • 【设备】设备类型、设备台账
    • 【设备】点检保养项目、点检保养方案
    • 【设备】点检记录、保养记录、维修单
    • 【工具】工具类型、工装夹具台账
    • 【排班】班组设置、节假日设置
    • 【排班】排班计划、排班日历
    • 移动端 MES
  • WMS手册

    • WMS 演示
    • 功能开启
    • 【基础】仓库
    • 【基础】商品、SKU、分类、品牌
    • 【基础】往来企业(供应商、客户)
    • 【库存】库存记录、流水、统计
    • 【单据】入库
    • 【单据】出库
    • 【单据】移库
    • 【单据】盘库
    • 【其它】WMS、MES、ERP 对比
    • 移动端 WMS
  • HRM人力资源

    • HRM 演示
    • 功能开启
    • 【组织】工作台、组织架构
    • 【员工】员工管理
    • 【招聘】招聘管理
    • 【考勤】考勤管理
    • 【社保】社保管理
    • 【薪资】计薪设置、薪资档案
    • 【薪资】月度工资、工资条
    • 【绩效】绩效模板、绩效计划
    • 【绩效】绩效考核、绩效档案
    • 移动端 HRM
  • FMS财务管理

    • FMS 演示
    • 功能开启
    • 【设置】账套管理、财务参数、财务指标
    • 【设置】币别、科目、辅助核算、初始余额
    • 【设置】凭证字、常用摘要、凭证模板
    • 【凭证】凭证管理
    • 【账簿】账簿管理
    • 【报表】财务报表
    • 【结账】期末结账
    • 移动端 FMS
  • PMS项目管理

    • PMS 演示
    • 功能开启
    • 【项目中心】工作台与项目管理
    • 【项目中心】项目详情与迭代
    • 【项目中心】工作项与协作
    • 【知识中心】知识库管理
    • 【知识中心】文档与协作
    • 移动端 PMS
  • OA协同办公

    • OA 演示
    • 功能开启
    • 【协作】日程、任务、计划与汇报
    • 【协作】公告、讨论、通讯录与笔记
    • 【办公】企业邮箱
      • 1. 邮箱服务配置
        • 1.1 主表表结构
        • 1.2 管理后台
      • 2. 我的邮箱账号
        • 2.1 主表表结构
        • 2.2 管理后台
      • 3. 收件箱与邮件
        • 3.1 文件夹表结构
        • 3.2 邮件索引表结构
        • 3.3 同步与删除流转
        • 3.4 管理后台
    • 【办公】企业云盘
    • 【行政】办公用品、用印管理
    • 【行政】会议室、车辆管理
    • 【流程】公文管理
    • 【流程】出差、费用报销
    • 【流程】考勤、请假、加班、转正与离职
    • 移动端 OA
  • IM即时通讯手册

    • IM 演示
    • 功能开启
    • 【好友】好友关系、好友申请
    • 【群聊】群组、群成员、入群申请
    • 【消息】私聊、群聊、频道消息
    • 【频道】频道、频道素材
    • 【内容】表情、敏感词
    • 【通话】语音通话、视频通话、共享屏幕
    • 【WebSocket】实时推送与离线消息
    • 移动端 IM 即时通讯
  • 公众号手册

    • 功能开启
    • 公众号接入
    • 公众号粉丝
    • 公众号标签
    • 公众号消息
    • 模版消息
    • 自动回复
    • 公众号菜单
    • 公众号素材
    • 公众号图文
    • 公众号统计
    • 移动端公众号管理
  • 系统手册

    • 短信配置
    • 邮件配置
    • 站内信配置
    • Webhook(钉钉、飞书、企微)
    • 数据脱敏、字段权限
    • 敏感词
    • 地区 & IP 库
  • 运维手册

    • 开发环境
    • Linux 部署
    • Docker 部署
    • Jenkins 部署
    • 宝塔部署
    • 1Panel 部署
    • HTTPS 证书
    • 服务监控
    • Tomcat WAR 部署
  • 前端手册 Vue 3.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • CRUD 组件
    • 国际化
    • IDE 调试
    • 代码格式化
  • 前端手册 Vben 5.x

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
    • IDE 调试
    • 代码格式化
  • 前端手册 Vue 2.x

    • 开发规范
    • 菜单路由
    • Icon 图标
    • 字典数据
    • 系统组件
    • 通用方法
    • 配置读取
  • 前端手册 Admin Uniapp

    • 开发规范
    • 菜单路由
    • 图标、主题、国际化
    • 字典数据
    • 系统组件
    • 通用方法
    • IDE 调试
    • 代码格式化
    • 运行发布
  • 更新日志

    • 【v2026-09】
    • 【v2026-08】
    • 【v2026-07】
    • 【v2026-06】
    • 【v2026-05】
    • 【v2026-04】
    • 【v2026-03】
    • 【v2026-01】
    • 【v2025-12】
    • 【v2025-11】
    • 【v2025-10】
    • 【v2025-09】
    • 【v2025-08】
  • 开发指南
  • OA协同办公
芋道源码
2026-09-17
目录

【办公】企业邮箱

企业邮箱,由 yudao-module-oa 后端模块的 mail 包实现,前端实现在 @/views/oa/mail/provider、@/views/oa/mail/account、@/views/oa/mail/inbox 目录。

企业邮箱通过 IMAP 读取邮件,通过 SMTP 发送邮件。管理员维护邮件服务配置,用户绑定自己的邮箱账号;文件夹、邮件索引和已读取正文分别保存,附件文件仍从远端邮件服务器读取。

本文涉及表如下图所示:

企业邮箱表关系

# 1. 邮箱服务配置

邮箱服务配置,由 OaMailProviderController 提供接口(/oa/mail-provider)。

# 1.1 主表表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

邮箱服务配置表 oa_mail_provider,保存企业统一的 IMAP、SMTP 连接参数:

CREATE TABLE `oa_mail_provider` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `name` varchar(255) NOT NULL COMMENT '名称',

  `imap` json NOT NULL COMMENT 'IMAP 连接配置',
  `smtp` json NOT NULL COMMENT 'SMTP 连接配置',

  `status` tinyint NOT NULL COMMENT '状态',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='企业邮箱服务配置';

① name 是服务配置的展示名称。同一租户可以配置多套服务商参数,供个人账号绑定时选择。删除前必须先解除账号引用,由 OaMailProviderServiceImpl 的 deleteMailProvider 调用 getMailAccountCountByProviderId 校验,仍有关联账号时抛出 MAIL_PROVIDER_IN_USE 异常。

② imap、smtp 以 JSON 保存对应协议的连接配置,结构相同,对应 OaMailProviderDO.ConnectionConfig。SSL 与 STARTTLS 二选一,由 OaMailProviderSaveReqVO.ConnectionConfig.isEncryptionValid 校验(@AssertTrue):

imap / smtp(连接配置)
{
  "host": "imap.example.com",
  "port": 993,
  "sslEnable": true,
  "starttlsEnable": false
}
字段 类型 说明
host String 服务器域名
port Integer 服务器端口,取值 1 ~ 65535
sslEnable Boolean 是否开启 SSL
starttlsEnable Boolean 是否开启 STARTTLS

SMTP 示例通常为 host = smtp.example.com、port = 465(SSL)或 587(STARTTLS),字段结构与 IMAP 一致。

③ 枚举 status 启用状态(CommonStatusEnum),对应字典 common_status。本模块没有 OA_MAIL_* 字典,服务配置与个人账号共用框架通用状态:

值 枚举 说明
0 ENABLE 开启
1 DISABLE 关闭

绑定账号、设置默认账号、连接测试前,都会通过 validateMailProviderEnabled 校验服务配置处于开启状态,否则抛出 MAIL_PROVIDER_DISABLED。

# 1.2 管理后台

对应 [OA 办公协同 -> 企业邮箱 -> 邮箱服务配置] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/mail/provider 目录。

# 列表

查看已配置的邮件服务及启用状态。

管理后台 - 邮箱服务配置

# 新增与修改

点击【新增】打开 MailProviderForm.vue,填写服务名称、IMAP 和 SMTP 配置。主机、端口及安全连接参数应与企业邮箱服务商提供的参数一致,保存后供个人账号绑定时选择。

管理后台 - 邮箱服务配置表单

# 删除

点击【删除】并确认。服务配置存在关联账号时,应先处理账号绑定关系,再删除服务配置。

# 2. 我的邮箱账号

我的邮箱账号,由 OaMailAccountController 提供接口(/oa/mail-account)。

# 2.1 主表表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

个人账号表 oa_mail_account,保存用户绑定的邮箱地址和登录凭据:

CREATE TABLE `oa_mail_account` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `provider_id` bigint NOT NULL COMMENT '服务配置编号',
  `mail` varchar(255) NOT NULL COMMENT '邮箱地址',
  `username` varchar(255) NOT NULL COMMENT '登录用户名',
  `password` text NOT NULL COMMENT '密码或授权码',

  `default_status` bit(1) NOT NULL COMMENT '是否默认发件账号',
  `status` tinyint NOT NULL COMMENT '状态',

  `default_creator` varchar(64) GENERATED ALWAYS AS (CASE WHEN default_status = b'1' AND deleted = b'0' THEN creator ELSE NULL END) STORED,
  PRIMARY KEY (`id`),
  KEY `idx_creator` (`tenant_id`, `creator`, `deleted`),
  KEY `idx_provider` (`tenant_id`, `provider_id`, `deleted`),
  UNIQUE KEY `uk_default_creator` (`tenant_id`, `default_creator`)
) ENGINE=InnoDB COMMENT='企业邮箱个人账号';

① provider_id 关联 oa_mail_provider 表的 id 字段。账号没有独立的所属人字段,通用字段 creator 即绑定该账号的后台用户(关联 system_users 表的 id 字段),由 OaMailAccountServiceImpl 的 validateMailAccount 校验归属。idx_creator 支撑【我的邮箱账号】按用户查询。

② mail 是邮箱地址,username 是服务端登录名,password 保存加密后的密码或授权码。mail / username / provider_id 绑定后不可修改,修改时若三者任一变化,updateMailAccount 抛出 MAIL_ACCOUNT_IDENTITY_IMMUTABLE 异常——换邮箱需新增绑定,避免旧邮件索引归到新账号。

③ default_status 标记是否为当前用户的默认发件账号,不是全局默认邮箱。生成列 default_creator + 唯一索引 uk_default_creator 保证每个用户至多一个默认账号;设置默认时由 updateMailAccountDefault / createMailAccount 先 clearDefaultAccounts 再写入。关闭状态的账号不能设为默认,否则抛出 MAIL_ACCOUNT_DISABLED。

④ 枚举 status 启用状态同样使用 CommonStatusEnum,对应字典 common_status(0 开启 / 1 关闭),与服务配置一致。

⑤ 删除账号只移除本地绑定(deleteMailAccount):不解绑远端邮箱服务商账号,也不级联清理 oa_mail_folder / oa_mail_message。

# 2.2 管理后台

对应 [OA 办公协同 -> 企业邮箱 -> 我的邮箱账号] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/mail/account 目录。

# 绑定与修改

点击【新增】打开 MailAccountForm.vue,选择邮箱服务,填写邮箱地址、登录名和密码或授权码,设置启用状态后保存。

管理后台 - 我的邮箱账号

# 连接测试与默认账号

通过连接测试确认账号可以访问邮箱服务,由 POST /oa/mail-account/test-connection 提供接口(testMailAccountConnection),分别探测 IMAP 与 SMTP,不发送真实邮件。设置默认账号时调用 PUT /oa/mail-account/update-default,写信时使用当前用户的默认发件账号。

# 移除绑定

删除账号用于移除本人邮箱绑定;企业邮箱中的远端账号仍由邮件服务商管理。

# 3. 收件箱与邮件

收件箱与邮件,由 OaMailMessageController 提供接口(/oa/mail-message);文件夹列表由 OaMailFolderController 提供接口(/oa/mail-folder)。

# 3.1 文件夹表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

文件夹表 oa_mail_folder,保存远端邮箱的文件夹及其同步进度:

CREATE TABLE `oa_mail_folder` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `account_id` bigint NOT NULL COMMENT '邮箱账号编号',
  `name` varchar(255) NOT NULL COMMENT '远端文件夹完整名称',
  `type` varchar(20) NOT NULL COMMENT '文件夹类型',

  `uid_validity` bigint DEFAULT NULL COMMENT '远端文件夹 UID 有效期',
  `sync_time` datetime DEFAULT NULL COMMENT '最近完整同步时间',
  `available` bit(1) NOT NULL DEFAULT b'1' COMMENT '远端文件夹是否可用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_account_folder` (`tenant_id`, `account_id`, `name`)
) ENGINE=InnoDB COMMENT='企业邮箱文件夹';

① account_id 关联 oa_mail_account 表的 id 字段。name 是远端文件夹的完整路径名,uk_account_folder 唯一索引保证同一账号下远端文件夹名不重复。

② 枚举 type 文件夹类型(OaMailFolderTypeEnum)。本模块没有对应字典,类型值直接使用字符串常量:

值 枚举 说明
INBOX INBOX 收件箱
SENT SENT 已发送
DRAFTS DRAFTS 草稿箱
TRASH TRASH 已删除
CUSTOM CUSTOM 自定义文件夹

③ uid_validity 记录远端文件夹的 UIDVALIDITY,与邮件的 uid 一起定位远端邮件。available 标记远端是否还存在该文件夹:同步时若远端已删除,本地只把 available 置为 false,保留旧索引但不再展示。由 OaMailFolderServiceImpl 的 validateMailFolder 校验文件夹归属账号。

④ 同步不会在远端创建目录,只映射服务商已有的标准 / 自定义文件夹(syncMailMessageList → getFolders)。


该功能还包含邮件索引表:

  • oa_mail_message(邮件索引):在同步、查看、写信时维护,保存主题、收发人和阅读状态;正文按需缓存。

# 3.2 邮件索引表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

邮件索引表 oa_mail_message,保存邮件的主题、收发人和阅读状态;附件文件仍从远端读取:

CREATE TABLE `oa_mail_message` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `account_id` bigint NOT NULL COMMENT '邮箱账号编号',
  `folder_id` bigint NOT NULL COMMENT '文件夹编号',
  `uid_validity` bigint NOT NULL COMMENT '远端文件夹 UID 有效期',
  `uid` bigint NOT NULL COMMENT '远端邮件 UID',

  `subject` longtext NOT NULL COMMENT '邮件主题',
  `content` longtext DEFAULT NULL COMMENT '安全正文缓存,NULL 表示未读取',

  `sender` text COMMENT '发件人',
  `recipients` json COMMENT '收件人',
  `ccs` json COMMENT '抄送人',
  `reply_tos` json DEFAULT NULL COMMENT '回复地址',

  `receive_time` datetime DEFAULT NULL COMMENT '接收时间',
  `read_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已读',
  `has_attach` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否有附件',
  `attachments` json DEFAULT NULL COMMENT '附件目录缓存,附件文件仍从远端读取',
  `size` int DEFAULT NULL COMMENT '邮件大小,单位字节',
  PRIMARY KEY (`id`),
  KEY `idx_folder_uid` (`tenant_id`, `folder_id`, `uid_validity`, `uid`, `deleted`),
  KEY `idx_account_folder_time` (`tenant_id`, `account_id`, `folder_id`, `deleted`, `receive_time`)
) ENGINE=InnoDB COMMENT='企业邮箱邮件索引';

① account_id 关联 oa_mail_account 表的 id 字段,folder_id 关联 oa_mail_folder 表的 id 字段。远端主键是 (uid_validity, uid),idx_folder_uid 支撑按文件夹定位远端邮件;idx_account_folder_time 支撑收件箱按接收时间分页。归属由 validateMessage → validateMailAccount 校验。

② content 是经安全过滤后的正文缓存:null 表示尚未拉取,空字符串表示正文为空。首次打开详情(getMailMessage)才从远端读取并回写;列表同步一般只写索引字段。

③ recipients、ccs、reply_tos、attachments 均为 JSON。附件只缓存目录元数据(部件路径、名称、大小),文件内容仍按需从远端读取(getMailMessageAttachment):

recipients / ccs / reply_tos(地址列表)与 attachments(附件目录)

地址类字段均为字符串数组,例如:

["alice@example.com", "bob@example.com"]

attachments 对应 OaMailMessageDO.Attachment:

[
  {
    "part": "1.2",
    "name": "需求说明.pdf",
    "size": 204800
  }
]
字段 类型 说明
part String MIME 部件路径
name String 附件名称
size Integer 附件大小,单位字节

④ read_status 是否已读。更新时(updateMailMessageRead)会同步远端 SEEN 标志。前端虚拟入口 UNREAD = 收件箱(INBOX)+ readStatus = false,由 OaMailFolderKeyEnum.UNREAD 标识,不是真实远端文件夹。

# 3.3 同步与删除流转

邮件同步与删除由 OaMailMessageServiceImpl / OaMailMessageClientImpl 控制。文件夹类型见 §3.1,阅读状态见上表 read_status。

由于各家邮件服务商支持的 IMAP 扩展不同,写操作前会先用 hasCapability 探测远端能力(OaMailCapabilityEnum),缺失时直接抛异常而不降级:

值 枚举 说明
UIDPLUS UID_PLUS 按 UID 操作,彻底删除与草稿替换必需
MOVE MOVE 移动邮件,删除到已删除文件夹必需
ID ID 客户端身份,部分服务商(如网易)要求上报后才允许收发
场景 关键能力 说明 可执行操作
同步索引 账号行锁 lockMailAccount 串行化同一账号的同步与写操作 同步、查看、已读、删除、草稿、发送
非回收站删除 IMAP MOVE 移到远端 TRASH 删除(软删远端)
回收站删除 IMAP UIDPLUS 按 UID expunge 指定邮件 彻底删除
草稿 / 发送 IMAP UIDPLUS 草稿替换、发送后清理依赖 UIDPLUS 保存草稿、发送

状态流转说明

同步(syncMailMessageList)
  └─ 映射远端已有文件夹 → 写入/更新 oa_mail_folder + oa_mail_message 索引
     (不在远端新建目录;远端已消失的文件夹 → available = false)

删除(deleteMailMessage)
  普通文件夹 ──IMAP MOVE──→ TRASH(远端移入已删除,本地删索引)
  已在 TRASH ──UIDPLUS expunge──→ 远端物理清除指定 UID(本地删索引)

草稿(saveMailMessageDraft) / 发送(sendMailMessage)
  └─ 依赖 UIDPLUS;草稿先追加再按 UID 清理旧草稿,不允许全文件夹 expunge
  • 同步(syncMailMessageList):先 lockMailAccount 加账号锁,再打开 IMAP Store,按远端已有文件夹逐个 syncFolder。不会创建远端目录;远端已不存在的文件夹只把本地 available 置为 false。
  • 删除(deleteMailMessage → deleteMessage):当前不在 TRASH 时,要求服务商支持 MOVE,把邮件移到已删除文件夹;已在 TRASH 时要求 UIDPLUS,对该 UID 执行 expunge。远端成功后再删本地索引。
  • 草稿 / 发送:saveMailMessageDraft、发送流程依赖 UIDPLUS 做按 UID 的安全替换;缺少能力时分别抛出 MAIL_DRAFT_REPLACE_UNSUPPORTED、MAIL_PERMANENT_DELETE_UNSUPPORTED 等异常。
  • 未读入口:getMailFolderList 在收件箱后插入虚拟 UNREAD;getMailMessagePage 把 folderKey = UNREAD 转为 INBOX + readStatus = false。

# 3.4 管理后台

对应 [OA 办公协同 -> 企业邮箱 -> 收件箱] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/oa/mail/inbox 目录。

# 同步与查询

选择本人邮箱账号和文件夹后查看邮件;同步通过 POST /oa/mail-message/sync 拉取邮件索引,列表由 MailMessageList.vue 展示。侧边栏可切换收件箱、未读、已发送、草稿箱、已删除及自定义文件夹。

管理后台 - 收件箱与邮件

# 查看邮件

点击邮件打开 MailMessageDetail.vue,查看发件人、收件人、抄送人、正文和附件。邮件详情由 /oa/mail-message/get 提供,阅读状态通过 /oa/mail-message/update-read 更新。

管理后台 - 邮件详情

# 写信与保存草稿

打开 MailMessageForm.vue,选择发件账号,填写收件人、抄送人、主题、正文和附件。保存草稿调用 POST /oa/mail-message/save-draft,发送调用 POST /oa/mail-message/send。

管理后台 - 写信

# 回复与转发

在邮件详情中进入回复、回复全部或转发,前端调用 GET /oa/mail-message/compose 获得预填信息,再打开写信表单。确认收件人和正文后发送。

mode 写信方式(OaMailComposeModeEnum)决定预填内容,接口用 @InEnum 限定取值:

值 枚举 说明
new NEW 新邮件,不预填;不作为 compose 的入参,仅作为草稿回显时返回给前端的模式
draft DRAFT 编辑草稿,原样回填收件人、抄送人、主题、正文和附件,并带上 draftId
reply REPLY 回复,收件人取 reply_tos,为空时回落到 sender;主题加 Re: 前缀
replyAll REPLY_ALL 回复全部,在回复基础上把原收件人并入收件人、原抄送人并入抄送人
forward FORWARD 转发,主题加 Fwd: 前缀,收件人留空,并携带原附件
  • draft 要求原邮件确实位于草稿箱,否则抛出 MAIL_NOT_DRAFT;回显时接口把 mode 改写为 new,前端按新邮件处理。
  • 只有 draft 和 forward 会带上原附件;reply / replyAll 不携带。
  • 所有地址都会剔除本人邮箱并去重,且收件人中已出现的地址会从抄送人中移除。
  • reply / replyAll / forward 的正文以 blockquote 引用原文,原始邮件头做 HTML 转义,并移除邮件自带 CSS 避免样式泄漏。

# 删除邮件

选择邮件执行删除,调用 DELETE /oa/mail-message/delete。该操作涉及远端邮箱,确认所选账号和文件夹后再执行;非已删除文件夹会先移到回收站,已在回收站则彻底清除。

【协作】公告、讨论、通讯录与笔记
【办公】企业云盘

← 【协作】公告、讨论、通讯录与笔记 【办公】企业云盘→

Theme by Vdoing | Copyright © 2019-2026 芋道源码 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×