This page, along with the Sieve Scripts and SecurityGateway Sieve Extensions pages, provides a basic outline of the Sieve email filtering language and its implementation within SecurityGateway. The first section of this page outlines the basic parts of a Sieve Script. The next section outlines various structural elements of the language. Then there are lists of the standard Control, Test, and Action commands that are supported. And last, there are several sample scripts provided at the bottom of the page for your review.
|
For a more extensive look at the Sieve email filtering language, you should review the authoritative documents online at the IETF web site: Sieve: An Email Filtering Language (RFC-5228), Sieve's Copy Extension (RFC 3894), Sieve's Body Extension (RFC-5173), Sieve's Reject Extension (RFC-5429), Sieve's Variables Extension (RFC-5229), and Spamtest and VirusTest Extensions (RFC-3685). You can also visit www.mdaemon.com/Support/ for SecurityGateway's latest technical support and help options, including: telephone support, email support, a Knowledge Base, Frequently Asked Questions, community forums, and more. |
A Sieve Script has four basic parts:
1.Requirements—this part is used to declare the Sieve extensions that are required for a given script. When commands belonging to optional extensions will be used in a script, you MUST use the require control command to list those required extensions at the beginning of the script. A semicolon is required at the end of the require command's arguments.
Examples:
require "securitygateway";
-and-
require ["securitygateway", "fileinto"];
2.Conditions—this part of a script is where you declare the specific types of things you are looking for in a message and how you will be testing and comparing those things.
Examples:
if size :over 1M
-and-
if header :contains ["to", "cc"] "Frank Thomas"
3.Actions—these are the actions that will be taken and commands that will be executed when the designated conditions are True. Each Action must be followed by a semicolon and each block of actions must be contained in curly braces (i.e. "{" and "}").
Examples:
if size :over 1M { discard; }
-and-
if header :contains ["to", "cc"] "Frank Thomas" {
bayes-learn "spam";
fileinto "spam";
}
4.Comments—you can include comments in your Sieve scripts for your own reference, to remind you what the script does, and the like. There are two types of comments that you can use: single-line comments and multi-line comments. Single-line comments start with "#" and continue to the end of the line (i.e. until the next CRLF). Multi-line comments start with "/*", can span multiple lines, and then end with "*/".
Examples:
# discards messages over 1 mb
if size :over 1M { discard; }
-and-
if header :contains "from" "Frank Thomas" {
/* Frank Thomas sends mostly spam to us, so this script
will automatically move everything we get from him to
the user quarantine. */
fileinto "spam";
}
Strings
Text strings start and end with a single double-quote. For example: "Frank Thomas".
To include a backslash or double-quote within a quoted string the character must be preceded by another backslash. So, \\ will be treated as \ and \" will be treated as " in a quoted string. No other characters should be escaped in strings.
String Lists
Whenever you wish to use a groups of strings in a script, separate each quoted string with a comma and enclose the set in square brackets.
Example:
if header :contains ["to", "cc"] ["me@xyz.com", "you@xyz.com", "us@xyz.com"]
The result of this test is True if either the To or CC header contains any of the three addresses.
Headers
Do not include a colon in header names.
Example:
if header :is "to:" (invalid)
if header :is "to" (valid)
Test Lists
Similar to string lists, you can include a group of tests in a script by enclosing the group in parentheses. This is sometimes necessary when using the allof or anyof Test commands, since those are logical "AND" and logical "OR" statements respectively.
Example:
if anyof (size :over 1M, header :contains "subject" ["big file", "mega file"])
{
discard;
}
Arguments and Match Types
Most commands take one or more arguments in order for you to specify what to do. There are several types of arguments, such as positional arguments, tagged arguments, and optional arguments. Tagged arguments and Match Type arguments, for example, are preceded by a colon. :contains, :is, :matches, :over, and :under are all examples of tagged arguments. Some tagged arguments are limited to specific commands. For more on the different types of arguments, see: RFC-5228.
Actions
Each action must be followed by a semicolon and each block of actions must be enclosed in curly braces.
Example:
if header :contains ["to", "cc"] "Frank Thomas" {
bayes-learn "spam";
fileinto "spam";
}
There are three control commands used in the Sieve language:
require
This control command is used at the beginning of a script to declare which optional extensions will be used in the script.
Example:
require ["securitygateway", "fileinto"];
if / elsif / else
The if command is the core control command. Although there are technically three interrelated commands, elsif and else cannot be used independently of if. When if is encountered in a script, the test condition will be evaluated to see if it is true. If it is, then the actions associated with it will be executed.
If the if test is false then the first elsif test will be evaluated. If the elsif is true then the actions associated with that test will be executed. If the elsif test proves to be false as well, then the process will continue with the next elsif, and so on until one of them is true.
If the if and all elsif tests are false, and if there is an else command, then that command's actions will be executed.
stop
The stop control command ends all processing.
These are the standard Test commands supported in SecurityGateway's implementation of Sieve. The body and envelope commands are extensions, however, so you must include them in the require control command whenever you wish to use either of them in a script. Further, there is a significant number of additional Test commands included in the securitygateway extension outlined on the SecurityGateway Sieve Extensions page.
address
With this command you can test on only an email address in a header rather than on the included phrase or name it might contain. For example, if the "to" header contained "Frank Thomas" <frank@example.com>, then the result of the the test header :is "to" "frank@example.com" would be false. But the test address :is "to" "frank@example.com" would be true because only the address is considered in the evaluation.
There are also three optional tagged arguments you can use with this command: ":localpart", ":domain", and ":all". The :localpart argument evaluates only the left part of the address (e.g. "frank" in "frank@example.com"), the :domain argument only uses the domain portion of the address (e.g. "example.com"), and :all uses the entire address. If none of these arguments are included then :all is used by default.
Example:
require "fileinto";
if address :domain :is "from" "spammer.com" {
fileinto "spam";
}
allof
This test is a logical "AND", meaning that ALL of the conditions being evaluated must be true in order for the action be taken.
Example:
if allof (header :contains "from" "J.Lovell", header :contains "to" "Bubba")
{
fileinto "spam";
}
anyof
This test is a logical "OR", meaning that if ANY of the conditions being evaluated are true then the associated action will be taken.
Example:
if anyof (size :over 1M, header :contains "subject" "big file attached")
{
reject "I don't want messages that claim to have big files.";
}
body
The body test command is an optional extension and therefore you must use the require "body" control command at the beginning of any script that will use it. This command compares against the message's body. For more on this command, see: Sieve's Body Extension (RFC-5173).
Example:
require ["body", "fileinto"];
if body :text :contains "secret formula" {
fileinto "admin";
}
envelope
The envelope command is an optional extension and therefore you must use the require "envelope" control command at the beginning of any script that will use it. This command compares against the SMTP MAIL From and RCPT To envelope parts when "from" or "to" is used respectively as the command's argument.
Example:
require "envelope";
if envelope :is "from" "MrsFrank@company.com" {
redirect "frankshome@example.com";
}
exists
This test is true if the headers listed in the argument exist within the message. All listed headers must exist or the test is false.
Example:
if exists "x-custom-header" {
redirect "admin@example.com";
}
-and-
if not exists ["from", "date"] {
discard;
}
false
This test always evaluates to "FALSE".
header
The header test evaluates to true when the value of the named header matches the conditions set by the argument. When no Match Type argument is specified, :is will be used by default.
Example:
require "fileinto"
if header :is "x-custom-header" "01" {
fileinto "admin";
}
not
Using this command with another test means that the result of the test must be reversed in order for the test's action to be taken. For example, the test if not exists ["from", "date"] { discard; } means that if a message does NOT contain both "from" and "date" headers then the discard action will be taken. If the not command were omitted then that would mean the message would be discarded if the headers DID exist.
size
The size command accepts the tagged arguments ":over" and ":under", which must be followed by a numerical value. These arguments are used to designate whether a message's size must be higher or lower than the specified value in order for the test to be TRUE. You can use an M after the value to indicate megabytes, a K for kilobytes, or no letter for bytes.
Example:
if size :over 500K {
discard;
}
spamtest
The spamtest command is an optional Sieve extension discussed in the Spamtest and VirusTest Extensions (RFC-3685) document at ietf.org. See that document for information on this extension.
true
This test always evaluates to "TRUE".
virustest
The virustest command is an optional Sieve extension discussed in the Spamtest and VirusTest Extensions (RFC-3685) document at ietf.org. See that document for information on this extension.
vnd.mdaemon.ai.prompt
Used in AI Classification, this test invokes a pre-configured AI prompt (defined in Security > AI Classification > AI Prompts) which sends message content to an AI service and receives a classification response.
Syntax: vnd.mdaemon.ai.prompt [MATCH-TYPE] <prompt-name> <expected-response>
•prompt-name (string) - The name of a configured AI prompt
•expected-response (string) - The value to match against the AI's response
Match Types Supported:
•:is - Exact string match (default)
•:contains - Substring match
•:matches - Wildcard pattern match (using * and ?)
Requires: vnd.mdaemon.ai
Valid at: DATA event and later (after message content is available)
Performance Considerations
Important: AI prompt execution is synchronous and occurs during message processing. To avoid delaying mail delivery:
•Design prompts to return quickly - Use concise prompts and efficient AI models
•Configure appropriate timeouts - Set timeout values in AI Model settings to prevent indefinite blocking
•Avoid thinking modes - Do not use AI models with extended "thinking" or "reasoning" modes (e.g., o1, o3, o1-pro) as they significantly increase response time
•Use selective conditions - Combine with other Sieve tests to limit when AI is invoked:
require ["vnd.mdaemon.ai", "spamtest"];
# Only run AI on messages that pass basic spam checks
if allof(spamtest :value "lt" :comparator "i;ascii-numeric" "5",
not header :contains "subject" "unsubscribe") {
if vnd.mdaemon.ai.prompt :is "PhishingCheck" "YES" {
discard;
}
}
Configuration Requirements
Before using this test in Sieve rules, you must configure the following in SecurityGateway's web interface:
1.AI Models (Security > AI Classification > AI Models)
oConfigure connection to an OpenAI-compatible AI service
oSet endpoint URL, model name, and authentication token
oConfigure timeout settings
2.AI Prompts (Security > AI Classification > AI Prompts)
oCreate a prompt with a unique name (referenced in Sieve rules)
oAssociate the prompt with a configured AI model
oDefine the prompt template with message variables
oConfigure response parsing
The prompt name specified in the Sieve test must exactly match the name of a configured AI prompt.
Examples:
Phishing Detection
Detect and quarantine sophisticated phishing attempts:
require "vnd.mdaemon.ai";
if vnd.mdaemon.ai.prompt :is "PhishingCheck" "YES" {
quarantine "AI detected potential phishing attempt";
}
Content Classification with Wildcards
Classify messages by category and file into appropriate folders:
require ["vnd.mdaemon.ai", "fileinto"];
if vnd.mdaemon.ai.prompt :matches "CategoryClassifier" "SPAM*" {
fileinto "Junk";
} elsif vnd.mdaemon.ai.prompt :matches "CategoryClassifier" "MARKETING*" {
fileinto "Marketing";
}
Priority Detection
Flag urgent messages for immediate attention:
require ["vnd.mdaemon.ai", "imap4flags"];
if vnd.mdaemon.ai.prompt :contains "UrgencyLevel" "HIGH" {
addflag "\\Flagged";
addheader "X-Priority" "1";
}
Sentiment Analysis
Route messages based on AI-detected sentiment:
require "vnd.mdaemon.ai";
if vnd.mdaemon.ai.prompt :is "SentimentAnalysis" "NEGATIVE" {
addheader "X-Customer-Sentiment" "Negative";
redirect "customer-support@example.com";
}
Compliance Detection
Identify messages that may contain sensitive information:
require "vnd.mdaemon.ai";
if vnd.mdaemon.ai.prompt :contains "ComplianceCheck" "PII" {
addheader "X-Contains-PII" "Yes";
redirect "compliance@example.com";
}
vnd.mdaemon.display_name_protection
Display Name Protection tests whether the message sender's display name (from the From header) is similar to a protected user's name, indicating a potential display name impersonation attack. A Similarity threshold parameter (0.0-1.0) controls the similarity sensitivity, where higher values require closer matches. Default is 1.0. It returns true if the sender's display name matches a protected user's name above the threshold and is not excluded, false otherwise.
The test includes two-tier exclusion checking:
•Domain-level sender exclusion list: Messages from senders in this list will never be flagged as display name spoofing, regardless of similarity. Wildcard patterns are supported (e.g., *@company.com, user*@domain.com). This list is configured in the Display Name Spoofing settings under "Do not check messages sent from email addresses listed below".
•Per-user personal address lists: If a sender is on a protected user's personal address list, the test will not flag the message for that specific recipient.
Syntax: vnd.mdaemon.display_name_protection [:nicknames] [threshold]
•Valid at DATA event and later (after message headers are available)
•:nicknames (optional): When specified, enables nickname/diminutive detection. Common first name variations are treated as matches (e.g., "Bob Smith" matches "Robert Smith", "Matt Jones" matches "Matthew Jones"). This helps detect impersonation attempts using informal name variations.
•threshold (optional): A decimal value between 0.0 and 1.0 representing the similarity threshold (default: 1.0). Higher values require closer matches to be considered spoofing.
Examples
Reject messages with display name spoofing using default threshold:
require "securitygateway";
if vnd.mdaemon.display_name_protection {
reject "Display name spoofing detected";
}
Enable nickname detection to catch informal name variations:
require "securitygateway";
if vnd.mdaemon.display_name_protection :nicknames "0.85" {
reject "Display name spoofing detected";
}
Use a stricter threshold (0.90) and quarantine instead of rejecting:
require "securitygateway";
if vnd.mdaemon.display_name_protection "0.90" {
fileinto "spam";
}
Apply stricter policies to external senders using free email with nickname detection:
require "securitygateway";
if allof (vnd.mdaemon.sender_is_free_email,
vnd.mdaemon.display_name_protection :nicknames "0.85") {
reject "Potential impersonation from free email provider";
}
Add a warning header for borderline cases:
require "securitygateway";
if vnd.mdaemon.display_name_protection "0.75" {
addheader "X-Possible-Spoofing" "Display name similarity detected";
}
vnd.mdaemon.sender_is_free_email
Tests whether the message sender's email address (from the From header) is from a free email provider such as Gmail, Yahoo, Hotmail, Outlook, ProtonMail, etc. The test returns true if the sender's domain matches any known free email provider, false otherwise.
Syntax: vnd.mdaemon.sender_is_free_email
•Valid at DATA event and later (after message headers are available)
•No arguments.
Recognized Free Email Providers
The test recognizes major free email providers including:
•Gmail (gmail.com , googlemail.com )
•Yahoo Mail (yahoo.com and regional variants)
•Outlook/Hotmail (hotmail.com , outlook.com , live.com , msn.com )
•ProtonMail (protonmail.com , proton.me)
•iCloud (icloud.com , me.com , mac.com )
•AOL (aol.com )
•And many others (GMX, Mail.com , Zoho, Yandex, Mail.ru, FastMail, Tutanota, etc.)
Examples
Flag messages from free email providers for additional review:
require "securitygateway";
if vnd.mdaemon.sender_is_free_email {
addheader "X-Free-Email-Provider" "Yes";
}
Apply stricter policies to external senders using free email:
require "securitygateway";
if allof (vnd.mdaemon.sender_is_free_email,
not vnd.mdaemon.display_name_spoofed "0.90") {
reject "Potential impersonation from free email provider";
}
These standard Action commands are supported by SecurityGateway. The fileinto and reject commands are extensions, so you must include them in the require control command whenever you wish to use either of them in a script. There are many other action commands available via the securitygateway extension outlined on the SecurityGateway Sieve Extensions page.
fileinto
The fileinto action command is an optional extension and therefore you must use the require "fileinto" control command at the beginning of any script that will use it. This command accepts two arguments: "spam" and "admin". "spam" moves the message to the User quarantine and "admin" moves it to the Administrative quarantine.
Example:
require "fileinto";
if header :contains "from" "Frank Thomas" {
fileinto "spam";
}
discard
This action causes a message to be silently deleted, without sending a delivery status notification are any other message.
Example:
if size :over 2M { discard; }
keep
This action causes the message to be saved to the default location.
redirect
This command redirects the message to the address specified in the associated argument, without changing the message's body or existing headers. This command also supports the optional :copy extension, which will cause a copy of the message to be sent to the specified address rather then redirecting the message. This allows other actions to be performed in addition to sending a copy to the specified address.
Example:
require "copy";
if header :contains "subject" "Response to XYZ" {
redirect :copy "offers@example.com";
bayes-learn "ham";
}
reject
The reject action command is an optional extension and therefore you must use the require "reject" control command at the beginning of any script that will use it. This command causes the message to be refused during the SMTP process with a 5xx response code and an optional short message specified in the argument.
require "reject";
if size :over 5M {
reject "No way! This message is too big for me to accept.";
}
vnd.mdaemon.securewebmsg
Use this action command to use SecurityGateway's Secure Messaging web portal to send a message. It converts outbound messages to external recipients into secure web messages delivered through the portal. Instead of sending the email directly via SMTP, the message is stored in SecurityGateway's database and the recipient receives a notification email with a link to access the message securely through a web browser. This action provides end-to-end encryption and secure delivery for sensitive communications with external parties who may not have secure email infrastructure. Typical uses: Data Leak Prevention, sending confidential/sensitive information securely, and meeting compliance requirements.
This action is available in Content Filter and Data Leak Prevention rules ("Send as secure web message" action), and in manually created Sieve scripts.
Syntax: vnd.mdaemon.securewebmsg
Arguments: None
Requires: securitygateway
Valid at: Any time during message processing.
How It Works
When this action is applied to a message:
•The action only affects messages sent to external (non-local) recipients. Messages to local users are delivered normally.
•The recipient receives a notification email with a secure link to access the full message through SecurityGateway's web portal.
•An external user account is automatically created for the recipient if one doesn't exist (if auto-creation is enabled for the domain).
•Recipients access messages through a web browser using authentication (email verification, password, or multi-factor authentication depending on configuration).
•Message content is stored encrypted in SecurityGateway's database and transmitted over HTTPS.
Configuration Requirements
Before using this action, the Secure Message Portal must be configured:
Enable Secure Messaging - Enable secure messaging for the sending domain (Setup/Users > Secure Messaging > Configuration)
External User Settings - Configure external user creation policies and authentication requirements
Portal Access - Ensure the SecurityGateway web portal is accessible to external recipients
Notification Templates - Customize notification email templates (optional)
Examples
require ["securitygateway","reject","fileinto","envelope","body","regex"];
if allof(header :matches "subject" "[Secure Message]*")
{
vnd.mdaemon.securewebmsg;
}
Automatic Secure Delivery for Sensitive Keywords
Automatically send messages containing sensitive keywords via secure portal:
require "securitygateway";
if header :contains "subject" ["confidential", "private", "sensitive"] {
vnd.mdaemon.securewebmsg;
}
Secure Delivery Based on Recipient Domain
Send all messages to specific external domains via secure portal:
require "securitygateway";
if address :domain :is "to" ["competitor.com", "external-partner.net"] {
vnd.mdaemon.securewebmsg;
}
Secure Delivery for Large Attachments
Use secure portal for messages with large attachments to avoid email size limits:
require ["securitygateway", "fileinto"];
if size :over 10M {
vnd.mdaemon.securewebmsg;
}
Compliance-Driven Secure Delivery
Combine with content analysis to enforce secure delivery for regulated data:
require "securitygateway";
# Send messages containing potential PII via secure portal
if header :contains "X-Contains-PII" "Yes" {
vnd.mdaemon.securewebmsg;
}
Secure Delivery for Specific Senders
Enforce secure delivery for messages from specific internal users:
require "securitygateway";
if address :is "from" ["ceo@example.com", "legal@example.com", "hr@example.com"] {
vnd.mdaemon.securewebmsg;
}
Combined with Other Actions
You can combine secure web message with other actions:
require "securitygateway";
if header :contains "subject" "confidential" {
addheader "X-Sensitive-Content" "Yes";
vnd.mdaemon.securewebmsg;
}
Reject any message with subject containing "[SPAM]"
require "reject";
if header :contains "subject" "[SPAM]"
{
reject "I don't want your spam";
}
Reject any message to a specific real name
require ["securitygateway","reject"];
if header :contains "to" "Real Name"
{
bayes-learn "spam";
reject "I don't want your spam";
}
Custom Bayes Auto Learning
require ["securitygateway","comparator-i;ascii-numeric"];
if allowlisted
{
bayes-learn "ham";
}
elsif anyof(blocklisted,spamtotal :value "gt" :comparator "i;ascii-numeric" "20.0")
{
bayes-learn "spam";
}
Greylist DNSBL matches
require "securitygateway"];
if not lookup "rblip" "all" {greylist;}
Notify admin when large message is received
require ["securitygateway"];
if size :over 1M
{
alert text:
To: admin@company.mail
From: postmaster@$RECIPIENTDOMAIN$
Subject: SecurityGateway Content-Filter Message
X-Attach-Msg: No
$RECIPIENT$ received a message larger that 1MB.
.
;
}
Send as a secure message when subject starts with "[Secure Message]"
require ["securitygateway","reject","fileinto","envelope","body","regex"];
if allof(header :matches "subject" "[Secure Message]*")
{
vnd.mdaemon.securewebmsg;
}