Skip to content

Instantly share code, notes, and snippets.

@Hotrod369
Last active June 18, 2025 15:14
Show Gist options
  • Save Hotrod369/6b7a24e1ea060e48e0c02459cbb950a0 to your computer and use it in GitHub Desktop.
Save Hotrod369/6b7a24e1ea060e48e0c02459cbb950a0 to your computer and use it in GitHub Desktop.
This Gist provides a comprehensive cheatsheet for Sieve scripts, covering various objects, attributes, parameters, and their possible values. Sieve is a powerful scripting language for filtering and organizing emails, commonly used with email clients and servers. This cheatsheet includes tests, actions, comparators, and extensions to help you cr…

Sieve Scripting Cheat Sheet

Table of Contents


Basic Syntax

Require Statement

  • The require statement specifies the extensions your script will use. Always ensure you list all necessary extensions to prevent runtime errors:

    require ["fileinto", "imap4flags", "vacation"];

Tests

Address Test

  • Tests email addresses in headers. Useful attributes include :all, :localpart, :domain, and :comparator. Comparators: i;ascii-casemap, i;unicode-casemap

    if address :all :comparator "i;unicode-casemap" :matches "From" "[email protected]" {
        ...
    }

Header Test

  • Tests header fields with attributes like :is, :contains, and :matches.

    if header :contains "subject" "urgent" {
        ...
    }

Size Test

  • Tests the size of the email using attributes :over or :under

    if size :over 1M {
        ...
    }

Body Test

  • Searches the email body. Available attributes include :contains and :matches.

    if body :contains "keyword" {
        ...
    }

Date Test

  • Tests the date of the email.

  • Attributes: :value, :zone

  • Some implementations use currentdate for dynamic checks:

    if currentdate :value "ge" "date" "2025-02-21" {
        ...
    }
  • Other implementations may require the date test directly on a header (typically "Date"). Be sure to check the required date format and timezone handling:

    if date :value "ge" "2025-02-21" {
        ...
    }

Logical Operators: allof and anyof

  • Combine multiple tests to form more complex conditions:

    if allof (
        header :contains "subject" "urgent",
        size :over 1M
    ) {
        discard;
    }
  • Or to match any of several conditions:

    if anyof (
        header :contains "subject" "alert",
        header :contains "subject" "warning"
    ) {
        fileinto "Alerts";
    }

Envelope Test

  • Filters based on the SMTP envelope rather than header fields. This is useful when you want to filter by the actual sender:

    if envelope :is "from" "[email protected]" {
        fileinto "Important";
    }

Actions

Fileinto, Keep, and Discard

  • These actions determine how the message is processed:

    • fileinto: Files the email into a specified folder.

      fileinto "Inbox";
    • keep: Keeps the email in the inbox.

      keep;
    • discard: Silently discards the email.

      discard;

Redirect, Reject, and Vacation

  • Manage email redirection and automated responses:

    • redirect: Sends the email to another address.

      redirect "[email protected]";
    • reject: Rejects the email with a specified message.

      reject "Your email was rejected.";
    • vacation: Sends an auto-reply. Attributes: :days, :subject

      vacation :days 1 :subject "Out of Office" text:
      "Thank you for your email. I am currently out of the office and will get back to you shortly."
      ;

Flag Actions: addflag, setflag, and removeflag

  • Manage email flags for further processing or visual cues:

    addflag "\\Flag";
    setflag "\\Flag";
    removeflag "\\Flag";

Comparators

  • i;ascii-casemap: Case-insensitive ASCII comparison.
  • i;unicode-casemap: Case-insensitive Unicode comparison.
  • i;octet: Byte-by-byte comparison.

Extensions

Include

  • Allows you to include another Sieve script, which is useful for modularizing your filtering rules.

    include :personal "other-script";

Environment

  • Tests environment variables, useful in some server-specific implementations.

    if environment :matches "vnd.proton.spam-threshold" "*" {
        ...
    }

Forwarding Mail

  • The Sieve redirect command is used to forward incoming mail to another email address. Depending on your needs, you can forward the mail and either remove it from the original mailbox or keep a copy.

