Feature: extended filter rules — attachment field + multi-value conditions

Adds an "Attachment" condition field (is present / of type <ext>) backed by
the RFC 5703 Sieve mime extension, matching the filename in both
Content-Disposition and Content-Type headers so real-world senders that only
put the name in Content-Type (Microsoft SMTPSVC, etc.) are caught. Users type
extensions (pdf, doc) not MIME types.

Also makes each text condition accept comma-separated multiple values emitted
as a Sieve string list (OR within the condition), so "(domain1 OR domain2)
AND attachment pdf/xml" is expressible in one rule. value is now string |
string[] (single-value rules stay strings -> backward compatible). New filter
locale keys in all 17 locales.
This commit is contained in:
dealerweb
2026-05-30 15:45:33 +02:00
committed by Linus Rath
parent 229992853b
commit 8353b28b33
22 changed files with 431 additions and 64 deletions
+19 -3
View File
@@ -13,14 +13,21 @@ export interface SieveCapabilities {
externalLists: string[];
}
export type FilterConditionField = 'from' | 'to' | 'cc' | 'subject' | 'header' | 'size' | 'body';
export type FilterConditionField =
| 'from' | 'to' | 'cc' | 'subject' | 'header' | 'size' | 'body'
| 'attachment';
export type FilterComparator =
| 'contains' | 'not_contains'
| 'is' | 'not_is'
| 'starts_with' | 'ends_with'
| 'matches'
| 'greater_than' | 'less_than';
| 'greater_than' | 'less_than'
// For field === 'attachment':
// has_any → message has any attachment (Content-Disposition: attachment)
// has_type → message has an attachment whose Content-Type matches `value`
// (substring match, e.g. "application/pdf" or "image/")
| 'has_any' | 'has_type';
export type FilterActionType =
| 'move' | 'copy' | 'forward'
@@ -30,7 +37,16 @@ export type FilterActionType =
export interface FilterCondition {
field: FilterConditionField;
comparator: FilterComparator;
value: string;
/**
* Match value. Use a string array for OR-within-condition semantics
* (e.g. `["@domain1.com", "@domain2.com"]` matches mail from either).
* Sieve emits the array as a list literal which the implementation
* treats as "matches any item". Use a plain string for single-value
* conditions; existing single-value rules continue to work unchanged.
*
* Not supported for: size (numeric), has_any (no value).
*/
value: string | string[];
headerName?: string;
}