Examples
This section collects example Sieve scripts that can serve as a starting point for custom rules. Each example is stored as a SieveSystemScript record (found in the WebUI under Settings › Sieve › System Scripts), with the script source in its contents field, and invoked from the relevant SMTP stage by setting the stage’s script expression to the script’s name.
Greylisting
Section titled “Greylisting”The following script implements a greylisting filter backed by an SQL store. Install it as a system script named greylist and reference it from the script field on the MtaStageRcpt singleton (found in the WebUI under Settings › MTA › Session › RCPT TO Stage) so that it runs at the RCPT TO stage.
require ["variables", "vnd.stalwart.expressions", "envelope", "reject"];
set "triplet" "${env.remote_ip}.${envelope.from}.${envelope.to}";
if eval "!query('sql', 'SELECT 1 FROM greylist WHERE addr = ? LIMIT 1', [triplet])" { eval "query('sql', 'INSERT INTO greylist (addr) VALUES (?)', [triplet])"; reject "422 4.2.2 Greylisted, please try again in a few moments.";}The first argument of query names the SQL store that holds the greylist table, sql in the script above; passing the empty string selects the default data store. The ? placeholders in the queries use SQLite or MySQL syntax; on PostgreSQL use $1, $2, … instead, since the query is passed to the database driver verbatim.
The script field on MtaStageRcpt then selects the script by name:
{ "script": {"else": "'greylist'"}}Domain blocklisting
Section titled “Domain blocklisting”The following script rejects messages whose HELO/EHLO domain is found in an SQL-backed list. Install it as a system script named is-blocked and reference it from the script field on the MtaStageEhlo singleton (found in the WebUI under Settings › MTA › Session › EHLO Stage).
require ["variables", "extlists", "reject"];
if string :list "${env.helo_domain}" "sql/blocked-domains" { reject "551 5.1.1 Your domain '${env.helo_domain}' has been blocklisted.";}The referenced sql/blocked-domains list is defined as a StoreLookup against the SQL store, using the query SELECT 1 FROM blocked_domains WHERE domain=? LIMIT 1 (on PostgreSQL the placeholder would be $1 instead of ?).
The script field on MtaStageEhlo then selects the script:
{ "script": {"else": "'is-blocked'"}}Message modification
Section titled “Message modification”The following script modifies the incoming message, replacing the contents of each HTML MIME part with its uppercase form and adding a custom header to every part. Install it as a system script named modify-message and reference it from the script field on the MtaStageData singleton (found in the WebUI under Settings › MTA › Session › DATA Stage).
require ["envelope", "variables", "replace", "mime", "foreverypart", "editheader", "extracttext"];
if envelope :domain :is "to" "example.net" { set "counter" "a"; foreverypart { if header :mime :contenttype "content-type" "text/html" { extracttext :upper "text_content"; replace "${text_content}"; } set :length "part_num" "${counter}"; addheader :last "X-Part-Number" "${part_num}"; set "counter" "${counter}a"; }}The script field on MtaStageData then selects the script:
{ "script": {"else": "'modify-message'"}}