Forwarding with Copy Preservation

  • If you want to forward a copy of the email while leaving the original message in your mailbox, you need to enable the copy extension. This requires including it with the require statement, then using the :copy option with redirect:

    require ["copy"];
    
    redirect :copy "[email protected]";

In this example, the :copy option tells the mail server to send a copy of the message to the specified address without removing it from your mailbox.

Standard Forwarding

  • If you simply want to forward the email without explicitly preserving a copy (which might result in the original being removed from your mailbox, depending on your server’s configuration), you can use the basic form of the redirect command:

    redirect "[email protected]";

Additional Considerations

  • Testing: Always test your Sieve script in your specific environment. Some servers may have subtle differences in how forwarding is handled.
  • Mail Loops: Be cautious of potential mail loops when forwarding messages. Ensure that the forwarded address is correctly configured to avoid continuous redirection.
  • Privacy: Forwarding mail can inadvertently expose sensitive information. Make sure that forwarding aligns with your privacy and security policies.

Variables and Script Flow

  • The variables extension allows you to assign and reuse values within your script. This can simplify complex conditions.

    set "sender" "[email protected]";
    if anyof (
        address :all "From" "${sender}",
        envelope :is "from" "${sender}"
    ) {
        fileinto "From_Example";
    }

Relational and Numeric Comparators

  • Use the relational extension to perform numeric comparisons. Some implementations require explicit comparator requirements for numeric tests:

    if spamtest :value "ge" :comparator "i;ascii-numeric" "5" {
        ...
    }

Spam Test

  • Tests the spam score of the email, often used in conjunction with relational tests.

    if spamtest :value "ge" :comparator "i;ascii-numeric" "5" {
        ...
    }

Notify Action

  • If supported, the notify extension can send alerts. This is useful for immediate notifications on incoming emails.

    notify "maildir" :options "silent" :message "You have a new email" "[email protected]";

Regex/Advanced Pattern Matching

  • Some Sieve implementations support regular expression matching via non-standard extensions. Include a disclaimer that these features are implementation-specific and may not be portable across all servers.

Implementation Notes and Debugging

  • Testing: Use tools like sieve-test or similar utilities provided by your mail server to debug your scripts.
  • Variability: Note that different servers (e.g., Dovecot vs. Cyrus) may have subtle differences in supported extensions and syntax.
  • Logging: If available, enable logging to diagnose issues with script execution.

Extending the require Statement

  • Always list all extensions your script utilizes to avoid runtime errors:

    require ["fileinto", "imap4flags", "vacation", "envelope", "variables", "relational"];

Complex Sieve Script Examples

  1. Greylisting with SQL Database: This script implements a simple greylisting filter using an SQL database.

    require ["variables", "vnd.stalwart.expressions", "envelope", "reject"];
    set "triplet" "${env.remote_ip}.${envelope.from}.${envelope.to}";
    if eval "!query(\"SELECT 1 FROM greylist WHERE addr = ? LIMIT 1\", [triplet])" {
        eval "query(\"INSERT INTO greylist (addr) VALUES (?)\", [triplet])";
        reject "422 4.2.2 Greylisted, please try again in a few moments.";
    }
  2. Domain Blocklisting: This script implements a domain blocklisting filter during the EHLO phase.

    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.";
    }
  3. Message Modification: This example modifies the incoming message by replacing the content of all HTML parts with their uppercase version and adding a custom header to each part.

    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";
        }
    }
  4. Spam Filtering with Numeric Score: This script discards emails with a spam score higher than or equal to 10.

    require ["comparator-i;ascii-numeric", "relational"];
    if allof (not header :matches "x-spam-score" "-*", header :value "ge" :comparator "i;ascii-numeric" "x-spam-score" "10") {
        discard;
        stop;
    }
  5. Dynamic Folder Creation: This example dynamically creates folders based on the sender's email address.

    require ["fileinto", "variables"];
    if address :domain :matches "From" "*" {
        set "folder" "User.${1}";
        fileinto "${folder}";
    }
  6. Quarantine and Notify: This example sends an email to a quarantine folder and notifies the user about it.

    require ["fileinto", "notify"];
    if allof (header :contains "subject" "spam", header :contains "X-Spam-Flag" "YES") {
        fileinto "Quarantine";
        notify :message "An email was moved to Quarantine due to spam detection.";
    }

