The syntax of policy
Comments
Any charactors between “/*” and “*/” are ignored.
Any charactors between “//” and the end of line are ignored.
SMTP Command blocks
The RPF policy consists of the following four SMTP Command blocks:
connect { ... }
mail_from { ... }
header { ... }
body { ... }
“header” and “body” corresponds to the SMTP DATA Command.
Statements
Each block should have one or more statements. Statements must be terminated by “;”.
The minimum statement is action itself. There are five actions:
- accept
- Accept the message with 250.
- discard
- Accept the message with 250 but silently discard it.
- reject
- Reject the message with 5xx.
- hold
- Temporarily reject the message with 4xx.
- continue
- Go to the next block.
Here is a meaningless example:
connect {
accept;
}
All messages are accepted when their SMTP connections are created and no further blocks will be evaluated.
Conditions
If action is followed by “:”, the rest of the line is a condition expression.
A condition expression is one of the followings:
- keyword == comma-separated-literals
- True if keyword is included in comma-separated-literals. Otherwise, false.
- keyword != comma-separated-literals
- True if keyword is not included in comma-separated-literals. Otherwise, false.
Here is an example to reject a message if the result of SPF is ‘softfail’ or ‘hardfail’:
reject: #spf == softfail, hardfail;
Logical AND can also be used:
- expression && expression
- True if both expressions are true. Otherwise false.
Here is an example to reject a message if the domain part of the SMTP MAIL FROM is “example.com” and the DKIM field does not exist.
reject: #mail_from == "example.com" && #sig_dkim == No;
Types and literals
Boolean
“Yes” means true while “No” indicates false.
Here is an example to accept a message if the DKIM field exists:
accept: #sig_dkim == Yes;
Domain
String enclosed in the double quotes is a domain.
Here is an exapmle to reject a message if the domain part of the From field is “example.com”:
reject: #from == "example.com";
IP address
You can use IPv4 and IPv6 numeric notation with an optional range.
Here is an exapmle to accept 127.0.0.1 and reject 2001:DB8::/32:
accept: #ip == 127.0.0.1;
reject: #ip == 2001:DB8::/32;
Results of domain authentication
Result values of domain authentication can be written as is.
You can specify one of ‘none’, ‘pass’, ‘fail’, ‘policy’, ‘neutral’, ‘temperror’, ‘permerror’, ‘nxdomain’, ‘unknown’, ‘discard’, ‘hardfail’, ‘softfail’.
Here is an example to hold a message if the result of SPF is ‘softfail’:
hold: #spf == softfail;
Keywords
A keyword started with “#”.
The timing when each keyword become available is as follows:
// #ip
connect { ... }
// #spf, #mail_from
mail_from { ... }
// #from, #pra, #sender_id, #dkim_from, #domainkeys_from,
// #sig_dkim, #sig_domainkeys
header { ... }
// #dkim, #domainkeys
body { ... }
For example, “#ip” is the source IP address of SMTP connection. It is decided before the “connect” block is evaluated and all further blocks can use it.
- #ip
- IP address of an SMTP peer.
- #mail_from
- Domain part of SMTP MAIL FROM.
- #from
- Domain part of the From field.
- #pra
- Domain part of PRA.
- #dkim_from
- Domain of DKIM.
- #domainkeys_from
- Domain of DomainKeys.
- #sig_dkim
- Boolean on whether or not the DKIM-Signature field exist.
- #sig_domainkeys
- Boolean on whether or not the DomainKey-Signature field exist.
- #spf
- Result of SPF.
- #sender_id
- Result of Sender ID.
- #dkim
- Result of DKIM.
- #domainkeys
- Result of DomainKeys.
User defined constants
A name can be given to comma-separated-literals. A name starts with “$” and followed by alphabet or number or ’_’ or ‘-’.
A name can be defined in the top level with “=”.
Here is a example:
$ip_white_lists = 127.0.0.1, ::1;
connect {
accept: #ip == $ip_white_lists;
}