How can I filter my e-mail with Sieve server-side filters?

This page is showing a generic answer.
To see a more detailed answer customized for you, type your e-mail address here:

Our servers support Sieve e-mail filtering. You can filter incoming e-mail messages as they’re being delivered to a mailbox on our servers.

On this page:

What can I do with Sieve?

Sieve is a powerful mail filtering system that, among other things, allows you to store mail in particular folders on the server. You can then view the folders using Webmail or another IMAP mail program. This allows you to sort your mail even if you use a mail reader like the iPhone that doesn’t directly support filtering.

Note that you can’t view server mail folders using a POP mail connection — you can only see them with Webmail and IMAP. You probably won’t want to use Sieve filters if you read e-mail using POP (unless the only thing you’re trying to do is put some messages in your “Trash” folder on the server, meaning you don’t care if you never see them at all through your POP connection).

How does Sieve work?

Sieve filters are made up of simple rules, like “put all messages from Amazon.com into the e-mail folder named ‘Amazon’”. The rules are written in the text-based Sieve “scripting language”.

You can write Sieve rules from scratch yourself, borrow rules from examples like the ones below, or use software that makes it easier. Some mail programs (or mail program “plugins”) can create Sieve rules for you.

However you create them, the rules get put in a text file that is placed on our servers. Some software can automatically put the file in the right place so you don’t need to worry about the files.

Note that Sieve filtering is different from client-side filtering rules that you might create in Webmail, Thunderbird, Outlook, or any other mail program. Those only affect mail that the client software sees. Sieve instead acts on messages at the mail server level when they arrive on our servers, before they’re seen by any mail software.

Sieve filtering for individual mailboxes

To use Sieve filtering for address@example.com, you’d place the Sieve script file at this location in the mailbox directory:

/home/ex/example.com/mailstore/address/mailbox.sieve

You can do that using FTP to your home directory or a shell connection. However, we also support (and recommend) using “Manage Sieve”, which allows you to manage the scripts using the Sieve add-on for Thunderbird and other Sieve management programs. Those programs automatically put the file in the right place.

Sieve filtering for an entire domain name

In addition to filters for each mailbox, it’s possible to create filters that apply to all addresses at your domain name. This is done by placing script files named “domain-before.sieve” and/or “domain-after.sieve” in your domain’s home directory:

/home/ex/example.com/domain-before.sieve
/home/ex/example.com/domain-after.sieve

A “domain-before.sieve” script (if one exists) runs before any per-mailbox “mailbox.sieve” script, and a “domain-after.sieve” script (if one exists) runs after. So when a message arrives, three different Sieve script files will be searched for and used if present, in this order:

/home/ex/example.com/domain-before.sieve
/home/ex/example.com/mailstore/address/mailbox.sieve
/home/ex/example.com/domain-after.sieve

Each script is used only if a previous script didn’t discard the message or file it into a folder, so the order matters. If you want to create domain-wide rules that override “mailbox.sieve” scripts, you’d put them in the “domain-before.sieve” script. To create domain-wide rules that are used only if “mailbox.sieve” doesn’t do anything, you’d put them in “domain-after.sieve”.

Sieve example rules

Here are some example rules to show what can be done with Sieve filtering.

Messages from a certain sender address

File a message from “someone@example.org” into a folder named “Someone”:

require ["fileinto", "mailbox"];
if address "From" "someone@example.org"
{
    fileinto :create "Someone";
}

The “fileinto :create” rule creates the folder if necessary (you may need to restart your e-mail program, or tell it to “subscribe to the IMAP folders”, to see the newly created folder).

If you want the rule to file messages only into folders that you’ve already created, omit the “create”:

require "fileinto";
if address "From" "someone@example.org"
{
    fileinto "Someone";
}

This next example shows how to file messages from any address @example.org into the Trash folder (which is dangerous!) using the “:domain” test to check only the part after the @ sign:

require "fileinto";
if address :domain "From" "example.org"
{
    fileinto "Trash";
}

And this example does the same thing in a different way, by checking whether the full “From” header address “contains” @example.org:

require "fileinto";
if address :contains "From" "@example.org"
{
    fileinto "Trash";
}

Messages to a certain address

File a message to “personal@example.com” into a folder named “Personal”:

require ["fileinto", "mailbox"];
if address "To" "personal@example.com"
{
    fileinto :create "Personal";
}

File a message that’s CCed to “personal@example.com” into a folder named “CCs”:

require ["fileinto", "mailbox"];
if address "CC" "personal@example.com"
{
    fileinto :create "CCs";
}

The difference between header addresses and envelope addresses

The examples above using the “address” test only work if that address actually appears in the “From”, “To” or “CC” headers of a message. It’s possible for you to receive a message where your address doesn’t appear in either header because it’s been BCCed to you (possibly through a mailing list that effectively BCCs all mail). The “envelope to” test can be used for that, because it tests the address the message actually arrived for:

require ["envelope", "fileinto", "mailbox"];
if envelope "To" "personal@example.com"
{
    fileinto :create "Personal";
}

