feat: ManageSieve (RFC 5804) Sieve script editing for IMAP accounts
Adds a minimal ManageSieve client so the existing "Email filters" UI works for IMAP accounts, not just JMAP. SieveRepository becomes a dispatcher that routes to JMAP or ManageSieve based on account.type. Account model + DB schema v15 grow manageSieveHost/Port/Ssl fields (default 4190 / TLS, host falls back to imapHost when blank). The Add and Edit account screens expose them inside a collapsed ExpansionTile to keep the form short for users who accept defaults. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
44d02afc46
commit
fc270590c4
@@ -6,6 +6,53 @@ Tasks get moved from next.md to done.md
|
||||
|
||||
## Tasks
|
||||
|
||||
## Sieve filter editing for IMAP accounts (ManageSieve)
|
||||
|
||||
The "Email filters" entry was previously hidden for IMAP accounts because
|
||||
`SieveRepository` only spoke JMAP. Added a minimal ManageSieve client
|
||||
(RFC 5804) so IMAP accounts can now list / fetch / upload / activate /
|
||||
delete server-side Sieve scripts.
|
||||
|
||||
New: `lib/data/imap/managesieve_client.dart` — implements CONNECT
|
||||
(implicit TLS or plaintext), AUTHENTICATE PLAIN (SASL), LISTSCRIPTS,
|
||||
GETSCRIPT, PUTSCRIPT, SETACTIVE, DELETESCRIPT, LOGOUT. Handles
|
||||
RFC 5804 quoted-strings and `{N+}` non-synchronizing literals (used for
|
||||
both reading script bodies and uploading them in PUTSCRIPT). The base64
|
||||
SASL PLAIN payload is redacted in the verbose protocol log.
|
||||
|
||||
`SieveRepository` (`lib/data/jmap/sieve_repository.dart`) is now a
|
||||
dispatcher: `account.type == imap` routes through `ManageSieveClient`
|
||||
(connecting per-call and `LOGOUT`-ing in `finally`); `account.type ==
|
||||
jmap` keeps the existing JMAP path unchanged. Public API is unchanged
|
||||
so the existing Sieve script list / edit screens work for both
|
||||
account types. For ManageSieve, where scripts are identified by name,
|
||||
`SieveScript.id` and `SieveScript.blobId` are both set to the script
|
||||
name. Renames are implemented as PUTSCRIPT(new) followed by
|
||||
DELETESCRIPT(old).
|
||||
|
||||
Account model + DB: added `manageSieveHost`, `manageSievePort` (default
|
||||
4190), `manageSieveSsl` (default true) to `Account` and `Accounts`
|
||||
table. Schema bumped to v15 with a forward-only migration that
|
||||
`addColumn`s the three fields. Empty `manageSieveHost` falls back to
|
||||
`imapHost` so the typical setup (Stalwart / Dovecot on the same host)
|
||||
needs no extra configuration.
|
||||
|
||||
UI: removed the `account.type == AccountType.jmap` guard from the
|
||||
"Email filters" entry in both `FolderDrawer` (the per-account drawer)
|
||||
and the popup menu in `AccountListScreen`, so IMAP accounts now see it
|
||||
too. The Add and Edit account screens grew a collapsed `ExpansionTile`
|
||||
labelled "ManageSieve (email filters)" containing host / port / SSL
|
||||
fields — collapsed by default so the form stays the same height for
|
||||
users who accept the defaults (which avoided pushing the Save button
|
||||
off the bottom of the Linux Xvfb 1280x720 viewport in the integration
|
||||
test).
|
||||
|
||||
`scripts/check_coverage.dart` excludes `managesieve_client.dart` from
|
||||
the unit-coverage gate (real-socket network code, like
|
||||
`imap_client_factory.dart`). Updated `add_account_screen_test` to
|
||||
expect 2 visible `SwitchListTile`s on the IMAP form (the third toggle
|
||||
lives inside the collapsed ExpansionTile).
|
||||
|
||||
## Render HTML email bodies
|
||||
|
||||
`lib/ui/screens/email_detail_screen.dart` now renders the message's
|
||||
|
||||
Reference in New Issue
Block a user