☰
Email Integration 深度指南:用 IMAP/SMTP 为 Botpress Agent 打通邮件收发
2026/10/7 8:39:18 网站建设 项目流程
  • AI 应用
  • 后端

【免费下载链接】botpress

The open-source hub to build & deploy GPT/LLM Agents ⚡️

项目地址:https://gitcode.com/gh_mirrors/bo/botpress
点击查看免费下载

本指南基于 Botpress 官方 Hub 中的 Email 集成文档(integrations/email/hub.md)及其源码展开,介绍如何通过 IMAP 读取邮件、通过 SMTP 发送邮件,将邮件通道接入 Botpress Agent。读完本文,你将掌握该集成的完整配置方法、四个核心 Action 的调用方式、邮件同步机制的底层原理,以及如何基于源码调试与扩展。

一、集成概览:IMAP 读、SMTP 发

Email 集成是 Botpress 官方提供的邮件通道解决方案,它把两种成熟的互联网邮件协议封装成 Agent 可用的 Action 与 Channel:

  • IMAP(Internet Message Access Protocol):负责读取收件箱中的邮件,将新邮件转成 Botpress 消息事件推送给 Agent;
  • SMTP(Simple Mail Transfer Protocol):负责发送邮件,让 Agent 可以直接回复用户或主动外发邮件。

从集成定义(integrations/email/integration.definition.ts)可以看出,官方对它的定位是"使用 IMAP 和 SMTP 协议发送和接收电子邮件"(Send and receive emails using IMAP and SMTP protocols),当前版本为0.1.4,归属"营销与邮件"(Marketing & Email)分类。

需要特别注意的一个能力边界:该集成目前不支持 HTML 邮件内容,收发双方都只处理纯文本。这意味着在 Agent 端构造邮件时,应使用纯文本描述内容,避免依赖富文本排版。

二、快速开始:配置文件与参数详解

2.1 官方文档给出的最小配置

在 Botpress Hub 中安装 Email 集成后,需要在集成配置中填写邮箱凭据。官方文档给出了如下示例:

user: yourEmailAccount@gmail.com password: yourAccountPassword host: imap.gmail.com #for gmail

2.2 完整的四个配置字段(以源码为准)

对照 integration.definition.ts 中的configuration.schema定义,实际配置共包含4 个必填字段,比文档示例多出smtpHost:

字段类型说明示例
userstring用于收发邮件的邮箱账号example@gmail.com
passwordstring该邮箱账号的密码或应用专用密码yourAccountPassword
imapHoststring要连接的 IMAP 服务器地址imap.gmail.com
smtpHoststring要连接的 SMTP 服务器地址smtp.gmail.com

四个字段全部为必填(.required())。对于 Gmail 等主流邮箱服务商,常见的配置组合是imapHost: imap.gmail.com+smtpHost: smtp.gmail.com;对于 QQ 邮箱则为imap.qq.com+smtp.qq.com。若使用企业邮箱或自建邮件服务器,请替换为对应的 IMAP/SMTP 主机名。

提示:多数主流邮箱要求为第三方应用开启 IMAP/SMTP 访问权限并生成"应用专用密码"(App Password),直接使用邮箱登录密码往往会被服务器拒绝。若注册集成时报连接错误,请优先检查这一点。

三、集成生命周期:注册时如何校验配置

