Files
govoplan-mail/README.md
T
zemion 1cbf4acaf4
Module Package Release / publish-packages (push) Successful in 12s
feat(mail): add governed JMAP mailbox sync and search
2026-08-22 17:09:05 +02:00

170 lines
8.6 KiB
Markdown

# govoplan-mail
<!-- govoplan-repository-type:start -->
**Repository type:** module (domain).
<!-- govoplan-repository-type:end -->
GovOPlaN Mail is the mail transport module. It owns reusable SMTP/IMAP/JMAP profile management, an explicitly enabled legacy POP3 import path, mail profile policy enforcement, mock mail infrastructure, and the mail WebUI package.
## Ownership
This repository owns:
- backend module manifest `mail`
- mail permissions such as `mail:profile:read`, `mail:profile:write_own`, `mail:profile:write`, `mail:profile:use`, `mail:profile:test`, and `mail:mailbox:read`
- SMTP/IMAP/JMAP profile models, dedicated legacy POP3 sources, policy checks, encrypted credential storage, and profile resolution
- SMTP send and IMAP append adapters, including mock transports for development
- development mock mailbox endpoints used by test-send flows
- WebUI package `@govoplan/mail-webui` with profile management, policy management, read-only mailbox components, and governed POP3 import
Core owns auth, tenants, RBAC evaluation, database/session primitives, secret helpers, CSRF/API helpers, and shell layout.
Mail publishes `privacy.dsar.mail` for Core's governed data-subject-request
workflow. It isolates matching mailbox header parties and returns bounded index,
personal-profile, delivery, reconciliation, bounce, and imported-message metadata. SMTP/IMAP/JMAP/POP3
configuration and credentials, encrypted messages and envelopes, source UIDL
and folder/UID
locators, worker and idempotency state, diagnostics, and opaque evidence are
excluded. Delivery and bounce outcomes remain retained evidence; mailbox and
profile changes require coordinated Mail and external-provider review, so the
provider does not perform direct erasure.
## Profile and credential ownership
Mail profiles are separate governed definitions. Mail owns their SMTP/IMAP/JMAP
endpoints, encrypted credentials, tests, scope, and policy. Consumers such as
Campaign store only a stable profile identifier and resolve the authorized,
active profile through `mail.campaign_delivery`; they never copy or override
transport settings or credentials in their own JSON.
The campaign capability returns read-only availability flags and random,
persisted Mail-owned transport revisions without decrypting secrets. Effect calls perform authorization,
revision comparison, credential resolution, policy checks, and SMTP/IMAP
effects inside Mail. Consumer-visible outcomes are sanitized: provider banners,
raw response bytes, hosts, account identities, and credentials are not returned.
Mail also owns a durable delivery-command outbox for effects that do not
already have a consumer-owned job ledger, including Campaign report messages.
It persists the command and attempt before SMTP, binds idempotency keys to
canonical request hashes, distinguishes partial refusal and unknown outcome,
and requires explicit evidence-backed reconciliation before any deliberate
resend. Business readers receive only counts and sanitized state; recipient
refusal details require `mail:delivery:diagnostic`.
Synchronous Campaign batches now preflight DNS, egress, connectivity, TLS, and
authentication before the first message, then reuse the authorized SMTP
connection for the bounded batch. A health check precedes reuse; a stale
connection is reopened before the next message, while a connection loss after
DATA starts remains outcome-unknown and is never replayed automatically.
Systemic authentication, sender, and connectivity failures pause remaining
Campaign jobs instead of producing one failure per recipient. Deployment
operators can disable reuse or bound connection lifetime and reconnects with
`GOVOPLAN_SMTP_BATCH_REUSE`, `GOVOPLAN_SMTP_BATCH_MAX_MESSAGES`,
`GOVOPLAN_SMTP_BATCH_RECONNECT_ATTEMPTS`, and
`GOVOPLAN_SMTP_BATCH_HEALTH_CHECK`.
SMTP effects decrypt only SMTP credentials; Sent-folder effects decrypt only
IMAP credentials. A connection loss after an effect starts is surfaced as an
unknown outcome. Campaign does not automatically retry an unknown IMAP append,
preventing silent duplicate Sent copies while an operator inspects the mailbox.
Every current outbox, Campaign SMTP, and Campaign Sent-folder attempt also
starts a Mail-owned Core recovery operation under a stable per-attempt effect
identifier before contacting the provider. Evidence contains only message,
address, and folder digests plus bounded outcome counts. A completed effect is
never replayed to repair caller state; unknown outcomes require explicit
provider-backed reconciliation.
Read-only mailbox folder/message indexing and bounce/calendar-reply scans use
distributed recovery fences. Cache rows or source cursors commit before an
independent verification closes the operation. A failed read rolls back and is
safe to repeat because these paths never move, delete, flag, or otherwise
mutate provider messages.
The existing SMTP/IMAP credential-inheritance policy remains part of the Mail
policy model for compatibility. Campaign delivery requires effective
inheritance: a policy that requires campaign-local credentials now fails
closed with guidance to store those credentials on a Mail profile and enable
inheritance.
Deleting a profile deactivates its non-secret tombstone metadata and scrubs
its encrypted SMTP, IMAP, JMAP, and POP3 credentials immediately in the same transaction as
a non-secret audit event. Destructive module retirement applies the same rule
to every remaining profile before any Mail table is dropped; a scrub or audit
failure blocks retirement.
Personal profile self-service is a distinct authorization path. An actor with
`mail:profile:write_own` can mutate only a user-scoped profile whose scope id is
their current tenant membership id; `mail:secret:manage_own` applies the same
ownership check to credentials. Neither scope permits profile-policy changes or
management of tenant, group, campaign, system, or another user's profiles.
Changing an SMTP/IMAP endpoint while a stored password remains is a secret
operation and requires the matching credential permission. Deactivating a
credential-free profile needs only profile-write authority; if a password will
be scrubbed, credential authority is required and the deletion is audited.
## Development
Install through the core environment:
```bash
cd /mnt/DATA/git/govoplan-core
./.venv/bin/python -m pip install -r requirements-dev.txt
```
Run the WebUI from the core host:
```bash
cd /mnt/DATA/git/govoplan-core/webui
PATH=/home/zemion/.nvm/versions/node/v22.22.3/bin:$PATH /home/zemion/.nvm/versions/node/v22.22.3/bin/npm run dev
```
## Module integration
Backend entry point:
```toml
[project.entry-points."govoplan.modules"]
mail = "govoplan_mail.backend.manifest:get_manifest"
```
Frontend package:
```text
@govoplan/mail-webui
```
The campaign module consumes `mail.campaign_delivery` for authorized runtime
profile resolution, sending, append-to-Sent behavior, profile selection, and
policy checks. Mail does not
import campaign internals; campaign-scoped policy and owner context are resolved
through the core `campaigns.mailPolicyContext` capability when the campaign
module is installed.
Development mailbox routes are registered by the mail module only when the
core runtime is in `dev` mode and `dev_mailbox_api_enabled` is enabled. Core
does not contribute these routes directly.
JMAP is available as an opt-in, read-only mailbox transport after the stable
IMAP baseline. It discovers RFC 8620/8621 capabilities, lists folders,
performs server-side message search and pagination, reads bounded message
bodies and attachment metadata, and exposes bounded incremental Email changes.
IMAP behavior is unchanged, and SMTP remains the send transport. JMAP Session
and advertised API origins are governed independently and credentials stay in
Mail's encrypted envelopes. The explicitly enabled POP3 slice remains limited
to bounded, encrypted, duplicate-safe legacy import. The protocol boundary is
documented in [docs/MAIL_PROTOCOL_ROADMAP.md](docs/MAIL_PROTOCOL_ROADMAP.md).
The same roadmap records the
approved S/MIME-first, OpenPGP-additional message-protection profile and its
no-silent-downgrade requirement.
Platform RBAC and governance rules are documented in `govoplan-core/docs/`.
The [Mail handbook](docs/MAIL_HANDBOOK.md) provides the adaptive user,
governance, technical, security, and operations perspectives.
The [Mail interface pattern inventory](docs/INTERFACE_PATTERN_MIGRATION.md)
records the route, administration, state, accessibility, consequence, and
privacy contracts for the Mail WebUI.
## Release packaging
The repository root includes a `package.json` for git-based WebUI installs. It exports the package `@govoplan/mail-webui` from `webui/src` so release builds can depend on tagged git refs instead of local `file:` paths.