Documentation
Mail rules reference
rules.toml lives at the root of the mail store and controls how Everlock
handles every message that passes through the system — inbound or outbound.
How rules work
Rules are evaluated in ascending priority order. The first rule that matches
wins. When no rule matches, the backend default is to store the message in the
recipient mailbox under inbox.
- lower priority numbers run first
- higher priority numbers run later
- omitted
prioritydefaults to10 - equal priorities preserve file order
priority = 0is valid
Rules have a direction — inbound or outbound. Inbound rules apply to mail
arriving over SMTP. Outbound rules apply to mail sent through the submission
listener. A rule only runs for its own direction; inbound rules never fire for
outbound mail and vice versa.
Rule shape
Each rule is one [[rule]] TOML block:
[[rule]]
id = "rule-default-inbox"
name = "catch-all inbox delivery"
priority = 10
direction = "inbound"
receiver = "*"
type = "store"
folder = "inbox"
direction defaults to inbound when omitted.
Required field
| Field | Description |
|---|---|
id | Unique rule identifier. Must start with rule-. |
Optional fields
| Field | Default | Description |
|---|---|---|
name | — | Human-readable label. Not used by the rule engine. |
priority | 10 | Evaluation order. Lower numbers run first. |
direction | inbound | inbound or outbound. |
Match fields
All match fields are optional. A rule with no match fields matches every message in its direction.
| Field | Type | Description |
|---|---|---|
sender | string | Envelope sender address. Supports * wildcard. Case-insensitive. |
receiver | string | Envelope recipient address. Supports * wildcard. Case-insensitive. |
domain | string | Recipient domain. Supports * wildcard. Case-insensitive. |
local_part | string | Recipient local part (before @). Supports * wildcard. Case-insensitive. |
subject_contains | string | Subject header substring. Case-sensitive. |
message_id | string | Exact Message-ID header value. |
header_from_contains | string | From header substring. Case-sensitive. |
header_to_contains | string | To header substring. Case-sensitive. |
size_gt | integer | Matches if message size in bytes is greater than this value. |
size_lt | integer | Matches if message size in bytes is less than this value. |
has_header | string | Matches if the named header is present in the message. |
Wildcard behavior:
*matches any sequence of characters including none*@example.commatches any sender at that domainalerts@*matchesalertsat any domain*alone matches everything
Actions
The action is written inline using the type key plus any action-specific
fields. The type value matches the action name exactly.
allow
Explicitly permit the message and stop evaluating further rules. The message is
handled as if no rule had matched — stored in the recipient mailbox for inbound,
sent normally for outbound. Useful as a priority-1 allowlist entry before a
lower-priority catch-all reject.
type = "allow"
reject
Reject the message with an SMTP error. The sender receives a permanent failure.
type = "reject"
drop
Accept the message but discard it silently. The sender sees a success reply.
type = "drop"
store
Store in the recipient mailbox. folder defaults to inbox when omitted.
type = "store"
folder = "inbox"
store_as
Store in a different mailbox than the envelope recipient. Useful for aliases and
shared inboxes. folder defaults to inbox when omitted.
type = "store_as"
mailbox = "admin@example.com"
folder = "support"
put_in_folder
Store in the recipient mailbox but place the message in a specific folder. Use this when you want to route to a folder without changing the destination mailbox.
type = "put_in_folder"
folder = "alerts"
set_flags
Store in the recipient mailbox and set IMAP flags on the message. All flags are
optional; omitted flags are left at their default (false).
type = "set_flags"
seen = true
flagged = true
answered = false
deleted = false
forward
Forward the message to another address without storing it locally. The original raw message is forwarded as-is. Uses MX lookup for delivery.
type = "forward"
address = "ops@example.net"
store_and_forward
Store locally and forward to another address. folder defaults to inbox when
omitted.
type = "store_and_forward"
address = "ops@example.net"
folder = "sales"
Outbound rules
Outbound rules apply to mail sent through the submission listener. They use the same match fields as inbound rules.
Only four actions are allowed for outbound rules:
allowrejectdropforward
Using any other action on an outbound rule will fail validation when
rules.toml is loaded. Everlock refuses to start with an invalid rules file.
Example: reject outbound mail over 10 MB:
[[rule]]
id = "rule-outbound-size-limit"
direction = "outbound"
size_gt = 10485760
type = "reject"
Example: redirect all outbound mail through a specific relay address:
[[rule]]
id = "rule-outbound-relay"
direction = "outbound"
sender = "*@example.com"
type = "forward"
address = "relay@outbound.example.net"
Example rules file
A complete rules.toml combining inbound and outbound rules:
# Drop list traffic before anything else
[[rule]]
id = "rule-drop-lists"
priority = 1
has_header = "List-Id"
type = "drop"
# Route alerts to a dedicated folder
[[rule]]
id = "rule-alerts"
priority = 5
receiver = "alerts@example.com"
type = "put_in_folder"
folder = "alerts"
# Route support tickets to the shared admin mailbox
[[rule]]
id = "rule-support"
priority = 5
receiver = "support@example.com"
type = "store_as"
mailbox = "admin@example.com"
folder = "support"
# Block oversized outbound messages
[[rule]]
id = "rule-outbound-no-large"
direction = "outbound"
size_gt = 10485760
type = "reject"
# Catch-all: store everything else in inbox
[[rule]]
id = "rule-default"
priority = 100
receiver = "*"
type = "store"
folder = "inbox"