Goal
Add native IMAP (TCP port 993) support via Cloudflare Spectrum, so standard email clients (Thunderbird, Apple Mail, Outlook) connect without a local proxy.
Requirements
Interface
// TCP-to-WebSocket bridge inside the Worker
// Spectrum terminates TLS and proxies raw TCP to the Worker
// Worker bridges TCP stream to DO WebSocket
interface TcpBridge {
handleTcpConnection(socket: Socket): Promise<void>;
}
Behavior
- Cloudflare Spectrum proxies IMAPS (port 993) TCP connections to the Worker
- Worker receives raw TCP stream, bridges to DO via WebSocket
- IMAP protocol is the same -- parser and handlers are transport-agnostic
- TLS terminated by Spectrum (client sees valid cert for the domain)
- Bidirectional: TCP bytes from client -> parse as IMAP commands -> dispatch to DO -> IMAP responses -> TCP bytes back to client
- Connection lifecycle matches DO session lifecycle
- Standard email clients work out of the box (Thunderbird, Apple Mail, Outlook, K-9 Mail)
Error Handling
- TCP connection failures: clean close
- Spectrum unavailable: WebSocket transport still works as fallback
- Malformed TCP data: send IMAP BAD response, close connection
- TLS handshake failure: handled by Spectrum, never reaches Worker
Out of Scope
- STARTTLS (not applicable -- Spectrum terminates TLS)
- Plain text IMAP on port 143 (never supported)
- Custom local proxy for WebSocket-only mode (separate tool if needed)
File Locations
- Implementation:
packages/imap/src/transport/tcp-bridge.ts
- Tests:
packages/imap/tests/transport/tcp-bridge.test.ts
- Spectrum config:
packages/imap/wrangler.toml (spectrum section)
Dev Workflow
Each step is mandatory. Do not skip steps or combine them.
- Build -- Implement the feature. Write tests alongside code. Run
pnpm test, pnpm check (oxlint + oxc-format). All must pass.
- Simplify -- Run
/simplify on all changed files. Accept structural improvements, flatten unnecessary abstractions, remove dead code.
- Review -- Run
/review-pr which launches parallel review agents (code review, silent failure hunter, type design analysis). Do not create the PR yet.
- Fix -- Address every issue the review found. Re-run tests after fixes.
- PR -- Create the PR. Reference this issue number.
Mail Rules
- No
any -- use unknown and narrow
- No emoji in code, comments, or commits
- UUIDv7 for all identifiers
- Zod is source of truth for schemas (types inferred via
z.infer<>)
- Zero vendor dependencies in core -- all external concerns are adapters
- pnpm only (never npm/yarn)
- oxlint for linting, oxfmt for formatting (no Biome)
- TypeScript 5.9, Vitest 4, Zod 4
- No barrel files -- use subpath exports in package.json
- Tests in
tests/ mirroring source tree, never colocated
Done When
This issue is complete when: Thunderbird, Apple Mail, and Outlook can connect to the IMAP server on port 993 via Spectrum and perform standard operations (list folders, read messages, flag messages, IDLE for push).
Context
Goal
Add native IMAP (TCP port 993) support via Cloudflare Spectrum, so standard email clients (Thunderbird, Apple Mail, Outlook) connect without a local proxy.
Requirements
Interface
Behavior
Error Handling
Out of Scope
File Locations
packages/imap/src/transport/tcp-bridge.tspackages/imap/tests/transport/tcp-bridge.test.tspackages/imap/wrangler.toml(spectrum section)Dev Workflow
Each step is mandatory. Do not skip steps or combine them.
pnpm test,pnpm check(oxlint + oxc-format). All must pass./simplifyon all changed files. Accept structural improvements, flatten unnecessary abstractions, remove dead code./review-prwhich launches parallel review agents (code review, silent failure hunter, type design analysis). Do not create the PR yet.Mail Rules
any-- useunknownand narrowz.infer<>)tests/mirroring source tree, never colocatedDone When
This issue is complete when: Thunderbird, Apple Mail, and Outlook can connect to the IMAP server on port 993 via Spectrum and perform standard operations (list folders, read messages, flag messages, IDLE for push).
Context