Server Side Mail Filtering using Sieve

Server Side Mail Filtering using Sieve

Sieve is a language designed to filter mail, and is used for server side filtering. Filtering e-mail on the server means that you set-up your filters once on the server and they will be applied to all mail you recieve. Your server side filter will always be used independent of mail client. Thus all your clients ( different e-mail programs on different machines, and webmail ) will be free of filtering rules, which may be hard/impossible to get in sync between different software. Also, while the filter is being applied on the server, the mail folder indexes are updated; this makes your e-mail access faster.

Using the Sieve Plugin in Webmail

You can use the sieve plugin in Roundcube Webmail to add/edit mail filtering rules rules. You can access the plugin via Settings→Filtering in Roundcube. You will found a default rule for spam mails, please leave it in place for proper spam filtering into spam mailbox. You can add new rules after the spam rule.

Manually Editing the Sieve File

Sieve language can be used to organize your e-mails to different folders as it arrives on the mail server. You can use it so seperate mailing lists, course related e-mail from your inbox. Or you can give out e-mails like 'myuser+amazon@ceng.metu.edu.tr' to distinguish e-mails given to web sites. Also you can use it for vacation autoresponder and rejecting, discarding, forwarding e-mail. The filtering language looks familiar, with C-like syntax.

You can use sieve by putting your filtering script in ~/.dovecot.sieve. The file DOES NOT need to be group or world readable. After you change the script send yourself a test mail. If there is an error in your sieve script, a file named ”.dovecot.sieve.err” will be created under your home directory, and this file will contain the error message. If there is an error, no filtering will be done and mails will be delivered to your inbox. If there are no errors, a compiled sieve file will appear with the name ”.dovecot.sievec” under your home directory, and your filters will be applied.

Here is how a sieve script operates:

  • A script will begin with a 'require' directive. That will enable needed extensions.
  • Then filtering rules will follow, with C-like syntax.
  • Filter rules can match a number of properties in mails;
    • From/To addresses with 'address' match, Subject headers and any custom headers with 'header' match.
    • The 'body' of the match will include actions like; fileinto, redirect, discard, reject… The actions are followed by a semi-colon, don't forget it. Note: For the “fileinto” action, which puts the mail in a mailbox, you have to create the mailbox with the same name used in the filer rule. Otherwise, if there is no such mailbox present, the mail will be put into your inbox.
  • Mail will continue to be processed by each rule until the file ends; if many independent rules match a mail, all of those rules will take actions on the mail. You can terminate processing of a mail by using 'stop' action.

Please see the example script below to learn how to create sieve rules. Also see the mail services page for general info about mail server and links to other example sieve scripts. You can use some advanced things with sieve, like setting IMAP flags, filtering based on regular expressions, etc.

Example Sieve Script

Here is the example script that you can use to form your own. Please also read the comments which explain sieve's operation.

/*
   ============= Example sieve script ============
*/
##### We will 'require' necessary modules first.
# Comments can be C-style or bash/perl/python style
require [ "fileinto", "subaddress", "vacation" ];
##### Filter the spam into your spam folder. This is done 
# on the global sieve script by default IF you don't have 
# a .dovecot.sieve file.  When you create your sieve script,
# the global one will be disabled so you have to filter 
# the spam in your own script.
if header :is "X-Spam-Flag" "YES" {
    fileinto "spam";
    stop; #---- this stops further processing; 
    #prevents sending replies and/or redirecting(forwarding)
}
##### If you have forwarded your other e-mail accounts to
# department e-mail, you can filter them into their own folders.
# Note that arrays can be used with square brackets.
if address :is [ "to", "cc", "bcc" ] "myself@cmail.com" { 
    fileinto "forwarded-cmail"; 
    stop;
}
##### Logical operators equivalents;
#     OR:  anyof 
#     AND: allof
#     NOT: not
if anyof ( address :is "from" 
			  [ "gueststudent1@example.com", 
			    "gueststudent2@example.com" ] ,
           header :contains "subject" "CENG777" ) 
{
    fileinto "courses";
    stop;
}
##### Rule for 'plus addressing/address extension' like gmail filters.
# If you give "myaddr+shopping@ceng.metu.edu.tr" as e-mail to 
# shopping sites, the following will put all mail sent to that address
# into 'shoppingMania' mailbox. Remeber to create the mailbox itself before
# using this rule
if address :detail "to" "shopping" { fileinto "shoppingMania"; stop; }
##### Send some of my mail to my brother.
# ':matches' is used for wildcard matches;
#     *: zero or more characters
#     ?: a single character
# This example matches 'Summer vacation photos' ,
# and also 'Istanbul vacation photo'

if header :matches "subject" "* vacation photo?" {  
    redirect "mybrother@hisuniversity.edu.tr";
    stop;
}

# ALSO you can use 'redirect' action as an 'advanced .forward file'
# If you redirect to your other addresses after the spam filter, 
# and outside an 'if' block the spams will not be redirected 
# and will be delivered to your department spambox. All other
# mail will be forwarded to your other address. 
# This usage is recommended over .forward files

# redirect "myotheraddress@example.com";



##### My friend forwards some annoying things, discard those 'Fwd' things 
# but not her other messages, hence allof(logical AND) is used

if allof (address :contains "from" "nova777@cmail.com",
            header :contains "subject" "Fwd") {
    discard;
    stop;
}

##### A complex rule for matching various development lists.
# You can use two arrays in a rule, like the 'header' rule in the first line.
# 'exists' checks for existance of mail headers inserted by some web services.
# The array syntax means AND in 'exists' match, so check them seperately.
# The ':is' can be omitted if you want, as can be seen in 'address' match

if anyof (header :contains [ "List-Id" , "X-Trac-Project" ]
                [ "RoundCube" ,
                    "screen-users.gnu.org",
                    "pdf-devel.gnu.org",
                    "gentoo-dev.gentoo.org",
                    "prayer-announce.lists.cam.ac.uk"
               ] ,
          address "From" "bugzilla-daemon@gentoo.org" ,
          exists "X-Savane-Server",  
          exists "X-Launchpad-Bug", 
          exists "X-Debian-PR-Message" 
  ) 
{
    fileinto "developersTimesThree";
    stop;
}


##### Vacation autoresponder.
# If you are away for vacation, set something like this.
# Do not overuse this feature as it tends to get annoying, 
# and generates unnecessary mail trafic on many servers.

vacation
# Reply at most once a week to a same sender
  :days 7
  :subject "Gone fishing"
# List of recipient addresses which are included in the auto replying.
# If a mail's recipient is not on this list, no vacation reply is sent for it.
# this feature is used to prevent replies to mailing lists.
 :addresses ["name.surname@ceng.metu.edu.tr", "e1234567@ceng.metu.edu.tr"]
"Having a lovely fishing trip, You can reach me from my cell phone 
if the issue is urgent ( 0 5xx 123 45 67 )

Best regards

- Ali Veli";