终审残余两处:换 address 就是换信箱;错误话的出口也剥 NUL

复审的两条范围外观察,都落在这一轮刚动过的那两段里,一并收掉:

① 收侧判据看不见 address —— `imapSettingsOf` 用的是 `login ?? address`,而 login **常常空着**,
   这时候真正决定「登到哪个信箱」的就是 address。上一刀把发信三键排除掉之后,
   换 address 判据为假:旧游标的 UID 说的是原来那个箱子,而 UID 是按信箱编号的。
   判据改认**实际登录名**:login 填了就比 login(这时 address 只是发信落款,换它不动收信),
   空着就比 address。wecom 不参与 —— 它的 address 由探测回填,比它会在回填那一刻误清游标。

② 治毒信的那道门自己会被同一个字符毒死 —— 降级存档把解析失败的原因写进正文与
   `last_poll_error`,而那串原因常常来自那封信自己的字节。`errorText` 出口一律剥 NUL:
   所有落库的错误话都从这一个出口出去,分散到每个调用点去剥,总会漏掉下一个新调用点。

两条测试都验过 RED→GREEN(拿掉修复各自变红,旁边的既有用例不受影响)。

顺带:`mail/CONTRACT.md` 两处点名的 `createFakeMailProvider` 全仓不存在(未定义、未导出、无调用方)——
契约文档摆一个不存在的出口,照它接线的人会去 import 一个没有的东西;改成实情。
debt 补 ⑳-㉔(IMAP 每轮重登录与腾讯频率限制 / wecom -1 无退避 / pollDue 每 tick 刷日志 /
notes 不设上限 / claimForResend 推 created_at 使该列不再是创建时刻)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
This commit is contained in:
xcs
2026-08-26 04:07:08 +08:00
co-authored by Claude Fable 5
parent 58b1111e7e
commit f70de44338
6 changed files with 84 additions and 7 deletions
+13
View File
@@ -1168,3 +1168,16 @@ pnpm 硬链到全局 store,真实占盘远小于这个数,但 `du` 看着吓人
下游会按一段「【降级存档】…」的正文起单。要么在重投前提醒,要么给这类行一个标(库里现在只能靠正文认)。
⑲ **`SEND_STALE_MS` 与 `claimForResend` 的 5 分钟是两处各写一份**:用例算 `staleBefore = now − SEND_STALE_MS` 传进去,
store 只按传进来的时刻判 —— 目前只有一个调用方所以对得上,但这个数没有一处共同的定义点。
⑳ **IMAP 每一轮都新建 TLS 连接 + 登录一次**:`withImap` 用完即 `logout`,而轮询间隔默认 30s、下限 10s ——
一个账号一天 2880-8640 次登录。腾讯企业邮箱对登录频率有限制,**上线前先拿真账号把 `pollIntervalSec`
压到 10s 跑一小时**看会不会被拒;这比 IDLE 缺席更早会成为事故。根治是连接复用(或 IDLE),
两者都要先解决「跨进程租约下谁持有那条连接」。
㉑ **wecom 的 `-1`(系统繁忙)重试没有退避**:`call` 连打 `BUSY_RETRIES` 次,中间不等 ——
对方正忙的时候我们打得更密。加指数退避即可。
㉒ **`pollDue` 对「未配置凭证」的账号每 tick 写一行 stderr**:5 秒一次、一个账号一行,
生产日志会被这条刷屏。应按**状态变化**打印(从能拉变成拉不动那一次说一句),而不是每轮说一遍。
㉓ **一轮里的 `notes` 不设上限**:50 封毒信就把 50 句话拼进同一个 `last_poll_error`(几 KB)。
不是错,但运营面那一格会变得没法读 —— 截断并注明「另有 N 条」即可。
㉔ **`claimForResend` 会把抢到的那一行的 `created_at` 推到当下**:这是 CAS 判据的一部分
(抢到即离开可抢集合),代价是**这一列不再是「这一行何时建的」** —— 谁要拿它当来源凭据都会读错。
要么另立一列记真正的创建时刻,要么在读它的地方写明。目前无人拿它做凭据。