前言¶
在 DeepSeek Harness(DSH)里做智能体时,常见需求是「对话里说一句,帮某人发一封邮件」。若自己对接 QQ 邮箱 OAuth、再拼发送逻辑,工作量大,且确认与安全边界容易不一致。本插件 dsh-qq-email(维护者 altmanWang,分类:联网工具)把发送逻辑集中在 Cordis 服务层,复用本机已授权的 agently-cli,同时提供 Agent 工具 send_qq_email 与 ctx.qqEmail 供其他插件调用;插件本身不保存 OAuth 凭据。
这是什么¶
一句话:dsh-qq-email 用已授权的 agently-cli 发 QQ 邮件,一个 npm 包两种入口——服务 ctx.qqEmail(service.js)给其他插件 inject: ['qqEmail'] 使用;工具 send_qq_email(tool.js)供对话里直接说「给 xxx 发封邮件」。发送逻辑只在服务层实现一次,工具只做参数翻译;两行插件可在 cordis.patch.yml 里独立开关。
当前版本(资料来源 package.json):0.1.0,许可证 MIT,DSH 引擎要求 0.2.x(见 engines.dsh)。
核心功能¶
- 对话发信:模型调用
send_qq_email后,DSH 弹出确认卡(发件人 / 收件人 / 抄送 / 密送 / 主题 / 正文预览),用户点「批准」后才发送。 - 插件内发信:
ctx.qqEmail.send(...);也可自管确认 UX:prepare()只拿确认令牌、不会发信,用户许可后再commit()。 - 默认 fail-closed:没有批准、没有确认入口、没有
confirmedByCaller都不会发送。 - 账号与额度:
ctx.qqEmail.account()可查当前授权账号与额度(默认缓存 60 秒)。 - 能力边界:只发送,不读信、不回复、不转发、不带附件;需要更多能力请直接用 agently-cli。
前置条件¶
- Node.js ≥ 22.19(DSH 运行环境自带)。
- DSH 0.2.x。
- 本机安装并授权 agently-cli:
npm install -g @tencent-qqmail/agently-cli
agently-cli auth login
agently-cli +me # 能打印出邮箱地址即授权成功
令牌由 agently-cli 自行管理(Windows 上为 DPAPI),插件以当前进程身份调用 CLI。
安装与启用¶
发布到 npm 后:
dsh plugin --profile web add dsh-qq-email
从 GitHub 安装(纯 JS,无构建步骤,不需要 allowBuilds):
dsh plugin --profile web add github:altmanWang/dsh-qq-email
本地开发目录:
dsh plugin --profile web add /绝对路径/plugin/dsh-qq-email
装完重启 dsh web(或刷新页面);Web UI 插件页应能看到服务与工具两行。
典型用法¶
在对话里¶
直接说明收件人、主题、正文与抄送,例如:
帮我给 alice@qq.com 发一封邮件,主题「项目进度同步」,正文「本周已完成 X,下周计划 Y」;抄送 bob@qq.com。
模型调用 send_qq_email 后出现确认卡,仅「批准」后发送。
在其他插件里¶
// 你的插件入口
export const inject = ['qqEmail']
export function apply(ctx) {
// 1) 最常用:完整流程。传 agent 上下文时,服务会弹出确认提示,用户批准后才发送。
const sent = await ctx.qqEmail.send(
{ to: 'alice@example.com', subject: '周报', body: '见附件' },
{ agent, callId, signal },
)
// 2) 自己管确认 UX(例如在 IM 频道里问):先预检,用户点头后再提交。
const pending = await ctx.qqEmail.prepare({ to: 'a@qq.com', subject: 'Hi', body: '你好' })
// …向用户展示 pending.summary / pending.request,拿到许可…
const sent2 = await ctx.qqEmail.commit(pending, { signal })
// 3) 查当前授权账号与额度(默认缓存 60 秒)
const { email, scopes, rateLimits } = await ctx.qqEmail.account()
}
agent 须为完整 DSH Agent 对象(如工具里的 exec.agent);prepare() + commit() 时确认责任在调用方。
TypeScript 可在插件内自行增强 Context(types.d.ts 不引用 @deepseek-ai/*):
import type { Context } from '@deepseek-ai/cordis'
import type { QqEmailService } from 'dsh-qq-email/types'
declare module '@deepseek-ai/cordis' {
interface Context { qqEmail: QqEmailService }
}
配置¶
CLI 入口按顺序解析,第一个存在的生效:
- 环境变量
DSH_QQ_EMAIL_CLI(指向.../agently-cli/scripts/run.js的绝对路径) - 插件 config 的
cliEntry(在 profile patch 里给该行加config:) - 各平台 npm 全局前缀推导(Windows / POSIX 常见路径,见 README)
示例(profile 的 cordis.patch.yml):
# profile 的 cordis.patch.yml
- id: qq-email-service
name: dsh-qq-email
config:
cliEntry: C:\Users\me\AppData\Roaming\npm\node_modules\@tencent-qqmail\agently-cli\scripts\run.js
确认与安全¶
- 两道确认:CLI 的
prepare(ctk_*令牌)+commit发送,以及 DSH 的approval;工具路径必须在界面点「批准」。 - 确认前不可变:
prepare()返回的request被深度冻结,确认卡与实际发送同源数据。 - 正文经 argv 传给 CLI,可能出现在本机进程命令行(同用户可读);Windows 命令行长度有限,超长会报
QQ_EMAIL_ARGS。 - 发送阶段被取消或超时,结果未知,错误信息会提示先查「已发送」,勿直接重试;确认令牌默认 5 分钟,批准过久时
send()会用同一请求重新预检再发。
错误处理请按 error.code 分支:QQ_EMAIL_ARGS、QQ_EMAIL_CLI_MISSING、QQ_EMAIL_CLI_FAILED、QQ_EMAIL_NOT_CONFIRMED、QQ_EMAIL_UNEXPECTED。
限制与适用注意¶
- 主题 UTF-8 约 4 KB;正文最多 20000 字符;收件人(to+cc+bcc)最多 50 个;同一地址不能同时在 cc 与 bcc。
- 工具路径必须由用户在 DSH 里确认;无头/自动化请用带
confirmedByCaller: true的插件调用路径,并自行负责确认。 - 插件以当前 dsh 进程权限运行,安装前建议阅读仓库源码与 MIT 许可证;社区目录 SkillHub 插件页 为独立站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-qq-email 把 QQ 发信接到 DSH 的确认模型与 Cordis 生态里:对话用工具、编排用服务,凭据留在 agently-cli。进一步了解与 issue 见 GitHub:altmanWang/dsh-qq-email,目录页见 SkillHub。