Mail Rules Specification v2
The first mail rules specification is lacking in several areas:
- There is no way to select rules based on the state of environment
variables (such as $RELAYCLIENT or $TCPREMOTEIP.
- There is no way to select rules based on the SMTP authentication
state.
- The dictionary and CDB lookups don't support wildcarding (minor).
This document proposes an improved mail rules specification that
addresses these problems.
Selection
The use of mail rules is controlled by the environment variable
$MAILRULES. This variable specifies the path to the mail rules
file. If $MAILRULES is set but the path that it points to
cannot be opened, processing will fail with a temporary error. There is
no default value -- if it is not set, mail rules processing is
disabled.
The rules listed are applied before any other sender or
recipient processing is done (such as checking against qmail's
badmailfrom file).
Syntax
Each rule in the file occupies a single line and has exactly the same
format. Empty lines and lines starting with "#" are ignored.
The other lines consist of a series of fields seperated by colons
(":"). The fields are:
- Conditions: a comma-seperated list of conditions. Each
condition follow the format in the following list. All conditions must
be true for the rule to execute. A rule with no conditions always
matches.
- !CONDITION True if the condition (one of the below) is
false.
- VAR=VALUE True if the variable named VAR is
defined and matches "VALUE" exactly.
- VAR~PATTERN True if the variable VAR is defined
and matches the pattern "PATTERN".
- VAR True if the variable VAR is defined (even if
it has been assigned an empty string).
Sender-only rules must contain the condition
"!recipient".
- Assignments: As before, except that databytes,
sender, and recipient are handled specially.
Assignment to recipient when handling a sender, and vice versa
has no effect. If the assignment contains $NAME or
${NAME}, the contents of the named variable are inserted.
- Action: One of the following:
- ACCEPT
- Accept the sender or recipient.
- DEFER
- Reject the sender or recipient with a temporary
error code.
- REJECT
- Reject the sender or recipient with a permanent
error code.
- DEFER-ALL
- Reject the message with a temporary error
(rejects all past and future recipients, and resets the state).
- REJECT-ALL
- Reject the message with a permanent error.
- PASS
- Pass the sender or recipient on to the next
processing state (ie $RELAYCLIENT or back-end validation).
- Response: The response message that will be given to the
client. The default for this message depends on the action.
Variables
The following variables are internally defined.
- authenticated: Defined if SMTP authentication has
succeeded.
- sender: The envelope sender address.
- recipient: The current envelope recipient address.
- databytes: The current maximum message size.
All other variable names are taken from environment variables.
Escaping
The following escape sequences are recognized in all the fields:
- \n newline (replaced with a CR+LF pair on output)
- \### character with octal value ### (exactly 3 digits)
- \\ backslash
- \: colon
Patterns
Pattern Syntax
A pattern is a string of stars and non-stars. It matches any
concatenation of strings matched by all the stars and non-stars in the
same order. A non-star matches itself. A star before the end of
pattern matches any string that does not include the next character in
pattern. A star at the end of pattern matches any string. Patterns
containing only "*" match anything. Note: An empty
pattern matches only the empty string.
Special Patterns
The following patterns are treated specially:
- [[@filename]]
- Matches the domain portion of the
address against the control file named filename.
Typical uses would be "recipient~[[@rcpthosts]]" and
"recipient~[[@morercpthosts.cdb]]".
- [[filename]]
- Matches the entire address against
the control file named filename. A typical use would be
"sender~[[badmailfrom]]".
If filename ends with .cdb, the control
file is opened as a CDB file. Addresses are translated to lower-case
before doing CDB lookups. Otherwise, control files are plain text
lists, with one entry per line. Empty lines and lines starting with
"#" are ignored. Lines starting with "@" match only
the domain portion of the address. All comparisons are case
insensitive. Missing CDB files are silently ignored. Missing text
files cause an error message at startup.
Semantics
Each rule is applied in the order they are listed in the rules file
until one matches. At that point, the command that triggered the rule
search is accepted, deferred, or rejected depending on the rule type.
If the sender is not accepted, no recipients can be accepted, as usual.
As long as at least one recipient is accepted the message data may be
accepted.
Rules with a recipient conditions will be tested when the client
transmits the recipient address. Otherwise, the rules are tested only
only when the client transmits the sender address.
Examples
qmail Rules
The following rules provide the functionality available in
qmail-smtpd:
sender~[[/var/qmail/control/badmailfrom]]:REJECT:Sorry, your envelope sender is in my badmailfrom list (#5.7.1)
recipient,$RELAYCLIENT:recipient=${recipient}$RELAYCLIENT:ACCEPT:Accepted
recipient,authenticated::ACCEPT:Accepted
recipient~[[@/var/qmail/control/rcpthosts]]::ACCEPT:Accepted
recipient~[[@/var/qmail/control/morercpthosts.cdb]]::ACCEPT:Accepted
recipient::REJECT:Sorry, that domain isn't in my list of allowed rcpthosts
Missing Features
The following features are absent from this description, and could be
added:
- Extended variable expansion: Borrow the following parameter/variable
expansion features from bash:
- ${parameter:-word}
- ${parameter:+word}
- ${parameter:offset}
- ${parameter:offset:length}
- ${#parameter}
- ${parameter#word}
- ${parameter##word}
- ${parameter%word}
- ${parameter%%word}
- ${parameter/pattern/string}
- ${parameter//pattern/string}