dsh-email 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/index.js +24 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,7 +120,7 @@ dsh plugin --profile web add dsh-email
|
|
|
120
120
|
|
|
121
121
|
- **授权码就是你的邮箱钥匙**。它写在本机(profile 的 `cordis.patch.yml` 或 `settings.yaml`),请勿提交到任何 Git 仓库;更推荐用环境变量 `DSH_EMAIL_PASSWORD`。
|
|
122
122
|
- `email_send` 默认走 DSH 审批通道:每次发信都显示「发送邮件给 xx,主题「xx」」,你批准才发出。没有审批通道的环境(如无 UI 的 headless)会**直接拒绝发信**,这是安全默认。
|
|
123
|
-
-
|
|
123
|
+
- 会话处于 **Full Access(完全访问)** 模式时,harness 的审批策略是 never(不弹任何确认框)——`email_send` 会**被拦截并给出明确提示**。两条出路:① 把访问模式切回 Read Only / Write;② 关闭 `sendApproval`(设置页勾掉「发信前确认」),即显式声明自行承担风险。
|
|
124
124
|
- 本插件不做任何联网上报,凭证只在内存中用于连接你的邮箱服务器。
|
|
125
125
|
|
|
126
126
|
## 已知限制(v0.3)
|
|
@@ -138,7 +138,7 @@ dsh plugin --profile web add dsh-email
|
|
|
138
138
|
```sh
|
|
139
139
|
pnpm install
|
|
140
140
|
pnpm run build # tsc → lib/
|
|
141
|
-
pnpm test # 构建 + node --test(配置/解析/注册与审批门,
|
|
141
|
+
pnpm test # 构建 + node --test(配置/解析/注册与审批门,37 个用例,无需真实邮箱)
|
|
142
142
|
```
|
|
143
143
|
|
|
144
144
|
## 协议
|
package/lib/index.js
CHANGED
|
@@ -164,6 +164,20 @@ function renderFolders(value) {
|
|
|
164
164
|
function renderAttachment(value) {
|
|
165
165
|
return oneText('账号 ' + value.account + ' 已下载附件 "' + value.filename + '"(' + value.contentType + ',' + value.size + ' 字节)到:\n' + value.path + '\n可用 read 工具读取该文件。');
|
|
166
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Best-effort read of the session's effective approval policy. Duck-typed on
|
|
169
|
+
* the permission-presets seam; any drift or absence yields undefined and the
|
|
170
|
+
* gate falls back to the plain ask flow.
|
|
171
|
+
*/
|
|
172
|
+
function effectiveApprovalPolicy(ctx, exec) {
|
|
173
|
+
try {
|
|
174
|
+
const preset = ctx.get?.('permissionPresets')?.current?.(exec?.agent?.session?.events);
|
|
175
|
+
return typeof preset?.approval === 'string' ? preset.approval : undefined;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
167
181
|
function fingerprintSettings(settings) {
|
|
168
182
|
return JSON.stringify({
|
|
169
183
|
accounts: [...settings.accounts.entries()].map(([name, account]) => [name, account]),
|
|
@@ -278,7 +292,7 @@ export function apply(ctx, config = {}) {
|
|
|
278
292
|
});
|
|
279
293
|
ctx.tools.register({
|
|
280
294
|
name: 'email_send',
|
|
281
|
-
description: 'Send an email from a configured account, optionally with file attachments (absolute paths, or relative to the dsh process cwd). Sending
|
|
295
|
+
description: 'Send an email from a configured account, optionally with file attachments (absolute paths, or relative to the dsh process cwd). Sending asks the user for approval (recipient, subject and attachment count are shown) unless sendApproval is disabled; in Full Access mode the approval policy never asks, so the send is refused with an explanation instead. Never invent recipients or content without the user\'s instruction.',
|
|
282
296
|
parameters: compileParameters({
|
|
283
297
|
to: { type: 'string', required: true, description: 'Recipient(s), comma-separated' },
|
|
284
298
|
subject: { type: 'string', required: true, description: 'Email subject' },
|
|
@@ -358,6 +372,15 @@ export function apply(ctx, config = {}) {
|
|
|
358
372
|
const args = (exec.args ?? {});
|
|
359
373
|
const attachCount = Array.isArray(args.attachments) ? args.attachments.length : 0;
|
|
360
374
|
const reason = '发送邮件给 ' + args.to + ',主题「' + args.subject + '」' + (attachCount > 0 ? ',附件 ' + attachCount + ' 个' : '');
|
|
375
|
+
// Full Access (approval policy 'never') rejects asks before any answerer
|
|
376
|
+
// runs, so surface the actionable explanation instead of a misleading
|
|
377
|
+
// "the user rejected" failure.
|
|
378
|
+
if (effectiveApprovalPolicy(ctx, exec) === 'never') {
|
|
379
|
+
return {
|
|
380
|
+
kind: 'deny',
|
|
381
|
+
reason: 'email_send 需要确认,但当前会话处于 Full Access(审批策略 never),不会弹出确认框。两条路:① 把访问模式切回 Read Only 或 Write 再发;② 在设置页关闭「发信前确认」(sendApproval: false),自行承担风险。',
|
|
382
|
+
};
|
|
383
|
+
}
|
|
361
384
|
return { kind: 'ask', reason };
|
|
362
385
|
}, { prepend: true });
|
|
363
386
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-email",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "IMAP/SMTP email tools for DeepSeek Harness: list, read, search and send mail, with QQ/163/126/Sina/Aliyun/Gmail/Outlook/iCloud presets.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|