Skip to content

Add a CardDAV contacts-aware Sieve test condition (e.g. address :contacts "From") #588

Description

@shaunwarman

Customer-suggested feature (spam triage use case, see support thread 2026-09-09). Request is for a Sieve test condition that checks whether a message's From address matches a saved CardDAV contact for that mailbox, so scripts can tag (not block) mail from non-contacts, e.g. addheader "X-Not-A-Contact" "true", for later review. Explicitly not looking for auto allow/deny, since plenty of legitimate mail (banks, government, retailers) will never be a personal contact.

Confirmed nothing like this exists today: grep -n "contacts" helpers/sieve/*.js -i returns zero matches across engine.js, extensions.js, filter-handler.js, integration.js, validator.js, security.js, managesieve-server.js, parser-generated.js, store.js, script-checker.js. No :contacts match-type, no contact test anywhere in the registered test inventory (engine.js, evaluateTest switch, lines ~637-739).

Feasibility: this is a scoped addition, not a rebuild or third-party fork. The Sieve engine is fully in-house (custom PEG grammar in helpers/sieve/grammar.pegjs, compiled to parser-generated.js, executed by a switch-dispatch interpreter in engine.js), so no vendored Sieve library constraint applies. Contacts are already stored per-alias (app/models/contacts.js, emails[].value field, isolated per-alias via the per-alias SQLite database in helpers/get-database.js), and the alias identity needed to query that alias's contacts is already threaded into the engine's execution context today (filter-handler.js processMessage(aliasId, message, context), populated from session.user.alias_id in helpers/parse-payload.js). The engine also already supports async test evaluation (see DuplicateTest, engine.js:713), so an async contacts lookup fits the existing pattern.

Scope of work: grammar change in grammar.pegjs (+ regenerate parser-generated.js) for a new test/match-type, a new case in engine.js's evaluateTest switch that queries Contacts by the alias's address book and matches against the From header, and updating the supported-capabilities lists (helpers/sieve/index.js, engine.js, filter-handler.js, managesieve-server.js, script-checker.js, validator.js, extensions.js) if exposed as a named extension/capability.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions