20020919
- Feature: reject_rbl <domain> for client address blacklisting
+ Feature: "reject_rbl <domain>" for client address blacklisting
by LaMont Jones, including $name expansion for per-domain
customized response messages. The obsolete reject_maps_rbl
is now a wrapper that uses the new code.
20020921
- Internal: added caching and reject reporting that can be
- used for both reject_rbl and for the upcoming reject_rhsbl.
+ Internal: added caching and factored out common code that
+ will be used for both reject_rbl and for the upcoming
+ reject_rhsbl restriction.
20020922
- Feature: reject_rhsbl <domain> for sender domain blacklisting.
- Provides the same per-domain customized response message
- mechanisms with $name expansion as reject_rbl.
+ Feature: "reject_rhsbl <domain>" for sender domain
+ blacklisting. Provides the same per-domain customized
+ response message mechanisms with $name expansion as
+ reject_rbl.
Safety: the smtpd_expansion_filter parameter controls what
characters are allowed in the expansion of $name macros in
result (i.e. the name does exist) will no longer cause
${name?text} to succeed. File: util/mac_expand.c.
+20020923
+
+ Cleanup. Renamed the RBL features according to a scheme
+ that was suggested by Liviu Daia in October 2001. The
+ names are reject_rbl_client and reject_rhsbl_sender,
+ respectively. Added domain name based reject_rhsbl_client
+ and reject_rhsbl_recipient restrictions for completeness.
+ The reject_rbl restriction name is still recognized for
+ compatibility with systems maintained by LaMont Jones.
+
Open problems:
Low: smtpd should log queue ID with reject/warn/hold/discard
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
-Incompatible changes with Postfix snapshot 1.1.11-20020922
+Incompatible changes with Postfix snapshot 1.1.11-20020923
==========================================================
Subtle change in ${name:result} macro expansions: the expansion
-no longer happens when $name is an empty string.
+no longer happens when $name is an empty string. This probably
+makes more sense than the old behavior.
-Major changes with Postfix snapshot 1.1.11-20020922
+The default RBL "reject" server reply now includes an indication
+of *what* is being rejected: Client host, Helo command, Sender
+address, or Recipient address.
+
+Major changes with Postfix snapshot 1.1.11-20020923
===================================================
-Complete rewrite of RBL internals to avoid unnecessary code
-duplication and to implement caching of results.
+Complete rewrite of the RBL blacklisting code. The names of RBL
+restrictions are now based on a suggestion that was made by Liviu
+Daia in October 2001. See conf/sample-smtpd.cf or html/uce.html
+for details.
-Feature: "reject_rbl rbl.domain.tld" for client IP address
-blacklisting. The old "reject_maps_rbl" is now implemented as a
-wrapper around the reject_rbl code. Based on code by LaMont Jones.
+Feature: "reject_rbl_client rbl.domain.tld" for client IP address
+blacklisting. Based on code by LaMont Jones. The old "reject_maps_rbl"
+is now implemented as a wrapper around the reject_rbl_client code.
-Feature: "reject_rhsbl rbl.domain.tld" for sender domain based
-blacklisting.
+Feature: "reject_rhsbl_sender rbl.domain.tld" for sender domain
+blacklisting. Also: reject_rhsbl_client and reject_rhsbl_recipient
+for client and recipient domain blacklisting.
"rbl_reply_maps" configuration parameter for lookup tables with
-template responses per RBL server. The template responses support
-$name expansion of client, helo, sender, recipient and RBL server
-attributes. See sample-smtpd.cf for details. Based on code by LaMont
-Jones.
+template responses per RBL server. Based on code by LaMont Jones.
+If no reply template is found the default template is used as
+specified with the default_rbl_reply configuration parameter. The
+template responses support $name expansion of client, helo, sender,
+recipient and RBL related attributes.
"smtpd_expansion_filter" configuration parameter to control what
-characters are allowed in the expansion of $name macros.
+characters are allowed in the expansion of template reply $name
+macros. Characters outside the allowed set are replaced by "_".
Incompatible changes with Postfix snapshot 1.1.11-20020917
==========================================================
#
# The smtpd_sender_login_maps parameter specifies the (SASL) login
-# name that owns a sender (MAIL FROM) address.
-#
+# name that owns a sender (MAIL FROM) address.
+#
# Specify zero or more maptype:mapname entries. Maps are created with
# postmap(1) or with equivalent means. The maps are searched in the
# specified order. Regexp tables are allowed.
-#
+#
# Each map entry specifies a sender address and the login name that
# owns the address. The search order is:
-#
+#
# 1) user@domain owner
-#
+#
# This form has the highest precedence.
-#
+#
# 2) user owner
-#
+#
# This matches user@site when site is equal to $myorigin, when site
# is listed in $mydestination, or when it is listed in $inet_interfaces.
-#
+#
# 3) @domain owner
-#
+#
# This matches every address in the specified domain, and has the
# lowest precedence.
-#
+#
#smtpd_sender_login_maps =
#
# reject_unknown_client: reject the request if the client hostname is unknown.
# permit_mynetworks: permit if the client address matches $mynetworks.
# check_client_access maptype:mapname
-# maptype:mapname: look up client name, parent domains, client address,
+# look up client name, parent domains, client address,
# or networks obtained by stripping octets.
# Reject if result is REJECT or "[45]xx text"
# Permit if result is OK or all numerical.
-# reject_maps_rbl: reject if the reverse client network address
-# is listed under $maps_rbl_domains.
+# reject_rbl_client domain.tld: reject if the reverse client network
+# address is listed in an A record under domain.tld.
+# reject_rhsbl_client domain.tld: reject if the client hostname is listed
+# in an A record under domain.tld.
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# warn_if_reject: next restriction logs a warning instead of rejecting.
+#
+# You may also list any helo or client restrictions here (see below).
+#
smtpd_etrn_restrictions =
# The smtpd_history_flush_threshold specifies how many lines the SMTP
# server command history is allowed to contain before it is flushed
# to postmaster upon receipt of EHLO, RSET, or end of DATA.
-#
+#
smtpd_history_flush_threshold = 100
# The smtpd_noop_commands parameter specifies a list of commands that
# are specified within <>, and that MAIL FROM and RCPT TO addresses
# do not contain RFC822-style comments or phrases. It's great to
# stop SPAM mailers. But it also trips up broken peecee clients.
-#
+#
# By default, Postfix SMTPD allows RFC822 syntax in MAIL FROM and RCPT TO.
-#
+#
strict_rfc821_envelopes = no
#
#
# By default (mynetworks_style = subnet), Postfix "trusts" SMTP
# clients in the same IP subnetworks as the local machine.
-#
+#
# Specify "mynetworks_style = class" when Postfix should "trust" SMTP
# clients in the same IP class A/B/C networks as the local machine.
# Don't do this with a dialup site - it would cause Postfix to "trust"
# your entire provider's network. Instead, specify an explicit
# mynetworks list by hand, as described below.
-#
+#
# Specify "mynetworks_style = host" when Postfix should "trust"
# only the local machine.
-#
+#
#mynetworks_style = class
mynetworks_style = subnet
#mynetworks_style = host
# reject_unknown_client: reject the request if the client hostname is unknown.
# permit_mynetworks: permit if the client address matches $mynetworks.
# check_client_access maptype:mapname
-# maptype:mapname: look up client name, parent domains, client address,
+# look up client name, parent domains, client address,
# or networks obtained by stripping octets.
# Reject if result is REJECT or "[45]xx text"
# Permit if result is OK or all numerical.
-# reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
+# reject_rbl_client domain.tld: reject if the reversed client IP address
+# is listed in an A record under domain.tld.
+# reject_rhsbl_client domain.tld: reject if the client hostname is listed
+# in an A record under domain.tld.
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# warn_if_reject: next restriction logs a warning instead of rejecting.
# Restrictions are applied in the order as specified; the first
# restriction that matches wins.
#
+# You may also list any helo, sender or recipient restrictions here.
+# These will have effect only when smtpd_delay_reject=yes, so that all
+# restrictions are evaluated at the time of the RCPT TO command.
+#
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
#smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
-#smtpd_client_restrictions = reject_maps_rbl, reject_unknown_client
-smtpd_client_restrictions =
+smtpd_client_restrictions =
# The smtpd_helo_required parameter optionally turns on the requirement
# that SMTP clients must introduce themselves at the beginning of an
# are available:
#
# permit_mynetworks: permit if the client address matches $mynetworks.
-# reject_unknown_client: reject the request if the client hostname is unknown.
-# reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
# reject_invalid_hostname: reject HELO hostname with bad syntax.
# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
# reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
# check_helo_access maptype:mapname
-# maptype:mapname: look up HELO hostname or parent domains.
+# look up HELO hostname or parent domains.
# Reject if result is REJECT or "[45]xx text"
# Permit if result is OK or all numerical.
-# check_client_access maptype:mapname: see smtpd_client_restrictions.
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# warn_if_reject: next restriction logs a warning instead of rejecting.
# Restrictions are applied in the order as specified; the first
# restriction that matches wins.
#
+# You may also list any client, sender or recipient restrictions here.
+# Sender and recipient restrictions will have effect only when
+# smtpd_delay_reject=yes, so that all restrictions are evaluated at
+# the time of the RCPT TO command.
+#
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
#smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
#smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
-smtpd_helo_restrictions =
+smtpd_helo_restrictions =
# The smtpd_sender_restrictions parameter specifies optional restrictions
# on sender addresses that SMTP clients can send in MAIL FROM commands.
-#
+#
# The default is to permit any sender address. The following
# restrictions are available:
#
# permit_mynetworks: permit if the client address matches $mynetworks.
-# reject_unknown_client: reject the request if the client hostname is unknown.
-# reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
-# reject_invalid_hostname: reject HELO hostname with bad syntax.
-# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
# reject_unknown_sender_domain: reject sender domain without A or MX record.
+# reject_rhsbl_sender domain.tld: reject sender domain name if it is listed
+# in an A record under domain.tld.
# check_sender_access maptype:mapname
-# maptype:mapname: look up sender address, parent domain, or localpart@.
+# look up sender address, parent domain, or localpart@.
# Reject if result is REJECT or "[45]xx text"
# Permit if result is OK or all numerical.
-# check_client_access maptype:mapname: see smtpd_client_restrictions.
-# check_helo_access maptype:mapname: see smtpd_helo_restrictions.
# reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies
# a MAIL FROM address owner, but the client is not (SASL) logged in as
# that MAIL FROM address owner; or if the client is (SASL) logged in, but
# the client login name doesn't own the MAIL FROM address according to
# $smtpd_sender_login_maps (see above).
-# reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
# reject_non_fqdn_sender: reject sender address that is not in FQDN form
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# Restrictions are applied in the order as specified; the first
# restriction that matches wins.
#
+# You may also list any helo, client or recipient restrictions here.
+# Recipient restrictions will have effect only when smtpd_delay_reject=yes,
+# so that all restrictions are evaluated at the time of the RCPT TO
+# command.
+#
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
#smtpd_sender_restrictions = reject_unknown_sender_domain
#smtpd_sender_restrictions = reject_unknown_sender_domain, hash:/etc/postfix/access
-smtpd_sender_restrictions =
+smtpd_sender_restrictions =
# The smtpd_recipient_restrictions parameter specifies restrictions on
# recipient addresses that SMTP clients can send in RCPT TO commands.
-#
+#
# By default, Postfix relays mail
# - from trusted clients whose IP address matches $mynetworks,
# - from trusted clients matching $relay_domains or subdomains thereof,
# - destinations that match $mydestination
# - destinations that match $virtual_maps.
# These destinations do not need to be listed in $relay_domains.
-#
+#
# The following restrictions are available (* is part of default setting):
#
# *permit_mynetworks: permit if the client address matches $mynetworks.
-# reject_unknown_client: reject the request if the client hostname is unknown.
-# reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
-# reject_invalid_hostname: reject HELO hostname with bad syntax.
-# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
# reject_unknown_sender_domain: reject sender domain without A or MX record.
-# *check_relay_domains: permit only mail
-# - to destinations matching $inet_interfaces, $mydestination,
+# reject_rhsbl_recipient domain.tld: reject recipient domain name if it is
+# listed in an A record under domain.tld.
+# *check_relay_domains: permit only mail
+# - to destinations matching $inet_interfaces, $mydestination,
# or $virtual_maps,
# - from trusted clients matching $relay_domains or subdomain thereof,
# - from untrusted clients to destinations matching $relay_domains or
# subdomain thereof (except addresses with sender-specified routing),
# Reject anything else.
-# permit_auth_destination: permit mail
-# - to destinations matching $inet_interfaces, $mydestination,
+# permit_auth_destination: permit mail
+# - to destinations matching $inet_interfaces, $mydestination,
# or $virtual_maps.
# - to destinations matching $relay_domains or subdomain thereof,
# except for addresses with sender-specified routing.
-# reject_unauth_destination: reject mail unless it is sent
-# - to destinations matching $inet_interfaces, $mydestination,
+# reject_unauth_destination: reject mail unless it is sent
+# - to destinations matching $inet_interfaces, $mydestination,
# or $virtual_maps.
# - to destinations matching $relay_domains or subdomain thereof,
# except for addresses with sender-specified routing.
# require that the primary MX hosts match a list of network blocks.
# reject_unknown_recipient_domain: reject domains without A or MX record.
# check_recipient_access maptype:mapname
-# maptype:mapname: look up recipient address, parent domain, or localpart@.
+# look up recipient address, parent domain, or localpart@.
# Reject if result is REJECT or "[45]xx text"
# Permit if result is OK or all numerical.
-# check_client_access maptype:mapname: see smtpd_client_restrictions.
-# check_helo_access maptype:mapname: see smtpd_helo_restrictions.
-# check_sender_access maptype:mapname: see smtpd_sender_restrictions.
-# reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies
-# a MAIL FROM address owner, but the client is not (SASL) logged in as
-# that MAIL FROM address owner; or if the client is (SASL) logged in, but
-# the client login name doesn't own the MAIL FROM address according to
-# $smtpd_sender_login_maps (see above).
-# reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
-# reject_non_fqdn_sender: reject sender address that is not in FQDN form
# reject_non_fqdn_recipient: reject recipient address that is not in FQDN form
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# Restrictions are applied in the order as specified; the first
# restriction that matches wins.
#
+# You may also list any helo, client or sender restrictions here.
+#
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
# forward mail with sender-specified routing (user[@%!]remote[@%!]site)
# from untrusted clients to destinations that are blessed by the
# relay_domains parameter.
-#
+#
# By default, untrusted clients are not allowed to specify routing.
# This closes a nasty open relay loophole where a backup MX host can
# be tricked into forwarding junk mail to a primary MX host which
#
allow_untrusted_routing = no
-# The maps_rbl_domains parameter specifies an optional list of DNS
-# domains that publish the network addresses of blacklisted hosts.
-#
-# By default, RBL blacklist lookups are disabled. See the
-# smtpd_client_restrictions parameter.
-#
-# The real-time blackhole list works as follows: reverse the client
-# network address, and reject service if it is listed below any of
-# the following domains.
-#
-#maps_rbl_domains = blackholes.mail-abuse.org relays.mail-abuse.org
-maps_rbl_domains = blackholes.mail-abuse.org
-
# The relay_domains parameter restricts what client hostname domains
# (and subdomains thereof) this mail system will relay mail from,
# and restricts what destination domains (and subdomains thereof)
# this system will relay mail to.
-#
+#
# By default, Postfix relays mail
-# - from trusted clients whose IP address matches $mynetworks,
+# - from trusted clients whose IP address matches $mynetworks,
# - from trusted clients matching $relay_domains or subdomains thereof,
# - from untrusted clients to destinations that match $relay_domains
# or subdomains thereof, except addresses with sender-specified routing.
-# The default relay_domains value is $mydestination.
-#
-# In addition to the above, the Postfix SMTP server by default accepts mail
+# The default relay_domains value is $mydestination.
+#
+# In addition to the above, the Postfix SMTP server by default accepts mail
# that Postfix is final destination for:
-# - destinations that match $inet_interfaces,
-# - destinations that match $mydestination
+# - destinations that match $inet_interfaces,
+# - destinations that match $mydestination
# - destinations that match $virtual_maps.
# These destinations do not need to be listed in $relay_domains.
#
#
access_map_reject_code = 550
+# The default_rbl_reply parameter specifies the SMTP server response
+# when an SMTP client request is rejected by a reject_rbl or reject_rhsbl
+# restriction.
+#
+# The template is subject to exactly one level of $name substitution:
+#
+# $client: client hostname and IP address, formatted as name[address].
+# $client_name: client hostname or unknown.
+# $client_address: client IP address.
+# $helo_name: hostname given in HELO or EHLO command or empty string.
+# $sender: sender address or <> in case of the null address.
+# $sender_name: sender address localpart or <> in case of the null address.
+# $sender_domain: sender address domain or empty string.
+# $recipient: recipient address or <> in case of the null address.
+# $recipient_name: recipient address localpart or <> in case of null address.
+# $recipient_domain: recipient address domain or empty string.
+# $rbl_what: the entity that is blacklisted (an IP address, a hostname,
+# a domain name, or an email address whose domain was blacklisted).
+# $rbl_reason: reason why $rbl_what is blacklisted or empty string.
+# $rbl_domain: RBL domain where $rbl_what is blacklisted.
+# $rbl_class: the blacklisted entity type: Client host, Helo command,
+# Sender address, or Recipient address.
+# $rbl_code: numerical server reply code, as specified with the
+# maps_rbl_reject_code configuration parameter.
+#
+# The smtpd_expansion_filter configuration parameter controls what
+# characters may appear in $name expansions.
+#
+# Instead of $name you can also specify ${name} or $(name).
+#
+# Conditional expansion:
+#
+# ${name?text} expands to `text' if $name is not empty.
+# ${name:text} expands to `text' if $name is empty.
+#
+default_rbl_reply = $rbl_code Service unavailable; $rbl_class [$rbl_what]
+ blocked using $rbl_domain${rbl_reason?; $rbl_reason}
+
# The defer_code parameter specifies the SMTP server response code
# when an SMTP client request is rejected by the "defer" restriction.
#
invalid_hostname_reject_code = 501
# The maps_rbl_reject_code parameter specifies the SMTP server response
-# when a client violates the maps_rbl_domains restriction.
+# when an SMTP client request is blocked by a reject_rbl or reject_rhsbl
+# restriction.
#
# Do not change this unless you have a complete understanding of RFC 821.
#
maps_rbl_reject_code = 550
+# The rbl_reply_maps parameter specifies tables with RBL response
+# templates, indexed by RBL domain name. By default, Postfix uses
+# the default template as specified with the default_rbl_reply
+# configuration parameter. See there for a discussion of the syntax
+# of RBL reply templates.
+#
+rbl_reply_maps =
+
# The reject_code parameter specifies the SMTP server response code
# when an SMTP client matches a reject restriction.
#
#
relay_domains_reject_code = 550
+# The smtpd_expansion_filter parameter specifies what characters are
+# allowed in $name expansions of RBL reply templates. Characters not
+# in the allowed set are replaced by "_". Use C like escapes to
+# specify special characters such as whitespace.
+#
+# This parameter is not subjected to the usual main.cf macro expansion.
+#
+smtpd_expansion_filter = \t\40!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+
# The unknown_address_reject_code parameter specifies the SMTP server
# response when a client violates the reject_unknown_sender_domain
# or reject_unknown_recipient_domain restrictions.
<b>UCE</b> <b>control</b> <b>responses</b>
<b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates an access
+ Response code when a client violates an access
database restriction.
+ <b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b>
+ Default template reply when a request is RBL black-
+ listed. This template is used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b>
+ and <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
+ <b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
+
<b>defer</b><i>_</i><b>code</b>
- Server response when a client request is rejected
- by the <b>defer</b> restriction.
+ Response code when a client request is rejected by
+ the <b>defer</b> restriction.
<b>invalid</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
+ Response code when a client violates the
<b>reject</b><i>_</i><b>invalid</b><i>_</i><b>hostname</b> restriction.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
- <b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> restriction.
+ Response code when a request is RBL blacklisted.
<b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b>
- Table with template responses, indexed by RBL
- domain name. These templates are used by the
- <b>reject</b><i>_</i><b>rbl</b> and <b>reject</b><i>_</i><b>rhsbl</b> restrictions. See also:
- <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
+ Table with template responses for RBL blacklisted
+ requests, indexed by RBL domain name. These tem-
+ plates are used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b> and
+ <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
+ <b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
<b>reject</b><i>_</i><b>code</b>
- Response code when the client matches a <b>reject</b>
+ Response code when the client matches a <b>reject</b>
restriction.
<b>relay</b><i>_</i><b>domains</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client attempts to violate
- the mail relay policy.
+ Response code when a client attempts to violate the
+ mail relay policy.
<b>unknown</b><i>_</i><b>address</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
+ Response code when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>address</b> restriction.
<b>unknown</b><i>_</i><b>client</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client without address to
- name mapping violates the <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
+ Response code when a client without address to name
+ mapping violates the <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
restriction.
<b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
+ Response code when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
<b>SEE</b> <b>ALSO</b>
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<p>
+In addition to restrictions that are specific to the client hostname
+or IP address, you may list here any restrictions based on the
+information passed with the <a href="#smtpd_helo_restrictions">
+HELO/EHLO command</a>, on the <a href="#smtpd_sender_restrictions">
+sender address </a> or on the <a href="#smtpd_recipient_restrictions">
+recipient address</a>. The HELO/EHLO, sender or recipient restrictions
+take effect only if <b>smtpd_delay_reject = yes</b> so that all
+restrictions are evaluated after the RCPT TO command.
+
+<p>
+
<dt>Examples:
<dd> <b>smtpd_client_restrictions = hash:/etc/postfix/access,
-reject_maps_rbl</b>
+reject_rbl_client relays.mail-abuse.org</b>
+
+<dd> <b>smtpd_client_restrictions = hash:/etc/postfix/access,
+reject_rhsbl_client dsn.rfc-ignorant.org</b>
<dd> <b>smtpd_client_restrictions = permit_mynetworks,
reject_unknown_client</b>
<p>
-<a name="check_client_access">
+<a name="reject_rbl_client">
-<dt> <b>check_client_access</b> <i>maptype</i>:<i>mapname</i>
+<dt> <b>reject_rbl_client</b> <i>domain.tld</i> <dd> Reject the
+request when the reversed client network address is listed with an
+A record under <i>domain.tld</i>.
-<dt> <i>maptype</i>:<i>mapname</i> <dd> Search the named <a
-href="access.5.html">access database</a> for the client hostname, parent
-domains, client IP address, or networks obtained by stripping least
-significant octets.
+The <b> maps_rbl_reject_code</b> parameter specifies the response
+code for rejected requests (default: <b>554</b>), the <b><a
+href="#default_rbl_reply"> default_rbl_reply </a></b> parameter
+specifies the default server reply, and the <b><a href="#rbl_reply_maps">
+rbl_reply_maps </a></b> parameter specifies tables with server replies
+indexed by RBL domain.
<p>
-<dl compact>
+<a name="reject_rhsbl_client">
-<dt>REJECT
-<dd>Reject the request. The <b>access_map_reject_code</b> parameter
-specifies the response code (default: <b>554</b>).
+<dt> <b>reject_rhsbl_client</b> <i>domain.tld</i> <dd> Reject the
+request when the client hostname is listed with an A record under
+<i>domain.tld</i>. See above for additional RBL related configuration
+parameters.
<p>
-<dt>[<b>45</b>]<i>XX text</i>
-<dd>Reject the request. Send the numerical code and text to the SMTP client.
-
-<p>
-
-<dt>OK
-<dt>RELAY
-<dt>all-numerical
-<dd>Permit the request.
-
-<p>
-
-<dt>HOLD
-<dd> Place the message on the <b>hold</b> queue. Mail on hold can
-be inspected with the <a href="postcat.1.html">postcat</a> command,
-and can be destroyed or taken off hold with the <a
-href="postsuper.1.html">postsuper</a> command.
-
-<b> Note: this action currently affects all recipients of a message.</b>
-
-<p>
-
-<dt>DISCARD
-<dd> Claim successful delivery and silently discard the message.
-
-<b> Note: this action currently affects all recipients of a message.</b>
-
-<p>
-
-<dt>FILTER <i>transport</i>:<i>nexthop</i> <dd>
-After the message is queued, send the entire message through
-a content filter. This requires different cleanup servers
-before and after the filter, with header/body checks turned
-off in the second cleanup server. More details about content
-filtering are in the Postfix FILTER_README file. This feature
-overrides the main.cf <b>content_filter</b> setting.
-
-<b> Note: this action currently affects all recipients of a message.</b>
-
-<p>
-
-<dt>Other<dd> Treat the result as another list of UCE restrictions.
-
-</dl>
-
-<p>
+<a name="check_client_access">
-<a name="reject_maps_rbl">
+<dt> <b>check_client_access</b> <i>maptype</i>:<i>mapname</i>
-<dt> <b>reject_maps_rbl</b> <dd> Reject the request when the reversed
-client network address is listed under any of the domains listed
-in <a href="#maps_rbl_domains">$maps_rbl_domains</a>. The <b>
-maps_rbl_reject_code</b> parameter specifies the response code for
-rejected requests (default: <b>554</b>).
+<dt> <i>maptype</i>:<i>mapname</i> <dd> Search the named <a
+href="access.5.html">access database</a> for the client hostname, parent
+domains, client IP address, or networks obtained by stripping least
+significant octets.
<p>
<p>
-In addition to restrictions that are specific to HELO (EHLO)
-command parameters, you can also specify restrictions based
-on the client hostname or network address.
+In addition to restrictions that are specific to HELO (EHLO) command
+parameters, you may list here any restrictions on the <a
+href="#smtpd_client_restrictions"> client hostname </a>, <a
+href="#smtpd_client_restrictions"> client address </a>, <a
+href="#smtpd_sender_restrictions"> sender address </a> or <a
+href="#smtpd_recipient_restrictions"> recipient address</a>. The
+sender or recipient restrictions take effect only if <b>smtpd_delay_reject
+= yes</b> so that all restrictions are evaluated after the RCPT TO
+command.
<p>
<dt> <i>maptype</i>:<i>mapname</i> <dd> Search the named <a
href="access.5.html">access database</a> for the <b>HELO</b> hostname
-or parent domains in the specified table. Reject the request if
-the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit
-the request when the result is <b>OK</b> or <b>RELAY</b> or
-all-numerical. Otherwise, treat the result as another list of UCE
-restrictions. The <b>access_map_reject_code </b> parameter specifies
-the response code for <b>REJECT</b> results (default: <b>554</b>).
-
-<p>
-
-<dt> <b><a href="#reject_maps_rbl">reject_maps_rbl</a></b>
-
-<dt> <b><a href="#reject_unknown_client">reject_unknown_client</a></b>
-
-<dt> <b><a href="#permit_mynetworks">permit_mynetworks</a></b>
-
-<dt> <b><a href="#check_client_access">check_client_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dd> See client hostname/address restrictions.
+or parent domains.
<p>
In addition to restrictions that are specific to sender mail
addresses, you can also specify restrictions based on the information
-passed with the HELO/EHLO command, and on the client hostname or
-network address.
+passed with the <a href="#smtpd_helo_restrictions"> HELO/EHLO
+command </a>, on the <a href="#smtpd_client_restrictions"> client
+hostname </a> or <a href="#smtpd_client_restrictions"> network
+address </a>, or on the <a href="#smtpd_recipient_restrictions">
+recipient address </a>. The recipient restrictions take effect
+only if <b>smtpd_delay_reject = yes</b> so that all restrictions
+are evaluated after the RCPT TO command.
<p>
<p>
+<a name="reject_rhsbl_sender">
+
+<dt> <b>reject_rhsbl_sender</b> <i>domain.tld</i> <dd> Reject the
+request when the sender mail address domain is listed with an A
+record under <i>domain.tld</i>.
+
+The <b> maps_rbl_reject_code</b> parameter specifies the response
+code for rejected requests (default: <b>554</b>), the <b><a
+href="#default_rbl_reply"> default_rbl_reply </a></b> parameter
+specifies the default server reply, and the <b><a href="#rbl_reply_maps">
+rbl_reply_maps </a></b> parameter specifies tables with server replies
+indexed by RBL domain.
+<p>
+
<a name="check_sender_access">
<dt> <b>check_sender_access</b> <i>maptype</i>:<i>mapname</i>
<dt> <i>maptype</i>:<i>mapname</i> <dd> Search the named <a
href="access.5.html">access database</a> for the sender mail address,
-parent domain, or <i>localpart</i>@. Reject the request if the
-result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit the
-request if the result is <b>OK</b> or <b>RELAY</b> or all-numerical.
-Otherwise, treat the result as another list of UCE restrictions. The
-<b>access_map_reject_code </b> parameter specifies the result code for
-rejected requests (default: <b>554</b>).
+sender domain and parent domain, or <i>localpart</i>@.
<p>
<p>
-<dt> <b><a href="#permit_naked_ip_address">permit_naked_ip_address</a></b>
-
-<dt> <b><a href="#reject_invalid_hostname">reject_invalid_hostname</a></b>
-
-<dt> <b><a href="#reject_unknown_hostname">reject_unknown_hostname</a></b>
-
-<dt> <b><a href="#reject_non_fqdn_hostname">reject_non_fqdn_hostname</a></b>
-
-<dt> <b><a href="#check_helo_access">check_helo_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dd> See HELO (EHLO) hostname restrictions.
-
-<p>
-
-<dt> <b><a href="#reject_maps_rbl">reject_maps_rbl</a></b>
-
-<dt> <b><a href="#reject_unknown_client">reject_unknown_client</a></b>
-
-<dt> <b><a href="#permit_mynetworks">permit_mynetworks</a></b>
-
-<dt> <b><a href="#check_client_access">check_client_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dd> See client hostname/address restrictions.
-
-<p>
-
<dt> <b><a href="#permit">permit</a></b>
<dt> <b><a href="#defer">defer</a></b>
<p>
In addition to restrictions that are specific to recipient mail
-addresses, you can also specify restrictions based on the sender mail
-address, on the information passed with the HELO/EHLO command, and
-on the client hostname or network address.
+addresses, you can also specify restrictions based on the <a
+href="#smtpd_sender_restrictions"> sender mail address</a>, on the
+information passed with the <a href="#smtpd_helo_restrictions">
+HELO/EHLO command </a>, and on the <a href="#smtpd_client_restrictions">
+client hostname </a> or <a href="#smtpd_client_restrictions">
+network address </a>.
<p>
<dt> <i>maptype</i>:<i>mapname</i> <dd> Search the named <a
href="access.5.html">access database</a> for the resolved destination
-address, parent domain, or <i>localpart</i>@. Reject the request if the
-result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit the
-request if the result is <b>OK</b> or <b>RELAY</b> or all-numerical.
-Otherwise, treat the result as another list of UCE restrictions. The
-<b>access_map_reject_code </b> parameter specifies the result code for
-rejected requests (default: <b>554</b>).
+address, recipient domain or parent domain, or <i>localpart</i>@.
<p>
<p>
-<a name="reject_non_fqdn_recipient">
-
-<dt> <b>reject_non_fqdn_recipient</b> <dd> Reject the request when
-the address in the client RCPT TO command is not in fully-qualified
-domain form. The <b>non_fqdn_reject_code</b> specifies the
-response code to rejected requests (default: <b>504</b>).
-
-<p>
-
-<dt> <b><a href="#reject_unknown_sender_domain">reject_unknown_sender_domain</a></b>
-
-<dt> <b><a href="#reject_non_fqdn_sender">reject_non_fqdn_sender</a></b>
-
-<dt> <b><a href="#check_sender_access">check_sender_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dt> <b><a href="#reject_sender_login_mismatch">reject_sender_login_mismatch
-</a></b>
-
-<dd> See sender address restrictions.
-
-<p>
-
-<dt> <b><a href="#permit_naked_ip_address">permit_naked_ip_address</a></b>
-
-<dt> <b><a href="#reject_invalid_hostname">reject_invalid_hostname</a></b>
-
-<dt> <b><a href="#reject_unknown_hostname">reject_unknown_hostname</a></b>
+<a name="reject_rhsbl_recipient">
-<dt> <b><a href="#reject_non_fqdn_hostname">reject_non_fqdn_hostname</a></b>
+<dt> <b>reject_rhsbl_recipient</b> <i>domain.tld</i> <dd> Reject the
+request when the recipient mail address domain is listed with an A
+record under <i>domain.tld</i>.
-<dt> <b><a href="#check_helo_access">check_helo_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dd> See HELO (EHLO) hostname restrictions.
+The <b> maps_rbl_reject_code</b> parameter specifies the response
+code for rejected requests (default: <b>554</b>), the <b><a
+href="#default_rbl_reply"> default_rbl_reply </a></b> parameter
+specifies the default server reply, and the <b><a href="#rbl_reply_maps">
+rbl_reply_maps </a></b> parameter specifies tables with server replies
+indexed by RBL domain.
<p>
-<dt> <b><a href="#reject_maps_rbl">reject_maps_rbl</a></b>
-
-<dt> <b><a href="#reject_unknown_client">reject_unknown_client</a></b>
-
-<dt> <b><a href="#permit_mynetworks">permit_mynetworks</a></b>
-
-<dt> <b><a href="#check_client_access">check_client_access</a></b> <i>maptype</i>:<i>mapname</i>
+<a name="reject_non_fqdn_recipient">
-<dd> See client hostname/address restrictions.
+<dt> <b>reject_non_fqdn_recipient</b> <dd> Reject the request when
+the address in the client RCPT TO command is not in fully-qualified
+domain form. The <b>non_fqdn_reject_code</b> specifies the
+response code to rejected requests (default: <b>504</b>).
<p>
In addition to restrictions that are specific to ETRN domain names,
you can also specify restrictions based on the information passed
-with the HELO/EHLO command, and on the client hostname or network
-address.
+with the <a href="#smtpd_helo_restrictions"> HELO/EHLO command
+</a>, and on the <a href="#smtpd_client_restrictions"> client
+hostname </a> or <a href="#smtpd_client_restrictions"> network
+address </a>.
<p>
<p>
-<dt> <b><a href="#permit_naked_ip_address">permit_naked_ip_address</a></b>
-
-<dt> <b><a href="#reject_invalid_hostname">reject_invalid_hostname</a></b>
-
-<dt> <b><a href="#reject_unknown_hostname">reject_unknown_hostname</a></b>
-
-<dt> <b><a href="#check_helo_access">check_helo_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dd> See HELO (EHLO) hostname restrictions.
-
-<p>
-
-<dt> <b><a href="#reject_maps_rbl">reject_maps_rbl</a></b>
-
-<dt> <b><a href="#reject_unknown_client">reject_unknown_client</a></b>
-
-<dt> <b><a href="#permit_mynetworks">permit_mynetworks</a></b>
-
-<dt> <b><a href="#check_client_access">check_client_access</a></b> <i>maptype</i>:<i>mapname</i>
-
-<dd> See client hostname/address restrictions.
-
-<p>
-
<dt> <b><a href="#permit">permit</a></b>
<dt> <b><a href="#defer">defer</a></b>
<dl>
+<a name="default_rbl_reply">
+
+<dt> <b>default_rbl_reply</b>
+
+<dd>The default reply template that is used when an SMTP client
+request is blocked by a <b>reject_rbl</b> or <b>reject_rhsbl</b>
+restriction. The reply template is subjected to exactly one level
+of $name macro substitution as described below. The
+<b>smtpd_expansion_filter</b> configuration parameter specifies
+the set of characters that are allowed in $name macro expansions.
+Characters outside the allowed set are replaced by "_".
+
+<p>
+
+<dl>
+
+<dt>Default:
+
+<dd><b> default_rbl_reply = $rbl_code Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason} </b>
+
+<p>
+
+Instead of the form $<i>name</i> you can also specify ${<i>name</i>}
+or $(<i>name</i>).
+
+<p>
+
+<dt>Macro expansion syntax:
+
+<dl>
+
+<dt> $client <dd> The client hostname and IP address, formatted as
+<i>name</i>[<i>address</i>].
+
+<dt> $client_name <dd> The client hostname, or <b>unknown</b>.
+
+<dt> $client_address <dd> The client IP address.
+
+<dt> $helo_name <dd> The hostname given in the HELO or EHLO command,
+or the empty string when no HELO or EHLO command was given.
+
+<dt> $sender <dd> The sender address, or <> in case of the null
+address.
+
+<dt> $sender_name <dd> The sender address localpart, or <> in case
+of the null address.
+
+<dt> $sender_domain <dd> The sender address domain, or the empty
+string when no domain is available.
+
+<dt> $recipient <dd> The recipient address, or <> in case of the
+null address.
+
+<dt> $recipient_name <dd> The recipient address localpart, or <>
+in case of the null address.
+
+<dt> $recipient_domain <dd> The recipient address domain, or the
+empty string when no domain is available.
+
+<dt> $rbl_what <dd> The blacklisted entity: an IP address, a
+hostname, a domain name, or an email address whose domain is
+blacklisted.
+
+<dt> $rbl_domain <dd> The RBL domain where $rbl_what is blacklisted
+with an A record.
+
+<dt> $rbl_reason <dd> The reason why $rbl_what is blacklisted, or
+the empty string when no information is available.
+
+<dt> $rbl_class <dd> The blacklisted entity type: Client host,
+Helo command, Sender address, or Recipient address.
+
+<dt> $rbl_code <dd> The numerical server reply code, as specified
+with the <b>maps_rbl_reject_code</b> configuration parameter
+(default: 554).
+
+<dt> All other text <dd> Copied without change, with the exception
+of conditional macro expansion as described below.
+
+</dl>
+
+<p>
+
+Conditional macro expansion syntax:
+
+<dl>
+
+<dt> ${<i>name</i>?<i>text</i>} <dd> expands to <i>text</i> if
+$<i>name</i> is not empty.
+
+<dt> ${<i>name</i>:<i>text</i>} <dd> expands to <i>text</i> if
+$<i>name</i> is empty.
+
+</dl>
+
+</dl>
+
+</dl>
+
+<p>
+
+<dl>
+
<a name="permit_mx_backup_networks">
<dt> <b>permit_mx_backup_networks</b>
</dl>
+<p>
+
<dl>
-<a name="maps_rbl_domains">
+<a name="rbl_reply_maps">
-<dt> <b>maps_rbl_domains</b>
+<dt> <b>rbl_reply_maps</b>
-<dd>This parameter controls the behavior of the <a
-href="#reject_maps_rbl">reject_maps_rbl</a> restriction that can
-appear as part of a client hostname/address restriction list.
+<dd> This parameter specifies lookup tables with RBL reply templates
+indexed by RBL domain name. If no template is found, the
+<a href="#default_rbl_reply"> default_rbl_reply </a> template is
+used instead.
<p>
<dt>Default:
-<dd><b>maps_rbl_domains = </b>
+<dd><b>rbl_reply_maps = </b>
<p>
-Note: RBL lookups are disabled by default.
+By default, Postfix always uses the <a href="#default_rbl_reply">
+default_rbl_reply </a> template.
<p>
<dt>Syntax:
-<dd> Zero or more DNS domains that blacklist client IP addresses. A
-host is blacklisted when its reversed IP address is listed as a
-subdomain under any of the domains listed in <b>$maps_rbl_domains.</b>
+<dd> Specify zero or more <i>type</i>:<i>name</i> lookup tables,
+separated by whitespace and/or commas. For the syntax of the
+template reply strings, see the <a href="#default_rbl_reply">
+default_rbl_reply </a> parameter description.
</dl>
-<p>
+</dl>
+
+<dl>
<a name="relay_domains">
.ad
.fi
.IP \fBaccess_map_reject_code\fR
-Server response when a client violates an access database restriction.
+Response code when a client violates an access database restriction.
+.IP \fBdefault_rbl_reply\fR
+Default template reply when a request is RBL blacklisted.
+This template is used by the \fBreject_rbl_*\fR and
+\fBreject_rhsbl_*\fR restrictions. See also:
+\fBrbl_reply_maps\fR and \fBsmtpd_expansion_filter\fR.
.IP \fBdefer_code\fR
-Server response when a client request is rejected by the \fBdefer\fR
+Response code when a client request is rejected by the \fBdefer\fR
restriction.
.IP \fBinvalid_hostname_reject_code\fR
-Server response when a client violates the \fBreject_invalid_hostname\fR
+Response code when a client violates the \fBreject_invalid_hostname\fR
restriction.
.IP \fBmaps_rbl_reject_code\fR
-Server response when a client violates the \fBmaps_rbl_domains\fR
-restriction.
+Response code when a request is RBL blacklisted.
.IP \fBrbl_reply_maps\fR
-Table with template responses, indexed by RBL domain name. These
-templates are used by the \fBreject_rbl\fR and \fBreject_rhsbl\fR
-restrictions. See also: \fBsmtpd_expansion_filter\fR.
+Table with template responses for RBL blacklisted requests, indexed by
+RBL domain name. These templates are used by the \fBreject_rbl_*\fR
+and \fBreject_rhsbl_*\fR restrictions. See also:
+\fBdefault_rbl_reply\fR and \fBsmtpd_expansion_filter\fR.
.IP \fBreject_code\fR
Response code when the client matches a \fBreject\fR restriction.
.IP \fBrelay_domains_reject_code\fR
-Server response when a client attempts to violate the mail relay
+Response code when a client attempts to violate the mail relay
policy.
.IP \fBunknown_address_reject_code\fR
-Server response when a client violates the \fBreject_unknown_address\fR
+Response code when a client violates the \fBreject_unknown_address\fR
restriction.
.IP \fBunknown_client_reject_code\fR
-Server response when a client without address to name mapping
+Response code when a client without address to name mapping
violates the \fBreject_unknown_clients\fR restriction.
.IP \fBunknown_hostname_reject_code\fR
-Server response when a client violates the \fBreject_unknown_hostname\fR
+Response code when a client violates the \fBreject_unknown_hostname\fR
restriction.
.SH SEE ALSO
.na
#define WARN_IF_REJECT "warn_if_reject"
-#define REJECT_RBL "reject_rbl"
-#define REJECT_RHSBL "reject_rhsbl"
+#define REJECT_RBL "reject_rbl" /* LaMont compatibility */
+#define REJECT_RBL_CLIENT "reject_rbl_client"
+#define REJECT_RHSBL_CLIENT "reject_rhsbl_client"
+#define REJECT_RHSBL_SENDER "reject_rhsbl_sender"
+#define REJECT_RHSBL_RECIPIENT "reject_rhsbl_recipient"
+
#define VAR_RBL_REPLY_MAPS "rbl_reply_maps"
#define DEF_RBL_REPLY_MAPS ""
extern char *var_rbl_reply_maps;
-#define REJECT_MAPS_RBL "reject_maps_rbl"
+#define VAR_DEF_RBL_REPLY "default_rbl_reply"
+#define DEF_DEF_RBL_REPLY "$rbl_code Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason}"
+extern char *var_def_rbl_reply;
+
+#define REJECT_MAPS_RBL "reject_maps_rbl" /* backwards compat */
#define VAR_MAPS_RBL_CODE "maps_rbl_reject_code"
#define DEF_MAPS_RBL_CODE 554
extern int var_maps_rbl_code;
-#define VAR_MAPS_RBL_DOMAINS "maps_rbl_domains"
+#define VAR_MAPS_RBL_DOMAINS "maps_rbl_domains" /* backwards compat */
#define DEF_MAPS_RBL_DOMAINS ""
extern char *var_maps_rbl_domains;
#define MAIL_ATTR_TRANSPORT "transport"
#define MAIL_ATTR_NEXTHOP "nexthop"
+ /*
+ * Suffixes for sender_name, sender_domain etc.
+ */
+#define MAIL_ATTR_S_NAME "_name"
+#define MAIL_ATTR_S_DOMAIN "_domain"
+
+ /*
+ * Special names for RBL results.
+ */
+#define MAIL_ATTR_RBL_WHAT "rbl_what"
+#define MAIL_ATTR_RBL_DOMAIN "rbl_domain"
+#define MAIL_ATTR_RBL_REASON "rbl_reason"
+#define MAIL_ATTR_RBL_TXT "rbl_txt" /* LaMont compatibility */
+#define MAIL_ATTR_RBL_CLASS "rbl_class"
+#define MAIL_ATTR_RBL_CODE "rbl_code"
+
/*
* The following attribute names are stored in queue files. Changing this
* means lots of work to maintain backwards compatibility with queued mail.
#define MAIL_ATTR_ENC_8BIT "8bit" /* 8BITMIME equivalent */
#define MAIL_ATTR_ENC_7BIT "7bit" /* 7BIT equivalent */
#define MAIL_ATTR_ENC_NONE "" /* encoding unknown */
+#define MAIL_ATTR_CLIENT "client" /* client name[addr] */
#define MAIL_ATTR_CLIENT_NAME "client_name" /* client hostname */
#define MAIL_ATTR_CLIENT_ADDR "client_address" /* client address */
#define MAIL_ATTR_HELO_NAME "helo_name" /* SMTP helo name */
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20020922"
+#define MAIL_RELEASE_DATE "20020923"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE
smtpd_check.o: ../../include/vstream.h
smtpd_check.o: ../../include/htable.h
smtpd_check.o: ../../include/ctable.h
+smtpd_check.o: ../../include/mac_expand.h
+smtpd_check.o: ../../include/mac_parse.h
smtpd_check.o: ../../include/dns.h
smtpd_check.o: ../../include/namadr_list.h
smtpd_check.o: ../../include/match_list.h
smtpd_check.o: ../../include/cleanup_user.h
smtpd_check.o: ../../include/record.h
smtpd_check.o: ../../include/rec_type.h
+smtpd_check.o: ../../include/mail_proto.h
+smtpd_check.o: ../../include/iostuff.h
+smtpd_check.o: ../../include/attr.h
smtpd_check.o: smtpd.h
smtpd_check.o: ../../include/mail_stream.h
smtpd_check.o: smtpd_sasl_glue.h
/* .ad
/* .fi
/* .IP \fBaccess_map_reject_code\fR
-/* Server response when a client violates an access database restriction.
+/* Response code when a client violates an access database restriction.
+/* .IP \fBdefault_rbl_reply\fR
+/* Default template reply when a request is RBL blacklisted.
+/* This template is used by the \fBreject_rbl_*\fR and
+/* \fBreject_rhsbl_*\fR restrictions. See also:
+/* \fBrbl_reply_maps\fR and \fBsmtpd_expansion_filter\fR.
/* .IP \fBdefer_code\fR
-/* Server response when a client request is rejected by the \fBdefer\fR
+/* Response code when a client request is rejected by the \fBdefer\fR
/* restriction.
/* .IP \fBinvalid_hostname_reject_code\fR
-/* Server response when a client violates the \fBreject_invalid_hostname\fR
+/* Response code when a client violates the \fBreject_invalid_hostname\fR
/* restriction.
/* .IP \fBmaps_rbl_reject_code\fR
-/* Server response when a client violates the \fBmaps_rbl_domains\fR
-/* restriction.
+/* Response code when a request is RBL blacklisted.
/* .IP \fBrbl_reply_maps\fR
-/* Table with template responses, indexed by RBL domain name. These
-/* templates are used by the \fBreject_rbl\fR and \fBreject_rhsbl\fR
-/* restrictions. See also: \fBsmtpd_expansion_filter\fR.
+/* Table with template responses for RBL blacklisted requests, indexed by
+/* RBL domain name. These templates are used by the \fBreject_rbl_*\fR
+/* and \fBreject_rhsbl_*\fR restrictions. See also:
+/* \fBdefault_rbl_reply\fR and \fBsmtpd_expansion_filter\fR.
/* .IP \fBreject_code\fR
/* Response code when the client matches a \fBreject\fR restriction.
/* .IP \fBrelay_domains_reject_code\fR
-/* Server response when a client attempts to violate the mail relay
+/* Response code when a client attempts to violate the mail relay
/* policy.
/* .IP \fBunknown_address_reject_code\fR
-/* Server response when a client violates the \fBreject_unknown_address\fR
+/* Response code when a client violates the \fBreject_unknown_address\fR
/* restriction.
/* .IP \fBunknown_client_reject_code\fR
-/* Server response when a client without address to name mapping
+/* Response code when a client without address to name mapping
/* violates the \fBreject_unknown_clients\fR restriction.
/* .IP \fBunknown_hostname_reject_code\fR
-/* Server response when a client violates the \fBreject_unknown_hostname\fR
+/* Response code when a client violates the \fBreject_unknown_hostname\fR
/* restriction.
/* SEE ALSO
/* cleanup(8) message canonicalization
char *var_smtpd_null_key;
int var_smtpd_hist_thrsh;
char *var_smtpd_exp_filter;
+char *var_def_rbl_reply;
/*
* Silly little macros.
};
static CONFIG_RAW_TABLE raw_table[] = {
VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
+ VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply, 1, 0,
0,
};
/* .IP "check_recipient_access maptype:mapname"
/* Look up the resolved recipient address in the named access table,
/* any parent domains of the recipient domain, and the localpart@.
-/* .IP reject_rbl rbl.domain.tld
+/* .IP reject_rbl_client rbl.domain.tld
/* Look up the reversed client network address in the specified
/* real-time blackhole DNS zone. The \fIrbl_reply_maps\fR configuration
/* parameter is used to generate the template for the reject message.
/* default template is used. The \fImaps_rbl_reject_code\fR
/* configuration parameter specifies the reject status code used in
/* the default template (default: 554).
-/* .IP reject_rhsbl rbl.domain.tld
-/* Look up the sender domain name in the specified real-time
-/* blackhole DNS zone. The \fIrbl_reply_maps\fR configuration
+/* .IP reject_rhsbl_client rbl.domain.tld
+/* .IP reject_rhsbl_sender rbl.domain.tld
+/* .IP reject_rhsbl_recipient rbl.domain.tld
+/* Look up the client/sender/recipient domain name in the specified
+/* real-time blackhole DNS zone. The \fIrbl_reply_maps\fR configuration
/* parameter is used to generate the template for the reject message.
/* If it is not specified, or the rbl domain cannot be found, then a
/* default template is used. The \fImaps_rbl_reject_code\fR
#include <cleanup_user.h>
#include <record.h>
#include <rec_type.h>
+#include <mail_proto.h>
/* Application-specific. */
SMTPD_STATE *state; /* general state */
SMTPD_RBL_STATE *rbl_state; /* cached RBL state */
const char *domain; /* query domain */
+ const char *what; /* rejected value */
+ const char *class; /* name of rejected value */
} SMTPD_RBL_EXPAND_CONTEXT;
/* resolve_pagein - page in an address resolver result */
/* smtpd_expand_addr - return address or substring thereof */
static const char *smtpd_expand_addr(VSTRING *buf, const char *addr,
- const char *name, int prefix_len)
+ const char *name, int prefix_len)
{
const char *p;
const char *suffix;
suffix = name + prefix_len;
/*
- * "sender" or "recipient".
+ * MAIL_ATTR_SENDER or MAIL_ATTR_RECIP.
*/
if (*suffix == 0) {
if (*addr)
*/
#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
- else if (STREQ(suffix, "_name")) {
+ else if (STREQ(suffix, MAIL_ATTR_S_NAME)) {
if (*addr) {
if ((p = strrchr(addr, '@')) != 0) {
vstring_strncpy(buf, addr, p - addr);
/*
* "sender_domain" or "recipient_domain".
*/
- else if (STREQ(suffix, "_domain")) {
+ else if (STREQ(suffix, MAIL_ATTR_S_DOMAIN)) {
if (*addr) {
if ((p = strrchr(addr, '@')) != 0) {
return (p + 1);
*
* Return NULL only for non-existent names.
*/
- if (STREQ(name, "client")) {
+ if (STREQ(name, MAIL_ATTR_CLIENT)) {
return (state->namaddr);
- } else if (STREQ(name, "client_address")) {
+ } else if (STREQ(name, MAIL_ATTR_CLIENT_ADDR)) {
return (state->addr);
- } else if (STREQ(name, "client_name")) {
+ } else if (STREQ(name, MAIL_ATTR_CLIENT_NAME)) {
return (state->name);
- } else if (STREQ(name, "helo_name")) {
+ } else if (STREQ(name, MAIL_ATTR_HELO_NAME)) {
return (state->helo_name ? state->helo_name : "");
- } else if (STREQN(name, "sender", CONST_LEN("sender"))) {
+ } else if (STREQN(name, MAIL_ATTR_SENDER, CONST_LEN(MAIL_ATTR_SENDER))) {
return (smtpd_expand_addr(state->expand_buf, state->sender,
- name, CONST_LEN("sender")));
- } else if (STREQN(name, "recipient", CONST_LEN("recipient"))) {
+ name, CONST_LEN(MAIL_ATTR_SENDER)));
+ } else if (STREQN(name, MAIL_ATTR_RECIP, CONST_LEN(MAIL_ATTR_RECIP))) {
return (smtpd_expand_addr(state->expand_buf, state->recipient,
- name, CONST_LEN("recipient")));
+ name, CONST_LEN(MAIL_ATTR_RECIP)));
} else {
smtpd_expand_unknown(name);
return (0);
}
}
-/* rbl_pagein - page in an RBL lookup result */
+/* rbl_pagein - look up an RBL lookup result */
static void *rbl_pagein(const char *query, void *unused_context)
{
return ((void *) rbl);
}
-/* rbl_pageout - page out an RBL lookup result */
+/* rbl_pageout - discard an RBL lookup result */
static void rbl_pageout(void *data, void *unused_context)
{
/*
* Be sure to return NULL only for non-existent names.
*/
- if (STREQ(name, "rbl_code")) {
+ if (STREQ(name, MAIL_ATTR_RBL_CODE)) {
vstring_sprintf(state->expand_buf, "%d", var_maps_rbl_code);
return (STR(state->expand_buf));
- } else if (STREQ(name, "rbl_domain")) {
+ } else if (STREQ(name, MAIL_ATTR_RBL_DOMAIN)) {
return (rbl_exp->domain);
- } else if (STREQ(name, "rbl_txt")) {
+ } else if (STREQ(name, MAIL_ATTR_RBL_REASON)) {
+ return (rbl->txt);
+ } else if (STREQ(name, MAIL_ATTR_RBL_TXT)) {/* LaMont compat */
return (rbl->txt);
+ } else if (STREQ(name, MAIL_ATTR_RBL_WHAT)) {
+ return (rbl_exp->what);
+ } else if (STREQ(name, MAIL_ATTR_RBL_CLASS)) {
+ return (rbl_exp->class);
} else {
return (smtpd_expand_lookup(name, mode, (char *) state));
}
/* rbl_reject_reply - format reply after RBL reject */
static int rbl_reject_reply(SMTPD_STATE *state, SMTPD_RBL_STATE *rbl,
- const char *rbl_domain)
+ const char *rbl_domain,
+ const char *what,
+ const char *reply_class)
{
const char *myname = "rbl_reject_reply";
VSTRING *why = 0;
SMTPD_RBL_EXPAND_CONTEXT rbl_exp;
int result;
+ /*
+ * Use the server-specific reply template or use the default one.
+ */
if (*var_rbl_reply_maps) {
low_name = lowercase(mystrdup(rbl_domain));
template = maps_find(rbl_reply_maps, low_name, 0);
myfree(low_name);
}
- if (template) {
- why = vstring_alloc(10);
- rbl_exp.state = state;
- rbl_exp.rbl_state = rbl;
- rbl_exp.domain = rbl_domain;
+ why = vstring_alloc(100);
+ rbl_exp.state = state;
+ rbl_exp.rbl_state = rbl;
+ rbl_exp.domain = rbl_domain;
+ rbl_exp.what = what;
+ rbl_exp.class = reply_class;
+ for (;;) {
+ if (template == 0)
+ template = var_def_rbl_reply;
if (mac_expand(why, template, MAC_EXP_FLAG_NONE,
STR(expand_filter), rbl_expand_lookup,
- (char *) &rbl_exp) != 0) {
- msg_warn("%s: bad rbl reply template: %s", myname, template);
- template = 0; /* pretend not found */
- }
- }
- if (template) {
- result = smtpd_check_reject(state, MAIL_ERROR_POLICY, STR(why));
- } else {
- /* Hard-coded to avoid trouble with future ?: ternary operator. */
- result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
- "%d Service unavailable; [%s] blocked using %s%s%s",
- var_maps_rbl_code, state->addr,
- rbl_domain, rbl->txt[0] ?
- ", reason: " : "", rbl->txt);
+ (char *) &rbl_exp) == 0)
+ break;
+ if (template == var_def_rbl_reply)
+ msg_fatal("%s: bad default rbl reply template: %s",
+ myname, var_def_rbl_reply);
+ msg_warn("%s: bad rbl reply template for domain %s: %s",
+ myname, rbl_domain, template);
+ template = 0; /* pretend not found */
}
+ result = smtpd_check_reject(state, MAIL_ERROR_POLICY, STR(why));
/*
* Clean up.
*/
- if (why)
- vstring_free(why);
+ vstring_free(why);
return (result);
}
-/* reject_rbl - reject if client address in real-time blackhole list */
+/* reject_rbl_addr - reject if address in real-time blackhole list */
-static int reject_rbl(SMTPD_STATE *state, const char *rbl_domain)
+static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain,
+ const char *addr, const char *reply_class)
{
char *myname = "reject_rbl";
ARGV *octets;
SMTPD_RBL_STATE *rbl;
if (msg_verbose)
- msg_info("%s: %s", myname, state->addr);
+ msg_info("%s: %s %s", myname, reply_class, addr);
/*
* IPv4 only for now
*/
#ifdef INET6
- if (inet_pton(AF_INET, state->addr, &a) != 1)
+ if (inet_pton(AF_INET, addr, &a) != 1)
return SMTPD_CHECK_DUNNO;
#endif
* the DNS for an A record.
*/
query = vstring_alloc(100);
- octets = argv_split(state->addr, ".");
+ octets = argv_split(addr, ".");
for (i = octets->argc - 1; i >= 0; i--) {
vstring_strcat(query, octets->argv[i]);
vstring_strcat(query, ".");
vstring_free(query);
/*
- * If the record exists, the client address is blacklisted.
+ * If the record exists, the address is blacklisted.
*/
if (rbl == 0) {
return (SMTPD_CHECK_DUNNO);
} else {
- return (rbl_reject_reply(state, rbl, rbl_domain));
+ return (rbl_reject_reply(state, rbl, rbl_domain, addr, reply_class));
}
}
-/* reject_rhsbl - reject if sender domain in real-time blackhole list */
+/* reject_rbl_domain - reject if domain in real-time blackhole list */
-static int reject_rhsbl(SMTPD_STATE *state, const char *rbl_domain)
+static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain,
+ const char *what, const char *reply_class)
{
- char *myname = "reject_rhsbl";
+ char *myname = "reject_rbl_domain";
VSTRING *query;
SMTPD_RBL_STATE *rbl;
const char *domain;
if (msg_verbose)
- msg_info("%s: %s", myname, state->sender);
+ msg_info("%s: %s %s", myname, reply_class, what);
/*
- * Extract the sender domain, tack on the RBL domain name and query the
- * DNS for an A record.
+ * Extract the domain, tack on the RBL domain name and query the DNS for
+ * an A record.
*/
- if ((domain = strrchr(state->sender, '@')) == 0)
- return (SMTPD_CHECK_DUNNO);
- domain += 1;
- if (domain[0] == 0 || domain[0] == '#' || domain[0] == '[')
+ if ((domain = strrchr(what, '@')) != 0) {
+ domain += 1;
+ if (domain[0] == '#' || domain[0] == '[')
+ return (SMTPD_CHECK_DUNNO);
+ } else
+ domain = what;
+ if (domain[0] == 0)
return (SMTPD_CHECK_DUNNO);
query = vstring_alloc(100);
vstring_free(query);
/*
- * If the record exists, the sender domain is blacklisted.
+ * If the record exists, the domain is blacklisted.
*/
if (rbl == 0) {
return (SMTPD_CHECK_DUNNO);
} else {
- return (rbl_reject_reply(state, rbl, rbl_domain));
+ return (rbl_reject_reply(state, rbl, rbl_domain, what, reply_class));
}
}
msg_info("%s: %s", myname, state->addr);
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
- result = reject_rbl(state, rbl_domain);
+ result = reject_rbl_addr(state, rbl_domain, state->addr,
+ SMTPD_NAME_CLIENT);
if (result != SMTPD_CHECK_DUNNO)
break;
}
SMTPD_NAME_CLIENT, def_acl);
} else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
status = reject_maps_rbl(state);
- } else if (strcasecmp(name, REJECT_RBL) == 0) {
+ } else if (strcasecmp(name, REJECT_RBL_CLIENT) == 0
+ || strcasecmp(name, REJECT_RBL) == 0) {
if (*(cpp[1]) == 0)
- msg_warn("restriction %s requires domain name argument",
- REJECT_RBL);
+ msg_warn("restriction %s requires domain name argument", name);
else
- status = reject_rbl(state, *(cpp += 1));
+ status = reject_rbl_addr(state, *(cpp += 1), state->addr,
+ SMTPD_NAME_CLIENT);
+ } else if (strcasecmp(name, REJECT_RHSBL_CLIENT) == 0) {
+ if (*(cpp[1]) == 0)
+ msg_warn("restriction %s requires domain name argument",
+ name);
+ else if (strcasecmp(state->name, "unknown") != 0)
+ status = reject_rbl_domain(state, *(cpp += 1), state->name,
+ SMTPD_NAME_CLIENT);
}
/*
} else if (strcasecmp(name, REJECT_SENDER_LOGIN_MISMATCH) == 0) {
if (state->sender && *state->sender)
status = reject_sender_login_mismatch(state, state->sender);
- } else if (strcasecmp(name, REJECT_RHSBL) == 0) {
+ } else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) {
if (cpp[1] == 0)
- msg_warn("restriction %s requires domain name argument",
- REJECT_RHSBL);
+ msg_warn("restriction %s requires domain name argument", name);
else if (state->sender && *state->sender)
- status = reject_rhsbl(state, *(cpp += 1));
+ status = reject_rbl_domain(state, *(cpp += 1), state->sender,
+ SMTPD_NAME_SENDER);
}
/*
if (state->recipient)
status = reject_non_fqdn_address(state, state->recipient,
state->recipient, SMTPD_NAME_RECIPIENT);
+ } else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) {
+ if (cpp[1] == 0)
+ msg_warn("restriction %s requires domain name argument", name);
+ else if (state->recipient)
+ status = reject_rbl_domain(state, *(cpp += 1), state->recipient,
+ SMTPD_NAME_RECIPIENT);
}
/*
char *var_double_bounce_sender;
char *var_rbl_reply_maps;
char *var_smtpd_exp_filter;
+char *var_def_rbl_reply;
typedef struct {
char *name;
VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender,
VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps,
VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter,
+ VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply,
0,
};
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
-./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using blackholes.mail-abuse.org, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
-554 Service unavailable; [127.0.0.2] blocked using blackholes.mail-abuse.org, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; Client host [127.0.0.2] blocked using blackholes.mail-abuse.org; Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
+554 Service unavailable; Client host [127.0.0.2] blocked using blackholes.mail-abuse.org; Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
>>> #
>>> # Hybrids
>>> #
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
-./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using blackholes.mail-abuse.org, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
-554 Service unavailable; [127.0.0.2] blocked using blackholes.mail-abuse.org, reason: Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; Client host [127.0.0.2] blocked using blackholes.mail-abuse.org; Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
+554 Service unavailable; Client host [127.0.0.2] blocked using blackholes.mail-abuse.org; Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
>>> #
>>> # unknown sender/recipient domain
>>> #
client_name=$client_name helo_name=$helo_name
sender=$sender sender_name=$sender_name sender_domain=$sender_domain
recipient=$recipient recipient_name=$recipient_name recipient_domain=$recipient_domain
- rbl_code=$rbl_code rbl_domain=$rbl_domain rbl_txt=$rbl_txt
+ rbl_code=$rbl_code rbl_domain=$rbl_domain rbl_txt=$rbl_txt rbl_what=$rbl_what
+ rbl_class=$rbl_class
dsn.rfc-ignorant.org $rbl_code client=$client
client_address=$client_address
client_name=$client_name helo_name=$helo_name
sender=$sender sender_name=$sender_name sender_domain=$sender_domain
recipient=$recipient recipient_name=$recipient_name recipient_domain=$recipient_domain
- rbl_code=$rbl_code rbl_domain=$rbl_domain rbl_txt=$rbl_txt
+ rbl_code=$rbl_code rbl_domain=$rbl_domain rbl_txt=$rbl_txt rbl_what=$rbl_what
+ rbl_class=$rbl_class
client foo 127.0.0.2
rcpt rname@rdomain
#
-recipient_restrictions reject_rbl,blackholes.mail-abuse.org
+recipient_restrictions reject_rbl_client,blackholes.mail-abuse.org
client spike.porcupine.org 168.100.189.2
rcpt rname@rdomain
client foo 127.0.0.2
rcpt rname@rdomain
#
-# RHSBL
+# RHSBL sender domain name
#
-recipient_restrictions reject_rhsbl,dsn.rfc-ignorant.org
+recipient_restrictions reject_rhsbl_sender,dsn.rfc-ignorant.org
client spike.porcupine.org 168.100.189.2
mail sname@example.tld
rcpt rname@rdomain
mail sname@sdomain
rcpt rname@rdomain
+#
+# RHSBL client domain name
+#
+recipient_restrictions reject_rhsbl_client,dsn.rfc-ignorant.org
+client example.tld 1.2.3.4
+mail sname@sdomain
+rcpt rname@rdomain
+#
+# RHSBL recipient domain name
+#
+recipient_restrictions reject_rhsbl_recipient,dsn.rfc-ignorant.org
+client spike.porcupine.org 168.100.189.2
+mail sname@sdomain
+rcpt rname@rdomain
+rcpt rname@example.tld
>>> client foo 127.0.0.2
OK
>>> rcpt rname@rdomain
-./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<sname@sdomain> to=<rname@rdomain>
-554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2> rbl_what=127.0.0.2 rbl_class=Client host; from=<sname@sdomain> to=<rname@rdomain>
+554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2> rbl_what=127.0.0.2 rbl_class=Client host
>>> #
->>> recipient_restrictions reject_rbl,blackholes.mail-abuse.org
+>>> recipient_restrictions reject_rbl_client,blackholes.mail-abuse.org
OK
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
OK
>>> rcpt rname@rdomain
-./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<sname@sdomain> to=<rname@rdomain>
-554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
+./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2> rbl_what=127.0.0.2 rbl_class=Client host; from=<sname@sdomain> to=<rname@rdomain>
+554 client=foo[127.0.0.2] client_address=127.0.0.2 client_name=foo helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=blackholes.mail-abuse.org rbl_txt=Blackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2> rbl_what=127.0.0.2 rbl_class=Client host
>>> #
->>> # RHSBL
+>>> # RHSBL sender domain name
>>> #
->>> recipient_restrictions reject_rhsbl,dsn.rfc-ignorant.org
+>>> recipient_restrictions reject_rhsbl_sender,dsn.rfc-ignorant.org
OK
>>> client spike.porcupine.org 168.100.189.2
OK
>>> mail sname@example.tld
OK
>>> rcpt rname@rdomain
-./smtpd_check: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 client=spike.porcupine.org[168.100.189.2] client_address=168.100.189.2 client_name=spike.porcupine.org helo_name=foobar sender=sname@example.tld sender_name=sname sender_domain=example.tld recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN); from=<sname@example.tld> to=<rname@rdomain>
-554 client=spike.porcupine.org[168.100.189.2] client_address=168.100.189.2 client_name=spike.porcupine.org helo_name=foobar sender=sname@example.tld sender_name=sname sender_domain=example.tld recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN)
+./smtpd_check: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 client=spike.porcupine.org[168.100.189.2] client_address=168.100.189.2 client_name=spike.porcupine.org helo_name=foobar sender=sname@example.tld sender_name=sname sender_domain=example.tld recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN) rbl_what=sname@example.tld rbl_class=Sender address; from=<sname@example.tld> to=<rname@rdomain>
+554 client=spike.porcupine.org[168.100.189.2] client_address=168.100.189.2 client_name=spike.porcupine.org helo_name=foobar sender=sname@example.tld sender_name=sname sender_domain=example.tld recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN) rbl_what=sname@example.tld rbl_class=Sender address
>>> mail sname@sdomain
OK
>>> rcpt rname@rdomain
OK
+>>> #
+>>> # RHSBL client domain name
+>>> #
+>>> recipient_restrictions reject_rhsbl_client,dsn.rfc-ignorant.org
+OK
+>>> client example.tld 1.2.3.4
+OK
+>>> mail sname@sdomain
+OK
+>>> rcpt rname@rdomain
+./smtpd_check: reject: RCPT from example.tld[1.2.3.4]: 554 client=example.tld[1.2.3.4] client_address=1.2.3.4 client_name=example.tld helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN) rbl_what=example.tld rbl_class=Client host; from=<sname@sdomain> to=<rname@rdomain>
+554 client=example.tld[1.2.3.4] client_address=1.2.3.4 client_name=example.tld helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@rdomain recipient_name=rname recipient_domain=rdomain rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN) rbl_what=example.tld rbl_class=Client host
+>>> #
+>>> # RHSBL recipient domain name
+>>> #
+>>> recipient_restrictions reject_rhsbl_recipient,dsn.rfc-ignorant.org
+OK
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>> mail sname@sdomain
+OK
+>>> rcpt rname@rdomain
+OK
+>>> rcpt rname@example.tld
+./smtpd_check: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 client=spike.porcupine.org[168.100.189.2] client_address=168.100.189.2 client_name=spike.porcupine.org helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@example.tld recipient_name=rname recipient_domain=example.tld rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN) rbl_what=rname@example.tld rbl_class=Recipient address; from=<sname@sdomain> to=<rname@example.tld>
+554 client=spike.porcupine.org[168.100.189.2] client_address=168.100.189.2 client_name=spike.porcupine.org helo_name=foobar sender=sname@sdomain sender_name=sname sender_domain=sdomain recipient=rname@example.tld recipient_name=rname recipient_domain=example.tld rbl_code=554 rbl_domain=dsn.rfc-ignorant.org rbl_txt=Not supporting null originator (DSN) rbl_what=rname@example.tld rbl_class=Recipient address
/*
/* The following expansions are implemented:
/* .IP "$name, ${name}, $(name)"
-/* Unconditional expansion. If the named attribute is non-empty, the
+/* Unconditional expansion. If the named attribute value is non-empty, the
/* expansion is the value of the named attribute, optionally subjected
/* to further $name expansions. Otherwise, the expansion is empty.
/* .IP "${name?text}, $(name?text)"
-/* Conditional expansion. If the named attribute is non-empty, the
+/* Conditional expansion. If the named attribute value is non-empty, the
/* expansion is the given text, subjected to another iteration of
/* $name expansion. Otherwise, the expansion is empty.
/* .IP "${name:text}, $(name:text)"
-/* Conditional expansion. If the named attribute is empty or undefined,
+/* Conditional expansion. If the attribute value is empty or undefined,
/* the expansion is the given text, subjected to another iteration
/* of $name expansion. Otherwise, the expansion is empty.
/* .PP