# Incoming business mailbox

The IMAP connector is built for `qasimvayani@phonebuzz.me` on `mail.phonebuzz.me:993`, using verified implicit TLS and password authentication, as specified in the supplied Apple mail profile. It is disabled by default. **No live mailbox has been activated or tested by this development milestone.** The user selected **new emails from activation onward**; existing INBOX messages are excluded.

The web and native iOS/Android inboxes show connection state, the last successful check, imported/skipped/duplicate counts and paginated sync history. All active staff can read imported emails. Administrators can request sync, pause or resume; these actions require a running server worker to fetch anything. Status is refreshed explicitly and is not a worker health guarantee. Drafts remain unsent.

## Server activation

Use the platform API host, not the legacy PHP website's public directory. Back up the database and apply `alembic upgrade head` from `platform/apps/api` first. Production requires PostgreSQL and private attachment storage for stock/device/reservation evidence; incoming email originals are stored in the database. Keep the API and worker on the same database and settings.

In the API host's private environment or `apps/api/.env`, configure:

```dotenv
PB_IMAP_ENABLED=true
PB_IMAP_HOST=mail.phonebuzz.me
PB_IMAP_PORT=993
PB_IMAP_USERNAME=qasimvayani@phonebuzz.me
PB_IMAP_ADDRESS=qasimvayani@phonebuzz.me
PB_IMAP_FOLDER=INBOX
PB_IMAP_PASSWORD='REPLACE_WITH_THE_MAILBOX_PASSWORD'
```

The example password is a placeholder. Enter the actual password privately; do not put it into web/mobile environment variables, shell arguments, source control, screenshots or support logs. A private `.env` file should have mode 0600. Use dotenv quoting appropriate to its actual characters. Never reuse it as a platform staff login. The API and worker read settings at process startup; restart both after configuration changes.

From `platform/apps/api`, activate with an existing active platform administrator's email (replace the example):

```sh
.venv/bin/python -m phonebuzz.mailbox_worker initialize --admin-email admin@example.com
.venv/bin/python -m phonebuzz.mailbox_worker run-once
.venv/bin/python -m phonebuzz.mailbox_worker watch
```

Initialization connects read-only, records UIDVALIDITY and UIDNEXT−1, and exits. The starting point is the mailbox snapshot taken during that command. Only higher UIDs are eligible afterward. The command refuses to reset an existing checkpoint. Confirm the address and staff access before activation. `run-once` prints a sanitized outcome; it may report disabled, not_initialized, waiting, paused, synced or an error code. Watch mode requires configuration and initialization, checks every five seconds, and respects the database's next-attempt time. Run it under your hosting's process supervisor with restart policy, a private service account and monitoring. A local terminal session is not a production service. No deployment or scheduling service was created here.

## Import behavior

- INBOX only. The adapter uses read-only selection and `BODY.PEEK`; it never sends, marks read, moves or deletes remote mail. TLS certificate verification remains enabled. See the [IMAP specification](https://www.rfc-editor.org/rfc/rfc9051.html).
- Each run scans at most 500 UID positions and imports at most 20 messages. Successful idle checks schedule the next attempt after 60 seconds; backlog batches after five seconds. Gaps/expunged messages are handled without reversing a UID range.
- Each email transaction saves its conversation entry, mailbox UID provenance and checkpoint together. An interrupted run resumes after its last committed message. A database lease protects against overlapping workers; it is renewed during long downloads. Pause revokes the lease, preventing subsequent commits from an in-flight worker. Emails already committed before pause remain available.
- Duplicate mailbox/UIDVALIDITY/UID values cannot produce another record. Identical raw message bytes already imported at another UID are recorded as duplicates without creating another conversation entry. Changed bytes sharing a Message-ID are not automatically discarded. Manual email records have separate retry protection and are not deduplicated against IMAP content.
- Replies join a conversation only when explicit References/In-Reply-To IDs resolve to exactly one known conversation and the sender address matches exactly. Ambiguous references, different senders and matching subjects alone create separate conversations. A received reply reopens its conversation, advances its version and retains the saved draft and assignment. Staff must reload after stale edits.
- Text/plain is preferred; HTML is converted to plain text without fetching remote content or rendering active markup. Sender headers are not independently authenticated. Reply-To is flagged for review. No content is treated as an instruction to tools or staff permissions.
- Email size limit: 8 MiB including MIME encoding; body fetches use 64 KiB chunks. Text is capped at 16,000 characters, subject at 200, MIME nesting at 20 and MIME parts at 100. Truncation and encoding fallbacks are reported. Unsafe/malformed/oversized messages are recorded as skipped and advance the checkpoint; review them in the original mailbox. There is no automatic skipped-message retry action in this milestone.
- Attachment names are listed. Newly synced supported attachments are validated and retained privately with optional staff-reviewed text extraction; unsupported files show a reason. See EMAIL-ATTACHMENTS.md for formats, limits and the confirmation workflow. Older messages remain names-only; there is no refetch. Raw email bytes are hashed for duplicate checks and discarded after processing. Provenance retains UID, Message-ID and IMAP INTERNALDATE. That mailbox timestamp is distinct from import time and is not proof of initial sender delivery time. Messages removed or moved from INBOX before the worker reads them cannot be recovered here.

## Failures and recovery

Network/protocol/authentication errors produce sanitized status; neither passwords nor raw server errors are returned. Delays increase from 30 seconds to a maximum of 30 minutes. After five consecutive failures, polling stops until an administrator explicitly requests sync. Successful sync resets failures. Pause also stops polling. Resume requests an attempt using the existing checkpoint; mail arriving while paused remains eligible if still in INBOX.

Changed mailbox identity (host, port, login, address or folder), UIDVALIDITY or an unavailable administrator owner blocks sync. No UI control resets these safeguards. Review the original mailbox and database backup before any operator repair; deleting a checkpoint and initializing again can exclude unprocessed messages. Password rotation does not change identity. Pause first, update the private secret, restart API/worker and resume. Re-enabling a previously disabled owner still requires operator review of the blocked state. Stale control versions return a conflict; refresh first.

## API and migration

- `GET /v1/mailbox`: authenticated, sanitized status; no password or login secret.
- `GET /v1/mailbox/messages`: authenticated, paginated provenance and outcome filters.
- `POST /v1/mailbox/control`: administrator-only, version-checked sync/pause/resume.
- Existing conversation entries include nullable `source` metadata for imported emails.

Migration `0144d5c97475` adds `mailboxes` and `mailbox_messages` without changing existing business values. No real mailbox is seeded. Downgrade refuses to discard initialized checkpoints. Preserve the database and credentials together in tested private backups.

## Remaining integration work

Live hosting connectivity/authentication and controlled receive tests, PostgreSQL contention tests, native device testing, production supervision/monitoring and retention/export policies remain pending. Incoming attachment validation, private storage and staff review are built; malware scanning and production isolation remain pending. Outbound email needs reviewed recipients/content, approval tied to exact content, idempotent delivery handling and delivery tracking. Manual email-to-trading review is now available (EMAIL-TRADING.md). Optional AI extraction and reviewed local examples are built (AI-EXTRACTION.md, LEARNING.md). WhatsApp, generated replies and automatic trading-record creation remain separate milestones. Live receiving tests are deferred at the user’s request.
