Syntax
Stalwart Mail Server offers a flexible configuration system through the use of rules. These rules, which consist of single or nested if
blocks, provide system administrators the ability to tailor the server behavior based on contextual variables such as IP address, sender, recipient and more. Rules can be applied to most parameters of the configuration file and are represented using nested TOML structures containing if
, else
, all-of
, any-of
and none-of
attributes.
A rule is comprised of a TOML array that includes one or multiple single or nested conditional blocks, followed by an else
block. Each if
block within a rule evaluates a specific context variable using a comparator. If the condition is met, the then
block is executed. If the condition is not met, the else
block is executed.
ABNF
The ABNF (Augmented Backus-Naur Form) representation of a setting can be expressed as follows:
SETTING = <string> "=" (VALUE / RULE)
RULE = "[" (1*CONDITION) "," THEN_BLOCK "]"
IF_BLOCK = "{" "if" "=" VARIABLE "," COMPARATOR "=" CMP_VALUE "," "then" "=" VALUE "}"
THEN_BLOCK = "{" "then" "=" VALUE }
ALL_OF_BLOCK = "{" "all-of" "=" "[" 1*CONDITION "]" "}"
ANY_OF_BLOCK = "{" "any-of" "=" "[" 1*CONDITION "]" "}"
NONE_OF_BLOCK = "{" "none-of" "=" "[" 1*CONDITION "]" "}"
CONDITION = IF_BLOCK / ALL_OF_BLOCK / ANY_OF_BLOCK / NONE_OF_BLOCK
VARIABLE = <string>
COMPARATOR = "eq" / "ne" / "starts-with" / "not-starts-with" / "ends-with" /
"not-ends-with" "in-list" / "not-in-list" / "matches" / "not-matches"
CMP_VALUE = <string> / <number> / IP_CIDR
IP_CIDR = <ip_address> ["/" <integer>]
VALUE = <string> / <number> / <array> / <duration>
Example
A simple rule to enable the CHUNKING
extension only for the IP address 10.0.0.25 would look like this:
chunking = [ { if = "remote-ip", eq = "10.0.0.25", then = true},
{ else = false } ]
Or, an example of a complex rule that combines nested conditions using the all-of
, any-of
and none-of
operands could look like this:
chunking = [ { any-of = [ { if = "rcpt-domain", eq = "example.org" },
{ if = "remote-ip", eq = "192.168.0.0/24" },
{ all-of = [
{ if = "rcpt", starts-with = "no-reply@" },
{ if = "sender", ends-with = "@domain.org" },
{ none-of = [
{ if = "priority", eq = 1 },
{ if = "priority", ne = -2 },
]}
]}
], then = false },
{ else = true } ]
The use of rules in the configuration file is optional though, static values can also be assigned to settings, for example:
chunking = true