Dovecot Sieve plugin
====================

 1. Dovecot Sieve plugin
     1. Introduction
     2. Getting the sources
     3. Compiling
     4. Configuring
     5. Per-user Sieve script location
     6. Script compiling and errors
     7. How to stop using sieve
     8. Features
         1. CMUSieve Plug-in
         2. New Sieve Plug-in
     9. ManageSieve server
     10. Validate your script
     11. v1.0 namespaces and fileinto
     12. Vacation auto-reply
     13. Example scripts
          1. SpamAssassin tagged mail filtering
          2. Mail filtering by various headers
          3. Flagging or Highlighting your mail
          4. Vacation auto-reply
          5. Include scripts
     14. French Howto
     15. Migration from Procmail

Introduction
------------

The Dovecot Sieve plug-in provides mail filtering facilities at time of final
message delivery using the Sieve (RFC 5228
[http://www.ietf.org/rfc/rfc5228.txt]) language. By writing Sieve scripts,
users can customize how messages are delivered, e.g. whether they are forwarded
or stored in special folders. The Sieve language is meant to be simple,
extensible and system independent. And, unlike most other mail filtering script
languages, it does not allow users to execute arbitrary programs. This is
particularly useful to prevent virtual users from having full access to the
mail store. The intention of the language is to make it impossible for users to
do anything more complex (and dangerous) than write simple mail filters.

This wiki page explains how to use the Sieve language with Dovecot. It is
implemented as a plug-in to the deliver [http://wiki.dovecot.org/LDA] LDA.
Currently, two concurrent implementations of the Sieve plug-in are available.
The original plug-in called *CMUSieve* uses the Sieve interpreter from the
Cyrus project and has been available for Dovecot versions ranging from v1.0 to
the latest v1.2. Recently, a fully rewritten implementation was released for
Dovecot v1.2. This new plug-in is simply called *Sieve*. The main reason for
rewriting the Sieve engine is to provide more reliable script execution and to
provide better error messages to users and system administrators.

Getting the sources
-------------------

Both implementations of the Sieve plug-in are distributed in a separate
package:

 * You can get the CMUSieve plug-in from Dovecot's download page
   [http://www.dovecot.org/download.html].
 * You can get the new Sieve plug-in at this web page
   [http://www.rename-it.nl/dovecot/1.2/]. The tarballs for the Sieve releases
   are called dovecot-1.2-sieve-x.y.z.tar.gz in which the x.y.z represents the
   particular version.

Alternatively, you can obtain the latest versions from Mercurial repositories:

 * The CMUSieve plug-in has different repositories for the available Dovecot
   versions:
    * For v1.0: 'http://hg.dovecot.org/dovecot-sieve-1.0'
    * For v1.1 and v1.2: 'http://hg.dovecot.org/dovecot-sieve-1.1'
 * The repository of the new Sieve plugin is:
   'http://hg.rename-it.nl/dovecot-libsieve'

In Ubuntu, starting from version 7.10 Gutsy, the CMUSieve plug-in already comes
with Dovecot regular install. In this case you do not have to download
additional packages. Simply skip "Compiling" section and proceed to
"Configuring". This is also true for Debian Etch.

Compiling
---------

Compilation is identical among the CMUSieve and the new Sieve plug-in. Use
'--with-dovecot=<path>' to point to 'dovecot-config' file's directory. There
are two possibilities where this could exist:

 1. If you configured Dovecot with '--enable-header-install', you'll have
    'dovecot-config' installed in '$prefix/lib/dovecot/' directory.
 2. Compiled Dovecot sources' root directory.

So for example:

---%<-------------------------------------------------------------------------
./configure --with-dovecot=/usr/local/lib/dovecot
make
sudo make install
---%<-------------------------------------------------------------------------

If you downloaded the sources using Mercurial, you will need to execute
'./autogen.sh' first to build the automake structure in your source tree. This
process requires autotools and libtool to be installed.

Binaries for command line tools like 'sievec' and 'sieved' are built only if
you use method 2, because they need to link with Dovecot's libraries. These two
tools can be used to compile and decompile Sieve scripts. You probably do not
need these, except when using the Python<ManageSieve.txt> server (it uses
'sievec' to verify uploaded scripts). The new Sieve implementation has a few
additional tools that can be used to verify and debug scripts from the command
line (refer to the README file for more information).

Configuring
-----------

First, you'll need to make sure you're using Dovecot's <deliver> [LDA.txt] to
deliver incoming mail to users' mailboxes. Then you need to enable the Sieve
plugin in your 'dovecot.conf'. The CMUSieve plugin is called 'cmusieve' and the
new Sieve plugin is called 'sieve'. The CMUSieve plugin is for example enabled
as follows:

---%<-------------------------------------------------------------------------
protocol lda {
..
  # If there is no user-specific Sieve-script, global Sieve script is
  # executed if set. (v1.0.1 and older used "global_script_path")
  # (e.g. /etc/dovecot/default.sieve)
  #sieve_global_path =
  # Support for dynamically loadable plugins. mail_plugins is a space separated
  # list of plugins to load.
  mail_plugins = cmusieve # ... other plugins like quota
}
---%<-------------------------------------------------------------------------

In this context /sieve_global_path/ refers to a *filename*, and not a
directory.

Per-user Sieve script location
------------------------------

By default Dovecot looks for user's Sieve script from '.dovecot.sieve' file in
user's home directory. This requires that the<home directory>
[VirtualUsers.txt] is set for the user.

If you want to store the script elsewhere, you can override the default by
returning 'sieve' setting containing path to the file. This can be done in two
ways:

 1. Define 'sieve' setting in plugin section of 'dovecot.conf'.
 2. Return 'sieve' extra field from <userdb extra fields>
    [UserDatabase.ExtraFields.txt].

For example to create a Sieve script file named '<username>.sieve' in
'/var/sieve-scripts', use:

---%<-------------------------------------------------------------------------
plugin {
 # NOTE: %variable expansion works only with Dovecot v1.0.2+
 sieve = /var/sieve-scripts/%u.sieve
}
---%<-------------------------------------------------------------------------

You may use templates like %u in the example. See all <variables>
[Variables.txt].

A relative path (or just a filename) will be interpreted to point under the
user's home directory.

Script compiling and errors
---------------------------

When the Sieve script is executed for the first time (or after it has been
changed), it's compiled into into a binary form. This is where the CMUSieve
plug-in and the new Sieve plug-in differ:

 * For CMUSieve, the binary is stored by appending "c" letter after the script
   name (e.g. ".dovecot.sievec"). If there are errors in the script, the error
   messages are stored into a ".err" file (e.g. ".dovecot.sieve.err"). This
   means that deliver must have write access to the directory where the script
   is stored. Global scripts have the same problem. Either allow deliver to
   write to the global script's directory, or compile the script before deliver
   sees it. Scripts can be compiled using the 'sievec' tool.
 * The new Sieve implementation uses the '.svbin' extension to store compiled
   Sieve scripts (e.g. ".dovecot.svbin"). If there are errors or warnings in
   the script, the messages are appended to a ".log" file (e.g.
   ".dovecot.sieve.log") until it grows too large. When that happens, the old
   log file is rotated to a ".log.0" file and an empty log file is started.
   Currently, scripts included using the include extension are compiled into
   the main binary, meaning that the plug-in only needs write access to the
   directory where the main script is located. This is also where the log file
   is always written. Messages that could be of interest to the system
   administrator are also written to the Dovecot logging facility (usually
   syslog).

How to stop using sieve
-----------------------

A user may want to stop using his/her own sieve (and maybe return to using
global sieve script). Or the administrator may want to disable global sieve.

To stop using sieve, both the .sieve source file and the compiled .sieve *c*
file must be deleted(or renamed).

Features
--------

Both implementations of the Sieve plug-in support various extensions to the
Sieve language. You can find more information about these at the Sieve Mail
Filtering Language Charter
[http://www.ietf.org/html.charters/sieve-charter.html] or the Sieve.info wiki
page [http://www.sieve.info/].

*NB: Sieve doesn't support running external programs*.

CMUSieve Plug-in
----------------

The CMUSieve plugin v1.0.x code is taken from Cyrus IMAP v2.2.12. The CMUSieve
plugin v1.1.x code is taken from Cyrus IMAP v2.3.8. Whatever information you
can find about those versions of Cyrus Sieve, it should also apply to these
plug-ins.

The supported Sieve features are:

 * fileinto
 * reject
 * envelope
 * vacation
 * imapflags (old draft specification)
 * notify (old draft specification)
 * regex
 * subaddress
 * relational
 * copy (v1.1 only)
 * body (v1.1 only)
 * include (v1.1 only)

New Sieve Plug-in
-----------------

The new Sieve plug-in aims to at least match the extensions supported by the
CMUSieve plug-in:

 * fileinto
 * reject
 * envelope
 * vacation
 * imap4flags
 * regex
 * subaddress
 * relational
 * copy
 * body
 * include
 * encoded-character
 * variables

In this respect the notify extension is notably missing. This is currently
under development. Note that the CMUSieve plug-in implements an older
specification that calls this extension *notify* and not *enotify* as it is
called nowadays. Something similar is true for the *imapflags* extension which
is now called *imap4flags*. The most valuable extension that the new Sieve
implementation adds to the list is the *variables* extension. As the name
implies, this adds support for variables to the language.

ManageSieve server
------------------

To give users the ability to upload their own Sieve scripts to your server,
i.e. without the need for shell or FTP access, you can use the Manage ''Sieve
protocol. Two alternatives are available for Dovecot:

 * Python implementation: http://woozle.org/~neale/src/pysieved/
 * <Dovecot native ManageSieve implementation> [ManageSieve.txt]

Validate your script
--------------------

Use the following page to validate your sieve rules:
http://libsieve-php.sourceforge.net/

v1.0 namespaces and fileinto
----------------------------

Dovecot v1.0's deliver doesn't support namespaces, so if you have a namespace
prefix configured for IMAP, you must not use it with *fileinto* command. This
also means that delivering mails to multiple namespaces isn't possible.

v1.1's deliver supports namespaces and the namespace prefixes must be used with
*fileinto* commands.

Vacation auto-reply
-------------------

Vacation uses envelope sender and envelope recipient. They're taken from:

 * v1.0:
    * Envelope sender: Return-Path: header in the message.
    * Envelope recipient: -d parameter to deliver. If -d isn't given
      (delivering to system users), the $USER environment is used.
 * v1.1:
    * Envelope sender: -f parameter to deliver if given, otherwise Return-Path:
      header in the message.
    * Envelope recipient: -a parameter to deliver if given, otherwise -d
      parameter to deliver. If neither is given (delivering to system users),
      the $USER environment is used.

The vacation replies are sent to the envelope sender.

List of autoreplied senders is stored in '.dovecot.lda-dupes' file in user's
home directory. When you're testing the vacation feature, it's easy to forget
that the reply is sent only once in the number of configured days. If you've
problems getting the vacation reply, try deleting this file. If that didn't
help, make sure the problem isn't related to sending mails in general by trying
the "reject" Sieve command.

The automatic replies aren't sent if any of the following is true:

 * Auto-Submitted: header exists with any value except "no"
 * Precedence: header exists with value "junk", "bulk" or "list"
 * The envelope sender
    * begins with "MAILER-DAEMON" (case-insensitive)
    * begins with "LISTSERV" (case-insensitive)
    * begins with "majordomo" (case-insensitive)
    * begins with "owner-" (case-sensitive)
    * contains the string "-request" anywhere within it (case-sensitive)
 * The envelope sender and envelope recipient are the same
 * The envelope recipient is not found in the message To:, Cc: or Bcc: fields.

A bare username without a domain gets canonicalised by the libsieve code to
"<username>@unspecified-domain", which means it is highly unlikely to pass the
last two tests in the list above.

Example scripts
---------------

Below are some simple Sieve code examples, more can be found from
http://libsieve.sourceforge.net/script1.php and
http://wiki.fastmail.fm/index.php?title=SieveExamples.

SpamAssassin tagged mail filtering
----------------------------------

Redirect <SpamAssassin.txt> tagged mails into mbox folder "spam":

---%<-------------------------------------------------------------------------
require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
  fileinto "spam";
}
---%<-------------------------------------------------------------------------

Discard <SpamAssassin.txt> tagged mails:

---%<-------------------------------------------------------------------------
if header :contains "X-Spam-Flag" "YES" {
  discard;
}
---%<-------------------------------------------------------------------------

Mail filtering by various headers
---------------------------------

Use if/elsif/else to store messages into various folders/subfolders:

 * ---%<----------------------------------------------------------------------
   require "fileinto";
   if address :is "to" "dovecot@dovecot.org" {
     fileinto "Dovecot-list";
   } elsif address :is "Return-path" "owner-cipe-l@inka.de" {
     fileinto "lists.cipe";
   } elsif anyof (header :contains "X-listname" "lugog@cip.rz.fh-offenburg.de",
                  header :contains "List-Id" "Linux User Group Offenburg") {
     fileinto "ml.lugog";
   } else {
     # The rest goes into INBOX
     # default is "implicit keep", we do it explicitly here
     keep;
   }
   ---%<----------------------------------------------------------------------
   "anyof" means logical OR, "allof" is AND.

Forward mails with "order" or "buy" in their subject to another address:

 * ---%<----------------------------------------------------------------------
   if header :contains "subject" ["order", "buy"] {
     redirect "orders@company.dom";
   }
   ---%<----------------------------------------------------------------------

Message-ID and recipient of forwarded message are stored in a
'.dovecot.lda-dupes' at users home directory to prevent mail loops.

Flagging or Highlighting your mail
----------------------------------

Some mail readers use these flags:

---%<-------------------------------------------------------------------------
require "imapflags";
if anyof (exists "X-Cron-Env",
          header :regex    ["subject"] [".* security run output",
                                        ".* monthly run output",
                                        ".* daily run output",
                                        ".* weekly run output"]) {
  addflag "$label1"; # ie 'Important'/red label within Thunderbird

# Other flags:
# addflag "$label1";  # Important: #ff0000 => red
# addflag "$label2";  # Work:      #ff9900 => orange
# addflag "$label3";  # personal:  #009900 => green
# addflag "$label4";  # todo:      #3333ff => blue
# addflag "$label5";  # later:     #993399 => violet
#
}
---%<-------------------------------------------------------------------------

Local copy of your emails:

---%<-------------------------------------------------------------------------
if address ["Return-Path"] ["my_address@my_domain.com"]
{
   setflag "\\seen";
}
---%<-------------------------------------------------------------------------

/Useful, when you want sieve to manage your incoming *and* outgoing email (you
must ask your mail reader to Bcc your mail to your dovecot in this case)./

More flags fun can be found here:

Vacation auto-reply
-------------------

---%<-------------------------------------------------------------------------
require ["fileinto", "vacation"];
# Move spam to spam folder
if header :contains "X-Spam-Flag" "YES" {
  fileinto "spam";
  # Stop here so that we do not reply on spams
  stop;
}
vacation
  # Reply at most once a day to a same sender
  :days 1
  :subject "Out of office reply"
  # 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.
  :addresses ["j.doe@company.dom", "john.doe@company.dom"]
"I'm out of office, please contact Joan Doe instead.
Best regards
John Doe";
---%<-------------------------------------------------------------------------

Include scripts
---------------

With v1.1 it's possible to include other Sieve scripts in your script:

---%<-------------------------------------------------------------------------
require ["include"];
include :global "global-spam.sieve";
include :personal "my-own-spam.sieve";
---%<-------------------------------------------------------------------------

If you want to use global scripts, you'll need to set up the global script
directory:

---%<-------------------------------------------------------------------------
protocol lda {
  # ..
  sieve_global_dir = /etc/dovecot/sieve/
}
---%<-------------------------------------------------------------------------

Personal scripts are looked up from 'sieve_dir' if it's returned in <userdb
extra fields> [UserDatabase.ExtraFields.txt], or home directory if not. If
neither is known, the include fails.

It's not currently possible to use subdirectories for the scripts. Having a '/'
character in the script name always fails the include. This is just an extra
check to avoid potential problems with including scripts within mail
directories.

French Howto
------------

http://casys.crevetor.org/index.php/Filtres_côté_serveur

Migration from Procmail
-----------------------

There exists a script which attempts to translate simple Procmail rules into
Sieve rules:http://www.earth.ox.ac.uk/~steve/sieve/procmail2sieve.pl
(dovecot.org mirror [http://dovecot.org/tools/procmail2sieve.pl])

Here's the original post announcing it:
http://dovecot.org/list/dovecot/2007-March/020895.html 

(This file was created from the wiki on 2009-01-07 04:42)
