Using Sieve for server-side mail filtering

If your mail server supports Sieve mail filtering language, you can use a simple text scripts to enable powerful mail filtering and management that is applied directly on server-side. This allows you to create filters that will works client-independenty (a true saviour for those enforced to use Microsoft Outlook).

Sieve has no variables, and no loops (but does have conditionals). Thus, it is limited to simple filtering operations.

But that is enough for:

  • developing simple anti-spam system,
  • managing and organising mails, but auto-moving incoming messages to corresponding folders,
  • rejecting certain e-mails automatically (i.e. if they're too big or contain invalid attachment).

Here you will find some general info and a few simple script examples.

Sieve's grammar is limited and has a significant number of restrictions, in order to reduce the complexity of parsing the language and by the same time -- to reduce resources eaten by execution of Sieve's scripts. Sieve is fully Unicode-aware.

Rules

Never forget about these general rules:

  • first condition always starts with if,
  • following conditions starts with elseif,
  • last condition always starts with else and is mandatory (see below),
  • script starts with require clause which lists all extensions that are used in following filtering rules,
  • single rules are written directly; multi-conditional rules require anyof clause, putting them into brackets and separating them with commas (see examples).

In addition to third rule, the last condition is always mandatory and must contain keep command in order to deliver all e-mails, that are not filtered out by earlier rules, in an unchanged way.

Examples

Some examples follows.

Example no 1: Automatic rejection of all e-mails that are larger than 10 MB. This covers e-mail size in general -- both attachments and in-line media:

# Messages bigger than 10M will be rejected with an error message.
#
if size :over 10M {
   reject "E-mails larger than 10 MB in size are automatically rejected
   by this system. Please upload larger files to some service or a FTP 
   server and send the link instead. Thanks.";
}

The require ["reject"]; clause is required in first line -- to declare extension used in above script.

Example no 2: Auto-put messages in certain conditions to a selected folder:

# Mailing list-related e-mails will be put into corresponding folder.
#
if address :is ["From", "To"] "training@nobleprog.co.uk" {
   fileinto "INBOX.NobleProg";
}

The require ["fileinto"]; clause is required in first line -- to declare extension used in above script.

Example no 3: Similar to above, move all e-mails automatically generated by an Atlassian software's to folders:

# Message contain "JIRA" or "COKS" in subject will put into the "JIRA" folder,
# which is a sub-folder of an "Atlassian" root folder (and not in Inbox).
#
if header :matches "Subject" ["*JIRA*","*COKS*"] {
      fileinto "[0] Atlassian.JIRA";
}

or:

# Message contain "Confluence" in subject will put into the "Confluence" folder,
# which is a sub-folder of an "Atlassian" root folder (and not in Inbox).
#
if header :matches "Subject" ["*Confluence*"] {
      fileinto "[0] Atlassian.Confluence";
}

Again this require the require ["fileinto"]; clause in first line in order to work.

Example no 4: Simple spam-filtering system:

# Message that does not contain certain (my) address in To:, CC: or BCC: (in
# header) or message with something like "money" or "Viagra" in subject will be
# put automatically to Spam-folder.
#
if anyof (
    not address :all :contains ["To", "Cc", "Bcc"] "john.doe@false.server", 
    header :matches "Subject" ["*money*","*Viagra*"]
    ) {
      fileinto "INBOX.spam";
}

Summary

Don't forget about:

  • keep clause at the end,
  • declaration of required extensions in the beginning,
  • correct usage of if, elseif and else, if you have more than one condition.

The whole example Sieve script could look like this:

# Declare the extensions used by this script.
#
require ["fileinto"];

# Message contain "JIRA" or "COKS" in subject will put into the "JIRA" folder.
#
if header :matches "Subject" ["*JIRA*","*COKS*"] {
      fileinto "[0] Atlassian.JIRA";
}

# Message contain "Confluence" in subject will put into the "Confluence" folder.
#
elsif header :matches "Subject" ["*Confluence*"] {
      fileinto "[0] Atlassian.Confluence";
}

# Keep the rest.
# This is not necessary because there is a "implicit keep" Rule
#
else {
     keep;
}

Conclusion

With this simple scripting language and a number of easy-to-learn clauses you can filter-out e-mails (on any mail server supporting Sieve) easily and increase your productivity a little bit.

Blog post based on Wikipedia article and own experience.

Leave a Reply