In general, the “envelope to” test is the most reliable if you’re checking which address a message was sent to.

Similarly, each message has what’s called an “envelope sender” or “Return-Path” address that’s normally invisible unless you view the full headers of a message. This address is usually the same as the “From” header address, but it can sometimes be different, especially with spam or mailing lists. The “envelope from” test can be used to match that:

require ["envelope", "fileinto", "mailbox"];
if envelope "From" "someone@i-dont-like.com"
{
    fileinto :create "Trash";
}

if envelope :domain "From" "spammer.com"
{
    fileinto :create "Spam";
}

Messages from a name

You might want to filter all messages that include a certain name in a message’s “From”, regardless of what address it comes from. To do that, use header :contains "From":

require ["fileinto", "mailbox"];
if header :contains "From" "George Washington"
{
    fileinto :create "Revolutionary Correspondence";
}

Detecting BCCs

One thing you might notice is that most of the spam you get appears to have been BCCed to you: your address doesn’t appear in the “To” or “CC” headers of a message. The same is true of most (but not all) mail from mailing lists.

You can detect a lot of this automated mail with this rule:

require ["fileinto", "mailbox"];
if not address ["To", "CC"] "address@example.com"
{
    fileinto :create "Low Priority";
}

Conversely, this detects mail that is not BCCed to you, simply removing the “not”:

require ["fileinto", "mailbox"];
if address ["To", "CC"] "address@example.com"
{
    fileinto :create "High Priority";
}

Detecting mailing lists

Well-behaved mailing lists contain an invisible “Precedence” e-mail header with a value of “list”, and/or contain a “List-Id”. Other automated mail includes a precedence header of “bulk”.

Here’s a rule that files mail that has any of these characteristics:

require ["fileinto", "mailbox"];
if anyof
    (
        header "Precedence" "list",
        header "Precedence" "bulk",
        exists "List-Id"
    )
{
    fileinto :create "Low Priority";
}

SpamAssassin

This example files a message that receives a SpamAssassin score of 9 or higher in a folder named “Spam”:

require ["fileinto", "mailbox"];
if header :contains "X-Spam-Level" "*********"
{
    fileinto :create "Spam";
}

This slightly more complicated example uses the Sieve “allof” command to file a spam message only if the subject or body doesn’t contain the word “tiger”:

require ["body", "fileinto", "mailbox"];
if allof
    (
        header :contains "X-Spam-Level" "*********",
        not header :contains "Subject" "tiger",
        not body :contains "tiger",
        mailboxexists "Spam"
    )
{
    fileinto :create "Spam";
}

You can also flag a message if it matches a certain SpamAssassin rule. For example, this catches any message that triggers SpamAssassin’s “talks about lots of money” rule, comes from Yahoo, and don’t contain “example.com” in the "To" or "CC" header (meaning it was BCC:ed to you):

require ["envelope", "fileinto", "mailbox"];
if allof
    (
        header :contains "X-Spam-Status" "BILLION_DOLLARS=",
        envelope :domain "From" "yahoo.com",
        not address :domain ["To", "CC"] "example.com"
    )
{
    fileinto :create "Spam";
}

Plus addressing

If your e-mail address is “address@example.com”, our servers accept mail sent to tagged addresses like “address+something@example.com”, where “something” can be any text you want.

You can file messages based on the “+something” part, called a “subaddress” in Sieve:

require ["envelope", "fileinto", "mailbox", "subaddress"];

# file address+amazon@example.com into "Amazon" folder
if envelope :detail "to" "amazon"
{
    fileinto :create "Amazon";
}
# file address+ebay@example.com into "eBay" folder
if envelope :detail "to" "ebay"
{
    fileinto :create "eBay";
}

Flag a message

Flag a message from a certain sender so that it’s highlighted in the Inbox of many IMAP mail programs, including Webmail:

require ["imap4flags"];
if address "From" "someone@example.org"
{
   setflag "\\Flagged";
}

Mark a message as “seen”

Mark a message as “seen” or “already read” so that it doesn’t show as a new unread message:

require ["imap4flags"];
if address "From" "someone@example.org"
{
   setflag "\\Seen";
}

You can also combine this with rules that file messages into folders, so the the folders don’t show any unread messages:

require ["fileinto", "mailbox", "imap4flags"];
if address "From" "someone@example.org"
{
   setflag "\\Seen";
   fileinto :create "Trash";
}

Discarding all new mail

We occasionally hear from customers who need to keep all existing mail in a mailbox (perhaps for legal reasons), but want to discard all new mail, and don’t even want it to take up disk space in the Trash. You can do this with a sieve file containing this single line:

discard;

This is, of course, very dangerous. There’s no way to get it back if you do this.

Handling “bounces”

If a spammer forges your address and you get a lot of “bounces”, you can put them in a separate folder:

require ["envelope", "fileinto", "mailbox"];
if envelope :matches "From" [
    "MAILER-DAEMON",
    "MAILER-DAEMON@*",
    "postmaster@*"
    ]
{
    fileinto :create "Bounces";
}

Forwarding messages

