Docs / Email Servers / Server-Side Email Rules with Sieve Filters

Server-Side Email Rules with Sieve Filters

By Admin · Mar 15, 2026 · Updated Apr 23, 2026 · 218 views · 4 min read

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-test before deploying to production
  • Use fileinto over discard for safety — review discarded messages before switching
  • Keep vacation auto-replies rate-limited with the :days parameter to avoid loops
  • Compile global scripts with sievec for faster execution

Was this article helpful?