> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oximail.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# Filtrage : règles & Sieve

> Les deux couches de filtrage côté serveur : les règles structurées gérées en JMAP, et les scripts Sieve (RFC 5228) avec accès ManageSieve. Les deux s'appliquent à la remise finale, y compris pour le courrier local.

OxiMail filtre le courrier côté serveur à travers deux couches complémentaires :

* **Les règles** : des objets de filtre structurés (conditions vers actions) gérés en JMAP. C'est ce qu'édite un écran de réglages du webmail : pas de syntaxe de script, introspectable, ordonnable.
* **Les scripts Sieve** : le langage de filtrage standard ([RFC 5228](https://www.rfc-editor.org/rfc/rfc5228)), pour les utilisateurs avancés et pour les clients qui parlent ManageSieve. Un script peut exprimer ce que la forme structurée ne peut pas.

Les deux s'exécutent **à la remise finale**, là où la RFC 5228 §1.1 les place. Cela inclut le courrier qu'un collègue vous envoie depuis le même serveur : le raccourci de remise locale applique les règles du destinataire et sa réponse d'absence exactement comme pour un message reçu de l'extérieur (voir [la couche SMTP](../architecture/oximail-smtp) et l'ADR-117).

## Les règles

Une règle associe des conditions (expéditeur, destinataire, sujet, en-têtes...) à des actions (classer dans un dossier, marquer, transférer...). Deux propriétés comptent en exploitation :

* **Un ordre total et déterministe.** Les règles s'évaluent dans un ordre défini, sans égalité possible : le même message prend toujours le même chemin. L'ordre fait partie des données, pas d'un accident de stockage.
* **Application au courrier existant.** `Rule/apply` exécute une règle sur les messages existants d'un dossier, **du plus récent au plus ancien**, par lots bornés : la réponse porte `totalInFolder`, `truncated` et `nextPosition`, pour qu'un client continue explicitement au lieu de croire un plafond silencieux (chaque message évalué est une lecture de blob plus un déchiffrement : une application sans borne serait un déni de service auto-infligé). `dryRun: true` évalue et compte sans rien modifier, et les arguments inconnus sont rejetés en `invalidArguments` plutôt qu'ignorés : sur une méthode qui modifie en masse, un `dryRun` avalé en silence n'est pas acceptable.

## Les scripts Sieve

### En JMAP (RFC 9661)

Les scripts Sieve se gèrent avec les méthodes JMAP `SieveScript` de la [RFC 9661](https://www.rfc-editor.org/rfc/rfc9661). Le contenu du script voyage comme un **blob** : on téléverse le script, on le référence par `blobId` à la création ou à la mise à jour, et on le relit de la même façon (§2.1/2.2 : l'aller-retour renvoie les octets stockés à l'identique). La validation est une étape distincte de l'activation, et détruire le script actuellement **actif** est refusé avec `scriptIsActive` : désactivez d'abord, détruisez ensuite.

### Extensions prises en charge

L'interpréteur prend en charge, et la ligne de capacité ManageSieve annonce, exactement cet ensemble (l'annonce est construite depuis la liste du compilateur lui-même, les deux ne peuvent donc pas diverger) :

```text theme={null}
body  envelope  fileinto  imap4flags  reject  relational  vacation  variables
```

Un `require` de quoi que ce soit d'autre échoue bruyamment à la compilation. À noter : un test Sieve `header` avec plusieurs noms d'en-têtes (`["From", "Sender"]`) reconnaît chacun d'eux. La liste n'est jamais tronquée à son premier élément.

### Le script global

`[sieve] global_script` désigne un script optionnel à l'échelle du serveur, exécuté **avant** le script de chaque utilisateur. Si le script global se termine par une action terminale (`redirect`, `discard`, `reject` avec `stop`), le script de l'utilisateur est sauté. Utilisez-le pour une politique d'organisation que les utilisateurs ne doivent pas pouvoir contourner.

```toml theme={null}
[sieve]
global_script = "/etc/oximail/global.sieve"
```

Les scripts compilés sont rechargés à chaud par échange atomique de pointeur : modifier un script n'exige jamais de redémarrage et ne bloque jamais les remises en cours.

## ManageSieve (RFC 5804)

Les clients qui gèrent les scripts Sieve nativement (le module Sieve de Thunderbird, `sieve-connect`) parlent la [RFC 5804](https://www.rfc-editor.org/rfc/rfc5804). L'écouteur se lie par défaut à `127.0.0.1:4190`, **en local seulement**, parce que ManageSieve est antérieur aux conventions TLS modernes. Pour l'exposer, terminez le TLS devant (stunnel, `stream` nginx) et activez le protocole PROXY pour que le serveur voie encore la vraie adresse du client :

```toml theme={null}
[legacy]
managesieve_proxy_protocol = true   # l'écouteur attend un en-tête HAProxy PROXY v1
```

Sans l'en-tête PROXY, chaque connexion ressemblerait à la boucle locale (généralement de confiance) et les échecs de connexion ne pourraient pas alimenter fail2ban. L'authentification prend en charge SASL `PLAIN` et `LOGIN` (y compris la variante en plusieurs étapes), et les tentatives échouées comptent dans la même [mécanique fail2ban](./operations) que tous les autres protocoles. `GETSCRIPT` renvoie les octets originaux archivés du script, pas une resérialisation.

## La réponse automatique d'absence

La réponse d'absence est exposée deux fois, comme objet JMAP `VacationResponse` et comme extension Sieve `vacation`, au-dessus d'un seul mécanisme avec déduplication des réponses (une réponse automatique par correspondant et par période). Deux comportements à connaître :

* Les réponses d'absence sont **supprimées pour un compte désactivé** : le courrier est toujours remis, mais une identité désactivée ne parle pas.
* Une réponse d'absence est générée à la remise finale, donc elle répond aussi aux expéditeurs locaux.

## Où regarder quand un filtre se comporte mal

* Les verbes CLI `oximail sieve ...` et `oximail rule ...` inspectent et gèrent les deux couches par compte : voir la [référence CLI](./cli).
* Les décisions de remise sont journalisées avec le compte et le contexte de règle ou de script : voir [Exploitation](./operations) pour le travail avec journald.
* Une règle qui semble ignorer le courrier envoyé par un collègue du même serveur aurait relevé de la lacune d'avant #693 ; depuis, la remise locale exécute la politique du destinataire. Si vous l'observez, c'est un bug, pas une subtilité de configuration.