You can forward a copy of a message to a different address using Sieve. This example sends a copy of the message to a different address, saving the original in your Inbox, too:

require ["copy"];
if header :contains "Subject" "tiger"
{
    redirect :copy "other@example.net";
}

This version saves a copy of the forwarded message in a folder:

require ["copy", "fileinto", "mailbox"];
if header :contains "Subject" "tiger"
{
    redirect :copy "other@example.net";
    fileinto :create "Forwarded Messages";
}

Whereas this much more dangerous example sends a copy to another address and discards the original without putting it in your Inbox:

if header :contains "Subject" "tiger"
{
    redirect "other@example.net";
}

It’s wise to always include the “:copy” to avoid deleting the original. If you really think you don’t want to keep a copy of forwarded messages, you might want to put them in the Trash instead of discarding them, so you can retrieve them if something goes wrong:

require ["copy", "fileinto"];
if header :contains "Subject" "tiger"
{
    redirect :copy "other@example.net";
    fileinto "Trash";
}

Using regular expressions (regex)

Sometimes, just knowing whether a message contains certain specific text isn’t sufficient. You can match more complicated patterns using Sieve’s “regex” rules.

This example looks for messages that have a blank subject and only a link in the message body (which is a common spam pattern):

require ["regex", "body", "fileinto"];
if allof (
  not header :regex "Subject" "[[:graph:]]",
  body :regex "^[[:space:]]*http://[[:graph:]]+[[:space:]]*$"
  )
{
  fileinto "Trash";
}

This first checks that the message subject does not contain any printable characters, then checks that the message body contains only “http://” followed by one or more printable characters, possibly surrounded by spaces (but nothing else) on both sides.

Blocking certain filenames

You can use the “body” check with the extra keyword “:raw” to examine the “raw content” of a message, which lets you do things like block messages containing certain filenames (attachments).

We already block many malicious filetypes, but this example lets you also block all “.zip” and “.tgz” files:

require ["regex", "body", "fileinto"];
if body :raw :regex ["filename=.+\\.zip","filename=.+\\.tgz"]
{
  fileinto "Trash";
}

Note that unlike our general filetype blocking, this kind of thing only catches top-level filenames, and can’t “look inside” a .zip file, for example.

Learning more about Sieve

Other samples, and much more information, can be found on the Sieve home page.

The Sieve “reject” action

Some versions of Sieve offer a “reject” action, which creates a new outgoing “bounce” message to the person who sent the original e-mail.

We intentionally do not support “reject”. This is because it’s very difficult to tell who the true sender of a message is — in particular, if a message is spam, the spammer almost certainly forged the sending address.

If you used a “reject” action, you’d end up sending copies of spam to innocent strangers (this is called backscatter). Those strangers will complain to their ISP, who will block all mail from your domain name. You’ll then be unable to send any e-mail to people who use AOL, or Comcast, or another large site. This is not what you want.

Instead of using “reject”, file the message into a folder (or use “discard” if you’re feeling brave, although we’d never do that ourselves).

Why doesn’t the Mozilla Thunderbird Sieve add-on connect properly?

As of this writing, the featured 0.2.2 version of the Sieve add-on for Thunderbird does not work properly with Thunderbird 24 and later: it will simply fail to connect due to a Thunderbird incompatibility.

The development version 0.2.3 fixes this, and is available from the Sieve add-on “nightly builds” page. You can install the latest version by following the instructions there and it should work.

The correct settings for the add-on in the “Server” and “Security” screens are:

Server Name:IMAP Server: mail.tigertech.net
Server Port:4190 (Default)
Connection Security:Force TLS
Authentication:IMAP Username and Password

The other settings should usually be left alone, at their defaults.

If you have trouble connecting to the server, make sure that the “Proxy” setting is Direct Connection; we’ve seen a couple of cases where it somehow gets set to use a proxy instead.

Some technical notes

Sieve rules can be complicated, and there’s a lot to remember. Here are some notes about Sieve features that we often have to look up ourselves:

  • You can specify a mail subfolder by listing all of the folders on the “path” to the subfolder, each separated by a dot. For example, if you have a folder named “Travel” which then has a subfolder named “Summer Vacation”, you can specify the subfolder using fileinto "Travel.Summer Vacation".
  • The different comparisons available are :is (an exact, full match — recommended for full addresses or domain names), :contains (matches a substring), and :matches (a full match that allows DOS-style wildcards ? and *). If you don’t specify a comparison, :is will be used, so header :is "Subject" "Spam" does the same thing as header "Subject" "Spam".
  • By default, string comparisons are case-insensitive. Checking address "From" "address@example.com" does the same thing as checking address "From" "address@EXAMPLE.COM". (If you really want case-sensitive comparisons, RFC 3028 section 2.7.3 explains how.)
  • By default, the Sieve body check presents the message body as a single line string that contains no carriage returns or line feeds, allowing you to easily match regex rules against the entire message as in the “body :regex” example above.
  • If you want to test a Sieve filtering file and see exactly what it will do for a given messages, advanced users can use a program named “sieve-test” from the command line shell. Type man sieve-test to see the documentation for it.