emailengine-app 2.70.0 → 2.72.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/.github/workflows/codeql.yml +3 -0
- package/.github/workflows/e2e.yml +56 -0
- package/.github/workflows/test.yml +81 -12
- package/.ncurc.js +20 -20
- package/CHANGELOG.md +25 -0
- package/Gruntfile.js +19 -23
- package/bin/emailengine.js +8 -1
- package/config/default.toml +5 -0
- package/config/e2e.toml +35 -0
- package/config/test.toml +5 -0
- package/data/google-crawlers.json +1 -1
- package/getswagger.sh +4 -0
- package/lib/account.js +31 -25
- package/lib/api-routes/message-routes.js +125 -121
- package/lib/auth-token.js +83 -0
- package/lib/delivery-error.js +62 -0
- package/lib/document-store.js +22 -1
- package/lib/email-client/base-client.js +3 -2
- package/lib/email-client/gmail-client.js +33 -1
- package/lib/email-client/imap/mailbox.js +2 -2
- package/lib/email-client/notification-handler.js +2 -2
- package/lib/export.js +12 -0
- package/lib/feature-flags.js +6 -0
- package/lib/imap-proxy-auth.js +81 -0
- package/lib/imapproxy/imap-server.js +8 -103
- package/lib/license-beacon.js +367 -0
- package/lib/logger.js +11 -1
- package/lib/oauth/gmail.js +3 -0
- package/lib/oauth/outlook.js +3 -0
- package/lib/oauth2-apps.js +100 -11
- package/lib/routes-ui.js +2 -1
- package/lib/smtp-auth.js +70 -0
- package/lib/sub-script.js +8 -2
- package/lib/tools.js +26 -2
- package/lib/ui-routes/admin-config-routes.js +4 -3
- package/lib/ui-routes/document-store-routes.js +7 -1
- package/package.json +30 -24
- package/playwright.config.js +45 -0
- package/sbom.json +1 -1
- package/server.js +30 -8
- package/static/licenses.html +108 -128
- package/test-coverage-plan.md +233 -0
- package/translations/de.mo +0 -0
- package/translations/de.po +154 -142
- package/translations/et.mo +0 -0
- package/translations/et.po +129 -131
- package/translations/fr.mo +0 -0
- package/translations/fr.po +133 -136
- package/translations/ja.mo +0 -0
- package/translations/ja.po +126 -129
- package/translations/messages.pot +37 -37
- package/translations/nl.mo +0 -0
- package/translations/nl.po +128 -130
- package/translations/pl.mo +0 -0
- package/translations/pl.po +125 -128
- package/views/dashboard.hbs +22 -0
- package/workers/api.js +22 -5
- package/workers/export.js +58 -43
- package/workers/smtp.js +5 -85
- package/workers/submit.js +2 -12
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# EmailEngine - Feature Map & Prioritized Test Plan
|
|
2
|
+
|
|
3
|
+
Generated 2026-06-16. Read-only audit across five feature areas (email sync engine, REST API, admin UI, background workers/queues, core libraries). No source or tests were modified.
|
|
4
|
+
|
|
5
|
+
Baseline: ~70k LOC source (lib + workers + server.js) vs ~16.1k LOC unit tests, ~1.8k integration, 180 e2e.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Feature & functionality map
|
|
10
|
+
|
|
11
|
+
EmailEngine is a multi-threaded (Worker Threads), Redis-backed email sync platform exposing a REST API + admin UI.
|
|
12
|
+
|
|
13
|
+
### Email sync engine (lib/email-client/*, workers/imap.js, lib/account*)
|
|
14
|
+
- Three providers behind a shared `BaseClient`: IMAP (ImapFlow + IDLE), Gmail API (Pub/Sub + 10-min poll fallback), Outlook/Graph (subscription webhooks, 3-day renewal).
|
|
15
|
+
- Message ops: list/get/getText/getRawMessage/getAttachment/update/move/delete/upload (+ bulk variants).
|
|
16
|
+
- Mailbox ops: list/create/modify/delete; special-use resolution; provider path encoding (Outlook `/`,`%`; Gmail label<->folder).
|
|
17
|
+
- IMAP sync: `determineSyncStrategy` -> none/partial(condstore|simple)/full; UIDValidity change -> full resync + index reseed; lost-index silent reseed; batched fetch with retry/backoff.
|
|
18
|
+
- Reliability: exponential reconnect/backoff; auth-failure tracking + auto-disable (`setErrorState`); error classification -> account state (authenticationError vs connectError); state machine (account-state.js).
|
|
19
|
+
- Send path: `queueMessage`/`submitMessage` (SMTP + Gmail/Outlook API), idempotency keys, post-delivery Sent-folder upload + Answered/Forwarded flags + gateway stats.
|
|
20
|
+
|
|
21
|
+
### REST API (lib/api-routes/*, ~8.1k LOC, 20 modules)
|
|
22
|
+
- Account + message + mailbox CRUD/ops; submit; outbox; export; gateways; templates; tokens; settings; oauth2-apps; webhook-routes; blocklist; chat (doc-store-gated); delivery-test; license; pubsub; stats; bull-board.
|
|
23
|
+
- Single `api-token` bearer strategy: scope derived from route tags (all REST modules use `api`); account-token binding restricts to own `{account}`; IP/referrer allowlist + per-token rate limit; `disableTokens` open-API bypass.
|
|
24
|
+
|
|
25
|
+
### Admin UI (lib/ui-routes/*, lib/routes-ui.js, workers/api.js; ~128 routes)
|
|
26
|
+
- Auth: session cookie (`ee`), TOTP, passkeys/WebAuthn (intentionally bypasses TOTP), OKTA OAuth2, pbkdf2 password, `passwordVersion` force-logout.
|
|
27
|
+
- CSRF via @hapi/crumb (skip-list: api/metrics/static/external tags).
|
|
28
|
+
- Config screens: webhooks, service, AI, logging/Sentry, license, OAuth apps, network/proxy, SMTP/IMAP-proxy servers, document-store (deprecated, self-gates off).
|
|
29
|
+
- Public (auth:false) flows: add-account wizard (HMAC-signed form), OAuth start/redirect (account creation), unsubscribe.
|
|
30
|
+
|
|
31
|
+
### Background workers & servers (workers/*, server.js, lib/webhooks.js, lib/export.js)
|
|
32
|
+
- Submit worker: BullMQ delivery, retry/backoff classification (`NON_RETRYABLE_CODES`, 5xx-not-503 -> discard).
|
|
33
|
+
- Webhooks worker: BullMQ delivery (10 attempts, HMAC sig), custom routes with sandboxed `fn`/`map` (SubScript/vm).
|
|
34
|
+
- Export worker: phased NDJSON export, gzip + optional AES-256-GCM, recovery, atomic concurrency Lua.
|
|
35
|
+
- SMTP server (MSA) + IMAP proxy: three auth modes each (global password / scoped hex token / header or passthrough).
|
|
36
|
+
- Documents worker: deprecated Elasticsearch indexing, gated off by default.
|
|
37
|
+
- server.js main process: worker spawn/health/restart, account assignment (load-aware round-robin + rendezvous reassignment), RPC with timeout.
|
|
38
|
+
|
|
39
|
+
### Core libraries (lib/*)
|
|
40
|
+
- oauth2-apps.js (OAuth2 app config + token orchestration, 5 providers, WIF, Pub/Sub IAM), oauth/* providers.
|
|
41
|
+
- tokens.js (API + session tokens, hashed storage), encrypt.js (AES-256-GCM), settings.js (encrypted keys).
|
|
42
|
+
- tools.js (binary sync-state serialize/unserialize, license verify, signed-form HMAC, glob matcher, redaction).
|
|
43
|
+
- bounce-detect.js / arf-detect.js (DSN + FBL parsing), add-trackers.js, get-raw-email.js, autodetect-imap-settings.js, rewrite-text-nodes.js, templates.js, redis-operations.js.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. Current coverage assessment
|
|
48
|
+
|
|
49
|
+
Strong (real source imported, good cases):
|
|
50
|
+
- IMAP sync-strategy helpers, lost-index recovery, processChanges, null/event guards, mailbox-listing diff, Outlook folder encoding, label search filters, account-state helpers (email sync).
|
|
51
|
+
- Gmail Pub/Sub manager recovery, WIF external-account signer, OAuth token-request encoding + scope/nonce/error-status, tokens.js, encrypt.js, stream-encrypt, export.js internals + concurrency Lua, IMAP-proxy protocol hardening, redis-operations helpers, bounce/ARF structured (RFC 3464) parsing.
|
|
52
|
+
|
|
53
|
+
Thin or absent:
|
|
54
|
+
- Entire api-routes/ and ui-routes/ handler execution: exercised only via integration smoke (401-without-token + 200-with-`*`-token) and one e2e happy path. No scoped/cross-tenant token tests, no CSRF assertion, no POST mutation handlers, no parameterized routes.
|
|
55
|
+
- Send/submit pipeline, auth auto-disable, reconnect/backoff, Gmail history sync, Outlook subscription lifecycle: only the flaky non-hermetic live integration suite.
|
|
56
|
+
- SubScript sandbox, server.js account assignment/reassignment, SMTP/IMAP-proxy auth layers: zero tests.
|
|
57
|
+
- Large files barely touched: outlook-client.js (4584), gmail-client.js (3079), base-client.js (3279), imap/mailbox.js (3255), workers/api.js (3185), schemas.js (2497), tools.js (2372, ~27% of exports + all binary/crypto/async untested), oauth2-apps.js handler class, autodetect-imap-settings.js (779, 0 tests), get-raw-email.js (552, 0).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 3. Cross-cutting findings
|
|
62
|
+
|
|
63
|
+
### 3a. "Illusory coverage" - tests that re-implement source instead of importing it
|
|
64
|
+
These pass green even when the shipping code breaks. Highest ROI to fix:
|
|
65
|
+
- `worker-not-available-test.js` - copies the submit discard predicate; omits the `NON_RETRYABLE_CODES` (EAUTH/EOAUTH2/ETLS/...) branch entirely.
|
|
66
|
+
- `autoreply-test.js` - re-defines `isAutoreply`; real `BaseClient.isAutoreply` (base-client.js:2173) untested.
|
|
67
|
+
- `complaint-test.js` - re-implements `mightBeAComplaint`; real wrapper untested (underlying arf-detect IS tested).
|
|
68
|
+
- `email-client-test.js` - defines its own PageCursor + constants; real Gmail `PageCursor` untested.
|
|
69
|
+
- `retry-logic-test.js` - defines its own `calculateBackoffDelay`/`simulateRequestWithRetry`; real Outlook `requestWithRetry` (outlook-client.js:222) untested.
|
|
70
|
+
|
|
71
|
+
### 3b. Auth boundaries asserted only at "401 without any token"
|
|
72
|
+
Scope enforcement, cross-account binding, CSRF, session invalidation, and the admin auth gate are never positively tested with real (scoped / cross-tenant / crumb-less) requests. The test prepared token decodes to `scopes:["*"]`, so every integration/e2e run is a full-root token.
|
|
73
|
+
|
|
74
|
+
### 3c. Latent bugs surfaced during the audit (not tests - fix separately)
|
|
75
|
+
- arf-detect.js:112 - reads `report['source-ip']` but writes `report.arf['source-ip']` (source IP never populated).
|
|
76
|
+
- worker-not-available-test.js silently omits a whole discard branch (see 3a).
|
|
77
|
+
- `mightBeABounce`/`mightBeAComplaint`/`mightBeDSNResponse` are duplicated in both base-client.js (2832-2890) and imap/mailbox.js (3056-3204) - drift risk; consolidate.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 4. Prioritized test backlog
|
|
82
|
+
|
|
83
|
+
Priority = blast radius x regression likelihood x security sensitivity, weighted by cost-to-implement (cheap high-value first).
|
|
84
|
+
|
|
85
|
+
### P0 - Do first
|
|
86
|
+
|
|
87
|
+
| # | Test | Why | Type |
|
|
88
|
+
|---|------|-----|------|
|
|
89
|
+
| 1 | Fix the 5 "illusory coverage" tests to import real exports (submit discard incl. NON_RETRYABLE_CODES, isAutoreply, mightBeAComplaint, Gmail PageCursor, Outlook requestWithRetry) | False green today; cheapest possible win; unblocks trust in the suite | unit |
|
|
90
|
+
| 2 | SubScript sandbox (lib/sub-script.js) - timeout enforcement, no process/require/global escape, env/scriptEnv injection, payload isolation, compile-error caching | Arbitrary user JS runs in-process on every webhook; zero tests | unit |
|
|
91
|
+
| 3 | tools.serialize / unserialize round-trip - UID+flags+modseq+msgpack, D/N sentinels, BigInt modseq | Corrupts sync state for ALL accounts (dup/dropped messages + webhooks); zero tests; pure/cheap | unit |
|
|
92
|
+
| 4 | API token scope enforcement + cross-account binding (workers/api.js:1106,1121-1170) - smtp/imap-proxy-only token must 403 on /v1/*; account token must 403 on a different account; template special-casing | Core security boundaries, tested only at 401-without-token; provision tokens via lib/tokens.provision() in existing smoke harness | integration |
|
|
93
|
+
| 5 | Admin UI auth gate + CSRF + passwordVersion - boot server WITH admin password: anonymous /admin/* -> 302 login; crumb-less POST -> 403; passwordVersion bump invalidates old cookie | Closes the 3 highest-blast-radius UI gaps at once; a regression making admin world-readable passes all current tests | integration |
|
|
94
|
+
|
|
95
|
+
### P1 - High
|
|
96
|
+
|
|
97
|
+
| # | Test | Why | Type |
|
|
98
|
+
|---|------|-----|------|
|
|
99
|
+
| 6 | Send/submit pipeline + idempotency (base-client.js submitMessage/queueMessageEntry/handleSubmitError, checkIdempotencyKey) - permanent-5xx vs transient, Sent-folder upload, reference flags, gateway stats | Data loss / duplicate sends; only happy-path live coverage | unit + 1 integration error path |
|
|
100
|
+
| 7 | server.js account assignment & reassignment (assignAccounts, rendezvous reassign trigger, call-failure rollback, worker-exit -> unassigned, 10s failsafe, health -> restart) | Highest orchestration blast radius (one routing bug hits all accounts); zero tests | unit (extract) / integration with fake workers |
|
|
101
|
+
| 8 | setErrorState auth-failure auto-disable (base-client.js:383) - error-count, same-error dedupe, MAX_IMAP_AUTH_FAILURE_TIME threshold, disable+close | Safety mechanism vs reconnect storms; untested | unit (mock redis txn + clock) |
|
|
102
|
+
| 9 | SMTP server + IMAP-proxy AUTH layers (workers/smtp.js:112-246, imapproxy/imap-server.js:153-247) - global password, scoped hex token, account==username, IP restriction, API-only rejection | Auth-bypass surface; protocol hardening is tested but auth is not | integration |
|
|
103
|
+
| 10 | Bulk message mutate/delete REST (message-routes.js PUT /messages, /messages/move, /messages/delete?force) | Highest data-loss blast radius among untested endpoints; matches prior Outlook bulk-delete finding | integration |
|
|
104
|
+
| 11 | bounce-detect text-heuristic fallback (~13 vendor matchers: Exim/Postfix/Google/KDDI/Verizon/James/generic 5xx, bounce-detect.js:417-832) | Largest real-world regression surface; regex-fragile (ReDoS-hardened, no regression test) | unit (fixtures) |
|
|
105
|
+
| 12 | OAuth2AppsHandler stateful core (oauth2-apps.js create/update/del encryption, getServiceAccessToken caching/lock:1641, getClient per-provider:1422) + Gmail/Outlook checkForFlags error->flag mapping | Mis-stored/plaintext creds, token stampede, wrong auth flags; only leaf helpers tested today | unit |
|
|
106
|
+
| 13 | Gmail history sync (processHistory/processHistoryEntry, gmail-client.js:2737-3001) + Outlook subscription lifecycle (renewSubscription/ensureSubscription/syncMissedMessages, outlook-client.js:3224-3971) | Core real-time correctness; only flaky live coverage; silent event loss | unit (mock request) |
|
|
107
|
+
| 14 | IMAP reconnect/backoff + error->state classification (imap-client.js reconnect:910, start() catch:1557) | Timing-sensitive; high regression likelihood | unit (fake timers) |
|
|
108
|
+
|
|
109
|
+
### P2 - Medium
|
|
110
|
+
|
|
111
|
+
| # | Test | Why | Type |
|
|
112
|
+
|---|------|-----|------|
|
|
113
|
+
| 15 | bull-board auth (/admin/bull-board/* relies only on default session guard) | Queue job payloads (recipients/message data) leak if guard regresses | integration |
|
|
114
|
+
| 16 | chat / unified-search REST doc-store gating (/v1/chat 404 + /v1/unified/search runtime-404 when feature off) | doc-store-disabled test covers UI only | route-table + integration |
|
|
115
|
+
| 17 | Secret masking on read (GET /v1/account, /v1/oauth2 -> ******) | Assert secrets never round-trip cleartext | integration |
|
|
116
|
+
| 18 | Public account-setup HMAC verification (/accounts/new/imap/server, POST /v1/authentication/form) + signed-form replay/TTL/nonce | Unauth account creation + credential write if sig check regresses | integration + unit |
|
|
117
|
+
| 19 | settings.js secret encrypt/decrypt + POST /v1/settings write broadcast | Silent corruption of stored OAuth secrets/serviceSecret; global blast radius | unit + integration |
|
|
118
|
+
| 20 | Security redaction units: formatPartialSecretKey, add-trackers redirect rewriting (open-redirect via /redirect), get-raw-email X-EE-*/BCC stripping | Header/secret leakage on every outbound message | unit |
|
|
119
|
+
| 21 | UIDVALIDITY-change full-resync branch (mailbox.js onOpen:2102-2127) | Distinct from lost-index reseed; wrong handling re-floods or drops messages | unit |
|
|
120
|
+
| 22 | Export recovery + encryption end-to-end (markInterruptedAsFailed, gzip->encrypt->decryptable artifact, lease extension) | Classifiers tested in isolation; recovery flow not | integration |
|
|
121
|
+
| 23 | Webhook custom-route fn/map filter/transform end-to-end + payload formatting/truncation + route-disable-on-compile-error + HMAC sig value | Handler cache tested; actual filter/transform behavior not | unit/integration |
|
|
122
|
+
| 24 | autodetect-imap-settings.js (779 LOC, 0 tests) - provider table, autoconfig XML substitution, escapeXml autodiscover injection, SRV parsing | Every new-account config; high churn; injection surface | unit (stub dns/undici) |
|
|
123
|
+
| 25 | smtp-pool-manager generatePoolKey (credential isolation) + cleanupIdlePools | Pool-key collision could cross-send via wrong account | unit |
|
|
124
|
+
| 26 | Broad POST mutation + parameterized route execution (token provision/delete, account delete/edit, gateway/oauth/webhook/template CRUD, network config) with a prepared session | ~20 handlers only snapshot-checked, never run | integration / e2e |
|
|
125
|
+
| 27 | gateway CRUD + delivery-stats hincrby + encrypted-pass roundtrip | Holds SMTP creds; only route-name smoke today | unit/integration |
|
|
126
|
+
|
|
127
|
+
### P3 - Lower / opportunistic
|
|
128
|
+
|
|
129
|
+
- message-builder.js + notification-handler.js builders (synchronous, cheap; payload contract).
|
|
130
|
+
- export-routes / outbox / blocklist / template / license HTTP behavior (404 + force semantics + download stream).
|
|
131
|
+
- redis-url parsing, redis-scan-delete batching, reconnection-manager backoff cap, rate-limit bucket math, capa CSV parser, templates CRUD.
|
|
132
|
+
- arf-detect edge branches (and fix the source-ip read/write bug, 3c).
|
|
133
|
+
- OKTA login flow, disableTokens open-API mode, sess_ browse round-trip, requireTotp path-allowlist correctness.
|
|
134
|
+
- mergeObjects prototype-pollution guard, comparePattern/matcher glob+LRU, checkLicense ECDSA verify.
|
|
135
|
+
- Documents/ES enabled path (deprecated, off by default - lowest priority).
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 5. Suggested sequencing
|
|
140
|
+
|
|
141
|
+
1. Land P0 #1 (illusory-coverage fixes) immediately - cheapest, removes false confidence, and #1's submit/autoreply/complaint cases overlap with P1 #6/#11.
|
|
142
|
+
2. P0 #2/#3 (SubScript, serialize) - pure units, high blast radius, no infra needed.
|
|
143
|
+
3. P0 #4/#5 + P2 #15/#16/#17/#26 share one new integration harness: boot the test server with an admin password and provision scoped tokens via lib/tokens.provision(). Build that harness once, then the auth/scope/CSRF/masking/gating tests are incremental.
|
|
144
|
+
4. P1 #6-#14 are the email-engine correctness core; most are unit-testable with mocked redis/transport/request and benefit from extracting pure logic out of the giant client files as you go.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 6. Implementation status (2026-06-16)
|
|
149
|
+
|
|
150
|
+
Branch `test-coverage-p0-p1`. Each test file was verified to pass individually
|
|
151
|
+
(the full local suite cannot run all files in parallel on a dev machine due to
|
|
152
|
+
process-isolation + Redis connection accumulation; CI runs the unit tier in a
|
|
153
|
+
clean dedicated job). Source changes are additive exports or behavior-preserving
|
|
154
|
+
extractions, verified not to break existing consumers.
|
|
155
|
+
|
|
156
|
+
Done (committed):
|
|
157
|
+
- P0 #1 - illusory-coverage tests now exercise real code (submit discard via new
|
|
158
|
+
lib/delivery-error.js incl. NON_RETRYABLE_CODES; isAutoreply; Mailbox
|
|
159
|
+
mightBeAComplaint + base-client drift; Gmail PageCursor; Outlook
|
|
160
|
+
requestWithRetry incl. transient-network branch).
|
|
161
|
+
- P0 #2 - SubScript sandbox (timeout, context isolation, env, compile cache).
|
|
162
|
+
- P0 #3 - tools.serialize/unserialize round-trip.
|
|
163
|
+
- P0 #4 - API token scope enforcement + cross-account binding (integration).
|
|
164
|
+
- P0 #5 - admin CSRF crumb enforcement (integration). [partial]
|
|
165
|
+
- P1 #8 - setErrorState auth-failure tracking + IMAP auto-disable.
|
|
166
|
+
- P1 #11 - bounce-detect text-heuristic fallback.
|
|
167
|
+
- P1 #12 - Gmail/Outlook checkForFlags/checkForUserFlags error mapping. [partial]
|
|
168
|
+
- P1 #14 - ReconnectionManager backoff/jitter/reset. [partial]
|
|
169
|
+
- P1 #6 - idempotency-key handling (duplicate-submission guard). [partial]
|
|
170
|
+
|
|
171
|
+
Remaining (deferred, with reason):
|
|
172
|
+
- P0 #5 remainder - anonymous /admin/* -> 302 redirect and passwordVersion
|
|
173
|
+
session invalidation need an isolated server WITH an admin password; belongs
|
|
174
|
+
in the Playwright e2e suite (cannot verify locally without Chromium + the
|
|
175
|
+
external trial endpoint). The shared integration server is password-less by
|
|
176
|
+
design, so these must not mutate its global auth state.
|
|
177
|
+
- P1 #6 remainder - full submitMessage pipeline (permanent-vs-transient retry,
|
|
178
|
+
Sent-folder upload, reference flags, gateway stats): large surface in a
|
|
179
|
+
3.3k-line client, heavy transport/Redis mocking.
|
|
180
|
+
- P1 #7 - server.js account assignment/reassignment: highest blast radius but
|
|
181
|
+
the orchestration is entangled with module state; needs logic extraction (a
|
|
182
|
+
refactor of a critical orchestrator) or a fake-worker harness.
|
|
183
|
+
- P1 #9 - SMTP server + IMAP-proxy auth: those servers are not enabled in the
|
|
184
|
+
shared test config; needs a dedicated server boot with them enabled.
|
|
185
|
+
- P1 #10 - bulk message mutate/delete REST: needs a connected mailbox with
|
|
186
|
+
messages; not meaningfully testable against the credential-less test server.
|
|
187
|
+
- P1 #12 remainder - OAuth2AppsHandler CRUD encryption / getServiceAccessToken
|
|
188
|
+
caching / getClient: stateful, needs Redis + secret + provider mocking.
|
|
189
|
+
- P1 #13 - Gmail history sync + Outlook subscription lifecycle: heavy mocking of
|
|
190
|
+
the 3k-4.5k-line client classes.
|
|
191
|
+
- P1 #14 remainder - imap-client reconnect() method + start() error->state
|
|
192
|
+
classification: needs an IMAPClient instance with a mocked ImapFlow + fake
|
|
193
|
+
timers.
|
|
194
|
+
|
|
195
|
+
Guiding constraint: no unverified or fragile tests were committed. The deferred
|
|
196
|
+
items each require infrastructure (extra server, live mailbox, orchestrator
|
|
197
|
+
refactor, or large-class mocking) beyond what a test can assert reliably in this
|
|
198
|
+
environment.
|
|
199
|
+
|
|
200
|
+
## 7. Deferred-item follow-up (2026-06-16, same branch)
|
|
201
|
+
|
|
202
|
+
A second pass converted most of the deferred items into verified tests by
|
|
203
|
+
extracting testable units (leaf workers only - never server.js) and using the
|
|
204
|
+
real handlers against the test Redis:
|
|
205
|
+
|
|
206
|
+
Done (committed):
|
|
207
|
+
- P1 #12 remainder - OAuth2AppsHandler create/get/update/list/del with
|
|
208
|
+
credential encryption at rest (oauth2-apps-crud-test.js).
|
|
209
|
+
- P1 #9 - SMTP auth (extracted lib/smtp-auth.js) and IMAP-proxy auth (extracted
|
|
210
|
+
lib/imap-proxy-auth.js): rejection paths (password/token account/scope/IP) and
|
|
211
|
+
accept paths, plus the IMAP-proxy API-only-account ACCOUNTDISABLED rejection.
|
|
212
|
+
- P1 #14 remainder - IMAPClient.reconnect() guard logic (no double-connect /
|
|
213
|
+
reconnect-storm), via the prototype with start() stubbed.
|
|
214
|
+
- P1 #13 (partial) - Gmail flag/label mapping (flagToLabel/flagsToLabelIds incl.
|
|
215
|
+
inverse \Seen<->UNREAD and set precedence) and Outlook parseExpirationDate.
|
|
216
|
+
- P1 #6 (decision logic) - message-builder send-pipeline deciders
|
|
217
|
+
(SentMailCopyDecider, ProviderMessageIdHandler, SmtpErrorBuilder,
|
|
218
|
+
NetworkRoutingBuilder, NotificationBuilder).
|
|
219
|
+
|
|
220
|
+
Still remaining (genuinely blocked):
|
|
221
|
+
- P1 #7 - server.js account assignment: the assignAccounts loop is entangled
|
|
222
|
+
with module state and per-iteration rollback; a faithful extraction risks
|
|
223
|
+
changing assignment behavior on worker-crash recovery (highest blast radius).
|
|
224
|
+
Not done autonomously - needs a reviewed refactor. The consistency-critical
|
|
225
|
+
half (rendezvous reassignment) is already covered by tools-test.js.
|
|
226
|
+
- P1 #6 remainder - the full submitMessage orchestration (actual SMTP send +
|
|
227
|
+
retry loop) - decision logic is now covered; the glue needs integration/e2e.
|
|
228
|
+
- P1 #13 remainder - Gmail processHistoryEntry / Outlook renew-subscription
|
|
229
|
+
orchestration: multi-step async over 3k-4.5k-line client classes.
|
|
230
|
+
- P0 #5 remainder / P1 #10 - e2e auth-gate + passwordVersion and bulk-message
|
|
231
|
+
REST: need the Playwright e2e instance (isolated server with a password and a
|
|
232
|
+
live mailbox) which depends on Chromium + external endpoints not reliably
|
|
233
|
+
reachable here.
|
package/translations/de.mo
CHANGED
|
Binary file
|