Online Sieve Testing Tools

  • When testing Sieve scripts for email filtering, consider the following tools and resources:
  1. Dovecot Sieve Script Testing:
    Dovecot’s documentation includes information on testing and debugging Sieve scripts. Although not a dedicated online tester, it provides guidelines and examples that you can replicate in your local environment.
    Reference: Dovecot Sieve Documentation citeDovecotSieve

  2. Command-Line Tools:
    Most Sieve implementations (e.g., Cyrus, Dovecot) include a command-line tool such as sieve-test that allows you to validate and debug your Sieve scripts locally. This is invaluable for catching syntax errors and testing script logic before deployment.

  3. Stalwart Labs Resources:
    Stalwart Labs provides a range of documentation and community discussions on Sieve scripting. While not an online tester per se, these resources offer practical examples, troubleshooting tips, and sample scripts that can help you refine your filters.
    Reference: Stalwart Labs - Sieve Scripting citeCyrusSieve

  4. GitHub Projects and Community Tools:
    Search GitHub for community-driven projects related to Sieve script validation. These projects often provide test harnesses or simulation environments that allow you to run and debug your Sieve scripts in an online or local setup.

Note: These tools and resources are focused on the Sieve mail filtering language. They differ from tools used for physical sieve analysis, so ensure you’re referencing resources specific to email filtering when testing your Sieve scripts.

Sieve Scripting Forums

  1. Stack Overflow: A community where you can ask questions and share knowledge about Sieve scripts and email filtering. Stack Overflow - Sieve

  2. DirectAdmin Forums: A forum for discussing Sieve scripts and troubleshooting issues. DirectAdmin Forums

  3. Stalwart Labs: A resource for Sieve scripting, including documentation and examples. Stalwart Labs

  4. GitHub Discussions: A place to discuss Sieve scripting and related topics. GitHub Discussions

Sieve Scripting Documentation and Tutorials

  1. Protonmail Sieve filter (advanced custom filters)

  2. GandiMail Sieve filtering documentation and tutorials Sample Sieve Filters for Email

  3. Sieve Info Sieve Info

  4. Sieve Tutorial Sieve Tutorial

  5. Coderdose Setting up Email Filtering Sieve Scripts

  6. HowtoForge SIEVE Language for Mail Filtering Quick Guide

  7. Docker Mailserver Email Filtering with Sieve

  8. pair Sieve Syntax and Common Recipes

  9. Ourshack Using Sieve scripts to filter mail automatically

Troubleshooting & Common Pitfalls

  • Extension Support: Not all servers support every extension. Check your server’s documentation to confirm compatibility.
  • Date Formatting: Ensure you use the correct date format and consider timezone differences. Some servers may require additional timezone settings.
  • Logical Operator Syntax: When using allof and anyof, verify that your conditions are properly separated by commas and enclosed in parentheses.
  • Variable Scope: Variables in Sieve are limited in scope; reuse them carefully and ensure they are set before use.
  • Debugging Tools: Use command-line tools or server logs to troubleshoot issues, especially for complex scripts.

References


