dsh-email 0.14.1 → 0.14.3
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/CHANGELOG.md +10 -0
- package/README.en.md +4 -4
- package/README.md +4 -4
- package/lib/config.d.ts +12 -0
- package/lib/config.js +30 -8
- package/lib/settings.js +13 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.14.3(2026-09-28)
|
|
4
|
+
|
|
5
|
+
- 兼容验证更新到 Harness 0.2.0-rc.1:282 项邮件测试与 18 插件共同加载检查通过。
|
|
6
|
+
- 运行时代码未变;同步中英文兼容性声明。
|
|
7
|
+
|
|
8
|
+
## 0.14.2(2026-09-28)
|
|
9
|
+
|
|
10
|
+
- 修复 [#17](https://github.com/STARDUSTLC666/dsh-email/issues/17):空主机配合未修改的表单默认端口/TLS 不再覆盖服务商预设;Outlook 恢复 587/STARTTLS。旧设置转换和 Harness 0.1.7 已迁移配置共用归一化规则,保留自定义主机、非默认组合和不含占位 host 的显式端口覆盖。
|
|
11
|
+
- 感谢 [SenkjM 的 PR #18](https://github.com/STARDUSTLC666/dsh-email/pull/18) 提供复现与修复方向。本次补齐新版运行时路径并避免误删明确的端口设置;282 项邮件测试通过。配置和界面验证不代表真实 SMTP 投递已验证。
|
|
12
|
+
|
|
3
13
|
## 0.14.1(2026-09-27)
|
|
4
14
|
|
|
5
15
|
- 未补全的账号和服务器预设会显示未保存提示;避免草稿丢失和错误的“已保存”状态。测试连接只校验所选账号,错误直接指向设置页中的对应字段。
|
package/README.en.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# dsh-email
|
|
2
2
|
|
|
3
|
-
## 0.14.
|
|
3
|
+
## 0.14.2 update (2026-09-28)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Fixes saved blank-host defaults overriding Outlook's 587/STARTTLS preset, including legacy settings migrated to Harness 0.1.7. Explicit custom hosts, ports and TLS choices remain effective. Thanks to [SenkjM for the reproduction and proposed fix in #17 / #18](https://github.com/STARDUSTLC666/dsh-email/pull/18).
|
|
6
6
|
|
|
7
|
-
Validation host: Harness 0.
|
|
7
|
+
Validation host: Harness `0.2.0-rc.1` built from official sources (commit `407e65c8`) with Node `24.16.0` on 2026-09-28. All 282 plugin tests pass in an isolated environment; all 18 plugins mount together in one host registering 10 tools, with tool schemas and health-check contracts passing. No live ports or external services were exercised in this round.
|
|
8
8
|
|
|
9
9
|
   
|
|
10
10
|
|
|
@@ -53,7 +53,7 @@ Example:
|
|
|
53
53
|
- **0.10.8 and earlier**: see [CHANGELOG.md](CHANGELOG.md).
|
|
54
54
|
## Compatibility
|
|
55
55
|
|
|
56
|
-
The current baseline is official-source Harness **0.
|
|
56
|
+
The current baseline is official-source Harness **0.2.0-rc.1** (2026-09-28, with a local `Symbol.for` tool-scheduler fix). All 18 plugins load together. Settings coverage includes legacy migration, real Web UI editing and automatic saving, refresh, revision conflicts and restart persistence with isolated fixture accounts. No live mailbox connection or sending was exercised in this round.
|
|
57
57
|
|
|
58
58
|
2026-09-21: the current release package was installed through the official CLI in an isolated profile and co-loaded with the other two most-downloaded plugins on source-built Harness `0.1.6-alpha.2`. All 18 plugin tools registered; calendar/email configuration checks, PPT theme listing and 17-row table generation passed. The host is based on the official alpha.2 release plus the tool-scheduler `Symbol.for` fix (`93badd88`). This run did not connect to live mail or calendar services.
|
|
59
59
|
|
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
# dsh-email
|
|
4
4
|
|
|
5
|
-
## 0.14.
|
|
5
|
+
## 0.14.2 更新(2026-09-28)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
修复保存过的空服务器默认值覆盖 Outlook 预设的问题:恢复 `587 / STARTTLS`,并覆盖 Harness 0.1.7 的旧配置迁移路径。明确设置的自定义主机、端口和 TLS 仍然生效。感谢 [SenkjM 在 #17 / #18 提供复现和修复方向](https://github.com/STARDUSTLC666/dsh-email/pull/18)。
|
|
8
8
|
|
|
9
|
-
验证宿主:官方源码构建的 Harness 0.
|
|
9
|
+
验证宿主:官方源码构建的 Harness `0.2.0-rc.1`(commit `407e65c8`)+ Node `24.16.0`(2026-09-28)。282 项插件测试在隔离环境全部通过;同一个宿主里 18 个插件共同加载,注册 10 个工具,工具 schema 与健康检查契约通过。本轮未启用真实端口与外部服务。
|
|
10
10
|
|
|
11
11
|
> **让 agent 协助处理邮件**:收发、搜索、回复转发、附件、邮件整理与新邮件提醒,支持八种常见邮箱服务预设。
|
|
12
12
|
|
|
@@ -61,7 +61,7 @@ IMAP/SMTP email tools for DeepSeek Harness, with replies, forwarding, mailbox or
|
|
|
61
61
|
- **0.10.8 及更早**:见 [CHANGELOG.md](CHANGELOG.md)。
|
|
62
62
|
## 兼容性
|
|
63
63
|
|
|
64
|
-
当前验证基线为官方源码构建的 Harness **0.
|
|
64
|
+
当前验证基线为官方源码构建的 Harness **0.2.0-rc.1**(2026-09-28,含本地工具调度器 `Symbol.for` 修复)。18 个插件共同加载;邮件设置覆盖旧配置迁移、真实网页编辑与自动保存、刷新恢复、修订冲突和重启持久化检查。本轮使用隔离测试账号,未连接真实邮箱或发送邮件。
|
|
65
65
|
|
|
66
66
|
2026-09-21:当前发布包经官方 CLI 安装到隔离 profile,在源码构建的 Harness `0.1.6-alpha.2` 上与另外两个下载量前三插件共同加载,18 个插件工具注册正常;日历/邮件配置自检、PPT 主题查询和 17 行表格生成通过。测试本体基于官方 alpha.2 发布提交,另含工具调度器 `Symbol.for` 修复(`93badd88`)。本轮未连接真实邮箱或日历服务。
|
|
67
67
|
|
package/lib/config.d.ts
CHANGED
|
@@ -56,6 +56,18 @@ export interface SmtpConfig {
|
|
|
56
56
|
port?: number;
|
|
57
57
|
secure?: boolean;
|
|
58
58
|
}
|
|
59
|
+
/** Legacy form placeholders; an untouched blank-host endpoint delegates to its provider. */
|
|
60
|
+
export declare const ENDPOINT_DEFAULTS: {
|
|
61
|
+
readonly imap: {
|
|
62
|
+
readonly port: 993;
|
|
63
|
+
readonly secure: true;
|
|
64
|
+
};
|
|
65
|
+
readonly smtp: {
|
|
66
|
+
readonly port: 465;
|
|
67
|
+
readonly secure: true;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export declare function normalizeSettingsEndpoint<T extends SmtpConfig>(value: T, kind: keyof typeof ENDPOINT_DEFAULTS): Omit<T, 'host' | 'port' | 'secure'> & SmtpConfig;
|
|
59
71
|
/** One mailbox account. Top-level shorthand fields act as shared defaults. */
|
|
60
72
|
export interface AccountConfig {
|
|
61
73
|
/** Built-in provider name, or a custom serverPresets name. */
|
package/lib/config.js
CHANGED
|
@@ -34,6 +34,24 @@ export const OUTLOOK_IMAP_HOST = 'outlook.office365.com';
|
|
|
34
34
|
* them, so such a release asks every built-in account to log in one more time.
|
|
35
35
|
*/
|
|
36
36
|
export const OUTLOOK_OAUTH2_CLIENT_ID = '15dcd5aa-00dd-487f-82d7-1d2b2c299e14';
|
|
37
|
+
/** Legacy form placeholders; an untouched blank-host endpoint delegates to its provider. */
|
|
38
|
+
export const ENDPOINT_DEFAULTS = {
|
|
39
|
+
imap: { port: 993, secure: true }, smtp: { port: 465, secure: true },
|
|
40
|
+
};
|
|
41
|
+
export function normalizeSettingsEndpoint(value, kind) {
|
|
42
|
+
if (typeof value.host !== 'string' || value.host.trim() !== '')
|
|
43
|
+
return value;
|
|
44
|
+
const normalized = { ...value };
|
|
45
|
+
delete normalized.host;
|
|
46
|
+
const defaults = ENDPOINT_DEFAULTS[kind];
|
|
47
|
+
// A changed port or TLS choice is intentional; preserve that whole combination.
|
|
48
|
+
if ((value.port === undefined || value.port === defaults.port)
|
|
49
|
+
&& (value.secure === undefined || value.secure === defaults.secure)) {
|
|
50
|
+
delete normalized.port;
|
|
51
|
+
delete normalized.secure;
|
|
52
|
+
}
|
|
53
|
+
return normalized;
|
|
54
|
+
}
|
|
37
55
|
export const PROVIDER_PRESETS = {
|
|
38
56
|
qq: { imap: { host: 'imap.qq.com', port: 993, secure: true }, smtp: { host: 'smtp.qq.com', port: 465, secure: true } },
|
|
39
57
|
'163': { imap: { host: 'imap.163.com', port: 993, secure: true }, smtp: { host: 'smtp.163.com', port: 465, secure: true } },
|
|
@@ -340,17 +358,21 @@ function resolveAccount(name, common, acc, allowEnvPassword, providers, known) {
|
|
|
340
358
|
const authUser = (acc.authUser ?? common.authUser ?? '').trim() || user;
|
|
341
359
|
const authPassword = (acc.authPassword ?? common.authPassword) || password;
|
|
342
360
|
const senderName = (acc.senderName ?? common.senderName ?? '').trim();
|
|
361
|
+
const accountImap = acc.imap && normalizeSettingsEndpoint(acc.imap, 'imap');
|
|
362
|
+
const sharedImap = common.imap && normalizeSettingsEndpoint(common.imap, 'imap');
|
|
363
|
+
const accountSmtp = acc.smtp && normalizeSettingsEndpoint(acc.smtp, 'smtp');
|
|
364
|
+
const sharedSmtp = common.smtp && normalizeSettingsEndpoint(common.smtp, 'smtp');
|
|
343
365
|
const imap = {
|
|
344
|
-
host:
|
|
345
|
-
port:
|
|
346
|
-
secure:
|
|
347
|
-
connectionTimeoutMs:
|
|
348
|
-
socketTimeoutMs:
|
|
366
|
+
host: accountImap?.host ?? sharedImap?.host ?? preset?.imap.host,
|
|
367
|
+
port: accountImap?.port ?? sharedImap?.port ?? preset?.imap.port,
|
|
368
|
+
secure: accountImap?.secure ?? sharedImap?.secure ?? preset?.imap.secure,
|
|
369
|
+
connectionTimeoutMs: accountImap?.connectionTimeoutMs ?? sharedImap?.connectionTimeoutMs,
|
|
370
|
+
socketTimeoutMs: accountImap?.socketTimeoutMs ?? sharedImap?.socketTimeoutMs,
|
|
349
371
|
};
|
|
350
372
|
const smtp = {
|
|
351
|
-
host:
|
|
352
|
-
port:
|
|
353
|
-
secure:
|
|
373
|
+
host: accountSmtp?.host ?? sharedSmtp?.host ?? preset?.smtp.host,
|
|
374
|
+
port: accountSmtp?.port ?? sharedSmtp?.port ?? preset?.smtp.port,
|
|
375
|
+
secure: accountSmtp?.secure ?? sharedSmtp?.secure ?? preset?.smtp.secure,
|
|
354
376
|
};
|
|
355
377
|
const problems = [];
|
|
356
378
|
if (user === '')
|
package/lib/settings.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import z from 'schemastery';
|
|
2
|
-
import { PROVIDER_NAMES } from './config.js';
|
|
2
|
+
import { ENDPOINT_DEFAULTS, normalizeSettingsEndpoint, PROVIDER_NAMES } from './config.js';
|
|
3
3
|
/** Settings-document namespace this plugin owns (editable from the Web settings page). */
|
|
4
4
|
export const SETTINGS_NAMESPACE = 'dsh-email';
|
|
5
5
|
/**
|
|
@@ -22,13 +22,13 @@ export const EmailSettingsSchema = z.object({
|
|
|
22
22
|
serverPresets: z.string().default(''),
|
|
23
23
|
imap: z.object({
|
|
24
24
|
host: z.string().default(''),
|
|
25
|
-
port: z.number().default(
|
|
26
|
-
secure: z.boolean().default(
|
|
25
|
+
port: z.number().default(ENDPOINT_DEFAULTS.imap.port),
|
|
26
|
+
secure: z.boolean().default(ENDPOINT_DEFAULTS.imap.secure),
|
|
27
27
|
}),
|
|
28
28
|
smtp: z.object({
|
|
29
29
|
host: z.string().default(''),
|
|
30
|
-
port: z.number().default(
|
|
31
|
-
secure: z.boolean().default(
|
|
30
|
+
port: z.number().default(ENDPOINT_DEFAULTS.smtp.port),
|
|
31
|
+
secure: z.boolean().default(ENDPOINT_DEFAULTS.smtp.secure),
|
|
32
32
|
}),
|
|
33
33
|
});
|
|
34
34
|
/** Project the row config (cordis.patch.yml) into the settings-schema base shape. */
|
|
@@ -45,15 +45,15 @@ export function toSettingsBase(config) {
|
|
|
45
45
|
...(config.imap !== undefined ? {
|
|
46
46
|
imap: {
|
|
47
47
|
host: config.imap.host ?? '',
|
|
48
|
-
port: config.imap.port ??
|
|
49
|
-
secure: config.imap.secure ??
|
|
48
|
+
port: config.imap.port ?? ENDPOINT_DEFAULTS.imap.port,
|
|
49
|
+
secure: config.imap.secure ?? ENDPOINT_DEFAULTS.imap.secure,
|
|
50
50
|
},
|
|
51
51
|
} : {}),
|
|
52
52
|
...(config.smtp !== undefined ? {
|
|
53
53
|
smtp: {
|
|
54
54
|
host: config.smtp.host ?? '',
|
|
55
|
-
port: config.smtp.port ??
|
|
56
|
-
secure: config.smtp.secure ??
|
|
55
|
+
port: config.smtp.port ?? ENDPOINT_DEFAULTS.smtp.port,
|
|
56
|
+
secure: config.smtp.secure ?? ENDPOINT_DEFAULTS.smtp.secure,
|
|
57
57
|
},
|
|
58
58
|
} : {}),
|
|
59
59
|
};
|
|
@@ -131,7 +131,9 @@ export function toEmailConfig(value, user) {
|
|
|
131
131
|
// serverPresets is intentionally NOT projected: it is UI-side metadata that
|
|
132
132
|
// resolution never reads, and projecting it would put it into the resolved
|
|
133
133
|
// fingerprint, so saving a preset would dispose every live IMAP connection.
|
|
134
|
-
|
|
134
|
+
// Only a persisted blank host signals a placeholder. A schema-added blank
|
|
135
|
+
// host must not erase an explicit port-only override from the raw document.
|
|
136
|
+
const imapValue = user?.imap?.host !== undefined && draft.imap ? normalizeSettingsEndpoint(draft.imap, 'imap') : draft.imap;
|
|
135
137
|
const imapKeys = user === null ? imapValue : user?.imap;
|
|
136
138
|
if (isSet(imapKeys) && isSet(imapValue)) {
|
|
137
139
|
const imap = {};
|
|
@@ -145,7 +147,7 @@ export function toEmailConfig(value, user) {
|
|
|
145
147
|
imap.secure = imapValue.secure;
|
|
146
148
|
out.imap = imap;
|
|
147
149
|
}
|
|
148
|
-
const smtpValue = draft.smtp;
|
|
150
|
+
const smtpValue = user?.smtp?.host !== undefined && draft.smtp ? normalizeSettingsEndpoint(draft.smtp, 'smtp') : draft.smtp;
|
|
149
151
|
const smtpKeys = user === null ? smtpValue : user?.smtp;
|
|
150
152
|
if (isSet(smtpKeys) && isSet(smtpValue)) {
|
|
151
153
|
const smtp = {};
|