Sieve: what RFC 5228 actually defines
A standards-first look at Sieve: the non-Turing-complete scripting language behind most server-side mail filters, and why the limit is by design.
Before a standard filtering language existed, server-side mail filtering, moving a message to a folder, forwarding it, sending an auto-reply, discarding it outright, was whatever configuration format one specific mail server happened to support. A filter script written for one platform's rules engine meant nothing to another. Move mail systems, and you rebuilt every filter from scratch. RFC 5228 closes that gap.
What Sieve defines
RFC 5228 defines Sieve, a small scripting language for server-side mail filtering. Sieve is deliberately not Turing-complete: it has no loops and no mechanism for arbitrary code execution. That restriction keeps a script simple enough to validate safely. A mail server can run a script it didn't write itself without risking the kind of runaway behavior a general-purpose language would allow.
How it works
A Sieve script is a sequence of test-and-action rules. Each rule pairs a condition against the incoming message with an action to run when that condition matches:
if header :contains "subject" "invoice" {fileinto "Invoices";}
The mail server evaluates the script against each incoming message at delivery time and applies whichever action matches. The core actions are fileinto (move the message into a folder), redirect (forward it), discard (drop it silently), reject (bounce it back to the sender), and keep (deliver it to the default location, unchanged).
Anatomy
Core commands:
| Command | What it does |
|---|---|
if / elsif / else | Branches on a test's result |
require | Declares which Sieve extensions the script uses |
fileinto | Moves the message into a specified folder |
redirect | Forwards the message to another address |
discard | Drops the message silently |
keep | Delivers the message to the default location |
stop | Ends script processing for this message |
Common tests:
| Test | What it checks |
|---|---|
header | A header field's value, for example Subject or From |
address | A structured address field, parsed into its component parts |
size | The message's total size |
exists | Whether a given header is present at all |
Worked example
A short script that files invoices into their own folder and forwards anything from one specific sender:
require ["fileinto"];if header :contains "subject" "invoice" {fileinto "Invoices";}if address :is "from" "billing@example.com" {redirect "finance@example.com";}
The require line at the top declares that the script depends on the fileinto extension. A conforming implementation refuses to run a script that uses a command it hasn't declared. The first rule catches any message with "invoice" in the subject and files it into an Invoices folder. The second matches messages from one exact address and forwards them to a shared finance inbox. Anything that matches neither rule falls through and gets delivered normally.
What Sieve doesn't do
Sieve leaves out loops and arbitrary code execution on purpose. A filtering language that ran unrestricted code against every arriving message would be a real risk: an infinite loop, a runaway test, a script doing something the mail server never intended to allow. Sieve's restricted grammar bounds a script's behavior before it ever executes, so the server can run it directly with no sandbox required.
RFC 5228 defines the language itself, not how a script gets onto the server in the first place. Uploading or editing a script over the network is a separate standard, ManageSieve (RFC 5804), and it isn't covered on this page.
Check it yourself
Check whether your mail provider exposes Sieve filtering directly. A few do, through a raw script editor tucked into account settings. Most others build their "filters" or "rules" page on top of Sieve without ever naming it: every rule you click together in that interface compiles down to a Sieve if block the server runs at delivery time.
Where Sieve fits
A Sieve header test inspects the same fields the message format guide defines the syntax for, Subject, From, or any other named header. Read that page first if you need the underlying header structure a Sieve rule operates on.
Sieve's discard and reject actions raise a related question: what happens when a recipient marks a message as unwanted. ARF covers the structured report format used for that. For the wider set of standards this cluster covers, see the reference hub.
FAQ
Can a Sieve script run an infinite loop?
No. Sieve has no loop constructs at all, by design. That's what makes it safe to run untrusted, user-written scripts directly on a mail server.
Does Sieve let me manage scripts remotely?
Not by itself. RFC 5228 defines the language only. Uploading and editing scripts over the network is covered by a separate standard, ManageSieve, RFC 5804.
What actions can a Sieve rule take?
Common actions include filing a message into a specific folder, redirecting it elsewhere, discarding it silently, rejecting it outright, or explicitly keeping it in the default location.
Is Sieve something end users write directly?
Rarely by hand. Most mail providers generate Sieve scripts behind a graphical filter or rules interface, even though the underlying language is what runs server-side.
RFC reference
RFCs covered: RFC 5228. Superseded / updated by: None for the base language. Many later RFCs extend it with additional tests and actions, not covered on this page.