feat(mail): add governed POP3 legacy import
Module Package Release / publish-packages (push) Successful in 11s
Module Package Release / publish-packages (push) Successful in 11s
This commit is contained in:
+75
-17
@@ -23,12 +23,13 @@ See also [Mail protocol roadmap](MAIL_PROTOCOL_ROADMAP.md) and the Campaign
|
||||
|
||||
Mail owns:
|
||||
|
||||
- reusable SMTP/IMAP profile definitions and scope;
|
||||
- encrypted SMTP/IMAP credentials and safe credential replacement;
|
||||
- reusable SMTP/IMAP profile definitions, dedicated legacy POP3 sources, and scope;
|
||||
- encrypted SMTP/IMAP/POP3 credentials and safe credential replacement;
|
||||
- effective profile policy and visibility/authorization decisions;
|
||||
- connection tests and protocol adapters;
|
||||
- SMTP send and IMAP append operations exposed to consumers;
|
||||
- read-only mailbox folder/message access and its bounded indexes; and
|
||||
- read-only mailbox folder/message access, bounded indexes, and encrypted
|
||||
pending-review records imported from legacy POP3 sources; and
|
||||
- the transport sanitization boundary and throttling behavior. A general
|
||||
Mail-owned provider-attempt/diagnostic ledger remains planned.
|
||||
|
||||
@@ -65,6 +66,10 @@ profile test and Ops health surfaces. If the receipt says SMTP is unavailable,
|
||||
is invalid, or is not mounted, import is blocked with an operator-facing
|
||||
resolution instead of creating a partial profile.
|
||||
|
||||
Configuration packages remain SMTP-focused. A POP3 legacy source is a deliberate
|
||||
operational migration action and is not silently exported, cloned, or enabled by
|
||||
an SMTP profile package.
|
||||
|
||||
## Interface patterns and unavailable actions
|
||||
|
||||
Mail uses the platform's shared explorer, connection tree, adaptive form,
|
||||
@@ -89,9 +94,10 @@ deactivating a profile may scrub Mail-owned credentials as described below.
|
||||
### Profile
|
||||
|
||||
A profile is a reusable, named delivery identity with optional SMTP and IMAP
|
||||
configuration. It has a stable id, lifecycle state, scope, owner context, and
|
||||
non-secret connection metadata. Passwords are write-only encrypted values and
|
||||
are never returned through list/read/capability responses.
|
||||
configuration. It can additionally own a dedicated POP3 endpoint for an
|
||||
explicit legacy-import workflow. It has a stable id, lifecycle state, scope,
|
||||
owner context, and non-secret connection metadata. Passwords are write-only
|
||||
encrypted values and are never returned through list/read/capability responses.
|
||||
|
||||
An IMAP server may map the standard Inbox, Sent, Drafts, Trash, Archive, and
|
||||
Junk roles to exact provider folder names. These mappings belong to the reusable
|
||||
@@ -128,6 +134,11 @@ authorization. Mail re-evaluates profile activity, visibility, policy, and
|
||||
revision immediately before it resolves credentials and performs the
|
||||
effect.
|
||||
|
||||
POP3 imports pin the endpoint/credential transport revision at preview time. A
|
||||
changed revision or a missing provider UIDL stops import and requires a fresh
|
||||
preview. POP3 does not participate in the ordinary mailbox folder/message
|
||||
projection.
|
||||
|
||||
### Provider outcomes
|
||||
|
||||
SMTP acceptance, partial or complete recipient refusal, temporary/permanent
|
||||
@@ -202,6 +213,46 @@ not mutate read/unread, delete, move, or reply state. Message responses are
|
||||
bounded by the deployment response policy; ordinary UI should avoid loading a
|
||||
whole large mailbox or attachment merely to show a list.
|
||||
|
||||
### Import a legacy POP3 mailbox
|
||||
|
||||
POP3 is available only for bounded migration from a legacy server that cannot
|
||||
provide IMAP or JMAP. It is disabled by default and is not a replacement for
|
||||
the read-only mailbox UI.
|
||||
|
||||
1. An actor with profile-write, secret-management, and `mail:pop3:manage`
|
||||
authority opens **Legacy POP3 import**, selects a Mail profile, and creates a
|
||||
dedicated source. The UI stages the endpoint disabled, stores its encrypted
|
||||
username/password credential, and enables it only after both operations
|
||||
succeed.
|
||||
2. The administrator explicitly enables legacy import, sets TLS mode, timeout,
|
||||
maximum message and batch sizes, and preview body lines, and tests connection,
|
||||
authentication, TLS, and provider message count. Plain transport remains
|
||||
subject to deployment egress/security policy and should not be used across
|
||||
an untrusted network.
|
||||
3. An operator with `mail:profile:use` and `mail:pop3:import` refreshes a live
|
||||
preview of at most 100 messages. Preview sends no `DELE`, changes no flags,
|
||||
and exposes only bounded headers/body text. A server without stable UIDL
|
||||
identifiers is rejected. If `TOP` is unavailable, Mail uses `RETR` only
|
||||
inside the configured size bound and suppresses an oversized preview.
|
||||
4. The operator selects messages. Mail downloads within the size gate and
|
||||
creates encrypted local `pending_review` records. Tenant, profile, endpoint,
|
||||
and UIDL form the duplicate boundary. Raw content never appears in list,
|
||||
provider-state, audit, or DSAR output.
|
||||
5. Source messages remain untouched by default. Delete-after-import requires
|
||||
the endpoint's separate `allow_delete_after_import` policy, the operator's
|
||||
`mail:pop3:delete` permission, an explicit per-batch choice, and destructive
|
||||
confirmation. Mail commits the local import plus `mail.pop3.imported` audit
|
||||
evidence before sending `DELE`. It separately records
|
||||
`mail.pop3.source_deletion`; disconnect during `QUIT` is outcome-unknown and
|
||||
must be reconciled before another destructive attempt.
|
||||
|
||||
The supplied **Mail legacy import operator** role can test, preview, and import
|
||||
without deleting. The **Mail profile administrator** role also contains source
|
||||
management and destructive-delete permissions; deployments should remove or
|
||||
split `mail:pop3:delete` when operators must never delete provider messages.
|
||||
Imported records follow configured Mail/records retention and require manual
|
||||
review for a data-subject request or deletion decision.
|
||||
|
||||
## Profile administration
|
||||
|
||||
### Roles
|
||||
@@ -214,11 +265,16 @@ The supplied templates are:
|
||||
and manage credentials only for the current account's own user-scoped
|
||||
profiles, subject to the effective Mail policy.
|
||||
- **Mail profile administrator:** additionally create/update profiles and
|
||||
create/replace encrypted credentials across tenant-owned scopes.
|
||||
create/replace encrypted credentials across tenant-owned scopes, configure
|
||||
legacy POP3 imports, and—unless the template is narrowed—request source
|
||||
deletion after import.
|
||||
- **Mail legacy import operator:** test approved POP3 sources and preview/import
|
||||
messages without permission to delete them at the provider.
|
||||
|
||||
The specific permissions are `mail:profile:read`, `mail:profile:use`,
|
||||
`mail:profile:test`, `mail:mailbox:read`, `mail:profile:write_own`,
|
||||
`mail:secret:manage_own`, `mail:profile:write`, and `mail:secret:manage`.
|
||||
`mail:secret:manage_own`, `mail:profile:write`, `mail:secret:manage`,
|
||||
`mail:pop3:manage`, `mail:pop3:import`, and `mail:pop3:delete`.
|
||||
The `_own` permissions are enforced against the authenticated membership id and
|
||||
never authorize a tenant, group, campaign, system, or another user's profile.
|
||||
They also do not authorize profile-policy changes. System-scoped definitions
|
||||
@@ -305,10 +361,10 @@ tenant posture; it does not expose credential material.
|
||||
|
||||
Private-network connector access is controlled deployment-wide by
|
||||
`GOVOPLAN_CONNECTOR_ALLOW_PRIVATE_NETWORKS`. Whether private or public targets
|
||||
are allowed, SMTP and IMAP resolve, validate, and connect to the exact approved
|
||||
address records at connection time while retaining the original hostname for
|
||||
TLS SNI and certificate verification. A DNS change cannot redirect the socket
|
||||
after validation.
|
||||
are allowed, SMTP, IMAP, and legacy POP3 resolve, validate, and connect to the
|
||||
exact approved address records at connection time while retaining the original
|
||||
hostname for TLS SNI and certificate verification. A DNS change cannot redirect
|
||||
the socket after validation.
|
||||
|
||||
Transports that cannot pin every connection peer or revalidate protocol-managed
|
||||
redirects/referrals must fail before client construction. Do not weaken this
|
||||
@@ -383,10 +439,11 @@ state transition or outbound synchronization effect.
|
||||
|
||||
### Backup, restore, and retirement
|
||||
|
||||
Backups contain encrypted credentials and therefore need the same protection as
|
||||
the live database and key material. Restoring a Mail database without the
|
||||
matching encryption key makes credentials unusable; restoring it with keys can
|
||||
reactivate sensitive historical state and must be controlled.
|
||||
Backups contain encrypted credentials and encrypted raw POP3 import records and
|
||||
therefore need the same protection as the live database and key material.
|
||||
Restoring a Mail database without the matching encryption key makes those
|
||||
records unusable; restoring it with keys can reactivate sensitive historical
|
||||
state and must be controlled.
|
||||
|
||||
Destructive module retirement first applies the same immediate credential
|
||||
scrub/audit rule to every remaining profile, then drops Mail-owned tables after
|
||||
@@ -495,7 +552,8 @@ Before claiming a Mail composition is production-ready:
|
||||
Campaign business-action contract built on Mail transport operations.
|
||||
- JMAP mailbox synchronization/search; it is preferred only after the IMAP MVP
|
||||
is stable.
|
||||
- POP3 except for a future explicit legacy download/import requirement.
|
||||
- Expanding POP3 beyond the implemented explicit legacy download/import
|
||||
workflow; it has no folder, flag, search, or synchronization contract.
|
||||
- A full mail client with compose/reply/move/delete/read-state mutation.
|
||||
- Quick Access may launch the operating environment's configured composer via
|
||||
`mailto:`. That explicit handoff is not a GovOPlaN Mail delivery: it selects
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
# Mail Protocol Roadmap
|
||||
|
||||
GovOPlaN Mail currently focuses on SMTP sending and IMAP mailbox access. POP3
|
||||
and JMAP are deferred until the IMAP mailbox MVP is stable.
|
||||
GovOPlaN Mail focuses on SMTP sending and IMAP mailbox access. It also provides
|
||||
an explicitly enabled, bounded POP3 legacy-import path. JMAP remains deferred
|
||||
until the IMAP mailbox MVP and protocol-neutral mailbox contract are stable.
|
||||
|
||||
## Current Baseline
|
||||
|
||||
- SMTP is the send protocol.
|
||||
- IMAP is the read/append protocol.
|
||||
- POP3 is an optional legacy migration source, never a general mailbox
|
||||
protocol or default profile endpoint.
|
||||
- Mail profile policy, encrypted credentials, mailbox folder parsing, test
|
||||
buttons, and read-only mailbox UI are built around SMTP and IMAP.
|
||||
|
||||
@@ -56,17 +59,30 @@ JMAP should be added only after:
|
||||
|
||||
## POP3
|
||||
|
||||
POP3 should remain legacy-only.
|
||||
POP3 remains legacy-only. The bounded import slice is available when a concrete
|
||||
deployment must retire a mailbox that cannot offer IMAP or JMAP.
|
||||
|
||||
Add it only when a concrete deployment requires mailbox download from a server
|
||||
that cannot offer IMAP or JMAP. POP3 is a poor fit for the normal GovOPlaN
|
||||
mailbox UX because it has limited folder, sync, and server-side state semantics.
|
||||
It is disabled until an administrator creates a dedicated POP3 endpoint and
|
||||
sets `legacy_import_enabled`. The endpoint has its own encrypted credential,
|
||||
connection/TLS/authentication diagnostics, maximum message and batch sizes, preview body
|
||||
limit, and a separate `allow_delete_after_import` policy. Stable UIDL support is
|
||||
mandatory; Mail refuses import when a provider cannot supply it.
|
||||
|
||||
If implemented, POP3 should be scoped to explicit download/import workflows, not
|
||||
general mailbox browsing.
|
||||
Preview and ordinary import are non-destructive. Selected messages become
|
||||
encrypted `pending_review` records with a content digest, pinned transport
|
||||
revision, source UIDL, and audit evidence. Repeating a UIDL reports a duplicate.
|
||||
Provider deletion requires both endpoint policy and `mail:pop3:delete`, is
|
||||
chosen separately per batch, and runs only after the local import and its audit
|
||||
event commit. A disconnect while POP3 `QUIT` commits deletions becomes
|
||||
`outcome_unknown` and is never retried blindly.
|
||||
|
||||
POP3 does not supply folder, flag, thread, search, or synchronization semantics.
|
||||
It is therefore excluded from the normal mailbox UI and from the recommended
|
||||
ongoing Mail profile. Configuration-package export/import remains SMTP-focused;
|
||||
legacy source rollout is an explicit operational action.
|
||||
|
||||
## Decision
|
||||
|
||||
Do not add POP3 or JMAP now. Stabilize SMTP/IMAP first, design protocol-neutral
|
||||
mailbox DTOs, then prefer JMAP for modern servers and reserve POP3 for explicit
|
||||
legacy download requirements.
|
||||
Keep the implemented POP3 surface limited to governed legacy import. Do not
|
||||
expand it into mailbox browsing. Design protocol-neutral mailbox DTOs and
|
||||
prefer JMAP for future modern synchronization/search support.
|
||||
|
||||
Reference in New Issue
Block a user