# MAILDROPFILTER(7) - man - phpMan

[MAILDROPFILTER(7)](https://www.chedong.com/phpMan.php/man/MAILDROPFILTER/7/markdown)                      Double Precision, Inc.                      [MAILDROPFILTER(7)](https://www.chedong.com/phpMan.php/man/MAILDROPFILTER/7/markdown)



## 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)](https://www.chedong.com/phpMan.php/man/dot-courier/5/markdown)[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)](https://www.chedong.com/phpMan.php/man/gethostname/3/markdown).

       _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)](https://www.chedong.com/phpMan.php/man/maildirquota/8/markdown)[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)](https://www.chedong.com/phpMan.php/man/pcrepattern/3/markdown) 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)](https://www.chedong.com/phpMan.php/man/pcrepattern/3/markdown) 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)](https://www.chedong.com/phpMan.php/man/maildropgdbm/5/markdown)[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)](https://www.chedong.com/phpMan.php/man/maildropex/7/markdown)[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)](https://www.chedong.com/phpMan.php/man/lockmail/1/markdown)[20], [**maildrop**(1)](https://www.chedong.com/phpMan.php/man/maildrop/1/markdown)[21], [**maildropgdbm**(5)](https://www.chedong.com/phpMan.php/man/maildropgdbm/5/markdown)[16], [**maildirquota**(8)](https://www.chedong.com/phpMan.php/man/maildirquota/8/markdown)[4], [**reformail**(1)](https://www.chedong.com/phpMan.php/man/reformail/1/markdown)[22],
       [**egrep**(1)](https://www.chedong.com/phpMan.php/man/egrep/1/markdown), [**sendmail**(8)](https://www.chedong.com/phpMan.php/man/sendmail/8/markdown).

## AUTHOR
### Sam Varshavchik
           Author

## NOTES
        1. Courier mail server
           <http://www.courier-mta.org/>

        2. [**dot-courier**(5)](https://www.chedong.com/phpMan.php/man/dot-courier/5/markdown)
           <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)](https://www.chedong.com/phpMan.php/man/maildirquota/8/markdown)
           <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)](https://www.chedong.com/phpMan.php/man/maildropgdbm/5/markdown)
           <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)](https://www.chedong.com/phpMan.php/man/maildropex/7/markdown)
           <http://www.courier-mta.org/maildrop/maildropex.html>

       20. [**lockmail**(1)](https://www.chedong.com/phpMan.php/man/lockmail/1/markdown)
           <http://www.courier-mta.org/maildrop/lockmail.html>

       21. [**maildrop**(1)](https://www.chedong.com/phpMan.php/man/maildrop/1/markdown)
           <http://www.courier-mta.org/maildrop/maildrop.html>

       22. [**reformail**(1)](https://www.chedong.com/phpMan.php/man/reformail/1/markdown)
           <http://www.courier-mta.org/maildrop/reformail.html>



Courier Mail Server                          07/24/2017                            [MAILDROPFILTER(7)](https://www.chedong.com/phpMan.php/man/MAILDROPFILTER/7/markdown)
