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:
 
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:
 
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.
 
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 From_ line in the message. As the last resort, FROM defaults to the
  userid which invoked maildrop. 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.
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, or any mbox "From_" lines. 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 xfilter[5] 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, and the mbox From_ line. 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:
 
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:
 
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 specifies the text to look for in the message. 
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[6] 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:
 
•
 
UTF-8 string matching is not presently supported.
 
 
•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.
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.
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:
 
matches a line of the form:
 
From: postmaster@localhost 	 .PP 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:
 
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
 
 
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
 
 
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[7] 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[8] 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
 
 
 
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
 
 
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
 
 
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[7] 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[9], when message delivery instructions are not
  allowed.
 
 
 
flock - create an manual flock() lock
 
 
 
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[10] 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
 
 
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
 
 
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[7] and 
cc[11] 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.
 
 
 
to - deliver message to a mailbox
 
 
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[12], 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
 
 
 
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[13]" for more information.
 
 
 
/pattern/:options - pattern match against message
 
 
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[13]" 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.
 
 
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[14], 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)[15] 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[16]
  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[17] 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[17] 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:
 
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
 
 
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
 
 
The 
time function returns the current time, in seconds, since January 1,
  1970. This function is useful when using GDBM files. See
  
maildropex(7)[18] for an example of using the 
time
  function.
 
 
 
tolower(string) - Convert string to lowercase.
 
 
This function returns the 
string with all uppercase characters replaced
  by lowercase characters.
 
 
 
toupper(string) - Convert string to uppercase.
 
 
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)[19], 
maildrop(1)[20],
  
maildropgdbm(5)[15], 
maildirquota(8)[4],
  
reformail(1)[21], 
egrep(1), 
sendmail(8).
AUTHOR¶
Sam Varshavchik
Author
NOTES¶
  -  1.
 
  - Courier mail server
 
  -  2.
 
  - dot-courier(5)
 
[set
  $man.base.url.for.relative.links]/dot-courier.html
  -  3.
 
  - value of the -M option
 
[set
  $man.base.url.for.relative.links]/maildrop.html#moption
  -  4.
 
  - maildirquota(8)
 
[set
  $man.base.url.for.relative.links]/maildirquota.html
  -  5.
 
  - xfilter
 
[set
  $man.base.url.for.relative.links]/#xfilter
  -  6.
 
  - PCRE
 
  -  7.
 
  - See the to statement
 
[set
  $man.base.url.for.relative.links]/#to
  -  8.
 
  - flock statement
 
[set
  $man.base.url.for.relative.links]/#flock
  -  9.
 
  - embedded mode
 
[set
  $man.base.url.for.relative.links]/maildrop.html#embedded
  - 10.
 
  - dotlock statement
 
[set
  $man.base.url.for.relative.links]/#dotlock
  - 11.
 
  - cc
 
[set
  $man.base.url.for.relative.links]/#cc
  - 12.
 
  - evaluates to a logical true
 
[set
  $man.base.url.for.relative.links]/#if
  - 13.
 
  - Patterns
 
[set
  $man.base.url.for.relative.links]/#patterns
  - 14.
 
  - matching pattern sections
 
[set
  $man.base.url.for.relative.links]/#patmatch
  - 15.
 
  - maildropgdbm(5)
 
[set
  $man.base.url.for.relative.links]/maildropgdbm.html
  - 16.
 
  - RFC 2822
 
  - 17.
 
  - RFC 2822
 
  - 18.
 
  - maildropex(7)
 
[set
  $man.base.url.for.relative.links]/maildropex.html
  - 19.
 
  - lockmail(1)
 
[set
  $man.base.url.for.relative.links]/lockmail.html
  - 20.
 
  - maildrop(1)
 
[set
  $man.base.url.for.relative.links]/maildrop.html
  - 21.
 
  - reformail(1)
 
[set
  $man.base.url.for.relative.links]/reformail.html