Manual pages

shardpostctl-sieve(1)

Manage Sieve scripts and test them without side effects.

SHARDPOSTCTL-SIEVE(1) ShardPost Manual SHARDPOSTCTL-SIEVE(1)

NAME

shardpostctl-sieve - manage Sieve scripts and test them without side effects

SYNOPSIS

shardpostctl sieve list [--json] account
shardpostctl sieve show [--json] account name
shardpostctl sieve put [-activate] [-create] [-if-match etag] [-file path] account name
shardpostctl sieve delete [-if-match etag] account name
shardpostctl sieve activate account name
shardpostctl sieve deactivate account
shardpostctl sieve check [-name name] [-file path] [-message mailbox:uidvalidity:uid] [-from address] [-to address] [--json] account

DESCRIPTION

The account's Sieve scripts, the same ones ManageSieve serves. Exactly one script can be active; it is the one that runs on delivery.

The script jmap-vacation belongs to the server: it is a copy of the account's JMAP VacationResponse, written whenever a JMAP client changes that setting, so that the setting can be seen. Delivery does not read it; it answers from the setting itself, after the active script, when the active script sent no vacation reply of its own. The script is listed, can be shown and checked, and is never the active script; put, delete and activate refuse it.

sieve list

Every script with its size, its version (ETag) and a marker on the active one. Names and sizes only, no content, so the role diagnose is enough.

sieve show

The script text, with its ETag. Reads content, so it needs the role content.

sieve put

Stores a script from -file or standard input. The server compiles it first, with the account's own includes; a script that does not compile is refused and nothing is stored. -activate makes it the active script in the same step. -create stores it only if no script of that name exists yet, and -if-match stores it only if the stored script is still the version you read. Role: support.

sieve delete

Deletes a script. The active script cannot be deleted; deactivate it or activate another one first. Role: support.

sieve activate, sieve deactivate

Selects the active script, or switches filtering off entirely. deactivate takes no script name. Role: support.

sieve check

Compiles a script and, if you give it a message, runs it and reports what it would do.

Nothing is carried out. No mail is redirected, no vacation reply is sent, no notification goes out, no external program runs (an execute or filter test is treated as if the program had exited 0), no duplicate or vacation record is written, and the message is not filed anywhere. Every suppressed side effect is listed under suppressed, so you can see exactly what would have happened in production.

The message is checked the way a delivery sees it: with the Return-Path and Delivered-To fields a delivery adds on top. Without -from the envelope sender is the null sender, so the script sees Return-Path: <>.Avacationreplyisreportedwithits effective period, after the vacation period settings (sieve_vacation_min_period, sieve_vacation_max_period, sieve_vacation_default_period in sieve.settings): in the JSON output as days and seconds, in the text output as "every N days", "every N seconds" or "for every message" (a period of 0).

When the server runs global scripts around the account's own (sieve.before_dir, sieve.after_dir), the check runs the same sequence a delivery runs, with the checked script in the place of the active one, and lists the scripts that ran under scripts. A script that does not keep the message ends the sequence. A global script that fails is skipped, as in a delivery, and is reported as a failed script. An account without an active script can then be checked too, against a stored message: give -message and neither -name nor -file.

Which script is checked: -file or standard input for a script you are working on, -name for a stored one, and with neither, the active script.

Which message it runs on: -message names a stored message as mailbox:uidvalidity:uid, or standard input carries a test message when no script is read from there. -from and -to set the envelope; without -to, the account is the recipient. Without a message the script is only compiled.

Role: content when the script or the message comes from the store, otherwise diagnose.

OPTIONS

-file path
Read the script (or the test message) from this file instead of standard input.
-activate
Activate the script that is being stored.
-create
Refuse to overwrite an existing script.
-if-match etag
Store or delete only if the stored script is still this version (exit code 65 otherwise).
-name name
Check this stored script.
-message mailbox:uidvalidity:uid
Run the check on this stored message.
-from address
-to address
Envelope sender and recipient of the check.
--json
Print the answer as JSON.

EXAMPLES

What does the account filter with, and how does it look?

shardpostctl sieve list user@example.org
shardpostctl sieve show user@example.org main

Install a script from a file and switch it on:

shardpostctl sieve put -activate user@example.org main < main.sieve

Before you change the live script, try the new one against a message the user complains about. Nothing is delivered, forwarded or answered:

shardpostctl sieve check -file new.sieve \

-message INBOX:1789726963:933 user@example.org

"Why did this mail end up in Junk?" Run the active script over it:

shardpostctl sieve check -message INBOX:1789726963:933 user@example.org

Check a script against a message you have as a file, without touching the account's data:

shardpostctl sieve check -file rules.sieve \

-from sender@example.net user@example.org < sample.eml

Replace a script safely, so a parallel change is not lost:

shardpostctl sieve show user@example.org main      # prints the etag
shardpostctl sieve put -if-match '"s-1f0c3a9d2b4e5f60"' \

user@example.org main < main.sieve

Switch filtering off for a while, then back on:

shardpostctl sieve deactivate user@example.org
shardpostctl sieve activate user@example.org main

EXIT STATUS

0
Done; for sieve check the script compiles.
64
The script does not compile (sieve put); nothing was stored, and the message says where the error is.
65
The checked script does not compile (sieve check), the ETag no longer matches, the script is active and cannot be deleted, or the script is jmap-vacation and cannot be changed here.
67
No such account, script or message.
77
The caller lacks the role.

SEE ALSO

shardpostctl(1), shardpostctl-learning(1), shardpostctl-message(1)

IMAPSieve and the learning rules are described in docs/imapsieve.md.

2026-10-01 ShardPost 0.35.2

Rendered from docs/man/man1/shardpostctl-sieve.1 in the ShardPost repository.