Email 集成通过register与unregister两个生命周期钩子管理自身的启停(见 index.ts 与 setup.ts):

  • register(注册):设置初始lastSyncTimestamp状态,并立即发起一次 IMAP 连接(取 1 条消息)来验证配置正确性。若连接失败,会抛出运行时错误"注册集成时发生错误:... 请验证你的配置",从源头拦截错误凭据;
  • unregister(注销):无额外清理逻辑(源码注释// nothing to unregister)。
// integrations/email/src/setup.ts 中的校验逻辑(示意) try { await getMessages({ page: 0, perPage: 1 }, props) } catch (thrown: unknown) { throw new sdk.RuntimeError( `An error occured when registering the integration: ${err.message} Verify your configuration.` ) }

从 imap.ts 的_getConfig可以看到,IMAP 连接固定使用端口 993 + TLS 加密,并设置了rejectUnauthorized: false(跳过证书校验,便于连接部分自签名证书的邮件服务器):

const _getConfig = function (config: bp.configuration.Configuration) { return { user: config.user, password: config.password, host: config.imapHost, port: 993, tls: true, tlsOptions: { rejectUnauthorized: false }, } }

四、四大 Action:Agent 的邮件工具箱

集成对外暴露了 4 个 Action(定义见 integration.definition.ts,实现见 actions.ts),Agent 工作流中可直接调用:

4.1 listEmails:分页列出收件箱邮件

  • 输入:nextToken(可选,页号,从 0 开始);
  • 输出:messages(邮件数组)+nextToken(下一页令牌,无更多页时为 undefined);
  • 实现要点:每页固定50 封(ELEMENTS_PER_PAGE = 50,见 actions.ts);nextToken不能为负数,否则抛出RuntimeError;仅拉取邮件头(HEADER),不包含正文,适合快速扫描收件箱。

4.2 getEmail:按 ID 获取单封邮件

  • 输入:id(邮件的唯一标识,即 IMAP 服务器返回的message-id);
  • 输出:完整的emailSchema字段 +body(邮件正文);
  • 实现要点:通过 IMAPsearch按MESSAGE-ID头搜索邮件(见 imap.ts),找不到时返回 undefined 并抛出"找不到对应 ID 的邮件"错误。注意:搜索使用的 ID 是邮件头中的message-id,并非 IMAP 序号,跨会话稳定。

4.3 syncEmails:增量同步新邮件

  • 输入/输出:均为空对象;
  • 作用:把"未读过的"邮件作为新消息推送给 Agent,需要周期性调用才能让 Bot 持续收到新邮件;
  • 实现要点:这是接收邮件链路上最关键的 Action,下一节详细展开。

4.4 sendEmail:通过 SMTP 发送邮件

  • 输入:
    • to(必填):收件人邮箱;
    • subject(可选):邮件主题;
    • text(可选):邮件正文(纯文本);
    • inReplyTo(可选):要回复的邮件 ID,用于构造回复线程;
    • replyTo(可选):收件人回复时应使用的地址,允许与发件人不同;
  • 输出:空对象;
  • 实现要点:底层使用nodemailer创建 transporter 并调用sendMail(见 smtp.ts),from固定为配置中的user,同时把inReplyTo写入邮件的references头以维护线程:
const transporter = nodemailer.createTransport({ host: config.smtpHost, auth: { user: config.user, pass: config.password }, }) await transporter.sendMail({ from: config.user, ...props, references: props.inReplyTo, })

五、邮件同步的底层机制:状态、锁与去重

syncEmails是"收件"的核心,其实现逻辑(actions.ts)值得细读,它由三块机制协同完成:

5.1 同步锁:防止并发同步

locking.ts 中的LockHandler利用集成的syncLock状态(见 integration.definition.ts)实现互斥:

const currentlySyncing = await lock.readLock() if (currentlySyncing) throw new sdk.RuntimeError('The bot is still syncing the messages. Try again later.') await lock.setLock(true) // ... 同步逻辑 ... await lock.setLock(false)

如果上一次同步尚未结束,再次调用syncEmails会直接报错"Bot 仍在同步消息,请稍后再试",避免两个同步任务同时抢占 IMAP 连接。

5.2 时间戳状态:增量去重

lastSyncTimestamp状态记录了上一次成功同步的时间(integration.definition.ts)。同步时逐封对比邮件日期:

const messageAlreadySeen = message.date && lastSyncTimestamp && new Date(message.date) <= new Date(lastSyncTimestamp.lastSyncTimestamp) if (messageAlreadySeen) continue

日期不晚于上次同步时间的邮件视为已处理,直接跳过;同步完成后将当前时间写入状态。这样既避免重复推送,又能在 Bot 重启后从断点继续。

5.3 消息通知链路:从邮件到对话

未被跳过的邮件会进入_notifyNewMessage(actions.ts),完整链路为:

  1. 用户映射:以发件人邮箱为email标签,getOrCreateUser创建或复用 Botpress 用户;
  2. 会话映射:以firstMessageId(取邮件references头中最早的 message-id,否则回退为自身 id)为区分标签,getOrCreateConversation创建或复用会话,同时把subject、to、latestEmail写入会话标签(integration.definition.ts);
  3. 消息落库:createMessage以纯文本形式把邮件正文(message.body ?? '')写入会话,并打上邮件id标签。

发件人为配置中的user自己的邮件会被直接跳过(if (message.sender === props.ctx.configuration.user) continue),避免把 Bot 自己发出的邮件又当成新消息回灌。

六、Channel 视角:Bot 如何回复邮件

集成定义了default通道(integration.definition.ts,实现见 channels.ts),支持text类型消息。当 Agent 决定回复某封邮件时,通道处理器自动完成"回复拼接":

await smtp.sendNodemailerMail( props.ctx.configuration, { to: props.conversation.tags.to, subject: 'Sent from botpress email integration', text: props.payload.text, inReplyTo: props.conversation.tags.latestEmail, replyTo: props.ctx.configuration.user, }, props.logger )

几个值得注意的细节:

  • 收件人取自会话标签to:即原邮件的收件人,若会话缺少该标签会抛出"尝试在没有 'to' 头的情况下发送邮件"错误;
  • inReplyTo使用会话标签latestEmail:即该会话最新一封邮件的 ID,确保回复挂到正确的邮件线程上;
  • replyTo固定为配置中的user:收件人回复时会回到 Bot 的邮箱账号;
  • 主题固定为 "Sent from botpress email integration":如需自定义主题,应通过sendEmailAction 而非通道回复。

七、分页算法的实现细节与测试验证

listEmails的分页并非简单偏移量,而是基于 IMAP 序列号区间实现(paging.ts):

export const pageToSpan = (props: PageToSpanProps): Span => { if (props.totalElements <= 0) { throw new sdk.RuntimeError('Could not read the inbox: the number of messages in the inbox is 0') } const lastElementIndex = Math.max(1, props.totalElements - props.page * props.perPage) const firstElementIndex = Math.max(1, lastElementIndex - props.perPage + 1) return { firstElementIndex, lastElementIndex } } export const getNextToken = (props: NextTokenProps): number | undefined => { if (props.firstElementIndex === 1) return undefined return props.page + 1 }

其语义为:第 0 页取最新 50 封(收件箱末尾),页码越大越往旧邮件方向翻;当某一页已经覆盖到第 1 封(最旧)邮件时,getNextToken返回undefined,表示没有下一页了。

该算法有配套的单测覆盖(paging.test.ts),包括空收件箱抛错、单封邮件、不足一页、满页、翻页与 token 边界等场景,例如:

test('pageToSpan with full page returns first page', () => { expect(pageToSpan({ page: 0, perPage: 50, totalElements: 300 })).toEqual({ firstElementIndex: 251, lastElementIndex: 300, } satisfies Span) })

八、本地开发与调试

该集成位于integrations/email/目录下,package.json提供了完整的开发脚本:

{ "name": "@botpresshub/email", "scripts": { "check:type": "tsc --noEmit", "check:bplint": "bp lint", "build": "bp build", "test": "vitest --run" }, "dependencies": { "@botpress/client": "workspace:*", "@botpress/sdk": "workspace:*", "imap": "^0.8.17", "nodemailer": "^6.7.2" } }
  • 类型检查:tsc --noEmit,确认类型定义与.botpress生成代码一致;
  • 集成规范检查:bp lint,使用 Botpress CLI 校验集成定义是否符合平台规范;
  • 单元测试:vitest --run,目前覆盖分页算法;
  • 构建:bp build,产出可部署的集成包。

IMAP 相关错误在源码中均被包装为RuntimeError并附带原因,排查问题时重点关注两类报错:注册阶段的"验证你的配置"(多半是凭据或主机名问题)与同步阶段的"验证集成配置参数"(可能是网络或服务器权限问题)。

九、使用建议与限制总结

场景推荐做法
接收新邮件周期性(如每分钟)调用syncEmails,或在定时任务中触发
扫描收件箱调用listEmails分页浏览邮件头,配合nextToken翻页
读取邮件全文用listEmails得到的id调用getEmail获取body
主动发信调用sendEmail,可自定义收件人、主题、正文与回复线程
会话式回复让 Agent 在邮件会话上下文中回复,走default通道自动挂线程

当前版本的能力边界与已知限制包括:

  1. 不支持 HTML 内容:收发双方均为纯文本;
  2. IMAP 固定使用 993 端口 + TLS,且跳过证书校验(rejectUnauthorized: false),在安全性要求极高的内网环境需注意;
  3. syncEmails每次同步只处理最新一页(50 封)内的新邮件,超过 50 封的积压需要多次同步才能全部拉取;
  4. 同步为互斥操作,并发调用会直接报错;
  5. 默认仅处理收件箱(INBOX),不涉及其他 IMAP 文件夹。

参考文件索引

  • 官方文档:integrations/email/hub.md
  • 集成定义(配置/状态/Action/通道 Schema):integrations/email/integration.definition.ts
  • 入口与生命周期注册:integrations/email/src/index.ts、integrations/email/src/setup.ts
  • Action 实现(含同步机制):integrations/email/src/actions.ts
  • IMAP 实现:integrations/email/src/imap.ts
  • SMTP 实现:integrations/email/src/smtp.ts
  • 通道处理:integrations/email/src/channels.ts
  • 同步锁与分页:integrations/email/src/locking.ts、integrations/email/src/paging.ts
  • 分页单测:integrations/email/src/paging.test.ts
  • AI 应用
  • 后端

【免费下载链接】botpress

The open-source hub to build & deploy GPT/LLM Agents ⚡️

项目地址:https://gitcode.com/gh_mirrors/bo/botpress
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询