Sieve filters: evaluation of multiple scripts

The various different types of Sieve scripts  are located, loaded, and associated with the appropriate recipient addresses as early as possible:  Source channel scripts and the system Sieve script  (  and  ) are dealt with during  MAIL FROM processing and all others, with the exception of spam filter Sieves, are dealt with during RCPT TO processing. Spam filter Sieves (see the   MTA options)  are determined last: since they are derived from spam filter verdict processing, they can only be determined after message data is available.

Prior to Messaging Server 7.0, the internal linkage of Sieve script to recipients looked something like this:



Note that any given tier of the linkage tree can be omitted. As the arrows indicate, evaluation of Sieve scripts proceeded from the bottom to the top, while interpretation of Sieve script results proceeds from the recipients at the leaves down to the root (source channel Sieve filter).

The prior-to-7.0 organization just described was fine in terms of Sieve script evaluation semantics. However, after it was implemented and various additional Sieve extensions were defined, a number of problems emerged:



 Information flow up the tree from the root (source channel Sieve filter) to the leaves (recipient Sieve filters) wasn&#x27;t possible. This was a nonissue prior to the availability of the " ",  " ",  and " " extensions. But once these extensions entered the picture, it was only logical that the effects of more general scripts would be visible to more specific scripts. For example, a system Sieve that performs some test and decides a message is likely to be spam might want to indicate this fact either by adjusting the spamtest score or by inserting a header. But this doesn&#x27;t accomplish much when more specific scripts cannot see the results of these actions. 

 In some situations, Sieve scripts were loaded but then the recipient addresses they were associated with ended up being dropped from the recipient list. When this happened there was no easy way to remove the scripts from the evaluation list and scripts were evaluated unnecessarily. 

 Since the   test  can examine recipient addresses, any Sieve script that employs such a test is necessarily recipient-specific and must be reevaluated for each recipient. Even worse, since this can change the result of the script, it has a cascade effect forcing all more specific scripts to be reevaluated as well. In order to get these semantics, the linkage tree had to be split and dummy nodes had to be inserted. For example, if the system Sieve script called for the " " extension, the recipient  tree shown above ended up looking like this: 







 All Sieve scripts must list all of the extensions they employ in an initial require clause. However, it is common for an extension to be listed but not actually used - and this is not necessarily a result of poor coding practice. For example, a script might perform a header or address test and depending on the result of that test only then perform an  envelope test, as in the following example where the script is only recipient-specific given certain header values and it is unnecessary to reevaluate it for every recipient. But since the linkage tree has to be constructed prior to script evaluation the presence of the envelope extension in the require clause forces unnecessary reevaluations. 

 require &#x5b;"envelope", "subaddress"&#x5d;; if address :is "from" "user1@example.com" { if envelope :is :detail "to" "whatever" { ... } } 

 Sieve scripts often can be written to take advantage of a given extension if it is available but still function if it is not. The approach of enumerating of all extensions in the " " clause does not allow the construction of such scripts. The " " extension eliminates this restriction by adding a test that succeeds if the requested extension is available and fails if it is not. This would be extremely difficult to implement using the linkage tree approach since the extensions a given Sieve script uses can no longer be determined prior to Sieve script evaluation. 



A new way of linking scripts to users was needed and has been implemented in 7.0. The linkage tree is gone, replaced with a per-recipient array:



This new structure eliminates all of the issues the linkage tree had. Scripts are now evaluated during final recipient address processing, eliminating unnecessary evaluation. Evaluation poceeds down the array, and if a particular script has already been evaluated on behalf of some other recipient the results can easily be checked for recipient specificity and reused if no dependency exists. Even better, information can be passed from more general scripts to more specific ones, and the additional checks for recipient-specific information inheritance are reasonably straightforward. And finally, when reevaluation is required the resulting "split" is much more straightforward.

For example, given the previous set of scripts, a recipient-specific system sieve results in the following augmented data structure:



See also:
 * sourcefilter Option
 * systemfilter MTA Option
 * Sieve filters: types of scripts
 * spamfilter1_action_0 MTA Option
 * Sieve filters: semantics of multiple scripts
 * Sieve editheader extension
 * Sieve spamtest and virustest extensions
 * Sieve envelope extension
 * Sieve hierarchy
 * Sieve filters