Pigeonhole Sieve Configuration

Script Locations

The Sieve interpreter can retrieve Sieve scripts from several types of locations. The default file location type is a directory containing one or more Sieve script files with a symlink pointing to the active one. More complex setups can use other location types such as ldap or dict to fetch Sieve scripts from remote databases.

All settings that specify the location of one or more Sieve scripts accept the following syntax:

<setting> = [<type>:]path[;<option>[=<value>][;...]]

The following script location types are implemented by default:


The location path is a file system path pointing to a directory containing one or more script files with names structured as <script-name>.sieve with the active option (default ~/.dovecot.sieve) specifying a symlink to the one that will be used, or without the active option specified, it may be a script file instead of a directory.


The location path is a Dovecot dict uri.


LDAP database lookup. The location path is a configuration file with LDAP options.

If the type prefix is omitted, the script location type is file and the location is interpreted as a local filesystem path pointing to a Sieve script file or directory.

The following options are defined for all location types:


Set the name of the Sieve script that this location points to. If the name of the Sieve script is not contained in the location path and the location of a single script is specified, this option is required (e.g. for dict locations that must point to a particular script). If the name of the script is contained in the location path, the value of the name option overrides the name retrieved from the location. If the Sieve interpreter explicitly queries for a specific name (e.g. to let the Sieve include extension <pigeonhole_extension_include> retrieve a script from the sieve_global location), this option has no effect.


Points to the directory where the compiled binaries for this script location are stored. This directory is created automatically if possible. If this option is omitted, the behavior depends on the location type. For file type locations, the binary is then stored in the same directory as where the script file was found if possible. For `dict’ type locations, the binary is not stored at all in that case. Don’t specify the same directory for different script locations, as this will result in undefined behavior. Multiple mail users can share a single script directory if the script location is the same and all users share the same system credentials (uid, gid).


Pigeonhole versions before v0.3.1 do not support the location syntax described here. These versions only support bare filesystem paths pointing to files or directories as script storage location. Also, in that case a few additional deprecated settings are needed for configuration.

Basic Configuration

To use Sieve, you will first need to make sure you are using Dovecot LDA or LMTP for delivering incoming mail to users’ mailboxes. Then, you need to enable the Pigeonhole Sieve plugin in your configuration:

protocol lda {
  mail_plugins = $mail_plugins sieve
protocol lmtp {
  mail_plugins = $mail_plugins sieve

The sieve plugin recognizes the following configuration options in the plugin section of the config file (default values are shown if applicable):

sieve = file:~/sieve;active=~/.dovecot.sieve

The location of the user’s main Sieve script or script storage. The LDA Sieve plugin uses this to find the active script for Sieve filtering at delivery. The Sieve include extension uses this location for retrieving “:personal” scripts.

This location is also where the ManageSieve service will store the user’s scripts, if supported by the location type. For the file location type, the location will then be the path to the storage directory for all the user’s personal Sieve scripts. ManageSieve maintains a symbolic link pointing to the currently active script (the script executed at delivery). The location of this symbolic link can be configured using the ;active=<path> option.

For Pigeonhole versions before v0.3.1, this setting can only be a filesystem path pointing to a script file, or - when ManageSieve is used - it is the location of the symbolic link pointing to the active script in the storage directory. That storage directory is then configured using the deprecated sieve_dir setting.

sieve_default = (v0.3+)

The location of the default personal sieve script file which gets executed ONLY if user’s private Sieve script does not exist, e.g. file:/var/lib/dovecot/default.sieve (check the multiscript section for instructions on running global Sieve scripts before and after the user’s personal script). This is usually a global script, so be sure to pre-compile the specified script manually in that case using the sievec command line tool, as explained here. This setting used to be called sieve_global_path, but that name is now deprecated.

sieve_default_name = (v0.4.8+)

The name by which the default Sieve script is visible to ManageSieve clients. Normally, it is not visible at all. Refer to the visible default script section for more information.

sieve_global =

Location for :global include scripts for the Sieve include extension. This setting used to be called sieve_global_dir, but that name is now deprecated.

sieve_discard = (v0.4.16+)

The location of a Sieve script that is run for any message that is about to be discarded; i.e., it is not delivered anywhere by the normal Sieve execution. This only happens when the “implicit keep” is canceled, by e.g. the “discard” action, and no actions that deliver the message are executed. This “discard script” can prevent discarding the message, by executing alternative actions. If the discard script does nothing, the message is still discarded as it would be when no discard script is configured.

sieve_extensions =

Which Sieve language extensions are available to users. By default, all supported extensions are available, except for deprecated extensions, extensions that add the ability to change messages, extensions that require explicit configuration or extensions that are still under development. Some system administrators may want to disable certain Sieve extensions or enable those that are not available by default. All supported extensions are listed here. Normally, all enabled extensions must be listed for this setting, but starting with Pigeonhole version 0.1.7, this setting can use ‘+’ and ‘-’ to specify differences relative to the default. For example sieve_extensions = +imapflags will enable the deprecated imapflags extension in addition to all extensions enabled by default.

sieve_global_extensions = (v0.3+)

Which Sieve language extensions are ONLY available in global scripts. This can be used to restrict the use of certain Sieve extensions to administrator control, for instance when these extensions can cause security concerns. This setting has higher precedence than the sieve_extensions setting (above), meaning that the extensions enabled with this setting are never available to the user’s personal script no matter what is specified for the sieve_extensions setting. The syntax of this setting is similar to the sieve_extensions setting, with the difference that extensions are enabled or disabled for exclusive use in global scripts. Currently, no extensions are marked as such by default.

sieve_implicit_extensions = (v0.4.13+)

Which Sieve language extensions are implicitly available to users. The extensions listed in this setting do not need to be enabled explicitly using the Sieve “require” command. This behavior directly violates the Sieve standard, but can be necessary for compatibility with some existing implementations of Sieve (notably jSieve). Do not use this setting unless you really need to! The syntax and semantics of this setting are otherwise identical to the sieve_extensions setting.

sieve_plugins =

The Pigeonhole Sieve interpreter can have plugins of its own. Using this setting, the used plugins can be specified. Check the Sieve extensions and plugins for available plugins.

sieve_user_email = (v0.4.14+)

The primary e-mail address for the user. This is used as a default when no other appropriate address is available for sending messages. If this setting is not configured, either the postmaster or null “<>” address is used as a sender, depending on the action involved. This setting is important when there is no message envelope to extract addresses from, such as when the script is executed in IMAP.

sieve_user_log =

The path to the file where the user log file is written. If not configured, a default location is used. If the main user’s personal Sieve (as configured with sieve) is a file, the logfile is set to <filename>.log by default. If it is not a file, the default user log file is ~/.dovecot.sieve.log.

recipient_delimiter = +

The separator that is expected between the :user and :detail address parts introduced by the subaddress extension (RFC 5233). This may also be a sequence of characters (e.g. ‘–‘). The current implementation looks for the separator from the left of the localpart and uses the first one encountered. The :user part is left of the separator and the :detail part is right. This setting is also used by Dovecot’s LMTP service with identical semantics.

sieve_redirect_envelope_from = sender (v0.4.4+)

Specifies what envelope sender address is used for redirected messages. Normally, the Sieve “redirect” command copies the sender address for the redirected message from the processed message. So, the redirected message appears to originate from the original sender. The following values are supported for this setting:


The sender address is used (default)


The final recipient address is used


The original recipient is used

“user_email” (v0.4.14+)

The user’s primary address is used. This is configured with the “sieve_user_email” setting. If that setting is not configured, “user_mail” is equal to “sender” (the default).


The postmaster_address configured for LDA/LMTP.


Redirected messages are always sent from user@domain. The angle brackets are mandatory. The null “<>” address is also supported.

When the envelope sender of the processed message is the null address “<>”, the envelope sender of the redirected message is also always “<>”, irrespective of what is configured for this setting.

For example:

plugin {
   # The location of the user's main script storage. The active script
   # in this storage is used as the main user script executed during
   # delivery. The include extension fetches the :personal scripts
   # from this location. When ManageSieve is used, this is also where
   # scripts are uploaded. This example uses the file system as
   # storage, with all the user's scripts located in the directory
   # `~/sieve' and the active script (symbolic link) located at
   # `~/.dovecot.sieve'.
   sieve = file:~/sieve;active=~/.dovecot.sieve

   # If the user has no personal active script (i.e. if the location
   # indicated in sieve= does not exist or has no active script), use
   # this one:
   sieve_default = /var/lib/dovecot/sieve/default.sieve

   # The include extension fetches the :global scripts from this
   # location.
   sieve_global = /var/lib/dovecot/sieve/global/

Configurable Limits

sieve_max_script_size = 1M

The maximum size of a Sieve script. The compiler will refuse to compile any script larger than this limit. If set to 0, no limit on the script size is enforced.

sieve_max_actions = 32

The maximum number of actions that can be performed during a single script execution. If set to 0, no limit on the total number of actions is enforced.

sieve_max_redirects = 4

The maximum number of redirect actions that can be performed during a single script execution. The meaning of 0 differs based on your version. For versions v0.3.0 and beyond this means that redirect is prohibited. For older versions, however, this means that the number of redirects is unlimited, so be careful.

Extension-specific Configuration

The following Sieve language extensions have specific configuration options/needs:

Per-user Sieve script location

By default, the Dovecot Sieve plugin looks for the user’s Sieve script file in the user’s home directory (~/.dovecot.sieve). This requires that the home directory is set for the user.

If you want to store the script elsewhere, you can override the default using the sieve setting, which specifies the path to the user’s script file. This can be done in two ways:

  1. Define the sieve setting in the plugin section of dovecot.conf.

  2. Return sieve extra field from userdb extra fields.

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

plugin {

 sieve = /var/sieve-scripts/%u.sieve

You may use templates like %u, as shown in the example. See all variables.

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

Executing Multiple Scripts Sequentially

The Dovecot Sieve plugin allows executing multiple Sieve scripts sequentially. The extra scripts can be executed before and after the user’s private script. For example, this allows executing global Sieve policies before the user’s script. This is not possible using the sieve_default setting, because that is only used when the user’s private script does not exist. The following settings in the plugin section of the Dovecot config file control the execution sequence:

sieve_before =

sieve_before2 =

sieve_before3 = (etc..)

Location Sieve of scripts that need to be executed before the user’s personal script. If a file location path points to a directory, all the Sieve scripts contained therein (with the proper .sieve extension) are executed. The order of execution within that directory is determined by the file names, using a normal 8bit per-character comparison. Multiple script locations can be specified by appending an increasing number to the setting name. The Sieve scripts found from these locations are added to the script execution sequence in the specified order. Reading the numbered sieve_before settings stops at the first missing setting, so no numbers may be skipped.

sieve_after =

sieve_after2 =

sieve_after3 = (etc..)

Identical to sieve_before , but the specified scripts are executed after the user’s script (only when keep is still in effect, as explained below).

The script execution ends when the currently executing script in the sequence does not yield a “keep” result: when the script terminates, the next script is only executed if an implicit or explicit “keep” is in effect. Thus, to end all script execution, a script must not execute keep and it must cancel the implicit keep, e.g. by executing “discard; stop;”. This means that the command “keep;” has different semantics when used in a sequence of scripts. For normal Sieve execution, “keep;” is equivalent to “fileinto "INBOX";”, because both cause the message to be stored in INBOX. However, in sequential script execution, it only controls whether the next script is executed. Storing the message into INBOX (the default folder) is not done until the last script in the sequence executes (implicit) keep. To force storing the message into INBOX earlier in the sequence, the fileinto command can be used (with “:copy” or together with “keep;”).

Apart from the keep action, all actions triggered in a script in the sequence are executed before continuing to the next script. This means that when a script in the sequence encounters an error, actions from earlier executed scripts are not affected. The sequence is broken however, meaning that the script execution of the offending script is aborted and no further scripts are executed. An implicit keep is executed in stead.

Just as for executing a single script the normal way, the Dovecot Sieve plugin takes care never to duplicate deliveries, forwards or responses. When vacation actions are executed multiple times in different scripts, the usual error is not triggered: the subsequent duplicate vacation actions are simply discarded.

For example:

plugin {
   # Global scripts executed before the user's personal script.
   #   E.g. handling messages marked as dangerous
   sieve_before = /var/lib/dovecot/sieve/discard-viruses.sieve

   # Domain-level scripts retrieved from LDAP
   sieve_before2 = ldap:/etc/dovecot/sieve-ldap.conf;name=ldap-domain

   # User-specific scripts executed before the user's personal script.
   #   E.g. a vacation script managed through a non-ManageSieve GUI.
   sieve_before3 = /var/vmail/%d/%n/sieve-before

   # User-specific scripts executed after the user's personal script.
   # (if keep is still in effect)
   #   E.g. user-specific default mail filing rules
   sieve_after = /var/vmail/%d/%n/sieve-after

   # Global scripts executed after the user's personal script
   # (if keep is still in effect)
   #   E.g. default mail filing rules.
   sieve_after2 = /var/lib/dovecot/sieve/after.d/


Be sure to manually pre-compile the scripts specified by sieve_before and sieve_after using the sievec tool, as explained here.

Visible Default Script

The sieve_default setting specifies the location of a default script that is executed when the user has no active personal script. Normally, this default script is invisible to the user; i.e., it is not listed in ManageSieve. To give the user the ability to see and read the default script, it is possible to make it visible under a specific configurable name using the sieve_default_name setting. This feature is only supported for Pigeonhole versions 0.4.8 and higher.

ManageSieve will magically list the default script under that name, even though it does not actually exist in the user’s normal script storage location. This way, the ManageSieve client can see that it exists and it can retrieve its contents. If no normal script is active, the default is always listed as active. The user can replace the default with a custom script, by uploading it under the default script’s name. If that custom script is ever deleted, the default script will reappear from the shadows implicitly.

This way, ManageSieve clients will not need any special handling for this feature. If the name of the default script is equal to the name the client uses for the main script, it will initially see and read the default script when the user account is freshly created. The user can edit the script, and when the edited script is saved through the ManageSieve client, it will override the default script. If the user ever wants to revert to the default, the user only needs to delete the edited script and the default will reappear.

The name by which the default script will be known is configured using the sieve_default_name setting. Of course, the sieve_default setting needs to point to a valid script location as well for this to work. If the default script does not exist at the indicated location, it is not shown.

For example:

plugin {
  sieve = file:~/sieve;active=~/.dovecot.sieve

  sieve_default = /var/lib/dovecot/sieve/default.sieve
  sieve_default_name = roundcube

Trace Debugging

Trace debugging provides detailed insight in the operations performed by the Sieve script. Messages about what the Sieve script is doing are written to the specified directory. This feature is only supported for Pigeonhole versions 0.4.14 and higher.


On a busy server, this functionality can quickly fill up the trace directory with a lot of trace files. Enable this only temporarily and as selective as possible; e.g., enable this only for a few users by returning the settings below from userdb as userdb extra fields, rather than enabling these for everyone.

The following settings apply to both the LDA/LMTP Sieve plugin and the IMAPSieve plugin:

sieve_trace_dir =

The directory where trace files are written. Trace debugging is disabled if this setting is not configured or if the directory does not exist. If the path is relative or it starts with “~/” it is interpreted relative to the current user’s home directory.

sieve_trace_level =

The verbosity level of the trace messages. Trace debugging is disabled if this setting is not configured. Possible values are:


Only print executed action commands, like keep, fileinto, reject and redirect.


Print any executed command, excluding test commands.


Print all executed commands and performed tests.


Print all executed commands, performed tests and the values matched in those tests.

sieve_trace_debug = no

Enables highly verbose debugging messages that are usually only useful for developers.

sieve_trace_addresses = no

Enables showing byte code addresses in the trace output, rather than only the source line numbers.

Deprecated Settings

These settings are deprecated in newer versions, but still recognized:

sieve_global_path = (< v0.2)

The deprecated name for the sieve_default setting.

sieve_dir = ~/sieve (< v0.3.1)

Directory for :personal include scripts for the include extension. The Sieve interpreter only recognizes files that end with a .sieve extension, so the include extension expects a file called name.sieve to exist in the sieve_dir directory for a script called name. When using ManageSieve <pigeonhole_managesieve_server>, this is also the directory where scripts are uploaded. For recent Pigeonhole versions, this location is configured as part of the sieve setting.

sieve_global_dir = (< v0.3.1)

Directory for :global include scripts for the include extension. The Sieve interpreter only recognizes files that end with a .sieve extension, so the include extension expects a file called name.sieve to exist in the sieve_global_dir directory for a script called name. For recent Pigeonhole versions, a more generic version of this setting is called sieve_global and allows locations other than file system directories.


General Dovecot 2.0 changes

  • Note that the Dovecot v2.0 LDA does not create mailfolders automatically by default anymore. If your configuration relies on this, you need to enable the lda_mailbox_autocreate setting for LDA or start using the Sieve mailbox extension’s :create tag for fileinto commands.

  • Dovecot v2.0 adds support for LMTP. Much like the LDA it can make use of the Pigeonhole Sieve plugin. Since the LMTP service has its own protocol lmtp section in the config file, you need to add the Sieve plugin to the mail_plugins setting there too when you decide to use LMTP.

From CMUSieve (Dovecot v1.0/v1.1)

For the most part, migration from CMUSieve to Pigeonhole Sieve is just a matter of changing the used plugin name from cmusieve to sieve in the mail_plugins option in the protocol lda section of the config file (as explained above). However, there are a few important differences in the supported Sieve language features:

  • The imapflags extension is now called imap4flags. The CMUSieve implementation is based on an old imapflags draft specification that is not completely compatible with RFC 5232. Particularly, the mark and unmark commands were removed from the new specification. For backwards compatibility, support for the old imapflags extension can be enabled using the sieve_extensions setting. This is disabled by default.

  • The notify extension is now called enotify. The CMUSieve implementation is based on an old notify draft specification that is not completely compatible with RFC 5425. Particularly, the denotify command and $text$ substitutions were removed from the new specification. For backwards compatibility, support for the old imapflags extension can be enabled using the sieve_extensions setting. This is disabled by default.

  • The include extension now requires your script file names to end with “.sieve”. This means that include :personal "myscript" won’t work unless your script file is called “myscript.sieve” on disk. Also note that the “.sieve” extension has no special meaning within the Sieve script; if you include "myscript.sieve", the Sieve interpreter will look for a script file called myscript.sieve.sieve and not myscript.sieve.

  • Be sure to use UTF8 for the mailbox argument of the fileinto command. Older CMUSieve installations used modified UTF7 (as IMAP does) for the mailbox parameter. If not adjusted, the Pigeonhole Sieve plugin will use the wrong folder name for storing the message.

From Dovecot Sieve v0.1.x (Dovecot v1.2)