@chat-adapter/ gmail (英语)
npm 软件包 :
@chat-adapter/gmail
Gmail原始和可选的Chat SDK适配器,用于认证的邮箱通知和有线的电子邮件回复.
安装
pnpm add @chat-adapter/gmail
带CLI的脚手架
要用这个适配器和Redis状态预选的新 Gmail 机器人脚手架:
npx create-chat-sdk@latest my-bot --adapter gmail redis
访问 适配器目录 见其他官方和供应商官方适配器.
跟着 Gmail 引导 用于OAuth,经认证的Pub/Sub送出并监视更新. 独立的API不需要Chat实例;root适配器也需要持续状态和收取标签.
导入边框
| 导入 | 目的 | 装入聊天 |
|---|---|---|
@chat-adapter/gmail/api | OAuth 令牌提供者、信件、草稿、标签、历史和手表 | 没有 |
@chat-adapter/gmail/format | MIME 解析、组成和可序列化的回复上下文 | 没有 |
@chat-adapter/gmail/webhook | Pub/Sub通知解析和JWT核查 | 没有 |
@chat-adapter/gmail | 完整聊天 SDK 适配器 | 对 |
原始切入点及其生成的类型不导入 chat, (中文(简体) ), @chat-adapter/shared, (中文(简体) ), ai或者Google的完整客户端SDK. 他们不创建处理器,订阅器,锁,会话,或背景工人. 软件包仍然声明了可选的根适配器的聊天依赖性;这是运行时间隔离,而不是单独的安装脚印.
没有聊天
import {
createGmailDraft,
createGmailTokenProvider,
getGmailMessage,
} from "@chat-adapter/gmail/api";
import {
extractGmailContinuation,
parseGmailMessage,
} from "@chat-adapter/gmail/format";
const token = createGmailTokenProvider({
clientId: process.env.GMAIL_CLIENT_ID!,
clientSecret: process.env.GMAIL_CLIENT_SECRET!,
refreshToken: process.env.GMAIL_REFRESH_TOKEN!,
});
const options = { mailbox: "[email protected]", token };
const source = await getGmailMessage("native-message-id", options);
const email = await parseGmailMessage(source);
const continuation = extractGmailContinuation(email, options.mailbox);
const draft = await createGmailDraft({
continuation,
text: "Here is the proposed reply",
}, options);
现有的集成可以提供自己的符号字符串或async符号解析器,而不是 createGmailTokenProvider。API 选项还接受一个获取执行并中止信号.
内置令牌提供者在令牌到期前刷新并共享同时刷新请求. 它不运行初始同意流,也不在认证失败后自动重放API请求. 重新刷新后需要重新征得同意;检查 GmailApiError.reason 独立融合。 根适配器报告拒绝了证书 AuthenticationError。见 谷歌 OAuth 错误指南。 。 。 .
持续数据包含本地Gmail ID,邮箱,收件人,主题,以及 RFC 回复信头. 它的序列性很强,没有Chat订阅或会议依赖性. Reform-To 首选于 From;其他收件人不会自动复制. 将电子邮件内容和发送信头视为不信任的输入,而不是执行工具或发送邮件的授权.
全部回复时使用 extractGmailContinuation(email, mailbox, { replyAll: true })。它包括原始的 To 和 Cc 收件人,不包括已配置的邮箱和复制件,并且永远不会复制 Bcc 。 它不发现邮箱别名或扩展邮件列表. 在发送敏感内容之前先审查产生的收件人。 发送中的信息还可以明确 to 财务报告和审定财务报表 cc 数组.
在同一次谈话中,如需私人答复,请与 to: [{ address: recipient }] 财务报告和审定财务报表 cc: [] 改为 sendGmailMessage 或者说 createGmailDraft。这保留了主题和回复标题,而不复制续作的收件人。 给身体增加明显的私人通知. 如果打算稍后返回原组,则保留原续作.
createGmailDraft 保存草稿. sendGmailMessage 立即发送。 征召人拥有审批,出行,坚持和复试政策. API 不自动重试发送邮件 .
两种方法都接受提供者-本土 { raw, threadId? } 当调用者已经有一个基数64url-encoded MIME 消息时对象。 在构建原始回复时,调用者必须包括按下列要求匹配的主题、内调取和引用标题: 谷歌的线程合同。 。 。 .
本地事件和历史
拥有会话的集成可以不用根适配器的标签过滤或消息连接来使用原始. createGmailWebhookVerifier 返回已解码的通知字段并加上原包裹的 Pub/Sub envelope,包括交付元数据. 它验证传输身份和所配置的订阅,但不加载消息,更改光标或发送处理器. 检查 event.emailAddress 在进入邮箱前 与授权的邮箱对开. parseGmailNotification 只解析;它不认证请求.
经核实后,应用程序可以持久地对事件进行排队和确认,或在确认前完成处理. 不要承认在请求结束时可以消失的火和遗忘的工作. 该应用程序拥有重复处理、邮箱级序列化和检查站的持久性.
listGmailHistory 返回本地更改的一页: messagesAdded, (中文(简体) ), messagesDeleted, (中文(简体) ), labelsAdded, (中文(简体) ), labelsRemoved 和一般情况 messages 参考文献。 保留信件引用 labelIds 当谷歌提供它们。 使用特定的更改数组来避免两次处理同一信件;删除信件不同于添加 TRASH 标签。 没有隐含的信息水合.
import {
type GmailApiOptions,
type GmailHistory,
listGmailHistory,
} from "@chat-adapter/gmail/api";
async function catchUp(
startHistoryId: string,
options: GmailApiOptions,
consume: (changes: GmailHistory["history"]) => Promise<void>,
) {
let pageToken: string | undefined;
let cursor = startHistoryId;
do {
const page = await listGmailHistory({ startHistoryId, pageToken }, options);
await consume(page.history);
cursor = page.historyId;
pageToken = page.nextPageToken;
} while (pageToken);
return cursor;
}
只有在每一页都得到持久处理后,才能坚持返回的光标。 一个通知的 historyId 是一个醒目的水印,而不是替换所保存的光标。 历史标识符和页符仍然是字符串 。 历史由邮箱更改而不是电子邮件日期来排序;它包括根据所选过滤器发送和接收的邮件. 应用程序选择哪些内容需要转弯, 只加载需要的内容 getGmailMessage 财务报告和审定财务报表 parseGmailMessage。 。 。 . getGmailThread 返回命令的信息指针,而不是水合电子邮件机构.
历史保留有限。 一个过期 startHistoryId 返回时 GmailApiError 有状态 404;独立集成必须进行自己的完全同步. 要拖曳或恢复,在扫描当前消息之前抓取一个新的配置光标,调和扫描,然后从光标上追上. 原始人不会隐藏这个决定或默默地重设状态. 见 谷歌同步指南。 。 。 .
listGmailMessages({ q, labelId, includeSpamTrash, maxResults, pageToken }, options) 搜索当前邮箱内容和返回指针, nextPageToken 和可选 resultSizeEstimate。每个过滤器都是可选的,所以 {} 横跨邮箱列表。 使用 Gmail 的本土搜索 q 语法并需要一个范围,例如 gmail.readonly· ; gmail.metadata 不允许 q。搜索不是删除历史. listGmailHistory 接受可选 historyTypes, (中文(简体) ), labelId, (中文(简体) ), maxResults 财务报告和审定财务报表 pageToken。两个列表都调回一页,默认为100个记录,并允许最多500个记录;呼叫者决定是否继续.
watchGmailMailbox({ topicName }, options) 监视整个邮箱; 通过 labelId 限制通知。 它返回手表光标并到期, 但不会导入邮件或调度更新 。 root Chat适配器仍然需要其收取标签. 见 信件列表, (中文(简体) ), 历史列表 财务报告和审定财务报表 监视配置。 。 。 .
与聊天
import { createGmailAdapter } from "@chat-adapter/gmail";
import { createMemoryState } from "@chat-adapter/state-memory";
import { Chat } from "chat";
const gmail = createGmailAdapter();
const bot = new Chat({
userName: "agent",
adapters: { gmail },
state: createMemoryState(),
});
bot.onNewMention(async (thread) => {
await thread.post("Received, I will review this email");
});
Root适配器目前使用基于标签的交接. 它将同一对话中选定的电子邮件合并在一个同步中,运行到最新的消息中。 通过线条历史,老的信息仍然可用。 在生产中使用耐用状态;内相状态只适合局部实验.
选中的标签控制发送, 而不是 OAuth 访问邮箱 . thread.post() 立即发送电子邮件。 流出缓冲文本并发送一次;发送的电子邮件无法被编辑或撤回 。 执行自己文章/编辑流程的桥梁必须禁用电子邮件行为.
答复和私人递送
答复目标为答复,否则就是答复。 设定 createGmailAdapter({ replyAll: true }) 将原始 To 和 Cc 收件人包含在 thread.post() 财务报告和审定财务报表 thread.reply()。仅发送者回复仍然是默认的。 电子邮件可以包含外部收件人, 因此适配器报告频道可见度为 unknown,而不是作为授权或隐私保障.
Gmail没有原生的麻风信息. 使用私人电子邮件传送到一个明确的地址
bot.onNewMention(async (thread, message) => {
await thread.postEphemeral(message.author, "Please review this request", {
fallbackToDM: true,
});
});
这只将同一个 Gmail 线程中的永久邮件发送到所提供地址, 没有 Cc 或 Bcc , 并预缀给主体 (private only)。结果 usedFallback: true 和Gmail的实际线程ID. fallbackToDM: false 返回时 null 不发送,包括没有回放选项的直接适配器呼叫。 它从没有本地 Gmail 线索的频道或接收者路由中启动新的邮件主题 Private message。 。 。 .
处理器中,收到的信息会提供回复语境. 在处理器外,线条中最近传来的信息会提供它. 与 replyAll: true,使用时 thread.reply(originalMessageId, message) 在私人交换后返回原组; 答复最新的私人电子邮件不会恢复先前的收件人。 适配器从不自动引用更早的体或复制附件. Thread历史仍然可以同时包含私人和团体信息:应用程序必须防止私有内容输入后期的团体回复或共享模式上下文. 私人通知并不妨碍转发.
电子邮件的"From header"不是发送者身份的证明;应用程序必须选择一个可信任的收件人进行批准或证书,包括查看原始主体的许可. 其他电子邮件客户端可能以不同方式分组对话.
用于直接交付、使用 await gmail.postMessage(await gmail.openDM(address), message),或 bot.thread(await gmail.openDM(address)).post(message)。 。 。 . bot.openDM(address) 无法从电子邮件地址推断适配器 。 打开一个收件人路由不发送任何消息;每个邮件都会启动一个新的电子邮件并返回Gmail的实际线程ID. 路线本身没有消息历史. 答复是通过其原生的Gmail线索收到的,仍然需要输入标签.
设置
- 在您的 Google Cloud 项目中启用 Gmail API 和 Pub/ Sub 。 为邮箱获取用户文本 OAuth 证书 。 请求
gmail.readonly阅读和表,加gmail.send用于答复。 创建需求草案gmail.compose。适配器不需要允许删除电子邮件或修改标签。 见 Gmail 瞄准镜。 。 。 . - 在与OAuth客户端相同的Google Cloud项目中创建一个Pub/Sub主题. 赠款
[email protected]允许发布该主题. - 创建一个认证、 包裹的 Pub/ Sub 按下订阅 。 设置 Webhook URL 为其受众并配置一个 push 服务账户. 这个账户不同于Gmail的出版商账户. Pub/Sub服务代理商需要许可才能为它铸造一个身份标志. 跟随 谷歌认证的推力设置。 。 。 .
- 在 Gmail 中创建交接标签并用
listGmailLabels(options)从/api,用于 用户。 labels. list。标签的显示名称不是它的ID. - 配置适配器,初始化聊天并注册手表. 每天更新手表并运行
gmail.sync()定期发送通知,但邮箱不会停放.
例如,与 PROJECT, (中文(简体) ), PROJECT_NUMBER 财务报告和审定财务报表 WEBHOOK_URL 为您的部署设定 :
gcloud services enable gmail.googleapis.com pubsub.googleapis.com --project="$PROJECT"
gcloud beta services identity create --service=pubsub.googleapis.com --project="$PROJECT"
gcloud pubsub topics create gmail-events --project="$PROJECT"
gcloud pubsub topics add-iam-policy-binding gmail-events \
--project="$PROJECT" \
--member="serviceAccount:[email protected]" \
--role="roles/pubsub.publisher"
gcloud iam service-accounts create gmail-push --project="$PROJECT"
gcloud iam service-accounts add-iam-policy-binding \
"gmail-push@$PROJECT.iam.gserviceaccount.com" \
--project="$PROJECT" \
--member="serviceAccount:[email protected]" \
--role="roles/iam.serviceAccountTokenCreator"
gcloud pubsub subscriptions create gmail-webhook \
--project="$PROJECT" \
--topic=gmail-events \
--push-endpoint="$WEBHOOK_URL" \
--push-auth-service-account="gmail-push@$PROJECT.iam.gserviceaccount.com" \
--push-auth-token-audience="$WEBHOOK_URL"
操作员还需要许可才能创建这些资源和 iam.serviceAccounts.actAs 在推帐。 确保Pub/Sub服务代理在给予它象征性的创造器访问之前存在. 保持订阅包,并配置适配器与相同的订阅,受众和推取账户. 如果您的 Webhook 有额外的平台认证层, 请另建一个 .
| 配置 | 环境 |
|---|---|
mailbox | GMAIL_MAILBOX |
labelId | GMAIL_LABEL_ID |
clientId | GMAIL_CLIENT_ID |
clientSecret | GMAIL_CLIENT_SECRET |
refreshToken | GMAIL_REFRESH_TOKEN |
accessToken | GMAIL_ACCESS_TOKEN |
pubsubAudience | GMAIL_PUBSUB_AUDIENCE |
pubsubServiceAccountEmail | GMAIL_PUBSUB_SERVICE_ACCOUNT_EMAIL |
subscription | GMAIL_SUBSCRIPTION |
topicName | GMAIL_TOPIC_NAME |
replyAll | GMAIL_REPLY_ALL |
使用 OAuth 客户端/ 重新调试配置或 accessToken。当另一个系统已经管理更新时,推荐一个符号解析器。 明确的OAuth配置优先于环境访问符. 邮箱是一个电子邮件地址,订阅地址是 projects/PROJECT/subscriptions/SUBSCRIPTION,主题是 projects/PROJECT/topics/TOPIC。 。 。 .
使用实际的邮箱地址,而不是 Gmail 的地址 me 缩写。 适配器使用它来验证通知并隔离持续状态.
GMAIL_REPLY_ALL 只有在所有回复的数值完全正确时才允许回复 true明确 replyAll 配置值优先.
await bot.initialize();
await gmail.watch();
await gmail.sync();
展览 bot.webhooks.gmail(request) 从你的POST路线。 适配器只在同步完成后才能确认. 应用程序拥有调度;导入包不会启动工人. 停止应用程序不会解除邮箱表的注册 。 打电话 stopGmailMailbox(options) 从 /api 当永久断开邮箱时。 这个用 用户。 stop,它会停止邮箱通知,而不只是针对所选标签的通知。 也停止更新和同步任务; 此调用不会删除应用程序状态或取消 OAuth 同意 .
Google建议每天续约,要求至少每七天续约一次. 手表可以立即发出通知,所以路线必须已经可以使用. 见 推动交付和更新。 。 。 .
watch() 注册或更新通知并返回 Google 到期时间戳; 它不处理信件。 通话 sync() 后从已保存的光标上追上 。 在第一次设置时, 光标从表注册开始, 因此它不会导入已有标签的电子邮件 。 没有背景续订定时器:每日时间表 watch() 和定期 sync() 在您的申请中打电话.
自定义网点校验
webhookVerifier?: (request: Request) => unknown | Promise<unknown> 可以认证一个信任的转发服务,而不是Google的JWT. 真实结果接受请求;虚实结果或例外拒绝. 核查人收到可读的请求正文并可能消耗. 它优先于 pubsubAudience 财务报告和审定财务报表 pubsubServiceAccountEmail,在此模式中不需要。 没有习惯核查员,仍然需要对本地的Pub/Sub JWT进行核查.
覆盖只更改认证 。 有效载荷仍必须是包裹的Pub/Sub通知,并配置 subscription 还有邮箱 有效载荷尺寸限制和剖析仍然有效。 不要在公共端点上使用总是真实的验证器.
发送语义
- 初始表注册从Google返回光标开始,而不是从已存在的收件箱开始. 更新保存已保存的光标 。 已过期的历史触发了对目前贴有标签的信件的扫描;这可以包括从未发送过的更旧的贴有标签的电子邮件.
- Gmail 标签属于信件。应用对话标签会影响其现有信件。 未来回复不继承标签 。 明确标记这些回复或使用 Gmail 过滤器; 订阅 Chat 线索不会改变 Gmail 的标签 .
- 发送的信息、草稿、垃圾邮件和垃圾都排除在外。 标签检查发生在身体取回前,在发送前再次进行. 通知是读取历史的提示,而不是消息内容或可信任的光标更新.
- 持久收据取代了以前发出和取代的信息。 合作是每个同步运行,而不是保证每个人类UI动作一次召回. 删除并重新应用标签不会重放已被记录为已处理的信件 .
- 当多个被选中的消息属于一个对话时,同步在选择最新的合格消息之前只读取其命令的消息ID. 历史通过邮箱更改来排序,邮箱更改可能会在后期给更古老的信息贴上标签;它不能代替消息命令. 单个选中的消息不需要搜索线索 .
- 超大小的响应和MIME解析失败被单独记录为失败消息. 后来的对话继续同步;适配器不会回到失败的对话中一个更老的被选中的电子邮件. 失败的消息不会被自动获取, 包括在已过期的历史恢复期间 .
- 一个被拒绝的Chat 交接也被记录为失败,没有交付. 适配器登录本地消息ID, 线程ID 和一个原因 (
size, (中文(简体) ),format或者说handler),但不将消息内容包含在该失败日志中. 查特自己的日志配置仍然适用. 监控这些错误, 并使用本地身份证来明确检查或恢复受影响的电子邮件 . - 查特的去重复和通用语语义仍然适用. 失败的处理器不会自动重放, 因为处理器在丢弃前可能已经发送邮件 。 持久性应用工作并明确管理再试;在应用拥有其投放管时使用原始. 删除并重新应用标签不会重试记录的失败 .
- 信箱读取时的认证,速率限制和网络出错,以及持续同步状态出错,仍然会停止同步而不推进光标. 成功的Webhook确认意味着这些变化已经得到说明,包括记录的失败,而不是每个应用程序处理器都成功.
- 发送与状态更新无关 。 超时或进程失败可能使发送结果不确定. 在重试发件前调和;适配器和Gmail的接受响应都无法证明最终的收件人交付.
- MIME输入和输出被这个包所封顶为25 MiB,并有1 MiB缓冲流文本封顶. 这些是当地的安全限制,而不是Gmail账户或附件配额要求.
适配器不执行内Gmail按钮,全域部署,外出快递跟踪,或批准UI. 电子邮件头和内容不得作为特许工具的授权.
OAuth 部署
邮箱阅读访问是一个限制性范围. 生产部署必须评估谷歌的核查和安全评估要求,包括内部或测试应用的适用例外。 将符号材料和电子邮件内容保存在日志外,并对应用程序状态适用适当的保留和删除政策。 见 限制性核查 编辑 工作空间 API 数据政策。 。 。 .
核查
本地测试进行MIME,本地API合同,JWT验证,同步,Chat调度和导入边界. 一个子进程在使用已建成的原始输出时屏蔽 Chat 运行时间导入 。 来源和生成的申报图表分别检查. 经认证的集成测试使用本地生成的密钥并嘲笑了Gmail回复,而非真实的Google认证.
使用您自己的邮箱验证发送, 并认证配置后的 Pub/ Sub 订阅 。 仅一个成功的API请求并不能验证端到端的交付.
谷歌参考文献
AI 编码代理
安装 Chat SDK 技能 npx skills add vercel/chat可代理读取的文件 页:1 财务报告和审定财务报表 llms- full.txt (英语)。 。 。 .