Please enable JavaScript to view this site.

SecurityGateway for Email Servers v12.0

Navigation: Security > Sieve Scripts

Creating Sieve Scripts

Scroll Prev Top Next More

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.

Parts of a Sieve Script

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";

}

Structural Elements

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";

}

Control Commands

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.

Test Commands

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";

}

Action Commands

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;

}

Sample Sieve Scripts

 

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;

}