## MailFront

## SMTP Front Ends

# Mail Rules Specification

## 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. Blank lines and lines starting with "`#`" are ignored as comments.

### Selector Lines

Selector lines specify when the following rules are to be applied. A selector line starts with a colon ("`:`"). The following selectors are defined:

`:sender`
  Apply the following rules only to senders. Any recipient pattern present in the rule is ignored.
`:recipient`
  Apply the following rules only to recipients.

Rules that precede a selector are categorized as follows (for compatibility with existing rules:

- If the rule has a recipient pattern of "`*`" (which matches everything), it will be applied as a sender only rule.
- All other rules are applied as recipient rules.

### Rule Lines

Each rule line starts with one of the following prefixes:

`k`
  Accept the sender or recipient, passing control to the next plugin.
`K`
  Accept the sender or recipient, and bypass all further plugins.
`z`
  Reject the sender or recipient with a temporary error code.
`d`
  Reject the sender or recipient with a permanent error code.
`n`
  NO-OP: apply the databytes, relayclient, and/or environment settings, but continue processing further rules.
`p`
  Pass the sender or recipient on to the next processing state (ie `$RELAYCLIENT` or back-end validation).
`&`
  AND: the next rule is only tested if this one matches. This is useful for matching both a regular pattern and special pattern (see below) which can't normally be done in the same rule.

The remainder of the line consists of a series of fields seperated by colons (":"). The fields are:

1. Sender: A pattern applied to the envelope sender address.
2. Recipient: A pattern applied to the envelope recipient address.
3. Response: The response message that will be given to the client with the numerical code. The default for this message depends on the line's prefix.
4. Data Bytes: Reduces the maximum message size to the lesser of the current limit (as set at startup by `$DATABYTES`) and the specified number. This message size limit is reset to its original value before after each message. If empty or missing, no changes are made.
5. Relay Client: If present, the current recipient address is suffixed with this string. Only useful for "k" rules.
6. Environment: Environment variables to set as a result of matching this rule. This field contains a list of assignments seperated by commas. Each assignment is formatted as `NAME=VALUE`. If a value needs to contain a comma, it must be quoted as follows: `\.`.

## 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

Patterns are globs, similar to UNIX shell-style wildcards (but quite different from full regular expressions).

Pattern | Matches
--- | ---
`*` | Any sequence of characters (including the empty sequence).
`?` | Any single character.
`[seq]` | A single occurance of any character in `seq`.
`[!seq]` | A single occurance of any character not in `seq`.

Any other character matches itself, without regard for case. 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 "`[[@rcpthosts]]`" and "`[[@morercpthosts.cdb]]`" in the recipient field.
`[[filename]]`
  Matches the entire address against the control file named `filename`. A typical use would be "`[[badmailfrom]]`" in the sender field.

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.

### Negation

Prefixing the pattern with a `!` inverts the result of the match. That is, if the pattern match does not succeed, the rule will succeed instead of failing. This applies to all patterns including the special patterns above.

## 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.

## Examples

### qmail Rules

The following rules provide the functionality similar to that available in qmail-smtpd. Please note that the qmail validation routines already provide this functionality. These rules are listed for illustrative purposes only.

    :sender
    d[[/var/qmail/control/badmailfrom]]:*:sorry, your envelope sender is in my badmailfrom list (#5.7.1)
    :recipient
    k*:[[@/var/qmail/control/rcpthosts]]
    k*:[[@/var/qmail/control/morercpthosts.cdb]]

### Abused Patterns

The following rules block old exploitable addresses that are still commonly probed: bang paths, multiple domains, and percent hacks.

    d*:*!*: Sorry, we don't allow that here
    d*:*@*@*: Sorry, we don't allow that here
    d*:*%*: Sorry, percent hack not accepted here