Skip to content

feat: add experimental IMAP SMTP BYOK workspace and mobile scaffold - #2086

Closed
Tippye wants to merge 1 commit into
Mail-0:stagingfrom
Tippye:feat/imap-byok-mobile
Closed

feat: add experimental IMAP SMTP BYOK workspace and mobile scaffold#2086
Tippye wants to merge 1 commit into
Mail-0:stagingfrom
Tippye:feat/imap-byok-mobile

Conversation

@Tippye

@Tippye Tippye commented Sep 5, 2026

Copy link
Copy Markdown

READ CAREFULLY THEN REMOVE

Remove bullet points that are not relevant.

PLEASE REFRAIN FROM USING AI TO WRITE YOUR CODE AND PR DESCRIPTION. IF YOU DO USE AI TO WRITE YOUR CODE PLEASE PROVIDE A DESCRIPTION AND REVIEW IT CAREFULLY. MAKE SURE YOU UNDERSTAND THE CODE YOU ARE SUBMITTING USING AI.

  • Pull requests that do not follow these guidelines will be closed without review or comment.
  • If you use AI to write your PR description your pr will be close without review or comment.
  • If you are unsure about anything, feel free to ask for clarification.

Description

Please provide a clear description of your changes.


Type of Change

Please delete options that are not relevant.

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature with breaking changes)
  • 📝 Documentation update
  • 🎨 UI/UX improvement
  • 🔒 Security enhancement
  • ⚡ Performance improvement

Areas Affected

Please check all that apply:

  • Email Integration (Gmail, IMAP, etc.)
  • User Interface/Experience
  • Authentication/Authorization
  • Data Storage/Management
  • API Endpoints
  • Documentation
  • Testing Infrastructure
  • Development Workflow
  • Deployment/Infrastructure

Testing Done

Describe the tests you've done:

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • Cross-browser testing (if UI changes)
  • Mobile responsiveness verified (if UI changes)

Security Considerations

For changes involving data or authentication:

  • No sensitive data is exposed
  • Authentication checks are in place
  • Input validation is implemented
  • Rate limiting is considered (if applicable)

Checklist

  • I have read the CONTRIBUTING document
  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in complex areas
  • I have updated the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix/feature works
  • All tests pass locally
  • Any dependent changes are merged and published

Additional Notes

Add any other context about the pull request here.

Screenshots/Recordings

Add screenshots or recordings here if applicable.


By submitting this pull request, I confirm that my contribution is made under the terms of the project's license.

Copilot AI lite review requested due to automatic review settings September 5, 2026 08:57
@Tippye Tippye closed this Sep 5, 2026
@Tippye
Tippye deleted the feat/imap-byok-mobile branch September 5, 2026 08:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are confirmed issues that will break Docker builds (.dockerignore excludes package-lock.json) and additional safety/maintainability concerns that should be addressed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR introduces an experimental self-hosting IMAP/SMTP bridge (Node + Docker), a BYOK (bring-your-own-key) AI configuration path routed through the authenticated Zero backend, and an initial Capacitor-based mobile packaging scaffold for the mail frontend.

Changes:

  • Add integrations/imap-bridge: encrypted credential vault, IMAP/SMTP operations, BYOK AI proxying, Docker/Compose packaging, and CI workflow.
  • Add new server-side tRPC router + client helper to call the bridge (imap.* routes + imapBridge()), and add a new /imap mail workspace page in the React app.
  • Add native/mobile Capacitor scaffold plus a “prepare web assets” script + tests and supporting docs.
File summaries
File Description
SELF_HOSTING_IMAP.zh-CN.md Deployment + limitations guide for the experimental IMAP/BYOK/mobile scaffold.
native/mobile/scripts/prepare-web.test.mjs Tests for the Capacitor web-asset preparation script.
native/mobile/scripts/prepare-web.mjs Script to copy built SPA assets into the Capacitor www directory.
native/mobile/README.md Notes and scope/limitations for the mobile scaffold.
native/mobile/package.json Capacitor scaffold package + scripts.
native/mobile/capacitor.config.json Capacitor configuration for the scaffold.
native/mobile/.gitignore Ignores generated mobile platform projects, assets, and signing material.
integrations/imap-bridge/test/server.test.mjs Unit tests for bridge RPC/auth, BYOK settings, and redaction behaviors.
integrations/imap-bridge/test/mail.test.mjs Unit tests for IMAP listing/get/modify/move and SMTP send constraints.
integrations/imap-bridge/test/dependencies.mjs Tests verifying real installed dependency APIs (ImapFlow/Nodemailer/mailparser/sanitize-html).
integrations/imap-bridge/test/core.test.mjs Unit tests for crypto/vault, validation, IDs, pagination, idempotency.
integrations/imap-bridge/src/server.mjs HTTP RPC server + bridge operations (accounts/mail/ai).
integrations/imap-bridge/src/mail.mjs IMAP/SMTP implementation (ImapFlow + Nodemailer) with sanitization and limits.
integrations/imap-bridge/src/core.mjs Shared primitives: validation, AES-GCM vault, message IDs, AI endpoint allowlist, idempotent send.
integrations/imap-bridge/scripts/init-env.mjs Generates .env with bridge secret + encryption key.
integrations/imap-bridge/README.md Minimal bridge usage docs pointing to the full self-hosting guide.
integrations/imap-bridge/package.json Bridge package definition and scripts.
integrations/imap-bridge/package-lock.json Lockfile for the standalone bridge install.
integrations/imap-bridge/Dockerfile Container build for the bridge service.
integrations/imap-bridge/compose.yaml Compose deployment with restrictive runtime settings.
integrations/imap-bridge/Caddyfile.example Example HTTPS reverse proxy config for exposing the bridge to Workers.
integrations/imap-bridge/.gitignore Ignores env/data/logs for the standalone bridge module.
integrations/imap-bridge/.env.example Example env file for bridge configuration.
integrations/imap-bridge/.dockerignore Docker build context filters for bridge builds.
apps/server/src/trpc/routes/imap.ts New tRPC router exposing IMAP bridge operations to authenticated users.
apps/server/src/trpc/index.ts Registers the new imap router in the app router.
apps/server/src/lib/imap-bridge.ts Server-side helper to call the bridge over HTTP with validation and error mapping.
apps/mail/app/routes.ts Adds /imap route to the mail app.
apps/mail/app/imap/page.tsx IMAP workspace UI: account mgmt, folder/list/thread view, send, and BYOK AI actions.
.github/workflows/imap-bridge.yml CI workflow to test bridge unit/dependency suites and basic container startup.
Review details

Files not reviewed (1)

  • integrations/imap-bridge/package-lock.json: Generated file
  • Files reviewed: 29/30 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +1 to +5
**
!package.json
!src/
!src/**
!Dockerfile
Comment on lines +1 to +13
import { access, cp, mkdir, readFile, rm } from 'node:fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';

export async function prepareWeb(source, target, config) {
if (config.server?.url || config.server?.allowNavigation?.length) throw Error('Remote production WebView URLs/navigation allowlists are not allowed by this build scaffold.');
const index = resolve(source, 'index.html');
try { await access(index); } catch { throw Error('Web assets are missing. Build @zero/mail before preparing the native shell.'); }
const html = await readFile(index, 'utf8');
if (!/<html[\s>]/i.test(html)) throw Error('Invalid web build: index.html is not HTML.');
const destination = resolve(target), origin = resolve(source);
if (destination === origin || origin.startsWith(destination + '/') || destination.startsWith(origin + '/')) throw Error('Unsafe web asset output directory.');
await rm(destination, { recursive: true, force: true });
Comment on lines +10 to +16
// Deliberately do not use the upstream payload-logging middleware: inputs contain secrets and mail.
// The context and transformer match the parent router. Identity comes only from server authentication.
const t = initTRPC.context<{ c: Context<HonoContext> } & HonoVariables>().create({ transformer: superjson });
const owned = t.procedure.use(({ ctx, next }) => {
if (!ctx.sessionUser) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Sign in to Zero first.' });
return next({ ctx: { ...ctx, sessionUser: ctx.sessionUser } });
});
@Tippye
Tippye restored the feat/imap-byok-mobile branch September 5, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants