Provided by: maildrop_2.9.3-2.1_amd64 bug

NAME

       maildropfilter - maildrop's filtering language

SYNOPSIS

       /etc/maildroprc, $HOME/.mailfilter, $HOME/.mailfilters/*, and friends...

DESCRIPTION

       This manual page describes the language used by maildrop to filter E-mail messages. The
       mail filtering instructions are read from a file. The language is loosely structured, it
       is based on pattern matching. The language has a distinct lexical and syntactical
       structure, very similar to Perl's, but it is important to note that it is not Perl, and is
       very different from Perl, in certain cases.

       If the filtering instructions do not exist, maildrop delivers the message to the default
       mailbox without doing any additional processing, making it indistinguishable from the
       usual mail delivery agent.

       It is important to note that maildrop reads and parses the filter file before doing
       anything. If there are any errors maildrop prints an error message, and terminates with
       the exit code set to EX_TEMPFAIL. A compliant mail transport agent should re-queue the
       message for a later delivery attempt. Hopefully, most simple syntax errors will not cause
       mail to be bounced back if the error is caught and fixed quickly.

   Environment
       maildrop uses variables to access and manipulate messages. Variables are arbitrary text
       accessed by referring to the name of the variable, such as HOME, or DEFAULT. Text is
       placed into a variable by using an assignment statement, such as:

           FILE="IN.junk"

       This statement puts the text "IN.junk" (without the quotes) into a variable whose name is
       FILE. Later, the contents of a variable are accessed by using the $ symbol and the name
       for the variable. For example:

           to $FILE

       This will deliver the current message to the mailbox file (or a maildir directory) named
       "IN.junk".

       maildrop initially creates variables from the environment variables of the operating
       system, UNLESS maildrop runs in delivery mode. Each operating system environment variable
       becomes a maildrop variable. When running in delivery mode, maildrop does not import the
       environment for security reasons, except for the environment variables that define the
       process locale (LANG, LANGUAGE, and LC_*), which are still imported.

       In all cases maildrop resets the following variables to their default values: HOME,
       DEFAULT, SHELL, PATH, LOCKEXT, LOCKREFRESH, LOCKSLEEP, LOCKTIMEOUT, MAILDIRQUOTA, SENDMAIL
       and LOGNAME.

       There's one exception to this rule which applies to the version of maildrop that comes
       with the Courier mail server[1]. The following does not apply to the standalone version of
       maildrop: when running in delivery mode, if the -d flag was not used, or if it specifies
       the same userid as the one that's running maildrop: the following variables are
       automatically imported from the environment: HOME, SHELL, LOGNAME and MAILDIRQUOTA. These
       environment variables are initialized by the Courier mail server prior to running
       maildrop. Additionally, the initial value for the DEFAULT maildrop variable is imported
       from the MAILDROPDEFAULT environment variable. This is because the Courier mail server
       overloads the DEFAULT environment variable to store the defaulted portion of the local
       mailbox address. See the dot-courier(5)[2] man page in the Courier mail server
       distribution. You can get the Courier mail server's DEFAULT value by using the import
       command. Note, however, that this will clobber the old contents of DEFAULT, which is
       probably not what you want. The right way to do this would be something like this:

           SAVEDEFAULT=$DEFAULT
           import DEFAULT
           LOCALDEFAULT=$DEFAULT
           DEFAULT=$SAVEDEFAULT

       All internal variables are exported back as environment variables when maildrop runs an
       external command. Changes to internal variables, made by the filter file, are reflected in
       the exported environment.

   Lexical structure
       Most whitespace is generally ignored. The # character introduces a comment running to the
       end of the line, which is also ignored. Unlike other mail filters, maildrop parses the
       filter file before taking any action with the message. If there are syntax errors in the
       file, maildrop displays an error message, and returns EX_TEMPFAIL. That should cause the
       mail message to remain in the queue, and, hopefully allow the problem to be corrected,
       without bouncing any mail.

           Note
           In maildrop, the end of line is a lexical token. In order to continue a long statement
           on the next line, terminate the line with a backslash character.

   Literal text
       Literal text in the maildrop filtering language is surrounded by either single or double
       quotes. In order to enter a single quote into a text literal surrounded by single quotes,
       or a double quote into a literal surrounded by double quotes, prefix it with a backslash
       character. Use two backslash characters characters to enter one backslash character in the
       text literal.

           Note
           A backslash followed by either a backslash, or a matching quote, is the only situation
           where the backslash character is actually removed, leaving only the following
           character in the actual text literal. If a backslash character is followed by any
           other character, the backslash is NOT removed.

       Multiple text literals in a row are automatically concatenated, even if they use different
       quotes. For example:

           FOOBAR="Foo"'bar'
           SAVEDEFAULT=$DEFAULT
           import DEFAULT
           LOCALDEFAULT=$DEFAULT
           DEFAULT=$SAVEDEFAULT

       This sets the variable FOOBAR to the text "Foobar".

   Variable substitution
       Variable substitution is performed on text literals that's surrounded by double quotation
       marks. The "$" character, followed by a variable name, is replaced by that variable's
       contents.

           MAILBOX="$HOME/Mailbox"

       This sets the variable MAILBOX to the contents of the variable HOME followed by
       "/Mailbox". Variable names must begin with an uppercase letter, a lowercase letter, or an
       underscore. Following that, all letters, digits, and underscores are taken as a variable
       name, and its contents replace the $ sign, and the variable name. It is possible to access
       variables whose name includes other characters, by using braces as follows:

           MAILBOX="${HOME-WORD}/Mailbox"

       Inserts the contents of the HOME-WORD variable. If the variable does not exist, the empty
       text literal is used to replace the variable name. It is not possible to access variables
       whose names include the } character.

       If the $ character is not followed by a left brace, letter, or an underscore, the $
       character remains unmolested in the text literal. A backslash followed by the $ character
       results in a $ character in the text literal, without doing any variable substitution.

       Variable substitution is not done in text literals which are surrounded by single quotes
       (apostrophes).

   Command line arguments
       maildrop initializes special variables: $1, $2, and so on, with additional parameters
       specified on the maildrop command line. A filter file may use those variables just like
       any other variables.

   Predefined variables
       The following variables are automatically defined by maildrop. The default values for the
       following variables may be changed by the system administrator. For security reasons, the
       values of the following variables are always reset to their default values, and are never
       imported from the environment:

       DEFAULT
           The default mailbox to deliver the message to. If the filter file does not indicate a
           mailbox to deliver this message to, the message is delivered to this mailbox. The
           default mailbox is defined by the system administrator.

       FROM
           Message envelope sender. This is usually the same address as what appears in the From:
           header, but may not be. This information may or may not be available to maildrop on
           your system. The message envelope sender is usually specified with the -f option to
           maildrop. If the -f option is not given, maildrop looks for the Return-Path: header in
           the message. As the last resort, FROM defaults to “MAILER-DAEMON”. Note that FROM may
           be empty - the message envelope sender is empty for bounce messages.

       HOME
           Home directory of the user running maildrop.

       HOSTNAME
           Network name of the machine running maildrop. Obtained from gethostname(3).

       LOCKEXT
           Extension for dot-lock files (default: .lock).

       LOCKREFRESH
           Refresh interval, in seconds, for dot-locks (default: 15). When maildrop dot-locks a
           mailbox, maildrop tries to refresh the lock periodically in order to keep other
           programs from removing a stale dot-lock. This is only required if a dot-lock exists
           for a prolonged period of time, which should be discouraged anyway.

       LOCKSLEEP
           Number of seconds to wait to try again to create a dot-lock file, if one already
           exists (default: 5).

       LOCKTIMEOUT
           Number of seconds to wait before removing a stale dot-lock file (default: 60). If a
           dot-lock file still exists after LOCKTIMEOUT seconds, maildrop assumes that the
           process holding the lock no longer exists, and the dot-lock file can be safely
           removed. After removing the dot-lock file, maildrop waits LOCKSLEEP seconds before
           trying to create its own dot-lock file, in order to avoid a race condition with
           another process which is also trying to remove the same stale dot-lock, at the same
           time.

       LOGNAME
           Name of the user to who the message is being delivered.

       MAILDROP_OLD_REGEXP
           Revert to using the old legacy pattern matching engine. Versions of maildrop prior to
           version 2.0 (included in the Courier mail server 0.51, and earlier), used a built-in
           pattern matching engine, instead of using the PCRE library (see the “Patterns”
           section).  maildrop 1.x used a different syntax for patterns, which is no longer
           described in this manual page. The old pattern matching engine is still available, by
           setting MAILDROP_OLD_REGEXP to “1”. Setting this variable will use the legacy pattern
           matching engine for the rest of the maildrop recipe file.

           The pattern matching engine will be removed completely in a future version of
           maildrop. This setting provides for a transitional period of converting old recipes.
           MAILDROP_OLD_REGEXP can be set to “1” in the global maildroprc file, then reset to “0”
           in each individual maildrop recipe file, after it gets converted to the new syntax.

       MAILFILTER
           This is the name of the original filter file that was given to maildrop on the command
           line. This is mostly useful to -default filter files, it allows them to obtain the
           value of the -M option[3] specified on the command line.

       PATH
           Command execution path.  maildrop resets PATH to the system default (usually
           /bin:/usr/bin:/usr/local/bin).

       SENDMAIL
           The mail delivery agent. When maildrop is instructed to deliver the message to a
           mailbox whose name begins with the ! character, this is interpreted as a request to
           forward the message. The SENDMAIL command is executed to forward the message.

       SHELL
           The login shell. The shell is used to execute all commands invoked by maildrop.

       VERBOSE
           Current Debug level (default: 0). Setting VERBOSE to progressive higher values,
           between 1 and 9, produces debugging output on standard error.  maildrop ignores the
           VERBOSE variable in delivery mode (in order not to confuse the mail transport agent).

       UMASK
           The file creation mode mask, in octal. The default setting of 077 creates mailboxes
           that are readable and writable by the owner only. Use 007 to create mailboxes that are
           readable/writable by both owner and the group. Use 037 to create mailboxes that are
           readable by both owner and group, but writable by owner only. Permissions on existing
           mailboxes are not changed, this setting affects only new mailboxes. When delivering to
           maildirs this setting sets the permissions on new messages only. Access permissions on
           messages in maildirs are also affected by the permissions on the maildir directories.

   Other special variables
       The following variables are automatically used by maildrop when the filter file is being
       processed:

       EXITCODE
           Return code for maildrop. When maildrop successfully delivers a message, it terminates
           with this exit code, which defaults to 0. When the to or the cc command is used to
           deliver the message to an external process, via a pipe, maildrop will set this
           variable to the exit code of the external process. Since maildrop immediately
           terminates after completing the to command this means that maildrop's exit code will
           be the exit code of the external process. If the to command does not deliver the
           message to a process you must set EXITCODE before the to command, since maildrop
           terminates immediately after finishing the delivery.

       FLAGS
           The FLAGS variable is used only when delivering a message to a maildir, and may
           contain only the following letters: “D”, “F”, “R”, and “S”. They may appear in any
           order. When the message gets delivered to the maildir, the message will be marked with
           a draft, flag, replied, or seen, attribute, correspondingly.

           FLAGS must be set before the message is delivered to a maildir. The contents of FLAGS
           are ignored, when delivering on an mbox folder.

       KEYWORDS
           The KEYWORDS variable is used only when delivering a message to a maildir, and
           implements the optional IMAP keyword extension as implemented in the Courier IMAP
           server[1]. It may be optionally initialized to contain a comma-separate list of
           keywords. The to, or the cc command, delivers the message to the maildir normally, but
           also associated the list of keywords in KEYWORDS with the newly delivered message.

           KEYWORDS must be set before the message is delivered to a maildir. The contents of
           KEYWORDS are ignored, when delivering on an mbox folder.

       LINES
           Number of lines in the current message. Note that this may be an approximation. It may
           or may not take into account the -A option. Use this as criteria for filtering,
           nothing more.

       MAILDIRQUOTA
           Set this variable in order to manually enforce a maximum size on ANY maildir where the
           message is delivered. This is an optional feature that must be enabled by the system
           administrator, see maildirquota(8)[4] for more information.

       RETURNCODE
           This variable is set when maildrop runs the system[5] command, xfilter[6] command, or
           a command that's specified within a pair of backtick characters ( command substitution
           ). The RETURNCODE variable will be set to the exit code of the command, after it
           completes.

       SIZE
           Number of bytes in the message. This may or may not include the -A option. Use this as
           a criteria for filtering, nothing more.

   Unquoted text
       All text strings in filter files should be in single, or double quotes. However, for
       convenience sake, quotes can be omitted under certain circumstances.

       Text that includes ONLY letters, digits, and the following characters: _-.:/${}@ may
       appear without quotes. Note that this does not allow spaces, or backslashes to be entered,
       however the text is still variable-substituted, and the substituted text may contain other
       characters.

       Also, note that patterns (see below) begin with the slash character. Normally, anything
       that begins with the slash is interpreted as a pattern. However, text immediately after
       “VARIABLE=” is interpreted as a string even if it begins with a slash. This is why
       something like:

           MAILDIR=/var/mail

       works as expected. Using quotes, though, is highly recommended. You must use quotes to set
       a variable to a lone slash, because an unquoted slash is interpreted as a division sign.

       Long double or singly-quoted text can be broken across multiple lines by ending the line
       with a lone backslash character, like this:

           TEXT="This is a long \
              text string"

       The backslash, the newline, and all leading whitespace on the next line is removed,
       resulting in "This is a long text string".

   Command substitution
       Text enclosed in back-tick characters is interpreted as a shell command. The shell command
       is executed as a child process by maildrop. Its output is used in place of the command.
       For example:

           DIR=`ls`

       places the names of the files in the current directory into the DIR variable.

       The output of the command will have all newline characters replaced by spaces, and leading
       and trailing spaces will be stripped (multiple spaces are not removed, though). Also, the
       contents of the message being delivered is made available to the command on standard
       input.

   Patterns
       The pattern syntax in maildrop is similar to the grep command's syntax, with some minor
       differences. A pattern takes the following form in the filter file:

           /pattern/:options

       pattern specifies the text to look for in the message, in the UTF-8 codeset.  pattern must
       not begin with a space, otherwise the leading slash will then be interpreted as a division
       sign. If you must search for text that starts with a space, use something like "/[ ] ...
       /".

       The general syntax of maildrop's patterns is described in the pcrepattern(3) manual page,
       with certain exceptions noted below.  maildrop uses the PCRE[7] library to implement
       pattern matching. Not all features in PCRE are available in maildrop, and the “options”
       part, which follows the pattern specification, changes the pattern matching further.
       Consult the pcrepattern(3) manual page for more information, but note the following
       exceptions:

       •   Internal options settings are not supported (but see the “D” maildrop option, below).
           Do not include option settings in the pattern, doing so will lead to undefined
           results.

       •   Named subpatterns are not implemented. Numbered subpatterns are implemented, see
           “Pattern Match Results”, below.

       •   The search pattern gets executed not against the raw message text, but the message
           transcoded into a canonical UTF-8-based format. This process involves transcoding any
           non-UTF-8 message content into UTF-8. Additionally, message headers get converted into
           a canonical format before the search pattern gets executed.

           For structured headers with email addresses, the process involves removing extraneous
           punctuation, or adding missing ones (in situations where a missing punctuation
           character can be deduced). Additionally certain pre-RFC822 obsolete header formats get
           converted to canonical form.

           This means that header search patterns that include punctuation character may appear
           not to work against obviously-matching message text. Use “reformime -u <message.txt”,
           with message.txt containing the sample message, to see exactly the actual text that
           gets searched by patterns.

   Pattern options
       Following /pattern/, there may be an optional colon, followed by one. or more options. The
       following options may be specified in any order:

       h
           Match this pattern against the message header.

       b
           Match this pattern against the message body.

       D
           This is a case sensitive match. Normally the patterns match either uppercase or
           lowercase text.  /john/ will match "John", "john", or "JOHN". Specify the D option for
           a case-sensitive search: lowercase letters in the pattern must match lowercase letters
           in the message; ditto for uppercase.

       If neither 'h' or 'b' is specified, the pattern is matched against the header only.
       Specifying the 'b' option causes the pattern to be matched against the message body.
       Specifying both causes the pattern to be matched against the entire message.

       Normally, each line in the message gets matched against the pattern individually. When
       applying patterns to a header, multi-line headers (headers split on several lines by
       beginning each continuation line with whitespace) are silently combined into a single
       line, before the pattern is applied.

   MIME encoding
       The pattern must be a valid text string in the UTF-8 codeset, and maildrop should handle
       messages that use MIME encodings in other known character sets.  Options that specify a
       message header search result in maildrop searching the initial message headers, and any
       headers of additional MIME sections, in a multipart MIME message. Options that specify a
       message body search will search through all "text" MIME content.

       For a MIME search to succeed, the message must be a well-formed MIME message (with a
       Mime-Version: 1.0 header).

   Weighted scoring
       Patterns are evaluated by maildrop as any other numerical expression. If a pattern is
       found, maildrop's filter interprets the results of the pattern match as number 1, or true,
       for filtering purposes. If a pattern is not found the results of the pattern search is
       zero. Once a pattern is found, the search stops. Second, and subsequent occurrences of the
       same pattern are NOT searched for.

       maildrop can also do weighted scoring. In weighted scoring, multiple occurrences of the
       same pattern are used to calculate a numerical score.

       To use a weighted search, specify the pattern as follows:

           /pattern/:options,xxx,yyy

       where xxx and yyy are two numbers.  yyy is optional -- it will default to 1, if missing.

       The first occurrence of the pattern is evaluated as xxx. The second occurrence of the
       pattern is evaluated as xxx*yyy, the third as xxx*yyy*yyy, etc... All occurrences of the
       pattern are added up to calculate the final score.

           Note
           maildrop does not recognize multiple occurrences of the same pattern in the same line.
           Multiple occurences of the same pattern in one line count as one occurence.

   Pattern Match Results
       After a pattern is successfully matched, the actual text that is matched is placed in the
       MATCH variable. For example:

           /^From:.*/

       matches a line of the form:

           From: postmaster@localhost

       Here the variable MATCH will be set to "From: postmaster@localhost", which can be used in
       subsequent statements.

       If the pattern contains subpatterns, the portions of the text that match the first
       subpattern is placed in the MATCH1 variable. The second subpattern, if any, is placed in
       MATCH2, and so on:

           /^From:\s+(.*)@(.*)/

       matched against the same line will set MATCH to “From: postmaster@localhost”, MATCH1 to
       “postmaster”, and MATCH2 to “localhost”. Of course, in real world the “From:” header is
       usually much more complicated, and can't be handled that easily. This is just an
       illustrative example.

           Note
           Subpatterns are not processed in the foreach statement.

   Conversion of maildrop 1.x patterns to 2.0
       Although the new PCRE-based pattern matching code in maildrop is completely different from
       the built-in pattern matching code in maildrop 1.x, very few changes will be required to
       convert recipes to the new syntax. The only major differences are:

       •   The subexpression format has changed. Any pattern that uses subexpression needs to be
           converted. Additionally, references to MATCH2 must be replaced with MATCH1, MATCH3 to
           MATCH2, and so on. References to plain old MATCH will remain the same.

       •   The “w” pattern option is no longer possible, with PCRE. The very few recipes that use
           this option, if any actually exist, will have to be rewritten in some other fashion.

   Expressions
       Although maildrop evaluates expressions numerically, results of expressions are stored as
       text literals. When necessary, text literals are converted to numbers, then the results of
       a mathematical operation is converted back into a text literal.

       Operators
           The following operators carry their usual meaning, and are listed in order from lowest
           precedence, to the highest:

               ||
               &&
               <  <=  >  >=  ==  !=  lt  le  gt  ge  eq  ne
               |
               &
               +  -
               *  /
               =~ /pattern/
               /pattern/  !  ~  function()

       Variable assignment
               VARIABLE=expression

           Assigns the result of the expression to VARIABLE (note no leading $ in front of
           variable).

               Note
               If VARIABLE is NOT surrounded by quotes, then it may contain only letters,
               numbers, underscores, dashes, and a selected few other characters. In order to
               initialize a variable whose name contains non-standard punctuation marks, surround
               the name of the variable with quotes.

       cc - deliver a copy of the message
               cc expression

           The cc statement is very similar to the to statement, except that after delivering the
           message maildrop continues to process the filter file, unlike the to statement which
           immediately terminates maildrop after the delivery is complete. Essentially, the
           message is carbon copied to the given mailbox, and may be delivered again to another
           mailbox by another cc or to statement.

           See the to statement[8] for more details. When cc is used to deliver a message to a
           process maildrop will set the EXITCODE variable to the process's exit code.

       dotlock - create a manual dot-lock
               dotlock expression {

                  ...

               }

           maildrop automatically creates a lock when a message is delivered to a mailbox.
           Depending upon your system configuration, maildrop will use either dot-locks, or the
           flock() system call.

           The dotlock statement creates an explicit dot-lock file. Use the flock statement[9] to
           create an explicit flock() lock.

           The expression is a filename that should be used as a lock file.  maildrop creates the
           indicated dot-lock, executes the filtering instructions contained within the { ... }
           block, and removes the lock. The expression must be the name of the dot-lock file
           itself, NOT the name of the mailbox file you want to lock.

               Note
               With manual locking, it is possible to deadlock multiple maildrop processes (or
               any other processes that try to claim the same locks).

               No deadlock detection is possible with dot-locks, and since maildrop automatically
               refreshes all of its dot-locks regularly, they will never go stale. You'll have
               maildrop processes hanging in limbo, until their watchdog timers go off, aborting
               the mail delivery.

       echo - output diagnostic information
               echo expression

           maildrop will print the given text. This is usually used when maildrop runs in
           embedded mode, but can be used for debugging purposes. Normally, a newline is printed
           after the text. If text is terminated with a \c, no newline will be printed.

       exception - trap fatal errors
               exception {

                  ...

               }

           The exception statement traps errors that would normally cause maildrop to terminate.
           If a fatal error is encountered anywhere within the block of statements enclosed by
           the exception clause, execution will resume immediately following the exception
           clause.

       exit - terminate filtering unconditionally
               exit

           The exit statement immediately terminates filtering.  maildrop's return code is set to
           the value of the EXITCODE variable. Normally, maildrop terminates immediately after
           successfully delivering the message[8] to a mailbox. The exit statement causes
           maildrop to terminate without delivering the message anywhere.

           The exit statement is usually used when maildrop runs in embedded mode[10], when
           message delivery instructions are not allowed.

       flock - create an manual flock() lock
               flock expression {

                  ...

               }

           maildrop automatically creates a lock when a message is delivered to a mailbox.
           Depending upon your system configuration, maildrop will use either dot-locks, or the
           flock() system call.

           The flock statement creates a manual flock() lock. Use the dotlock statement[11] to
           create a manual dot-lock file.

           The expression is the name of the file that should be locked.  maildrop creates the
           lock on the indicated file, executes the filtering instructions contained within the {
           ... } block, and removes the lock.

               Note
               With manual locking, it is possible to deadlock multiple maildrop processes (or
               any other processes that try to claim the same locks). The operating system will
               automatically break flock() deadlocks. When that happens, one of the maildrop
               processes will terminate immediately. Use the exception statement in order to trap
               this exception condition, and execute an alternative set of filtering
               instructions.

       foreach - iterate over text sections matched by a pattern
               foreach /pattern/:options
               {
                  ...
               }

               foreach (expression) =~ /pattern/:options
               {
                  ...
               }

           The foreach statement executes a block of statements for each occurrence of the given
           pattern in the given message, or expression. On every iteration MATCH variable will be
           set to the matched string. All the usual options may be applied to the pattern match,
           EXCEPT the following:

           ,xxx,yyy
               Weighted scoring is meaningless, in this context.

           ( ... )
               Subpatterns are not processed. Only the MATCH variable will be set for each found
               pattern.

       if - conditional execution
               if (expression)
               {
                  ...
               }
               else
               {
                  ...
               }

           Conditional execution. If expression evaluates to a logical true (note - parenthesis
           are required) then the first set of statements is executed. The else keyword, and the
           subsequent statements, are optional. If present, and the expression evaluates to a
           logical false, the else part is executed.

           maildrop evaluates all expression as text strings. In the context of a logical
           expression, an empty string, or the number 0 constitutes a logical false value,
           anything else is a logical true value.

           If the if part, or the else part consists of only one statement, the braces may be
           omitted.

               Note
               The grammar of this if statement is stricter than usual. If you get baffling
               syntax errors from maildrop, make sure that the braces, and the if statement,
               appear on separate lines. Specifically: the closing parenthesis, the closing
               braces, and the else statement, must be at the end of the line (comments are
               allowed), and there may not be any blank lines in between (not even ones
               containing comments only).

           If the else part contains a single if, and nothing else, this may be combined into an
           elsif:

               if (expression)
               {
                  ...
               }
               elsif (expression)
               {
                  ...
               }

           The above example is logically identical to:

               if (expression)
               {
                  ...
               }
               else
               {
                  if (expression)
                  {
                     ...
                  }
               }

           Consecutive elsif sequences are allowed:

               if (expression)
               {
                  ...
               }
               elsif (expression)
               {
                  ...
               }
               elsif (expression)
               {
                  ...
               }

           Consecutive occurences of elsif commands eliminate a significant amount of
           indentation, and the resulting code is more readable.

       import - access original environment variable
               import variable

           When maildrop starts, it normally imports the contents of the environment variables,
           and assigns them to internal maildrop variables. For example, if there was an
           environment variable FOO, the internal maildrop variable FOO will have the contents of
           the environment variable. From then on, FOO will be no different than any other
           variable, and when maildrop runs an external command, the contents of maildrop's
           variables will be exported as the environment for the command.

           Certain variables, like HOME and PATH, are always reset to fixed defaults, for
           security reasons. Also, in delivery and embedded modes, the environment is not
           imported at all (with the exception of system locale environment variables), and
           maildrop starts with only the fixed default variables.

           The import statement initializes the specified variable with the contents of the
           original environment variable when maildrop started. For example:

               echo "PATH is $PATH"
               PATH="/bin"
               echo "PATH is $PATH"
               import PATH
               echo "PATH is $PATH"
               exit

           This results in the following output:

               PATH is /bin:/usr/bin:/usr/local/bin
               PATH is /bin
               PATH is /home/root/bin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin

           This shows that when maildrop starts PATH is set to the fixed default of
           /bin:/usr/bin:/usr/local/bin. However, the original contents of the PATH environment
           variable we different, and the import statement shows what it was.

       include - execute filtering instructions from another file
               include expression

           The include statement reads a file, and executes filtering instructions contained in
           that file. Note that the include statement is processed when the current filter file
           is being executed. When maildrop reads the initial filter file, any syntax errors in
           the filtering instructions are immediately reported, and maildrop will terminate with
           a return code of EX_TEMPFAIL. Any errors in files specified by include statements are
           NOT reported, because those files will not be read until the include statement is
           itself executed.

           If the specified file does not exist, or if there are any syntax errors in the file,
           maildrop reports the error, and terminates with a return code of EX_TEMPFAIL.

       log, logfile - log message deliveries
               logfile expression

               log expression

           Logging in maildrop is normally turned off. The logfile statement specifies the file
           where maildrop will log how the message has been disposed of. The parameter is then
           name of the file. If the file exists maildrop appends to the file.

           For each delivery (the to[8] and cc[12] statements, and default deliveries) maildrop
           records the From: and the Subject: fields, together with the current time, in the log
           file.

           The log statement adds additional logging text to the log file. The log statement
           works exactly like the echo statement, except that the text is written to the logfile,
           instead of standard output.

       system - execute a system command
               system expression

           expression specifies an external program that maildrop runs as a subprocess. The
           subprocess's standard input gets connected to /dev/null, and the subprocess inherits
           the standard output and error from maildrop.

       to - deliver message to a mailbox
               to expression

           The to statement delivers the message to a mailbox.  expression must evaluate to a
           valid mailbox. A valid mailbox is either a mailbox file, a maildir, or an external
           program (which includes forwarding to another address).

           The to statement is the final delivery statement.  maildrop delivers message, then
           immediately terminates, with its return code set to the EXITCODE variable. If there
           was an error while delivering the message, maildrop terminates with the EX_TEMPFAIL
           exit code. A properly-written mail transport agent should re-queue the message, and
           re-attempt delivery at some later time.

           An expression that begins with the "|" character specifies an external program to run
           to handle the actual delivery. The SHELL variable specifies the shell to execute the
           given command. The message is provided to the command on standard input.  maildrop's
           exit code will be the process's exit code.

           An expression that begins with an exclamation mark, "!" specifies a
           whitespace-delimited list of E-mail addresses to forward the message to. The program
           specified by the SENDMAIL variable is run as an external program, with the list of
           E-mail addresses provided as parameters to the program.

           Otherwise, expression names the mailbox where maildrop delivers the message. If
           expression is a directory, maildrop assumes that the directory is a maildir directory.
           Otherwise, maildrop will deliver the message to a file, formatted in traditional
           mailbox format.  maildrop will use either dot-locking, or flock()-locking when
           delivering the message to the file.

       while - repeatedly execute a block of statements
               while (expression)
               {
                  ...
               }

           The expression is repeatedly evaluated. Each time it evaluates to a logical true[13],
           the statements inside the braces are executed. When expression evaluates to a logical
           false, the while loop is over. Take care to avoid infinite loops.

       xfilter - filter message through another program
               xfilter expression

           expression specifies an external program that maildrop runs to filter the current
           message. The current message will be piped to the filter program as standard input.
           The output of the filter program replaces the current message being delivered. The
           external program must terminate with an exit code of 0. If the external program does
           not terminate with an exit code of 0, or if it does not read the message from the
           standard input, maildrop terminates with an exit code of EX_TEMPFAIL.

       || - logical or
               expression1 || expression2

           If expression1 evaluates to a logical true, the result of the || is expression1,
           otherwise it's expression2, which is evaluated.

           maildrop uses the following concept of true/false: an empty text literal, or a text
           literal that consists of the single character "0" is a logical false value. Anything
           else is a logical true value.

       && - logical and
               expression1 && expression2

           If expression1 evaluates to a logical false, the result of the && is expression1,
           otherwise it's expression2, which is evaluated.

           maildrop uses the following concept of true/false: an empty text literal, or a text
           literal that consists of the single character "0" is a logical false value. Anything
           else is a logical true value.

       <, <=, >, >=, ==, != - numerical comparison
               expression1 < expression2

               expression1 <= expression2

               expression1 > expression2

               expression1 >= expression2

               expression1 == expression2

               expression1 != expression2

           These operators compare their left hand side expression against their right hand side.
           These operators compare the numerical values of each side, as floating point numbers.
           If the numbers compare as indicated, the result of the comparison is the text string
           "1", otherwise it is the text string 0.

               Note
               Ccomparisons are not associative: "a < b < c" is an error. If it is absolutely
               necessary, use "(a < b) < c".

       lt, le, gt, ge, eq, ne - text comparison
               expression1 lt expression2

               expression1 le expression2

               expression1 gt expression2

               expression1 ge expression2

               expression1 eq expression2

               expression1 ne expression2

           These operators compare their left hand side expression against their right hand side.
           These operators compare each side as text strings (alphabetically, although the text
           may include anything). If the text strings compare as indicated, the result of the
           comparison is the text string "1", otherwise it is the text string 0.

               Note
               Comparisons are not associative: "a lt b lt c" is an error. If it is absolutely
               necessary, use "(a lt b) lt c". (But why would you?).

       | - bitwise or
               expression1 | expression2

           This is the bitwise or operator. Its result is a 32 bit integer, which is a bitwise-or
           combination of the left hand side and the right hand side.

       & - bitwise and
               expression1 & expression2

           This is the bitwise and operator. Its result is a 32 bit integer, which is a
           bitwise-and combination of the left hand side and the right hand side.

       +, -, *, / - numerical operations
               expression1 + expression2

               expression1 - expression2

               expression1 * expression2

               expression1 / expression2

           These are numerical, floating point, operators.

       =~ /pattern/:options - pattern match against string
               expression =~ /pattern/:option

           The left hand side of the =~ operator can be any expression. The right hand side is
           always a pattern specification. The result of the operator is the weighted match of
           the pattern against expression (if the options do not specify weighted scoring, the
           result is simply 1 if the pattern was found, 0 if not).

           See "Patterns[14]" for more information.

       /pattern/:options - pattern match against message
               /pattern/:option

           The result of this operator is the weighted match of the pattern against the current
           message (if the options do not specify weighted scoring, the result is simply 1 if the
           pattern was found, 0 if not).

           See "Patterns[14]" for more information.

       !, ~ - logical/bitwise not operator.
               ! expression

               ~ expression

           The result of the !  operator is a logical opposite of its right hand side expression.
           If the right hand side expression evaluated to a logical true, the result is a logical
           false. If it evaluated to a logical false, the result is a logical true.

           maildrop uses the following concept of true/false: an empty text literal, or a text
           literal that consists of the single character "0" is a logical false value. Anything
           else is a logical true value.

           The result of the ~ operator is a bitwise complement of its right hand side
           expression. The right hand side expression is evaluated as a 32 bit integer, and the
           result of this operator is a bitwise complement of the result.

       escape(string) - escape special characters in a string.
               escape(expression)

           The escape function returns its sole argument with every occurrence of a special
           character prefixed by a backslash. A special character is any of the following
           characters:

               |!$()[]\+*?.&;`'-~<>^{}"

           This can used when matching pattern sections[15], and then taking one section and
           matching it again. For example:

               if ( /^From:\s*(.*)/ )
               {
                  MATCH1=escape($MATCH1)
                  if ( /^Subject:.*$MATCH1/ )
                  {
                     ...
                  }
               }

           This example checks if the contents of the From: header can also be found in the
           Subject: header. If the escape function were not used, then any special characters in
           the From: header that are also used in regular expressions, such as * or +, would
           introduce unpredictable behavior, most likely a syntax error.

           The reason why this list of special characters also includes characters not used in
           maildrop's regular expressions is to allow maildrop's variables to be used on the
           command line of a shell command executed by the xfilter command, backtick characters,
           or to or cc commands.

           Although using data from an external data source is dangerous, and it may result in
           inadvertent exploits, using the escape function should hopefully result in fewer
           surprises.

       gdbmopen, gdbmclose, gdbmfetch, gdbmstore - GDBM support in maildrop
           These functions provide support for GDBM database files. See maildropgdbm(5)[16] for
           more information.

               Note
               The system administrator can disable GDBM support in maildrop, so these commands
               may not be available to you.

       getaddr(string) - extract RFC 2822 addresses from a header.
               if ( /^From:\s*(.*)/ )
               {
                  ADDR=getaddr($MATCH1)
               }

           This function is usually applied to a header that contains RFC 2822[17] addresses. It
           extracts the actual addresses from the header, without any comments or extraneous
           punctuation. Each address is followed by a newline character. For example, if string
           contains:

               joe@domain.com (Joe Brown), "Alex Smith" <alex@domain.com>, tom@domain.com

           The result of the getaddr function is the following string:

               joe@domain.com<NL>alex@domain.com<NL>tom@domain.com<NL>

               Note
               Because getaddr() interprets RFC 2822[18] loosely, it is not necessary to strip
               off the "To:" or the "Cc:" header from the string, before feeding it to getaddr().
               For example, the following snippet of code takes all addresses in the message, and
               concatenates them into a single string, separated by spaces:

                   ADDRLIST=""
                   foreach /^(To|Cc): .*/
                   {
                       foreach (getaddr $MATCH) =~ /.+/
                       {
                           ADDRLIST="$ADDRLIST $MATCH"
                       }
                   }

               Note
               In certain rare situations, RFC 2822[18] allows spaces to be included in E-mail
               addresses, so this example is just educational.

       hasaddr(string) - Search for an address.
               if ( hasaddr(string) )
               {
                  ...
               }

           "string" is of the form user@domain. The hasaddr function returns 1 if this address is
           included in any To:, Cc:,Resent-To:, or Resent-Cc:, header in the message, otherwise
           this function returns 0.

           This is more than just a simple text search. Each header is parsed according to
           RFC822. Addresses found in the header are extracted, ignoring all comments and names.
           The remaining addresses are checked, and if "string" is one of them, hasaddr returns
           1, otherwise it returns 0.

           The comparison is case-insensitive. This actually violates RFC822 (and several others)
           a little bit, because the user part of the address may be (but is not required to be)
           case sensitive.

       length (string) - length of a string
               if (length(string) > 80)
               {
                  ...
               }

           The length function returns the number of characters in string.

       lookup (expr, 'filename', 'options') - read file for patterns
               if (lookup(expr, file, "option"))
               {
                  ...
               }

           expr is any expression.  filename is a name of a file containing a list of patterns.
           Note that filename is relative to the current directory, which is the home directory
           of the user when maildrop runs in delivery mode, or embedded mode.  maildrop then
           reads the file. Blank lines will be ignored, as well as any lines that begin with the
           # character (comments).

           Leading whitespace (but not trailing whitespace, take care) is removed, and the
           remaining contents of each line are interpreted as a pattern which is matched against
           expr. As soon as the match is found, lookup returns "1". If no match is found after
           reading the entire file, lookup returns "0". For example:

               if ( /^To:\s*(.*)/ && lookup( $MATCH1, "badto.dat" ))
               {
                   exit
               }

           The file badto.dat contains the following two lines:

               friend@public
               ^[^@]*$

           If a message has a To: header that contains the text "friend@public", or does not
           contain at least one @ character, then the message will be silently dropped on the
           floor ( maildrop will terminate without delivering the message anywhere).

           options are the pattern matching options to use. The only supported option is "D" (the
           rest are meaningless, in this case).

               Note
               Be careful with discarding messages like that. Pattern matching can be tricky, and
               a slight miscalculation can cause mail to be unintentionally discarded. It is much
               desirable to first deliver message to a separate folder or mailbox, and once the
               filter is verified to work correctly, change it so the messages are discarded
               completely.

       substr(string,start [,count]) - return substring
               foo=substr($foo, 1, 10)

           The substr function extracts characters from string beginning with character #start.
           If count is specified, at most count characters starting at position start are kept,
           any excess is trimmed.

       time - return current time
               foo=time

           The time function returns the current time, in seconds, since January 1, 1970. This
           function is useful when using GDBM files. See maildropex(7)[19] for an example of
           using the time function.

       tolower(string) - Convert string to lowercase.
               foo=tolower(string)

           This function returns the string with all uppercase characters replaced by lowercase
           characters.

       toupper(string) - Convert string to uppercase.
               foo=toupper(string)

           This function returns the string with all lowercase characters replaced by uppercase
           characters.

   Statements
       The filter file is read by maildrop ($HOME/.mailfilter or another file), and it contains
       filtering statements, one per line. The filtering language used by maildrop has a loosely
       - defined grammatical structure.

       Statements are listed one per line. Multiple statements may be listed on the same line by
       separating them with semicolons. To continue a long statement on the next line, terminate
       the line with a backslash character.

BUGS

       If getaddr() or hasaddr() functions are used on broken headers, the results are
       unpredictable.

       hasaddr() is completely case insensitive. This actually violates a few RFCs, because the
       userid portion of the address could be case-sensitive, but it's not in too many cases, so
       there.

SEE ALSO

       lockmail(1)[20], maildrop(1)[21], maildropgdbm(5)[16], maildirquota(8)[4],
       reformail(1)[22], egrep(1), sendmail(8).

AUTHOR

       Sam Varshavchik
           Author

NOTES

        1. Courier mail server
           http://www.courier-mta.org/

        2. dot-courier(5)
           http://www.courier-mta.org/maildrop/dot-courier.html

        3. value of the -M option
           http://www.courier-mta.org/maildrop/maildrop.html#moption

        4. maildirquota(8)
           http://www.courier-mta.org/maildrop/maildirquota.html

        5. system
           http://www.courier-mta.org/maildrop/#system

        6. xfilter
           http://www.courier-mta.org/maildrop/#xfilter

        7. PCRE
           http://www.pcre.org

        8. See the to statement
           http://www.courier-mta.org/maildrop/#to

        9. flock statement
           http://www.courier-mta.org/maildrop/#flock

       10. embedded mode
           http://www.courier-mta.org/maildrop/maildrop.html#embedded

       11. dotlock statement
           http://www.courier-mta.org/maildrop/#dotlock

       12. cc
           http://www.courier-mta.org/maildrop/#cc

       13. evaluates to a logical true
           http://www.courier-mta.org/maildrop/#if

       14. Patterns
           http://www.courier-mta.org/maildrop/#patterns

       15. matching pattern sections
           http://www.courier-mta.org/maildrop/#patmatch

       16. maildropgdbm(5)
           http://www.courier-mta.org/maildrop/maildropgdbm.html

       17. RFC 2822
           http://www.rfc-editor.org/rfc/rfc2822.txt

       18. RFC 2822
           http://www.rfc-editor.org/rfc/rfc822.txt

       19. maildropex(7)
           http://www.courier-mta.org/maildrop/maildropex.html

       20. lockmail(1)
           http://www.courier-mta.org/maildrop/lockmail.html

       21. maildrop(1)
           http://www.courier-mta.org/maildrop/maildrop.html

       22. reformail(1)
           http://www.courier-mta.org/maildrop/reformail.html