This file documents the email (IMAP/SMTP) subsystem. Claude Code auto-loads it when a file under `devplacepy/services/email/` is read or edited.

## Email via Devii (`services/email/` + `services/devii/email/`)

A signed-in user's Devii can connect to their OWN external mailbox over IMAP/SMTP (non-platform, external protocol tools).

### Protocol engine and adapter

The protocol engine `services/email/` (`EmailAccount` dataclass + `EmailClient`) is built over the Python **stdlib** `imaplib`/`smtplib`/`email` - no new dependency, since IMAP/SMTP are not HTTP the stealth-client rule does not apply. It is wrapped by the Devii adapter `services/devii/email/EmailController` (`handler="email"`, registered in `registry.py`, specs in `actions/email_actions.py`, routed in `dispatcher.py`). Every blocking protocol call runs through `asyncio.to_thread` in the controller so the single worker loop never stalls (same discipline as `correction.py`).

### Tools

- Connection CRUD: `email_account_set`/`email_account_get`/`email_accounts_list`/`email_account_delete`.
- Message ops: `email_list_folders`, `email_list_messages`, `email_search`, `email_read_message` (read); `email_mark`/`email_set_flags`/`email_move_message` (organise); `email_delete_message`; `email_send`.

All are `requires_auth=True` AND additionally guarded to `owner_kind == "user"` (guests never reach email), gated by the admin `devii_email_enabled` flag (default on) / `devii_email_timeout` on the Devii service config ("Email" service-config group).

### Credentials

Credentials live in the soft-deletable per-owner `email_accounts` table (one row per `(owner_kind, owner_id, label)`; helpers `list/get/set/delete_email_account` in `database/`, sensible defaults imap 993/ssl + smtp 587/starttls applied in `set_email_account`). The password is stored **plaintext** (consistent with `api_key`/`gateway_api_key`) and is **NEVER echoed back** - `email_account_get`/`email_accounts_list` mask it as `password_set`.

### Configuration surface

Configuration is **Devii-only** (no HTTP route or profile UI), like the CSS/JS customization feature.

### Destructive actions and SSRF guard

`email_send` is a real outbound action, and the two delete tools (`email_account_delete`, `email_delete_message`) are confirmation-gated (`CONFIRM_REQUIRED`, each declaring a `confirm` param). The IMAP/SMTP host is run through `net_guard.guard_public_host_sync` before every connect (private/loopback addresses refused - SSRF/internal-scan defense, mirroring `guard_public_url`).

### Audit and metering

Audited via the existing `_audit_mechanic` choke point under the `email.*` domain (category `email`). Mutations are **not metered into the gateway ledger** (no LLM call is made).
