邮件接入——让 AI 收发邮件
Hermes 消息平台接入第7篇:Email。Hermes 通过邮件和你对话。
好嘞,今天咱们来聊聊怎么让 Hermes 帮你收发邮件。别紧张,这事儿比你想的简单多了——不需要什么特殊的客户端或者机器人 API,只要你的邮箱支持 IMAP/SMTP 协议(Gmail、Outlook、Yahoo、Fastmail 这些主流的基本都行),Hermes 就能直接收信、回信,而且回复会乖乖待在同一个邮件线程里,跟真人聊天似的。
这跟 Himalaya 技能有啥区别?
官方文档里特意提了一嘴,Hermes 内置了两种邮件玩法:
- 邮件网关适配器(今天的主角):用 Python 自带的
imaplib和smtplib,零外部依赖,配好就能用。 - Himalaya 邮件技能:让 agent 通过终端命令管理邮箱,但需要额外装
himalayaCLI 和配置文件。
简单说,你想让别人直接发邮件给 agent 并收到回复,用网关适配器就对了。
准备工作
- 一个专用的邮箱账号(别拿你个人邮箱折腾)
- 开启 IMAP
- 如果用的是 Gmail 或开了双重验证的邮箱,需要生成应用专用密码(16 位那个,不是你的登录密码)
Gmail 用户去 App Passwords 生成一个就行。Outlook 用户去 Security Settings 里找。其他邮箱就去翻翻提供商的文档,记下 IMAP 和 SMTP 的主机和端口(一般是 993 和 587)。
Proton Mail Bridge / 本地中继
如果你用的是 Proton Mail Bridge(或者自建的本地 MTA 这类中继),它们监听的是回环地址,走 STARTTLS 加自签名证书,所以默认配置(IMAP 993 隐式 TLS、校验证书)是连不上的。需要在 ~/.hermes/config.yaml 里覆盖传输设置:
platforms:
email:
enabled: true
extra:
imap_host: 127.0.0.1
imap_security: starttls # tls (默认) | starttls | plain
imap_tls_verify: false # Bridge 用的是自签名证书
smtp_host: 127.0.0.1
smtp_security: starttls # 默认:465 端口用 tls,其他情况用 starttls
smtp_tls_verify: false
然后在 ~/.hermes/.env 里,配合 Bridge 的凭据一起设置 EMAIL_IMAP_PORT=1143 / EMAIL_SMTP_PORT=1025。*_security 填了无法识别的值会打一条警告,并回退到安全默认值。*_tls_verify 只在回环地址上关闭——如果对非回环主机关闭校验,Hermes 会打警告。
第一步:配置 Hermes
最省事的方式:
hermes gateway setup
选 Email,跟着向导填邮箱、密码、IMAP/SMTP 主机和允许发件人列表就行。
想手动配?打开 ~/.hermes/.env 加上这些:
# 必填
EMAIL_ADDRESS=hermes@gmail.com
EMAIL_PASSWORD=abcd efgh ijkl mnop # 应用专用密码
EMAIL_IMAP_HOST=imap.gmail.com
EMAIL_SMTP_HOST=smtp.gmail.com
# 发件人认证(默认开启,强烈建议配置)
EMAIL_AUTHSERV_ID=mx.google.com
# 安全(强烈推荐)
EMAIL_ALLOWED_USERS=your@email.com,colleague@work.com
# 可选
EMAIL_IMAP_PORT=993
EMAIL_SMTP_PORT=587
EMAIL_POLL_INTERVAL=15 # 轮询间隔(秒)
EMAIL_HOME_ADDRESS=your@email.com # cron 任务的默认投递目标
关于 EMAIL_AUTHSERV_ID(发件人认证)
Hermes 默认会校验发件人身份:只有当收信服务器在 Authentication-Results 头里认证了邮件的 From: 域名(DMARC,或者对齐的 SPF/DKIM),Hermes 才会处理这封邮件。这是为了防止有人伪造 From: 地址,把垃圾内容塞进别人的会话里、还让 Hermes 替他回信。
EMAIL_AUTHSERV_ID 要填的,就是你收信服务器最顶层那个 Authentication-Results 头里、第一个分号 ; 之前的那个标识(authserv-id)。Gmail 的话就是 mx.google.com。
怎么找这个值?打开一封你服务器投递过来的邮件,看「显示原始邮件 / show original」,找到最顶层的 Authentication-Results 头,复制第一个 ; 前面的那段就行。
几个要点:
- 这个 pin 是必须的(只要发件人认证开着)。不配的话,Hermes 分不清哪个头是你服务器盖的、哪个是发件人自己写的,于是谁的都不信——所有需要认证
From:的邮件都会被丢弃,日志里会提示一次并给出修复方法。 - 如果这个标识在每封邮件里都不一样,那它其实是每台中继的主机名,不是 authserv-id。RFC 8601 规定 authserv-id 是管理域的稳定名称,得让你的 MTA 固定盖一个(比如 OpenDKIM / OpenDMARC 里的
AuthservID),然后 pin 那个。 - 匹配上只是「pin 住了」,不等于来源可信:请确认你的 MTA 在盖自己的头之前,会剥掉入站邮件里冒充它 id 的
Authentication-Results头。 - 如果实在没法固定一个稳定 id,可以显式关掉认证:设
platforms.email.require_authenticated_sender: false(或EMAIL_TRUST_FROM_HEADER=true),代价是From:就按字面信任了。 - 注意:即使开了
EMAIL_ALLOW_ALL_USERS/GATEWAY_ALLOW_ALL_USERS这种「来者不拒」模式,认证依然生效——开放访问只是允许任何发件人,但每个会话和每条回复都绑定From:,伪造的From:会把攻击者的内容塞进那个地址的会话里。配对码和拒绝通知同样需要认证过的From:。 - 日志里出现
Dropping sender with unauthenticated From警告,说明邮件因缺少认证头被丢弃;如果警告指向platforms.email.authserv_id(EMAIL_AUTHSERV_ID),说明最顶层的头里的 id 和你 pin 的不一致。
第二步:启动网关
hermes gateway # 前台运行
hermes gateway install # 安装为用户服务
sudo hermes gateway install --system # Linux 开机自启
启动时会自动测试 IMAP/SMTP 连接,把收件箱里已有的邮件标记为“已读”(只处理新邮件),然后开始轮询。
它是怎么工作的?
- 收信:默认每 15 秒检查一次未读邮件。主题行会作为上下文(比如
[Subject: Deploy to production]),回复邮件(Re:开头)不会重复加前缀。附件会缓存到本地——图片能喂给视觉工具,PDF、ZIP 等文档也能直接访问。HTML 邮件会去掉标签提取纯文本。 - 回信:通过 SMTP 发送,自动带上
In-Reply-To和References头保持线程,主题不会变成Re: Re: Re:。回复是纯文本(UTF-8)。 - 发附件:在回复里写
MEDIA:/path/to/file,文件就会作为附件发出去。 - 防骚扰:
noreply@、mailer-daemon@、bounce@、no-reply@,以及带Auto-Submitted、Precedence: bulk或List-Unsubscribe头的邮件会被静默忽略,不会触发回复。
访问控制
默认比聊天平台严格得多:
- 设置了
EMAIL_ALLOWED_USERS→ 只处理名单里的地址(以及GATEWAY_ALLOWED_USERS里的地址或已通过配对码批准的地址) - 没设置 → 未知发件人直接忽略
EMAIL_ALLOW_ALL_USERS=true→ 来者不拒(慎用!)platforms.email.unauthorized_dm_behavior: pair→ 未知发件人会收到配对码platforms.email.unauthorized_dm_behavior: decline→ 未知发件人会收到一次礼貌的拒绝,之后 24 小时内不再回应
名单里的条目按完整地址匹配。像 alice 这样的裸条目(比如 GATEWAY_ALLOWED_USERS 里的聊天用户名)绝不会放行任何域名下的 alice@,来自这类地址的邮件会被直接丢弃,而不是走配对或拒绝流程。
强烈建议用专用收件箱 + 配置 EMAIL_ALLOWED_USERS,别让 agent 乱回陌生邮件。
不想收附件?
在 config.yaml 里加:
platforms:
email:
skip_attachments: true
附件会被跳过,但邮件正文照常处理。
常见问题
| 问题 | 解决 |
|---|---|
| 启动时报 “IMAP connection failed” | 检查 EMAIL_IMAP_HOST 和端口,确认邮箱已开启 IMAP(Gmail 在设置 → 转发和 POP/IMAP 里开) |
| 收不到消息 | 检查 EMAIL_ALLOWED_USERS 里有没有发件人地址。如果网关日志显示 authserv-id is not configured,把 EMAIL_AUTHSERV_ID 设成你服务器最顶层 Authentication-Results 头里写的那个确切 id。也顺手看看垃圾邮件文件夹——有些提供商会把自动回复标成垃圾。 |
配置项速查
| 变量 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|
EMAIL_AUTHSERV_ID |
是(除非关掉发件人认证) | — | 收信服务器最顶层 Authentication-Results 头里的 authserv-id;不配的话,所有需要认证 From: 的邮件都会被丢弃 |
搞定!现在你的 Hermes 就能收发邮件了。去试试给它发一封吧,记得用允许列表里的地址哦。
📖 官方文档
本文根据 Hermes Agent 官方文档编写,原文见:官方文档 › user-guide/messaging/email