Sieve is a standardized email filtering language (RFC 5228) that runs on the mail server, processing messages before they reach the user's inbox. Unlike client-side rules that only work when the email client is open, Sieve filters run 24/7 on the server, handling sorting, forwarding, vacation replies, and spam management automatically. This guide covers Sieve with Dovecot's ManageSieve implementation.
Enabling Sieve in Dovecot
# Install the Sieve plugin
sudo apt install dovecot-sieve dovecot-managesieved # Ubuntu
sudo dnf install dovecot-pigeonhole # Rocky Linux
# Enable Sieve in Dovecot
# /etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
# /etc/dovecot/conf.d/20-managesieve.conf
protocols = $protocols sieve
service managesieve-login {
inet_listener sieve {
port = 4190
}
}
# /etc/dovecot/conf.d/90-sieve.conf
plugin {
sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_before = /etc/dovecot/sieve-before.d/
sieve_after = /etc/dovecot/sieve-after.d/
sieve_extensions = +editheader +vacation +imapflags +notify +duplicate
sieve_max_script_size = 1M
}
sudo systemctl restart dovecot
Sieve Script Basics
# Basic Sieve script structure
require ["fileinto", "reject", "vacation", "imap4flags"];
# Rule: Move newsletters to a folder
if header :contains "List-Unsubscribe" "" {
fileinto "Newsletters";
stop;
}
# Rule: Flag messages from boss as important
if address :is "from" "boss@company.com" {
addflag "\Flagged";
keep;
stop;
}
# Rule: Reject messages with specific subject
if header :contains "subject" "You have won" {
reject "This message was rejected by a server-side filter.";
stop;
}
# Default: keep in inbox
keep;
Common Sieve Recipes
Sort by Sender Domain
require ["fileinto", "envelope"];
# Sort client emails into per-domain folders
if address :domain "from" "clienta.com" {
fileinto "Clients.ClientA";
stop;
}
if address :domain "from" "clientb.com" {
fileinto "Clients.ClientB";
stop;
}
Vacation Auto-Reply
require ["vacation"];
vacation
:days 1
:subject "Out of Office"
:from "user@example.com"
:addresses ["user@example.com", "u.ser@example.com"]
"Thank you for your email. I am currently out of the office and will return on January 20, 2025.
For urgent matters, please contact backup@example.com.
Best regards,
User Name";
Spam Handling
require ["fileinto", "imap4flags"];
# Move spam (based on Rspamd/SpamAssassin headers)
if header :contains "X-Spam-Flag" "YES" {
fileinto "Junk";
stop;
}
# Additional spam score check
if header :value "gt" :comparator "i;ascii-numeric" "X-Spam-Score" "8" {
discard; # Silently discard high-score spam
stop;
}
# Medium-score spam to Junk folder
if header :value "gt" :comparator "i;ascii-numeric" "X-Spam-Score" "5" {
fileinto "Junk";
stop;
}
Forward with Copy
require ["copy"];
# Forward all mail to another address while keeping a copy
redirect :copy "backup@otherdomain.com";
# Conditional forwarding
if address :is "to" "sales@example.com" {
redirect :copy "crm-import@company.com";
}
Duplicate Detection
require ["duplicate", "fileinto"];
# Detect and file duplicate messages
if duplicate {
fileinto "Duplicates";
stop;
}
Large Attachment Notification
require ["fileinto", "imap4flags"];
# Flag messages over 10MB
if size :over 10M {
addflag "\Flagged";
fileinto "Large Attachments";
stop;
}
Global (Server-Wide) Sieve Scripts
# /etc/dovecot/sieve-before.d/spam.sieve
# Runs BEFORE user scripts — ideal for spam filtering
require ["fileinto"];
if header :contains "X-Spam-Flag" "YES" {
fileinto "Junk";
stop;
}
# Compile global scripts
sudo sievec /etc/dovecot/sieve-before.d/spam.sieve
ManageSieve Clients
Users can manage their Sieve scripts through:
- Roundcube — built-in Sieve plugin (Filters section in Settings)
- Thunderbird — Sieve extension (add-on)
- sieve-connect — command-line ManageSieve client
# Using sieve-connect
sudo apt install sieve-connect
# Upload a script
sieve-connect --server mail.example.com --user user@example.com \
--remotename myscript --upload myscript.sieve
# Activate a script
sieve-connect --server mail.example.com --user user@example.com \
--activate --remotename myscript
# List scripts
sieve-connect --server mail.example.com --user user@example.com --list
Testing Sieve Scripts
# Compile and check for errors
sievec /path/to/script.sieve
# Test with a sample email
sieve-test -t - /path/to/script.sieve /path/to/sample.eml
# Debug with trace output
sieve-test -t /tmp/sieve-trace.log /path/to/script.sieve /path/to/sample.eml
Best Practices
- Always end scripts with
keep;as a safety net to prevent accidental email loss - Use
stop;after each rule to prevent multiple rules from matching - Use server-wide scripts (
sieve_before) for spam filtering that applies to all users - Test scripts with
sieve-testbefore deploying to production - Use
fileintooverdiscardfor safety — review discarded messages before switching - Keep vacation auto-replies rate-limited with the
:daysparameter to avoid loops - Compile global scripts with
sievecfor faster execution