用 DavMail 接入企业邮箱(推荐)
如果你的邮箱是企业 Exchange / Microsoft 365,我们推荐用 DavMail 作为 MailAgent 的邮箱源,而不是默认的 AppleScript。它更快、更稳,且把”富文本回复全部 + 线程折叠 + 多文件夹 + 日历直读”这些能力真正打通。
本页从零讲清 DavMail:是什么、为什么、怎么装、怎么认证、怎么确认、怎么守护。
DavMail 是什么
Section titled “DavMail 是什么”DavMail 是一个开源的邮件协议网关(Java 程序)。它把微软 Exchange 的私有协议(EWS / Graph)翻译成标准的 IMAP / SMTP / CalDAV / LDAP,在你本机起一组本地端口:
Mail.app / Outlook 私有路径 DavMail 路径───────────────────────── ───────────────────────────────后端 → AppleScript → Mail.app 后端 → 本地 IMAP/SMTP → DavMail → Exchange(驱动 GUI,单封约 1 秒) (标准协议,单封约 236 毫秒)对 MailAgent 来说,启用 DavMail 后整条邮箱接入链路不再依赖 Mail.app 这个 GUI——后端直接用标准 IMAP 收信、SMTP 发信、CalDAV 读日历。DavMail 在后台常驻,负责跟 Exchange 服务端维持 OAuth 会话。
为什么推荐它
Section titled “为什么推荐它”| 维度 | DavMail(推荐) | AppleScript(兜底) |
|---|---|---|
| 取信速度 | 单封约 236 毫秒(IMAP UID FETCH) | 单封约 1 秒(驱动 Mail.app) |
| GUI 依赖 | 无——不需要 Mail.app 常开/前台 | 需要 Mail.app 登录好邮箱并保持运行 |
| 富文本回复全部 | 真正可用:multipart/alternative + In-Reply-To,Outlook 端正确折进原对话 | GUI 注入受限,富文本/线程折叠不稳 |
| 多文件夹同步 | 支持(勾选自定义 Exchange 文件夹并入主链路) | 不支持 |
| CalDAV 日历直读 | 支持(直接读 Outlook 服务端日历) | 不支持 |
| 系统权限 | 几乎不需要 macOS 自动化/辅助功能权限 | 需要完全磁盘访问 + 自动化 + 辅助功能等一整套 |
| 跨平台 | 标准协议,为将来迁 Linux 部署铺路 | 绑死 macOS + Mail.app |
一句话:Exchange 用户用 DavMail 体验明显更好。AppleScript 仍然是零额外组件、随时可用的兜底——任何时候把 MAILAGENT_BACKEND 改回 applescript 就能回切。
- 一个 Java 运行时(JRE/JDK 8+)。验证:
java -version能打印版本号即可。没有的话brew install openjdk(macOS 无需 sudo),或用 DavMail 自带的davmail azul拉一个内嵌 JRE。 - DavMail 6.7.0(jar 包)。本仓库已带在
davmail-poc/jar/davmail.jar,也可从 davmail.sourceforge.net 下载。 - 一个企业 Exchange / Microsoft 365 邮箱,且租户允许 OAuth 登录(见下方第 2 步的 broker check 说明)。
第 1 步:写好 davmail.properties
Section titled “第 1 步:写好 davmail.properties”DavMail 用一个 .properties 文件描述监听端口、OAuth 模式和凭据路径。在 davmail-poc/config/davmail.properties 写入:
# ===== O365 OAuth2 模式 =====# O365Manual:启动后控制台打印 OAuth URL,浏览器走 MFA 后把 redirect URL 粘回 stdindavmail.mode=O365Manualdavmail.url=https://outlook.office365.com/EWS/Exchange.asmx
# OAuth token 持久化路径(用绝对路径)davmail.oauth.tokenFilePath=/绝对路径/MailAgent/davmail-poc/token/token.dat
# ===== 伪装 Outlook for Windows well-known client_id =====# 用 Outlook 桌面端的公开 client_id 登录,绕开"第三方应用需 IT 审批"这道坎davmail.oauth.clientId=d3590ed6-52b3-4102-aeff-aad2292ab01cdavmail.oauth.redirectUri=urn:ietf:wg:oauth:2.0:oob
# ===== 监听端口(IMAP + SMTP + CalDAV)=====davmail.imapPort=1143davmail.smtpPort=1025davmail.caldavPort=1080davmail.ldapPort=0davmail.popPort=0
# ===== Server 模式(无 tray icon,适合后台常驻)=====davmail.server=truedavmail.disableUpdateCheck=true
# 本地明文通信(host 内不出物理机),关掉 TLSdavmail.smtpStartTls=falsedavmail.imapStartTls=falseclient_id 那两行是关键,下一步详解为什么这么填。
第 2 步:首次 OAuth 认证(含伪装 Outlook client_id)
Section titled “第 2 步:首次 OAuth 认证(含伪装 Outlook client_id)”为什么要伪装 client_id
Section titled “为什么要伪装 client_id”DavMail 自带的默认 client_id 是它自注册的第三方应用,多数企业租户会把它当独立第三方应用、要求 IT 审批才放行。而 Outlook for Windows 的公开 client_id(d3590ed6-52b3-4102-aeff-aad2292ab01c) 是微软官方桌面客户端,通常已在租户里被信任——用它登录就能直接拿到 EWS token,绕开审批这道坎。
先前台跑一次 DavMail,看控制台输出:
cd ~/Documents/MailAgent/davmail-poc/jarjava -jar davmail.jar ../config/davmail.properties- 控制台打印一条 OAuth URL(里面能看到
client_id=d3590ed6-...和你的login_hint)。 - 复制 URL → 浏览器打开 → 输入公司账号 + MFA。
- 微软可能弹一个 broker check:“正在尝试登录到 Microsoft Office 吗?仅在从信任的应用商店或网站下载应用时才继续。“——点继续即可。
这是因为 client_id 对应 Outlook for Windows,但当前进程不是真 Outlook(没有微软设备签名),触发了应用真实性二次确认。能点”继续”过去,恰恰说明你的租户没有对这个 client_id 做设备绑定的严校验。
- 点继续后会跳到一个一直 loading 的空白页(
urn:ietf:wg:oauth:2.0:oob这种回调方式现代浏览器已不原生支持,所以页面卡住——这是正常现象)。 - 从卡住的页面里抠出授权码:打开浏览器开发者工具 → Network(网络)标签 → 找最后一个失败/pending 的请求 → 从它的 Request URL 里复制
code=...这一段参数。 - 把完整的
code=...粘回 DavMail 控制台的 stdin,回车。 - DavMail 用这个 code 换到 access token,跟 Exchange 建立会话,并把凭据落盘到
token/token.dat(约 2 KB)。refresh token 默认 90 天有效,之后重启免重新授权。
看到控制台不再要求授权、token.dat 生成,认证就成了。可以 Ctrl-C 停掉这次前台运行,第 5 步再用 PM2 把它做成守护进程。
第 3 步:让 MailAgent 用 DavMail
Section titled “第 3 步:让 MailAgent 用 DavMail”桌面 App 用户:在 App 的设置面板里填写 DavMail 配置(用户邮箱、端口、Cipher Key),无需手动编辑 .env。
从源码运行后端的开发者:回到 ~/Documents/MailAgent/.env,把后端切到 davmail 并补几项(参数含义与 App 设置面板一一对应):
MAILAGENT_BACKEND=davmailDAVMAIL_CIPHER_KEY=任意一串固定字符串 # token 加密 key,见下方警告DAVMAIL_IMAP_PORT=1143 # 与 davmail.properties 一致DAVMAIL_SMTP_PORT=1025DAVMAIL_ROOT=/绝对路径/MailAgent/davmail-poc # 打包桌面 App 时必填绝对路径从源码运行时,改完重启 mail-sync 让新后端生效:
pm2 restart mail-sync第 4 步:确认 DavMail 在跑
Section titled “第 4 步:确认 DavMail 在跑”# 1) 端口通不通(IMAP / SMTP)nc -zv localhost 1143 # IMAP,期望 succeedednc -zv localhost 1025 # SMTP,期望 succeeded
# 2) DavMail 日志无认证错误tail -n 30 ~/Documents/MailAgent/davmail-poc/logs/davmail.log
# 3) token 已落盘且较新ls -la ~/Documents/MailAgent/davmail-poc/token/token.dat
# 4) 用 IMAP 实测能登录(把 KEY 换成你的 DAVMAIL_CIPHER_KEY)python3 - <<'PY'import imaplibm = imaplib.IMAP4("localhost", 1143)m.login("[email protected]", "KEY") # 密码填 DAVMAIL_CIPHER_KEYprint(m.list()[0]) # OK 即认证链路通m.logout()PY再确认 MailAgent 后端整体健康:
mailagent admin health -o json | jq .data.healthy # 期望 truetail -f logs/sync.log # 不应有 ERROR 行第 5 步:把 DavMail 做成守护进程(PM2)
Section titled “第 5 步:把 DavMail 做成守护进程(PM2)”DavMail 需要一直在后台跑,MailAgent 才能随时收发。用 PM2 让它常驻、开机自启、崩溃自拉起。直接守护 java 进程(不要靠终端前台):
pm2 start "$(which java)" --name davmail-poc -- \ -Xmx512M -Dsun.net.inetaddr.ttl=60 \ -jar ~/Documents/MailAgent/davmail-poc/jar/davmail.jar \ ~/Documents/MailAgent/davmail-poc/config/davmail.properties
pm2 save # 固化进程列表pm2 startup # 按提示执行一次,开机自启常用维护命令:
pm2 status # 看 davmail-poc 是否 onlinepm2 logs davmail-poc # 跟踪 DavMail 输出pm2 restart davmail-poc # 重启(改了 properties 后)token 失效时怎么办
Section titled “token 失效时怎么办”token.dat 里的 refresh token 默认 90 天有效,DavMail 会自动续期,正常不用管。但如果你的设备被管理员移出租户,refresh token 会被永久作废(日志报 AADSTS700003)——这时自动续期救不回来,需要重新走一遍第 2 步的交互认证:删掉旧 token.dat,前台跑一次 DavMail 重新授权,再 pm2 restart davmail-poc。
备选守护方式:DavMail 6.7 自带的
davmail启动脚本(davmail <properties 路径> -notray)或社区 Docker 镜像也能跑,但 PM2 守护 nativejava进程是本项目验证过的稳定方式。
DavMail 跑通后,下一步是 应用内首次配置 —— 在 App 里填好密钥、选好 AI 后端,就可以开始日常使用了。