# Filter by sender if spam score is low into Inbox
if allof (
address :all :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
],
spamtest :value "lt" :comparator "i;ascii-numeric" "${3}") {
addflag "\\Trusted";
fileinto "Inbox";
}
# Filter from unknown or untrusted senders into Quarantine folder
if not address :all :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
] {
addflag "\\Untrusted";
fileinto "Quarantine";
}
# Filter by sender into Potential Spam folder
if not address :all :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
] {
addflag "\\Potential Spam";
fileinto "Quarantine";
}
# Filter by sender domain or type into Crypto folder
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
] {
addflag "\\Crypto";
fileinto "Crypto";
}
# Filter by subject or content into Spam folder
if header :contains "subject" "urgent" {
addflag "\\High-Risk";
fileinto "Spam";
}
# Filter by specific sender domain or type into Spam folder
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
] {
addflag "\\High-Risk-Domain";
fileinto "Spam";
}
# Filter by Videos for specific senders into Videos folder
if allof (
address :all :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
]) {
addflag "\\Videos";
fileinto "Videos";
}
# Filter by Social Media for specific senders into Social Media folder
if allof (
address :all :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
]) {
addflag "\\Social";
fileinto "Social Media";
}
# Filter by sender into Promotions folder, with exclusions for transactional messages
if allof (
address :all :comparator "i;unicode-casemap" :matches "From"
[
"@example1.com",
"@example2.com",
"@example3.com"
],
# Exclude emails with subjects indicating transactional notifications
not header :matches "subject" [
"*Order Confirmation*",
"*Your Order*",
"*Shipping Update*",
"*Delivery Update*",
"*Account Notification*",
"*Your Subscription*"
]) {
addflag "\\Promotions";
fileinto "Promotions";
}
# Priority Inbox: Create a rule to prioritize important emails,
# such as those from certain contacts or containing specific keywords,
# and place them in a "Priority" folder.
if anyof (
address :all :comparator "i;unicode-casemap" :matches "From"
[
"[email protected]",
"[email protected]"
],
header :contains "subject" "Important",
header :contains "subject" "Urgent"
) {
addflag "\\Priority";
fileinto "Priority";
}
# Auto-Reply for Specific Senders: Send an automatic reply to certain senders to confirm receipt of their emails.
if address :all :comparator "i;unicode-casemap" :matches "From"
[
"[email protected]",
"[email protected]"
] {
# Auto-reply with a template message
# vacation :days 1 :subject "Received: ${1}" text:
"Thank you for your email. I have received your message and will get back to you shortly."
;
fileinto "Inbox";
}
# Categorizing Based on Keywords: Filter emails based on specific keywords in the subject or body and categorize them accordingly.
if header :contains "subject" "Newsletter" {
addflag "\\Newsletter";
fileinto "Newsletters";
}
if body :contains "job application" {
addflag "\\JobApplication";
fileinto "Job Applications";
}
# Flag High-Priority Senders: Automatically flag emails from high-priority senders to ensure they get your immediate attention.
if address :all :comparator "i;unicode-casemap" :matches "From"
[
"[email protected]",
"[email protected]"
] {
addflag "\\HighPriority";
fileinto "Inbox";
}
# Archiving Old Emails: Automatically archive emails older than a certain number of days to keep your inbox clean.
require ["date"];
if currentdate :value "ge" "date" "2025-02-21" {
addflag "\\Archive";
fileinto "Archive";
}
# Attachment Filtering: Filter emails with large attachments or specific types of attachments into a separate folder.
if header :value "ge" :comparator "i;ascii-numeric" "X-Attachment-Size" "1000000" {
addflag "\\LargeAttachment";
fileinto "Large Attachments";
}
if header :matches "content-type" "*application/pdf*" {
addflag "\\PDF";
fileinto "PDFs";
}
# Flagging Unread Emails by sender: Automatically flag unread emails to ensure they catch your attention.
# High-Priority senders
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"vipdomain1.com",
"vipdomain2.com"
] {
addflag "\\HighPriority";
fileinto "Inbox"; # or specify a different folder if needed
}
# Trusted senders
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"trusted1.com",
"trusted2.com"
] {
addflag "\\Trusted";
fileinto "Inbox"; # or specify a different folder if needed
}
# General senders
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"general1.com",
"general2.com"
] {
addflag "\\General";
fileinto "General";
}
# Add flag by sender domain into same folder with multiple flags
# High-Priority senders
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"vipdomain1.com",
"vipdomain2.com"
] {
addflag "\\HighPriority";
fileinto "General";
}
# Trusted senders
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"trusted1.com",
"trusted2.com"
] {
addflag "\\Trusted";
fileinto "General";
}
# General senders
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"general1.com",
"general2.com"
] {
addflag "\\General";
fileinto "General";
}
# Add flag by sender domain into same folder with multiple identical flags
if address :domain :comparator "i;unicode-casemap" :matches "From"
[
"domain1.com",
"domain2.com"
] {
addflag "\\Flag1";
addflag "\\Flag2";
fileinto "Inbox"; # or specify a different folder if needed
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment