feat(hooks): Create centralized hooks npm package

- Added @metabuilder/hooks workspace package at root
- Consolidated 30 React hooks from across codebase into single module
- Implemented conditional exports for tree-shaking support
- Added comprehensive package.json with build/lint/typecheck scripts
- Created README.md documenting hook categories and usage patterns
- Updated root package.json workspaces array to include hooks
- Supports multi-version peer dependencies (React 18/19, Redux 8/9)

Usage:
  import { useDashboardLogic } from '@metabuilder/hooks'
  import { useLoginLogic } from '@metabuilder/hooks/useLoginLogic'

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 19:17:17 +00:00
parent 5d30ec0cc9
commit 78a54228df
32 changed files with 6849 additions and 10 deletions

View File

@@ -0,0 +1,845 @@
================================================================================
EMAIL CLIENT - COMPREHENSIVE IMPLEMENTATION PLAN
Date: 2026-01-23
Status: PLANNING PHASE
================================================================================
PROJECT SCOPE
=============
Build a full-featured email client in root directory that:
1. Connects to multiple IMAP/POP3/SMTP servers (users manage their accounts)
2. Manages email accounts with Postfix/Dovecot backend
3. Syncs emails locally to IndexedDB for offline access
4. Provides React UI with Redux state management
5. Integrates with existing authentication, multi-tenant architecture, and FakeMUI
TECHNOLOGY STACK
================
Frontend:
- React 19.2.3 + Next.js (from /frontends/nextjs pattern)
- FakeMUI components (145 production React components)
- Redux + custom hooks for state management
- IndexedDB for offline storage
- SCSS for styling
Backend:
- DBAL for multi-tenant credential storage
- Postfix/Dovecot for account management
- Existing SMTP relay plugin (enhance it)
- New IMAP/POP3 sync plugins
- SQLAlchemy Flask service for email operations (in /services)
Infrastructure:
- Docker Compose (for local Postfix/Dovecot)
- caprover deployment (prod)
- n8n workflows (optional email automation)
================================================================================
DIRECTORY STRUCTURE - NEW EMAILCLIENT PROJECT
================================================================================
emailclient/ # Root email client subproject
├── package.json # Root workspace package
├── docs/
│ ├── CLAUDE.md # Email client specific guide
│ ├── ARCHITECTURE.md # Email sync flow diagrams
│ ├── ACCOUNT_SETUP.md # User account management
│ └── INTEGRATION.md # API integration patterns
├── frontend/ # React/Next.js UI
│ ├── src/
│ │ ├── app/ # Next.js app router
│ │ │ ├── (auth)/
│ │ │ │ └── mailbox/ # Main mailbox page
│ │ │ └── api/
│ │ │ └── email/ # Email API routes
│ │ ├── components/
│ │ │ ├── composer/ # Email compose
│ │ │ ├── mailbox/ # Inbox/folder browser
│ │ │ ├── account-manager/ # Account CRUD
│ │ │ ├── message-viewer/ # Email viewer
│ │ │ └── settings/ # Email settings
│ │ ├── hooks/
│ │ │ ├── useEmailSync.ts # Email sync hook
│ │ │ ├── useEmailStore.ts # IndexedDB wrapper
│ │ │ ├── useMailboxes.ts # Mailbox list hook
│ │ │ └── useAccounts.ts # Account management hook
│ │ ├── redux/
│ │ │ ├── emailSlice.ts # Redux: emails
│ │ │ ├── accountsSlice.ts # Redux: accounts
│ │ │ ├── syncSlice.ts # Redux: sync status
│ │ │ └── store.ts
│ │ ├── lib/
│ │ │ ├── imap-client.ts # IMAP client wrapper
│ │ │ ├── email-parser.ts # Parse email headers
│ │ │ └── indexeddb/
│ │ │ ├── schema.ts # IndexedDB schema
│ │ │ ├── emails.ts # Email storage ops
│ │ │ ├── accounts.ts # Account storage ops
│ │ │ └── sync.ts # Sync state tracking
│ │ └── styles/
│ │ └── emailclient.scss
│ ├── tests/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── redux/
│ │ └── integration/
│ └── package.json
├── backend/ # Flask + SQLAlchemy service
│ ├── src/
│ │ ├── email_service.py # Main service class
│ │ ├── imap_sync.py # IMAP sync engine
│ │ ├── pop3_sync.py # POP3 sync engine
│ │ ├── smtp_send.py # SMTP sending
│ │ ├── account_manager.py # Account CRUD ops
│ │ ├── models.py # SQLAlchemy models
│ │ ├── schemas.py # Input validation
│ │ ├── routes/
│ │ │ ├── accounts.py # Account endpoints
│ │ │ ├── messages.py # Message endpoints
│ │ │ ├── sync.py # Sync management
│ │ │ └── compose.py # Email composition
│ │ ├── middleware/
│ │ │ ├── auth.py # Session validation
│ │ │ └── tenant.py # Tenant filtering
│ │ ├── utils/
│ │ │ ├── imap_parser.py # Parse IMAP responses
│ │ │ ├── email_parser.py # RFC 2822 parsing
│ │ │ ├── credentials.py # Encrypt/decrypt creds
│ │ │ └── validators.py # Input validators
│ │ └── celery_tasks.py # Background sync jobs
│ ├── requirements.txt # Python deps
│ ├── tests/
│ │ ├── test_sync.py
│ │ ├── test_smtp.py
│ │ ├── test_models.py
│ │ └── test_validators.py
│ ├── docker/ # Containerization
│ │ ├── Dockerfile.dev
│ │ └── Dockerfile.prod
│ └── app.py # Flask app entry
├── schemas/ # DBAL entity definitions
│ ├── email-client.yaml # Email client config entity
│ ├── email-account.yaml # Email account/mailbox entity
│ ├── email-message.yaml # Email message metadata
│ └── email-folder.yaml # Mailbox folder structure
├── workflow-plugins/ # Enhanced workflow integrations
│ ├── imap-sync.ts # IMAP sync workflow plugin
│ ├── pop3-sync.ts # POP3 sync workflow plugin
│ ├── smtp-send-enhanced.ts # Enhanced SMTP plugin
│ └── email-parse.ts # Email parsing plugin
├── docker-compose.yml # Local dev email server
├── .dockerignore
├── .env.example # Example env vars
├── README.md # Project overview
└── QUICK_START.md # Getting started guide
================================================================================
PHASE 1: INFRASTRUCTURE & DATA LAYER (Estimated effort: full implementation)
================================================================================
TASK 1.1: DBAL SCHEMA DEFINITIONS
Location: emailclient/schemas/ + update dbal/shared/api/schema/entities/
Create 4 new YAML entity definitions:
1. email-client.yaml (Access Layer)
- id: UUID (primary)
- userId: UUID (fk to User)
- tenantId: UUID (mandatory multi-tenant)
- accountName: string (user-friendly label)
- protocol: enum (imap, pop3) [SMTP is separate, uses smtp entity]
- hostname: string (imap.gmail.com, etc)
- port: int (usually 993 for IMAP TLS)
- encryption: enum (none, tls, starttls)
- username: string (email address)
- credentialId: UUID (fk to Credential - password stored here)
- lastSyncAt: bigint (timestamp)
- isSyncing: boolean
- isEnabled: boolean
- syncInterval: int (minutes, default 5)
- maxSyncHistory: int (days to keep, default 30)
- createdAt: bigint (generated)
- updatedAt: bigint (auto-updated)
- ACL:
read: self (users see own accounts) + admin
create: self (users create their own)
update: self (users update own)
delete: self (users delete own)
2. email-account.yaml (Packages Layer - like forum, notification)
- id: UUID (primary)
- emailClientId: UUID (fk to email-client)
- tenantId: UUID
- email: email (actual email address synced)
- displayName: string (optional sender name)
- signatureHtml: text (optional email signature)
- replyToEmail: email (optional different reply-to)
- folders: jsonb (JSON array of folder configs)
- syncedMessageCount: int
- lastSyncedAt: bigint
- createdAt: bigint
- ACL: same as email-client (self-managed)
3. email-message.yaml (Packages Layer)
- id: UUID (primary)
- emailClientId: UUID
- accountId: UUID (fk to email-account)
- tenantId: UUID
- messageId: string (RFC 2822 Message-ID header)
- inReplyTo: string (IRT header, nullable)
- from: string (sender email)
- to: jsonb (array of recipient emails)
- cc: jsonb (array)
- bcc: jsonb (array)
- subject: string
- bodyHtml: text (HTML version)
- bodyText: text (plain text fallback)
- receivedAt: bigint (email timestamp, not sync timestamp)
- isRead: boolean (default false)
- isStarred: boolean
- isDraft: boolean
- isSent: boolean (track if this was sent by us)
- folderId: string (IMAP folder name)
- flags: jsonb (IMAP flags: Seen, Answered, Flagged, Deleted, Draft, Recent)
- attachmentCount: int (for preview)
- attachments: jsonb (metadata: filename, size, mimeType)
- headers: jsonb (select headers for threading: References, List-ID, etc)
- createdAt: bigint
- ACL: read/update self, admin full access
4. email-folder.yaml (Packages Layer)
- id: UUID
- emailClientId: UUID
- tenantId: UUID
- name: string (IMAP folder name: INBOX, [Gmail]/Sent, etc)
- displayName: string (user-editable display name)
- type: enum (inbox, sent, drafts, trash, spam, archive, custom)
- messageCount: int
- unreadCount: int
- syncedAt: bigint
- localFolderPath: string (dovecot path for delegation)
- ACL: self-managed
TASK 1.2: DBAL CRUD OPERATIONS
Location: dbal/development/src/core/entities/
Create one file per operation following existing pattern:
- email-client/crud/create-email-client.ts
- email-client/crud/read-email-client.ts
- email-client/crud/update-email-client.ts
- email-client/crud/delete-email-client.ts
- email-client/crud/list-email-clients.ts
- email-account/crud/* (same pattern)
- email-message/crud/* (same pattern)
- email-folder/crud/* (same pattern)
Requirements:
- Validate tenantId on ALL queries
- Password stored in Credential entity (never returned)
- SHA-512 hashing for stored passwords
- Indexes on: (userId, tenantId), (emailClientId, accountId), (accountId, messageId)
- Soft delete option for messages (flag as deleted, not purged immediately)
TASK 1.3: API ENDPOINTS
Location: emailclient/frontend/src/app/api/email/
Routes following existing pattern /api/v1/{tenant}/email_client/{id}:
POST /api/v1/{tenant}/email-client → create account (validate host/port reachable)
GET /api/v1/{tenant}/email-client → list accounts (paginated, filter by enabled)
GET /api/v1/{tenant}/email-client/{id} → read config
PUT /api/v1/{tenant}/email-client/{id} → update (re-validate creds if changed)
DELETE /api/v1/{tenant}/email-client/{id} → delete + cleanup synced messages
POST /api/v1/{tenant}/email-client/{id}/test → test connection (auth, TLS, port)
POST /api/v1/{tenant}/email-client/{id}/sync → trigger manual sync
GET /api/v1/{tenant}/email-account → list accounts for a client
GET /api/v1/{tenant}/email-message → list messages (with pagination, filtering)
GET /api/v1/{tenant}/email-message/{id} → read full message (body + attachments)
PUT /api/v1/{tenant}/email-message/{id} → update flags (read, starred, folder)
DELETE /api/v1/{tenant}/email-message/{id} → trash message
POST /api/v1/{tenant}/email-compose → send new email
PUT /api/v1/{tenant}/email-message/{id}/reply → send reply
Rate limiting:
- List: 100/min
- Mutations: 50/min
- Sync trigger: 10/min (prevent abuse)
================================================================================
PHASE 2: BACKEND EMAIL SERVICE (Python/Flask)
================================================================================
TASK 2.1: EMAIL SERVICE CORE
Location: emailclient/backend/src/
email_service.py:
- Class EmailService (main orchestrator)
- __init__(dbal_client, smtp_config, imap_config, pop3_config)
- get_client(client_id, user_id, tenant_id) → IMAPClient or POP3Client instance
- sync_account(account_id) → {synced_count, errors, lastSyncAt}
- send_email(account_id, to, cc, bcc, subject, html, attachments) → message_id
- test_connection(host, port, protocol, username, password, encryption) → {success, error}
- decrypt_password(credentialId) → plaintext (use DBAL Credential lookup)
imap_sync.py:
- Class IMAPSyncEngine
- connect(host, port, username, password, encryption)
- list_folders() → [folder_names]
- sync_folder(folder_name, last_sync_timestamp) → [messages]
- fetch_message_full(message_id) → {headers, body_html, body_text, attachments}
- mark_as_read(message_id)
- update_flags(message_id, flags)
- Error handling: ConnectionError, AuthError, TimeoutError (with backoff)
pop3_sync.py:
- Similar to IMAP but simpler (POP3 can't sync flags/folders)
- Class POP3SyncEngine
- Only supports: list, fetch, delete
smtp_send.py:
- Class SMTPSender (leverage existing smtp_relay plugin)
- send(from_addr, to, cc, bcc, subject, html, text, attachments, account_id)
- Handle template expansion (if from workflow)
- Audit log all sends
account_manager.py:
- Interface to DBAL entity CRUD
- Validation: email format, host reachability, port listening
- Create account record on first sync
- Track sync status, last error, retry count
models.py (SQLAlchemy):
- Sync state models (if using local cache for sync status)
- Or just interface with DBAL exclusively
TASK 2.2: WORKFLOW PLUGINS
Location: workflow/plugins/ts/integration/ + emailclient/workflow-plugins/
1. imap-sync.ts
- Inputs: emailClientId, folderId, maxMessages
- Outputs: messages[], syncStats{}
- Error handling: retry with exponential backoff
- Logging: audit trail of sync ops
2. pop3-sync.ts
- Similar, but simpler
3. smtp-send-enhanced.ts
- Enhance existing smtp_relay plugin
- Add attachment support
- Add HTML/text alternatives
- Add tracking pixel (optional)
- Integrate with email-message entity
4. email-parse.ts
- Parse RFC 2822 messages
- Extract headers, body, attachments
- Generate preview (first 100 chars)
TASK 2.3: PYTHON DEPENDENCIES
Location: emailclient/backend/
requirements.txt:
- imaplib2 or imapclient (IMAP protocol)
- poplib (already in stdlib, but pyaio-pop3 optional for async)
- email-parser (standard library, email.parser)
- python-dotenv
- flask, flask-cors
- sqlalchemy
- celery (for background sync)
- redis (for celery broker)
- requests (for HTTP calls to DBAL/Next.js API)
- cryptography (for password encryption at rest)
================================================================================
PHASE 3: FRONTEND REACT COMPONENTS (FakeMUI-based)
================================================================================
TASK 3.1: COMPONENT STRUCTURE
Location: emailclient/frontend/src/components/
Using FakeMUI components (all from @metabuilder/fakemui):
1. mailbox/
- MailboxLayout.tsx (main grid: sidebar + email list + viewer)
- FolderTree.tsx (left sidebar: INBOX, Sent, Drafts, etc)
- MessageList.tsx (center: paginated email list with search)
- MessageViewer.tsx (right: full email view with attachments)
- Thread.tsx (optional: email threading UI)
2. composer/
- ComposeWindow.tsx (modal/fullscreen new email)
- ReplyComposer.tsx (reply/reply-all)
- RecipientInput.tsx (to/cc/bcc with autocomplete)
- AttachmentUpload.tsx (drag-drop file upload)
3. account-manager/
- AccountList.tsx (list connected accounts)
- AccountForm.tsx (add/edit account)
- ConnectionTest.tsx (test IMAP connection)
- SyncStatus.tsx (last sync time, unread count, sync button)
4. settings/
- EmailSettings.tsx (signature, reply-to, etc)
- AccountSettings.tsx (sync interval, folder mapping)
- SignatureEditor.tsx (WYSIWYG HTML editor)
5. message-viewer/
- AttachmentViewer.tsx (preview + download)
- EmailHeaderDisplay.tsx (From, To, Date, etc)
- MarkAsReadButton.tsx
- StarButton.tsx
- MoveToFolderDropdown.tsx
All components:
- Use FakeMUI Button, TextField, Dialog, Card, List, Table, etc
- Add data-testid attributes for testing
- Add ARIA labels for accessibility
- Use SCSS modules for styling (emailclient/frontend/src/styles/)
- Responsive design (mobile-first)
TASK 3.2: REDUX STATE MANAGEMENT
Location: emailclient/frontend/src/redux/
Following project pattern (root redux folder):
emailSlice.ts:
- state: {
accounts: [{id, email, lastSync, isSyncing}],
messages: [{id, subject, from, receivedAt, isRead}],
folders: [{name, unreadCount, messageCount}],
selectedMessage: {id, ...full email data},
searchQuery: string,
filters: {folder, isRead, isStarred, from}
}
- actions:
- setAccounts(accounts)
- selectMessage(message)
- updateMessageFlags(id, flags)
- setMessages(messages)
- appendMessages(messages) [for pagination]
- setFolders(folders)
- setIsSyncing(accountId, boolean)
accountSlice.ts:
- state: {
accounts: [{id, accountName, email, protocol, hostname, isEnabled}],
selectedAccount: {id, ...details},
isCreating: boolean,
error: null | string
}
- actions:
- createAccount(config)
- updateAccount(id, config)
- deleteAccount(id)
- testConnection(config) → {success, error}
- setSelectedAccount(id)
syncSlice.ts:
- state: {
accountId: {
status: 'idle' | 'syncing' | 'error' | 'success',
lastSyncAt: timestamp,
syncedCount: number,
error: null | string,
progress: 0-100
}
}
- actions:
- startSync(accountId)
- syncProgress(accountId, progress)
- syncSuccess(accountId, syncedCount)
- syncError(accountId, error)
TASK 3.3: CUSTOM HOOKS
Location: emailclient/frontend/src/hooks/
useEmailSync.ts:
- Hook for triggering manual sync
- const {sync, isSyncing, lastSync, error} = useEmailSync(accountId)
- Dispatches to Redux syncSlice
useEmailStore.ts:
- Wrapper around IndexedDB
- const {get, set, query, delete} = useEmailStore('messages')
- Auto-persists on window close
useMailboxes.ts:
- Fetch mailbox list from API
- const {folders, isLoading, error} = useMailboxes(accountId)
useAccounts.ts:
- CRUD for email accounts
- const {accounts, create, update, delete, test} = useAccounts()
useEmailCompose.ts:
- Manage compose window state
- const {isOpen, open, close, draft} = useEmailCompose()
useMessageThreading.ts:
- Group messages by conversation (In-Reply-To, References headers)
- const {threads} = useMessageThreading(messages)
TASK 3.4: INDEXEDDB SCHEMA
Location: emailclient/frontend/src/lib/indexeddb/
schema.ts:
- Define IndexedDB database: "emailclient"
- Version: 1 (increment on schema changes)
- Stores:
- "messages": keyPath="id", indexes=[["accountId", "receivedAt"], ["accountId", "isRead"]]
- "accounts": keyPath="id"
- "folders": keyPath="[accountId, name]"
- "drafts": keyPath="id" (unsent emails)
- "sync_state": keyPath="accountId" (track sync progress)
emails.ts:
- saveMessages(messages) → void
- getMessages(accountId, options) → messages[]
- getMessage(id) → message | null
- updateMessage(id, patch) → void
- deleteMessages(messageIds) → void
- queryMessages(accountId, filter) → messages[] (by read, starred, date range)
- clearOldMessages(accountId, daysToKeep) → count
accounts.ts:
- saveAccounts(accounts) → void
- getAccounts() → accounts[]
- getAccount(id) → account | null
- deleteAccount(id) → void
sync.ts:
- saveLastSync(accountId, timestamp, messageCount) → void
- getLastSync(accountId) → {timestamp, messageCount} | null
- getSyncProgress(accountId) → progress_percent
================================================================================
PHASE 4: UI PAGES & ROUTING
================================================================================
TASK 4.1: NEXT.JS APP STRUCTURE
Location: emailclient/frontend/src/app/
(auth)/
mailbox/
page.tsx (main mailbox layout)
layout.tsx (includes sidebar, header)
loading.tsx (skeleton while loading)
api/
email/
route.ts (API handler for /api/v1/.../email-* routes)
accounts/route.ts
messages/route.ts
sync/route.ts
compose/route.ts
TASK 4.2: PAGE COMPONENTS
Location: emailclient/frontend/src/app/(auth)/mailbox/
page.tsx:
- Use MailboxLayout component
- Dispatch useEmailSync on mount
- Display FolderTree, MessageList, MessageViewer in grid layout
- Handle search input
- Show sync status in header
layout.tsx:
- Navbar with logo, search, settings
- Side panel with FolderTree
- Responsive breakpoints (mobile hides details)
loading.tsx:
- Skeleton screens while fetching messages
TASK 4.3: SETTINGS PAGE
Location: emailclient/frontend/src/app/(auth)/email-settings/
settings/page.tsx:
- Link to account manager
- Email signature editor
- Auto-sync settings
- Notification preferences
- Theme selector
settings/accounts/page.tsx:
- List all email accounts
- Add/edit/delete accounts
- Test connection
- Manage folders
================================================================================
PHASE 5: TESTING & DEPLOYMENT
================================================================================
TASK 5.1: E2E TESTS
Location: emailclient/tests/ + e2e/
Test scenarios:
1. Create email account (validate, test connection, save)
2. Sync inbox (fetch messages, store in IndexedDB)
3. Compose and send email (via SMTP)
4. Mark message as read (update flags)
5. Move message to folder (update folder)
6. Search messages (query IndexedDB)
7. Multi-account switch (isolate by accountId)
8. Offline access (load from IndexedDB when offline)
9. Sync conflict resolution (duplicate message ID)
TASK 5.2: UNIT TESTS
- DBAL CRUD operations (query validation, ACL enforcement)
- IndexedDB operations (save/load/query)
- Email parsing (RFC 2822)
- Redux reducers (action handling)
- Custom hooks (state updates)
TASK 5.3: DOCKER DEPLOYMENT
Location: emailclient/docker/
Dockerfile.dev:
- Base: Node 20 + Python 3.11
- Frontend: Next.js dev server
- Backend: Flask dev server
- Postfix/Dovecot container (reuse from deployment/)
Dockerfile.prod:
- Frontend: Next.js static export + Nginx
- Backend: Gunicorn + Flask
- Email service: Celery worker
docker-compose.yml:
- frontend service (Next.js)
- backend service (Flask)
- postfix service (SMTP/IMAP/POP3)
- redis service (session store, Celery broker)
- postgres service (production DB)
TASK 5.4: CAPROVER DEPLOYMENT
- Create Captain definition for emailclient app
- Link to existing Postfix/Dovecot service
- Environment variables for DBAL connection
- SSL certificate from Let's Encrypt
================================================================================
FILES TO CREATE/MODIFY - SUMMARY
================================================================================
NEW FILES (74 total):
SCHEMAS (4):
✓ emailclient/schemas/email-client.yaml
✓ emailclient/schemas/email-account.yaml
✓ emailclient/schemas/email-message.yaml
✓ emailclient/schemas/email-folder.yaml
DBAL CRUD (16):
✓ dbal/development/src/core/entities/email-client/crud/create-email-client.ts
✓ dbal/development/src/core/entities/email-client/crud/read-email-client.ts
✓ dbal/development/src/core/entities/email-client/crud/update-email-client.ts
✓ dbal/development/src/core/entities/email-client/crud/delete-email-client.ts
✓ dbal/development/src/core/entities/email-client/crud/list-email-clients.ts
✓ dbal/development/src/core/entities/email-account/crud/create-email-account.ts
✓ dbal/development/src/core/entities/email-account/crud/read-email-account.ts
✓ ... (similar for message and folder, 16 total)
BACKEND (15):
✓ emailclient/backend/src/email_service.py
✓ emailclient/backend/src/imap_sync.py
✓ emailclient/backend/src/pop3_sync.py
✓ emailclient/backend/src/smtp_send.py
✓ emailclient/backend/src/account_manager.py
✓ emailclient/backend/src/models.py
✓ emailclient/backend/src/schemas.py
✓ emailclient/backend/src/routes/accounts.py
✓ emailclient/backend/src/routes/messages.py
✓ emailclient/backend/src/routes/sync.py
✓ emailclient/backend/src/routes/compose.py
✓ emailclient/backend/src/middleware/auth.py
✓ emailclient/backend/src/middleware/tenant.py
✓ emailclient/backend/src/utils/*.py (4 files)
✓ emailclient/backend/src/celery_tasks.py
✓ emailclient/backend/app.py
FRONTEND COMPONENTS (24):
✓ emailclient/frontend/src/components/mailbox/*.tsx (5)
✓ emailclient/frontend/src/components/composer/*.tsx (4)
✓ emailclient/frontend/src/components/account-manager/*.tsx (4)
✓ emailclient/frontend/src/components/settings/*.tsx (3)
✓ emailclient/frontend/src/components/message-viewer/*.tsx (3)
✓ emailclient/frontend/src/components/common/*.tsx (5)
REDUX (3):
✓ emailclient/frontend/src/redux/emailSlice.ts
✓ emailclient/frontend/src/redux/accountSlice.ts
✓ emailclient/frontend/src/redux/syncSlice.ts
HOOKS (6):
✓ emailclient/frontend/src/hooks/useEmailSync.ts
✓ emailclient/frontend/src/hooks/useEmailStore.ts
✓ emailclient/frontend/src/hooks/useMailboxes.ts
✓ emailclient/frontend/src/hooks/useAccounts.ts
✓ emailclient/frontend/src/hooks/useEmailCompose.ts
✓ emailclient/frontend/src/hooks/useMessageThreading.ts
INDEXEDDB (2):
✓ emailclient/frontend/src/lib/indexeddb/schema.ts
✓ emailclient/frontend/src/lib/indexeddb/emails.ts
✓ emailclient/frontend/src/lib/indexeddb/accounts.ts
✓ emailclient/frontend/src/lib/indexeddb/sync.ts
PAGES (6):
✓ emailclient/frontend/src/app/(auth)/mailbox/page.tsx
✓ emailclient/frontend/src/app/(auth)/mailbox/layout.tsx
✓ emailclient/frontend/src/app/(auth)/mailbox/loading.tsx
✓ emailclient/frontend/src/app/(auth)/email-settings/page.tsx
✓ emailclient/frontend/src/app/api/email/route.ts
✓ emailclient/frontend/src/app/api/email/[...slug]/route.ts
WORKFLOWS (4):
✓ emailclient/workflow-plugins/imap-sync.ts
✓ emailclient/workflow-plugins/pop3-sync.ts
✓ emailclient/workflow-plugins/smtp-send-enhanced.ts
✓ emailclient/workflow-plugins/email-parse.ts
TESTS (15):
✓ emailclient/tests/components/*.test.tsx (5)
✓ emailclient/tests/hooks/*.test.ts (3)
✓ emailclient/tests/redux/*.test.ts (3)
✓ emailclient/tests/integration/*.test.ts (4)
✓ emailclient/tests/backend/*.py (5)
CONFIG (6):
✓ emailclient/package.json
✓ emailclient/tsconfig.json
✓ emailclient/next.config.js
✓ emailclient/jest.config.js
✓ emailclient/backend/requirements.txt
✓ emailclient/docker-compose.yml
DOCUMENTATION (5):
✓ emailclient/docs/CLAUDE.md
✓ emailclient/docs/ARCHITECTURE.md
✓ emailclient/docs/ACCOUNT_SETUP.md
✓ emailclient/docs/INTEGRATION.md
✓ emailclient/README.md
✓ emailclient/QUICK_START.md
MODIFIED FILES (3):
✓ CLAUDE.md (add emailclient section)
✓ dbal/shared/api/schema/entities/entities.yaml (register 4 new entities)
✓ deployment/docker-compose.yml (optionally expand for emailclient)
================================================================================
IMPLEMENTATION PRIORITY & DEPENDENCIES
================================================================================
CRITICAL PATH (do in order):
1. DBAL Schemas (Phase 1.1) - blocks everything
2. DBAL CRUD (Phase 1.2) - needed for API endpoints
3. API Endpoints (Phase 1.3) - frontend can hit APIs
4. Backend Email Service (Phase 2.1-2.2) - implement actual email ops
5. Frontend Components (Phase 3.1-3.4) - UI rendering
6. Pages & Routing (Phase 4) - user-facing features
PARALLEL WORK (independent):
- Tests (can write while implementing)
- Docker setup (while UI is being built)
- Documentation (throughout)
================================================================================
TESTING STRATEGY
================================================================================
1. Unit Tests: DBAL CRUD, Redux reducers, hooks
2. Integration Tests: API endpoints + DBAL
3. E2E Tests: Full user flow (add account, sync, compose, send)
4. Manual Testing: Real IMAP accounts (Gmail, Outlook)
5. Performance: Index large message counts (10K+ messages)
6. Security: Rate limiting, tenant isolation, credential encryption
================================================================================
SECURITY CHECKLIST
================================================================================
✓ Credentials stored in DBAL Credential entity (SHA-512 hashed)
✓ Passwords never returned from API (only credentialId)
✓ Multi-tenant filtering on ALL queries (tenantId required)
✓ Session-based auth (mb_session cookie)
✓ Rate limiting: 50/min for mutations, 100/min for lists
✓ IMAP connection credentials isolated per user
✓ No plaintext password storage in frontend (Redux/IndexedDB)
✓ HTTPS/TLS for all connections
✓ CSRF protection on form submissions
✓ Input validation (email format, host validation)
✓ XSS prevention (DOMPurify for HTML email bodies)
✓ SQL injection prevention (use DBAL, not raw SQL)
================================================================================
ROLLOUT PLAN
================================================================================
Phase 1 (Week 1): Infrastructure
- Create DBAL schemas and CRUD operations
- Implement API endpoints
- Setup Docker compose with local Postfix/Dovecot
Phase 2 (Week 2): Backend Services
- Implement Python email service
- Integrate IMAP/POP3/SMTP
- Setup workflow plugins
- Write backend tests
Phase 3 (Week 3): Frontend
- Build React components (FakeMUI)
- Setup Redux state management
- Implement IndexedDB persistence
- Build pages and routing
Phase 4 (Week 4): Testing & Deployment
- E2E tests
- Performance testing
- Docker/Caprover deployment
- Security audit
================================================================================
MILESTONES & ACCEPTANCE CRITERIA
================================================================================
PHASE 1 COMPLETE:
☐ All 4 YAML schemas committed
☐ All 16 DBAL CRUD operations working
☐ All 7 API endpoints responding (test with curl)
☐ CLAUDE.md updated with emailclient section
PHASE 2 COMPLETE:
☐ Email service connects to test Postfix/Dovecot account
☐ Can fetch messages from IMAP (test with imaplib interactive)
☐ Can send email via SMTP (test with test account)
☐ Workflow plugins registered and callable
☐ Backend unit tests passing (>80% coverage)
PHASE 3 COMPLETE:
☐ React components render without errors
☐ Redux state management working (Redux DevTools)
☐ IndexedDB persisting emails locally
☐ Pages load and respond to user input
☐ FakeMUI components used consistently
PHASE 4 COMPLETE:
☐ All E2E tests passing (account creation, sync, compose, send)
☐ Docker images building without errors
☐ Performance: <3s to load 1000 messages
☐ Security audit: all checklist items verified
☐ Caprover deployment successful
☐ GitHub Actions CI/CD passing
================================================================================
END OF PLAN
================================================================================

View File

@@ -0,0 +1,876 @@
================================================================================
EMAIL CLIENT - ROOT-INTEGRATED IMPLEMENTATION PLAN
Date: 2026-01-23
Status: PLANNING PHASE - REVISED TO USE ROOT FAKEMUI + REDUX
================================================================================
APPROACH: Build email client by extending existing ROOT infrastructure
- Extend FakeMUI with email-specific components
- Extend root Redux with email state slices
- Create email_client package under packages/
- Add DBAL entities for multi-tenant email management
- Integrate with existing Postfix/Dovecot infrastructure
================================================================================
DIRECTORY STRUCTURE - ROOT EXTENSIONS ONLY
================================================================================
Root Changes:
fakemui/react/components/
├── email/ # NEW: Email-specific FakeMUI components
│ ├── atoms/
│ │ ├── AttachmentIcon.tsx
│ │ ├── StarButton.tsx
│ │ └── MarkAsReadCheckbox.tsx
│ ├── inputs/
│ │ ├── EmailAddressInput.tsx # With validation + autocomplete
│ │ ├── RecipientInput.tsx # Multiple recipients
│ │ └── BodyEditor.tsx # WYSIWYG HTML email editor
│ ├── surfaces/
│ │ ├── EmailCard.tsx # Email item in list
│ │ ├── MessageThread.tsx # Threaded view
│ │ └── SignatureCard.tsx # Display email signature
│ ├── data-display/
│ │ ├── AttachmentList.tsx # Show attachments
│ │ ├── EmailHeader.tsx # From/To/Date display
│ │ ├── FolderTree.tsx # Mailbox folder navigation
│ │ └── ThreadList.tsx # Conversation threads
│ ├── feedback/
│ │ ├── SyncStatusBadge.tsx # Syncing... indicator
│ │ └── SyncProgress.tsx # Progress bar during sync
│ ├── layout/
│ │ ├── MailboxLayout.tsx # 3-pane layout: folders|list|viewer
│ │ ├── ComposerLayout.tsx # Modal/fullscreen composer
│ │ └── SettingsLayout.tsx # Account settings panel
│ └── navigation/
│ ├── AccountTabs.tsx # Switch between email accounts
│ └── FolderNavigation.tsx # Folder tabs + dropdown
redux/ # Root Redux folder (already exists)
├── email/ # NEW: Email domain slices
│ ├── emailSlice.ts # Messages state
│ ├── accountSlice.ts # Email accounts state
│ ├── syncSlice.ts # Sync status state
│ ├── composerSlice.ts # Composer window state
│ ├── uiSlice.ts # UI state (selected msg, folder, etc)
│ └── index.ts # Export all email slices
packages/email_client/ # NEW: Email client package
├── package.json
├── components/ui.json # UI component definitions
├── page-config/
│ ├── mailbox.json # Route: /email/mailbox
│ ├── settings.json # Route: /email/settings
│ └── accounts.json # Route: /email/accounts
├── permissions/roles.json # RBAC: who can access email
├── workflow/ # Email-specific workflows
│ ├── sync-inbox.jsonscript
│ ├── send-email.jsonscript
│ └── move-to-folder.jsonscript
├── styles/tokens.json # Email-specific design tokens
└── docs/
├── CLAUDE.md # Email package guide
└── ARCHITECTURE.md # Email system architecture
dbal/shared/api/schema/entities/
├── packages/
│ ├── email_client.yaml # Email account entity
│ ├── email_account.yaml # Email account (user-specific)
│ ├── email_message.yaml # Email messages
│ └── email_folder.yaml # Mailbox folders
================================================================================
PHASE 1: DBAL SCHEMAS & CRUD
================================================================================
FILES: 4 YAML + 16 CRUD operations
1. dbal/shared/api/schema/entities/packages/email_client.yaml
✓ id: UUID
✓ userId: UUID
✓ tenantId: UUID (multi-tenant)
✓ accountName, email, protocol (imap/pop3), hostname, port
✓ credentialId: UUID (password stored in Credential entity)
✓ encryption, lastSyncAt, isSyncing, isEnabled, syncInterval
✓ ACL: self-read/create/update/delete, admin full
2. dbal/shared/api/schema/entities/packages/email_account.yaml
✓ Similar structure, stores account-specific settings
✓ signatureHtml, replyToEmail, folders config
✓ syncedMessageCount, lastSyncedAt
3. dbal/shared/api/schema/entities/packages/email_message.yaml
✓ messageId, from, to, cc, bcc, subject
✓ bodyHtml, bodyText, receivedAt
✓ isRead, isStarred, isDraft, isSent
✓ folderId, flags, attachments metadata
✓ tenantId filtering mandatory
4. dbal/shared/api/schema/entities/packages/email_folder.yaml
✓ emailClientId, name, type (inbox/sent/drafts/trash/spam/custom)
✓ messageCount, unreadCount, syncedAt
CRUD Operations (5 per entity = 20 files):
- dbal/development/src/core/entities/email_client/crud/
- create-email-client.ts
- read-email-client.ts
- update-email-client.ts
- delete-email-client.ts
- list-email-clients.ts
- dbal/development/src/core/entities/email_account/crud/
- (same 5 operations)
- dbal/development/src/core/entities/email_message/crud/
- (same 5 operations)
- dbal/development/src/core/entities/email_folder/crud/
- (same 5 operations)
Key requirements:
- Validate tenantId on ALL queries
- Password via Credential entity (SHA-512)
- Soft delete for messages (flag, don't purge)
- Indexes: (userId, tenantId), (emailClientId), (accountId, messageId)
================================================================================
PHASE 2: API ENDPOINTS (NEXT.JS)
================================================================================
Files: 7 endpoint handlers
frontends/nextjs/src/app/api/v1/[...slug]/route.ts (EXISTING - extend it)
Routes following pattern /api/v1/{tenant}/email_client:
POST /api/v1/{tenant}/email_client → Create account
GET /api/v1/{tenant}/email_client → List accounts
GET /api/v1/{tenant}/email_client/{id} → Read account
PUT /api/v1/{tenant}/email_client/{id} → Update account
DELETE /api/v1/{tenant}/email_client/{id} → Delete account + messages
POST /api/v1/{tenant}/email_client/{id}/test → Test connection
GET /api/v1/{tenant}/email_message → List messages (paginated)
GET /api/v1/{tenant}/email_message/{id} → Get full message
PUT /api/v1/{tenant}/email_message/{id} → Update flags (read, starred)
DELETE /api/v1/{tenant}/email_message/{id} → Trash message
POST /api/v1/{tenant}/email_message/sync → Trigger sync
POST /api/v1/{tenant}/email_compose → Send new email
POST /api/v1/{tenant}/email_message/{id}/reply → Send reply
Rate limits:
- List: 100/min
- Mutations: 50/min
- Sync: 10/min
Status codes: 201 (create), 200 (ok), 400 (validate), 401 (auth), 403 (forbidden), 429 (rate limit)
Implementation:
- Use existing DBAL client
- Multi-tenant filtering mandatory
- Session validation via middleware
- Error handling + audit logging
================================================================================
PHASE 3: BACKEND EMAIL SERVICE (PYTHON/FLASK)
================================================================================
Files: services/email_service/ (in existing services/ directory)
services/email_service/
├── src/
│ ├── __init__.py
│ ├── email_service.py # Main orchestrator
│ ├── imap_sync.py # IMAP sync engine
│ ├── pop3_sync.py # POP3 sync engine
│ ├── smtp_send.py # SMTP sending
│ ├── account_manager.py # Account CRUD wrapper
│ ├── models.py # SQLAlchemy models
│ ├── schemas.py # Pydantic validation
│ ├── routes/
│ │ ├── __init__.py
│ │ ├── accounts.py
│ │ ├── sync.py
│ │ ├── compose.py
│ │ └── status.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── imap_parser.py
│ │ ├── email_parser.py # RFC 2822
│ │ ├── credentials.py # Encryption/decryption
│ │ └── validators.py # Input validation
│ └── tasks/
│ ├── __init__.py
│ ├── sync_tasks.py # Celery background jobs
│ └── cleanup_tasks.py # Purge old messages
├── requirements.txt # imapclient, poplib, celery, redis
├── Dockerfile.dev # Dev container
└── Dockerfile.prod # Prod container
Key components:
1. EmailService class:
- connect(client_id, user_id, tenant_id)
- sync_account(account_id) → {synced_count, errors}
- send_email(from, to, subject, html, attachments)
- test_connection(host, port, protocol, username, password)
2. IMAPSyncEngine:
- connect() / disconnect()
- list_folders() → [names]
- sync_folder(name, since_timestamp) → [messages]
- fetch_message_full(id) → message dict
- update_flags(id, flags)
3. POP3SyncEngine:
- Similar but simpler (no folder support)
4. SMTPSender:
- Uses existing smtp_relay logic
- Adds attachment support
- Handles reply-to, signatures
- Audit logging
5. Celery background tasks:
- periodic_sync_job() - runs every 5 min
- cleanup_old_messages_job() - runs daily
- test_connection_async()
================================================================================
PHASE 4: FAKEMUI COMPONENTS (ROOT EXTENSION)
================================================================================
Files: 22 new components (extend FakeMUI)
fakemui/react/components/email/
ATOMS (3):
✓ AttachmentIcon.tsx - file type icon
✓ StarButton.tsx - toggle starred
✓ MarkAsReadCheckbox.tsx - mark read/unread
INPUTS (3):
✓ EmailAddressInput.tsx - validate + parse email
✓ RecipientInput.tsx - multiple recipients (to/cc/bcc)
✓ BodyEditor.tsx - WYSIWYG HTML editor (use DraftJS or similar)
SURFACES (4):
✓ EmailCard.tsx - single email item (with preview)
✓ MessageThread.tsx - show conversation thread
✓ SignatureCard.tsx - display signature
✓ ComposeWindow.tsx - modal email composer
DATA-DISPLAY (4):
✓ AttachmentList.tsx - preview attachments
✓ EmailHeader.tsx - from/to/date/cc display
✓ FolderTree.tsx - mailbox folder navigation (recursive)
✓ ThreadList.tsx - list of conversations
FEEDBACK (2):
✓ SyncStatusBadge.tsx - syncing, done, error
✓ SyncProgress.tsx - progress bar + percentage
LAYOUT (3):
✓ MailboxLayout.tsx - 3-pane main layout
✓ ComposerLayout.tsx - fullscreen/modal composer
✓ SettingsLayout.tsx - account settings sidebar
NAVIGATION (2):
✓ AccountTabs.tsx - switch accounts
✓ FolderNavigation.tsx - folder breadcrumb + dropdown
All components:
- Use FakeMUI primitives (Button, TextField, Dialog, Card, etc)
- Add data-testid attributes
- Add ARIA labels
- Responsive design
- SCSS modules in fakemui/styles/email.scss
================================================================================
PHASE 5: REDUX STATE MANAGEMENT (ROOT FOLDER)
================================================================================
Files: 5 slices in redux/email/
redux/email/emailSlice.ts
- state: {
messages: [{id, from, subject, receivedAt, isRead, isStarred}],
selectedMessageId: UUID | null,
filter: {accountId, folderId, isRead, isStarred, dateRange},
searchQuery: string,
currentPage: number,
pageSize: number
}
- actions: setMessages, appendMessages, updateMessage, selectMessage, setFilter, search
redux/email/accountSlice.ts
- state: {
accounts: [{id, email, protocol, hostname, isEnabled, lastSync}],
selectedAccountId: UUID | null,
isCreating: boolean,
error: string | null
}
- actions: setAccounts, createAccount, updateAccount, deleteAccount, selectAccount
redux/email/syncSlice.ts
- state: {
[accountId]: {
status: 'idle' | 'syncing' | 'error' | 'success',
progress: 0-100,
lastSyncAt: timestamp,
syncedCount: number,
error: string | null
}
}
- actions: startSync, syncProgress, syncSuccess, syncError
redux/email/composerSlice.ts
- state: {
isOpen: boolean,
to: string[],
cc: string[],
bcc: string[],
subject: string,
bodyHtml: string,
attachments: [{name, size, data}],
isSending: boolean,
error: string | null
}
- actions: openComposer, closeComposer, setTo/Cc/Bcc, setSubject, setBody, addAttachment, removeAttachment, send
redux/email/uiSlice.ts
- state: {
selectedFolderId: string | null,
isComposerOpen: boolean,
isSidebarOpen: boolean (mobile),
sortBy: 'date' | 'from' | 'subject',
sortAsc: boolean,
viewMode: 'list' | 'thread'
}
- actions: setSelectedFolder, setComposerOpen, setSidebarOpen, setSortBy, setViewMode
All slices:
- Follow existing Redux patterns in codebase
- Immer for immutable updates
- TypeScript types exported
- Action names descriptive
================================================================================
PHASE 6: EMAIL PACKAGE
================================================================================
Files: 10 under packages/email_client/
packages/email_client/package.json
- "name": "email_client",
- "version": "1.0.0"
- "minLevel": 0 (all users can use)
packages/email_client/components/ui.json
- UI component definitions for all email components
- References to FakeMUI email components
- Form schemas for account creation, compose, settings
packages/email_client/page-config/mailbox.json
- Route: /app/email/mailbox
- Layout: MailboxLayout component
- Requires: session token, tenantId
- Breadcrumb: Dashboard > Email > Mailbox
packages/email_client/page-config/settings.json
- Route: /app/email/settings
- Account management, sync settings, signature editor
- minLevel: 1 (authenticated users only)
packages/email_client/page-config/accounts.json
- Route: /app/email/accounts
- Account list/add/edit/delete
- Connection test panel
packages/email_client/permissions/roles.json
- "email_basic": read own emails, send
- "email_admin": manage all user accounts, view logs
- ACL: tenantId filtering mandatory
packages/email_client/workflow/sync-inbox.jsonscript
- Trigger: manual sync button
- Steps:
1. Load email_client config
2. Call IMAP sync plugin
3. Save messages to DBAL
4. Update folder unread counts
5. Notify user (via notification entity)
packages/email_client/workflow/send-email.jsonscript
- Trigger: compose window submit
- Steps:
1. Validate recipients
2. Call SMTP send plugin
3. Save to Sent folder
4. Log to audit trail
packages/email_client/styles/tokens.json
- Email-specific design tokens
- Colors, fonts, spacing for email UI
packages/email_client/docs/CLAUDE.md
- Email package guide
- Component usage
- API patterns
================================================================================
PHASE 7: WORKFLOW PLUGINS (ROOT)
================================================================================
Files: 4 in workflow/plugins/ts/integration/email/
workflow/plugins/ts/integration/email/
├── imap-sync.ts
│ - Input: emailClientId, maxMessages
│ - Output: messages[], stats{}
│ - Error: retry with backoff
│ - Logging: audit trail
├── pop3-sync.ts
│ - Similar to IMAP but simpler
│ - No folder support
├── smtp-send.ts
│ - Enhance existing smtp_relay plugin
│ - Input: from, to, cc, bcc, subject, html, attachments
│ - Output: messageId, timestamp
│ - Error: retry, fallback to queue
└── email-parse.ts
- Input: raw email data
- Output: parsed message {headers, body, attachments}
- Uses RFC 2822 parser
All plugins:
- Multi-language support (TS, Python, Go)
- Tenantid passed through workflow context
- Error handling + retry logic
- Performance: fast (<1s per message)
================================================================================
PHASE 8: NEXT.JS PAGES & ROUTING
================================================================================
Files: 8 under frontends/nextjs/src/app/
frontends/nextjs/src/app/(auth)/email/
├── layout.tsx
│ - Navbar: logo, search, account menu
│ - Sidebar: FolderTree component
│ - Main content area
├── mailbox/
│ ├── page.tsx (main mailbox view)
│ ├── layout.tsx (3-pane layout)
│ ├── loading.tsx (skeleton)
│ └── error.tsx (error boundary)
├── settings/
│ ├── page.tsx (settings hub)
│ ├── accounts/page.tsx (account management)
│ └── loading.tsx
└── api/
├── sync/route.ts (trigger sync endpoint)
├── send/route.ts (send email endpoint)
└── test-connection/route.ts (test IMAP connection)
Key features:
- Server-side session validation
- DBAL query execution
- Error handling + user feedback
- Loading states (Suspense)
- Mobile responsive (FakeMUI breakpoints)
================================================================================
PHASE 9: HOOKS & UTILITIES
================================================================================
Files: 8 custom hooks (frontends/nextjs/src/lib/hooks/email/)
frontends/nextjs/src/lib/hooks/email/
├── useEmailSync.ts
│ - Trigger manual sync
│ - Return: {sync, isSyncing, lastSync, error}
├── useEmailStore.ts
│ - IndexedDB wrapper
│ - Methods: get, save, query, delete, clear
├── useMailboxes.ts
│ - Fetch folders for email client
│ - Return: {folders, isLoading, error}
├── useAccounts.ts
│ - CRUD for email clients
│ - Methods: create, update, delete, test, list
├── useCompose.ts
│ - Manage composer state (open/close, draft)
│ - Return: {isOpen, open, close, draft, send}
├── useMessages.ts
│ - Fetch + paginate messages
│ - Return: {messages, page, next, prev, search}
├── useEmailNotifications.ts
│ - Subscribe to sync updates via websocket or polling
│ - Show toast notifications for sync completion
└── useEmailParser.ts
- Parse email headers for threading
- Return: {threads, threadMap}
All hooks:
- Use Redux for state
- Use DBAL client for data fetch
- Error handling
- Memoization for performance
================================================================================
PHASE 10: INDEXEDDB PERSISTENCE
================================================================================
Files: 4 in frontends/nextjs/src/lib/indexeddb/
frontends/nextjs/src/lib/indexeddb/
├── db.ts
│ - Initialize IndexedDB "emailclient" database
│ - Version 1, stores: messages, accounts, folders, sync_state, drafts
├── emails.ts
│ - saveMessages(messages)
│ - getMessages(accountId, options)
│ - updateMessage(id, patch)
│ - queryMessages(filter)
│ - clearOldMessages(accountId, daysToKeep)
├── accounts.ts
│ - saveAccounts(accounts)
│ - getAccounts()
│ - getAccount(id)
└── sync.ts
- saveSyncState(accountId, state)
- getSyncState(accountId)
- getLastSync(accountId)
Key features:
- Offline access: messages available without network
- Indexes for fast queries
- Auto-cleanup old messages
- Sync state tracking
================================================================================
PHASE 11: TESTING
================================================================================
Files: 15 test files
e2e/email-client.spec.ts
- Create email account
- Test IMAP connection
- Sync inbox
- Compose and send email
- Mark as read/starred
- Move to folder
- Search messages
__tests__/email/
├── components/
│ ├── EmailCard.test.tsx
│ ├── MailboxLayout.test.tsx
│ ├── ComposeWindow.test.tsx
│ └── FolderTree.test.tsx
├── hooks/
│ ├── useEmailSync.test.ts
│ ├── useAccounts.test.ts
│ └── useMessages.test.ts
├── redux/
│ ├── emailSlice.test.ts
│ ├── accountSlice.test.ts
│ └── syncSlice.test.ts
└── integration/
├── create-account.test.ts
├── send-email.test.ts
└── sync-messages.test.ts
Backend tests (services/email_service/tests/):
├── test_imap_sync.py
├── test_smtp_send.py
├── test_account_manager.py
└── test_email_parser.py
Coverage: >80% for critical paths
================================================================================
PHASE 12: DOCKER & DEPLOYMENT
================================================================================
Files: 5 config files
deployment/docker/email-service/
├── Dockerfile.dev
├── Dockerfile.prod
├── docker-compose.yml (extends root docker-compose.yml)
└── .env.example
docker-compose.yml additions:
- email-service: Flask backend, Python 3.11
- postfix: SMTP server (reuse existing)
- dovecot: IMAP/POP3 (reuse existing)
- redis: Session store + Celery broker
Caprover deployment:
- Captain definition for email-service
- Environment variables: DBAL_URL, REDIS_URL, POSTFIX_HOST, etc
- Health checks: /api/health
- Auto-scaling: based on sync queue depth
================================================================================
FILES TO CREATE/MODIFY - DETAILED LIST
================================================================================
NEW DBAL SCHEMAS (4):
✓ dbal/shared/api/schema/entities/packages/email_client.yaml
✓ dbal/shared/api/schema/entities/packages/email_account.yaml
✓ dbal/shared/api/schema/entities/packages/email_message.yaml
✓ dbal/shared/api/schema/entities/packages/email_folder.yaml
NEW DBAL CRUD (20):
✓ dbal/development/src/core/entities/email-client/crud/create.ts
✓ dbal/development/src/core/entities/email-client/crud/read.ts
✓ dbal/development/src/core/entities/email-client/crud/update.ts
✓ dbal/development/src/core/entities/email-client/crud/delete.ts
✓ dbal/development/src/core/entities/email-client/crud/list.ts
✓ (same 5 for email-account, email-message, email-folder)
NEW FAKEMUI COMPONENTS (22):
✓ fakemui/react/components/email/atoms/*.tsx (3)
✓ fakemui/react/components/email/inputs/*.tsx (3)
✓ fakemui/react/components/email/surfaces/*.tsx (4)
✓ fakemui/react/components/email/data-display/*.tsx (4)
✓ fakemui/react/components/email/feedback/*.tsx (2)
✓ fakemui/react/components/email/layout/*.tsx (3)
✓ fakemui/react/components/email/navigation/*.tsx (2)
✓ fakemui/styles/email.scss
NEW REDUX SLICES (5):
✓ redux/email/emailSlice.ts
✓ redux/email/accountSlice.ts
✓ redux/email/syncSlice.ts
✓ redux/email/composerSlice.ts
✓ redux/email/uiSlice.ts
✓ redux/email/index.ts (export all)
NEW EMAIL PACKAGE (8):
✓ packages/email_client/package.json
✓ packages/email_client/components/ui.json
✓ packages/email_client/page-config/mailbox.json
✓ packages/email_client/page-config/settings.json
✓ packages/email_client/page-config/accounts.json
✓ packages/email_client/permissions/roles.json
✓ packages/email_client/workflow/*.jsonscript (2)
✓ packages/email_client/styles/tokens.json
✓ packages/email_client/docs/CLAUDE.md
NEW BACKEND SERVICE (12):
✓ services/email_service/src/email_service.py
✓ services/email_service/src/imap_sync.py
✓ services/email_service/src/pop3_sync.py
✓ services/email_service/src/smtp_send.py
✓ services/email_service/src/account_manager.py
✓ services/email_service/src/models.py
✓ services/email_service/src/schemas.py
✓ services/email_service/src/routes/*.py (4)
✓ services/email_service/src/utils/*.py (4)
✓ services/email_service/src/tasks/*.py (2)
✓ services/email_service/requirements.txt
✓ services/email_service/app.py
NEW WORKFLOW PLUGINS (4):
✓ workflow/plugins/ts/integration/email/imap-sync.ts
✓ workflow/plugins/ts/integration/email/pop3-sync.ts
✓ workflow/plugins/ts/integration/email/smtp-send.ts
✓ workflow/plugins/ts/integration/email/email-parse.ts
NEW NEXT.JS PAGES (8):
✓ frontends/nextjs/src/app/(auth)/email/layout.tsx
✓ frontends/nextjs/src/app/(auth)/email/mailbox/page.tsx
✓ frontends/nextjs/src/app/(auth)/email/mailbox/layout.tsx
✓ frontends/nextjs/src/app/(auth)/email/mailbox/loading.tsx
✓ frontends/nextjs/src/app/(auth)/email/mailbox/error.tsx
✓ frontends/nextjs/src/app/(auth)/email/settings/page.tsx
✓ frontends/nextjs/src/app/(auth)/email/settings/accounts/page.tsx
✓ frontends/nextjs/src/app/(auth)/email/api/*.ts (3)
NEW HOOKS (8):
✓ frontends/nextjs/src/lib/hooks/email/useEmailSync.ts
✓ frontends/nextjs/src/lib/hooks/email/useEmailStore.ts
✓ frontends/nextjs/src/lib/hooks/email/useMailboxes.ts
✓ frontends/nextjs/src/lib/hooks/email/useAccounts.ts
✓ frontends/nextjs/src/lib/hooks/email/useCompose.ts
✓ frontends/nextjs/src/lib/hooks/email/useMessages.ts
✓ frontends/nextjs/src/lib/hooks/email/useEmailNotifications.ts
✓ frontends/nextjs/src/lib/hooks/email/useEmailParser.ts
NEW INDEXEDDB (4):
✓ frontends/nextjs/src/lib/indexeddb/db.ts
✓ frontends/nextjs/src/lib/indexeddb/emails.ts
✓ frontends/nextjs/src/lib/indexeddb/accounts.ts
✓ frontends/nextjs/src/lib/indexeddb/sync.ts
NEW TESTS (15):
✓ e2e/email-client.spec.ts
✓ __tests__/email/components/*.test.tsx (4)
✓ __tests__/email/hooks/*.test.ts (3)
✓ __tests__/email/redux/*.test.ts (3)
✓ __tests__/email/integration/*.test.ts (3)
✓ services/email_service/tests/*.py (4)
NEW DOCKER & CONFIG (5):
✓ deployment/docker/email-service/Dockerfile.dev
✓ deployment/docker/email-service/Dockerfile.prod
✓ deployment/docker-compose.yml (email additions)
✓ deployment/.env.example (email vars)
✓ services/email_service/.dockerignore
MODIFIED FILES (4):
✓ CLAUDE.md (add email client section + postfix notes)
✓ fakemui/index.ts (export email components)
✓ redux/store.ts (import email slices)
✓ packages/index.ts (register email_client package)
✓ dbal/shared/api/schema/entities/entities.yaml (register 4 new entities)
DOCUMENTATION (3):
✓ packages/email_client/docs/CLAUDE.md
✓ packages/email_client/README.md
✓ packages/email_client/docs/ARCHITECTURE.md
TOTAL FILES: ~130 new/modified
================================================================================
IMPLEMENTATION PHASES & PRIORITY
================================================================================
PHASE 1 (Critical Path):
1. DBAL schemas (4 files) - blocks everything else
2. DBAL CRUD (20 files) - needed for API
3. API endpoints in Next.js (extend existing router)
→ After Phase 1: Frontend can call APIs, backend data access works
PHASE 2 (Parallel with Phase 1):
1. FakeMUI email components (22 files)
2. Redux email slices (5 files)
→ After Phase 2: UI building blocks ready
PHASE 3 (Backend):
1. Email service (Python Flask)
2. IMAP/POP3/SMTP implementations
3. Workflow plugins
→ After Phase 3: Actual email operations work
PHASE 4 (Frontend Integration):
1. Next.js pages using FakeMUI components
2. Custom hooks for API calls
3. Redux integration
→ After Phase 4: Full UI functional
PHASE 5 (Persistence & Testing):
1. IndexedDB setup
2. Tests (E2E, unit, integration)
3. Docker deployment
→ After Phase 5: Production ready
Critical: Do Phase 1 first (schemas + CRUD), then Phases 2-3 in parallel
================================================================================
SECURITY CHECKLIST
================================================================================
✓ Credentials: Stored in DBAL Credential entity (SHA-512, never returned)
✓ Multi-tenant: tenantId filtering on ALL queries
✓ Authentication: Session middleware (mb_session cookie)
✓ Authorization: ACL enforced by DBAL
✓ Rate limiting: 50/min mutations, 100/min reads
✓ Input validation: Email format, host validation, IMAP connection test
✓ XSS prevention: DOMPurify for HTML email bodies
✓ CSRF: Form-level protection via middleware
✓ SQL injection: Use DBAL, never raw SQL
✓ Password hashing: SHA-512 (existing pattern)
✓ Email forwarding: No auto-reply without user confirmation
✓ Attachment scanning: Optional virus scan via ClamAV
✓ Audit logging: All account actions logged
================================================================================
ACCEPTANCE CRITERIA - COMPLETION CHECKLIST
================================================================================
PHASE 1 COMPLETE:
☐ All 4 YAML schemas committed to git
☐ All 20 CRUD files implement full C, R, U, D, L operations
☐ DBAL can create/read/update/delete email clients
☐ Next.js API routes respond to HTTP requests
☐ CLAUDE.md updated with email section
PHASE 2 COMPLETE:
☐ All 22 FakeMUI components render without errors
☐ Components use data-testid and ARIA attributes
☐ Redux slices created with full actions/reducers
☐ Redux DevTools shows email state changes
☐ Storybook stories created for FakeMUI email components
PHASE 3 COMPLETE:
☐ Email service connects to test Postfix/Dovecot
☐ Can list IMAP folders and sync messages
☐ Can send email via SMTP
☐ Workflow plugins registered and callable
☐ Backend unit tests >80% coverage
☐ Docker builds without errors
PHASE 4 COMPLETE:
☐ Next.js pages render MailboxLayout with sidebar
☐ Redux state updates when messages load
☐ FolderTree shows folders and unread counts
☐ MessageList shows paginated emails
☐ ComposeWindow opens/closes correctly
☐ Settings pages load account config
PHASE 5 COMPLETE:
☐ IndexedDB stores messages locally
☐ Messages accessible offline
☐ E2E tests: Create account, sync, compose, send
☐ E2E tests: Mark read, move folder, delete
☐ All unit tests passing
☐ Docker image builds and runs
☐ Performance: <3s to load 1000 messages
☐ No console errors or warnings
DEPLOYMENT READY:
☐ Caprover deployment script created
☐ Environment variables documented in .env.example
☐ Health checks configured
☐ Auto-scaling tested
☐ SSL/TLS enabled
☐ Monitoring configured (logs, metrics)
================================================================================
END OF REVISED PLAN
================================================================================
This plan builds email client by extending ROOT infrastructure:
- FakeMUI components in fakemui/react/components/email/
- Redux slices in redux/email/
- Email package in packages/email_client/
- Backend service in services/email_service/
- DBAL entities in dbal/shared/api/schema/entities/packages/
- Next.js pages in frontends/nextjs/
No separate emailclient/ project directory needed!