notify" as with Postfix automatically-added BCC recipients.
Files: cleanup/cleanup_addr.c, cleanup/cleanup.h,
cleanup/cleanup_milter.c.
+
+20101105
+
+ Feature: DNS whitelist support in the Postfix SMTP server.
+ permit_dnswl_client whitelists a client by IP address, and
+ permit_rhswl_client whitelists a client by its hostname.
+ The syntax is the same as reject_rbl_client etc., but the
+ result is PERMIT instead of REJECT. For safety reasons,
+ permit_xxx_client are silently ignored when they would
+ override reject_unauth_destination. The result is
+ DEFER_IF_REJECT when DNSWL lookup fails. The implementation
+ is based on a design documented by Noel Jones (August 2010).
+ File: smtpd/smtpd_check.c.
postscreen parameters always evaluate as if the stress value is
equal to the empty string.
+Major changes with snapshot 20101105
+====================================
+
+The Postfix SMTP server now supports DNS-based whitelisting with
+several safety features: permit_dnswl_client whitelists a client
+by IP address, and permit_rhswl_client whitelists a client by its
+hostname. These features use the same syntax as reject_rbl_client
+and reject_rhsbl_client, respectively. The main difference is that
+they return PERMIT instead of REJECT.
+
+Whitelisting is primarily a tool to reduce the false positive rate
+of DNS blocklist lookups. Client name whitelisting should not be
+used to make exceptions to access rules. The reason is that client
+name lookup can fail unpredictably due to some temporary outage.
+
+For safety reasons, permit_dnswl_client and permit_rhswl_client are
+silently ignored when they would override reject_unauth_destination.
+Also for safety reasons, the result is DEFER_IF_REJECT when DNS
+whitelist lookup fails (this result will be made configurable).
+
Incompatibility with snapshot 20101103
======================================
anvil rate limit for sasl_username.
+ permit_tempfail_action (default: defer_if_reject) to be
+ used as the default value for dnswl_tempfail_action and
+ rhswl_tempfail_action. Steal liberally from the code that
+ implements unverified_recipient_tempfail_action etc.
+
Support filtering of messages that are generated by Postfix:
This would apply to postmaster notices and bounce messages
(DKIM), and address verification (BATV).
# The pattern domain.tld also matches subdomains, but
# only when the string smtpd_access_maps is listed in
# the Postfix parent_domain_matches_subdomains con-
-# figuration setting (note that this is the default
-# for some versions of Postfix). Otherwise, specify
-# .domain.tld (note the initial dot) in order to
-# match subdomains.
+# figuration setting.
+#
+# .domain.tld
+# Matches subdomains of domain.tld, but only when the
+# string smtpd_access_maps is not listed in the Post-
+# fix parent_domain_matches_subdomains configuration
+# setting.
#
# user@ Matches all mail addresses with the specified user
# part.
# The pattern domain.tld also matches subdomains, but
# only when the string smtpd_access_maps is listed in
# the Postfix parent_domain_matches_subdomains con-
-# figuration setting. Otherwise, specify .domain.tld
-# (note the initial dot) in order to match subdo-
-# mains.
+# figuration setting.
+#
+# .domain.tld
+# Matches subdomains of domain.tld, but only when the
+# string smtpd_access_maps is not listed in the Post-
+# fix parent_domain_matches_subdomains configuration
+# setting.
#
# net.work.addr.ess
#
#
# net.work
#
-# net Matches the specified IPv4 host address or subnet-
-# work. An IPv4 host address is a sequence of four
+# net Matches the specified IPv4 host address or subnet-
+# work. An IPv4 host address is a sequence of four
# decimal octets separated by ".".
#
-# Subnetworks are matched by repeatedly truncating
+# Subnetworks are matched by repeatedly truncating
# the last ".octet" from the remote IPv4 host address
-# string until a match is found in the access table,
+# string until a match is found in the access table,
# or until further truncation is not possible.
#
# NOTE 1: The access map lookup key must be in canon-
-# ical form: do not specify unnecessary null charac-
-# ters, and do not enclose network address informa-
+# ical form: do not specify unnecessary null charac-
+# ters, and do not enclose network address informa-
# tion with "[]" characters.
#
-# NOTE 2: use the cidr lookup table type to specify
+# NOTE 2: use the cidr lookup table type to specify
# network/netmask patterns. See cidr_table(5) for
# details.
#
#
# net:work
#
-# net Matches the specified IPv6 host address or subnet-
-# work. An IPv6 host address is a sequence of three
-# to eight hexadecimal octet pairs separated by ":".
+# net Matches the specified IPv6 host address or subnet-
+# work. An IPv6 host address is a sequence of three
+# to eight hexadecimal octet pairs separated by ":".
#
-# Subnetworks are matched by repeatedly truncating
-# the last ":octetpair" from the remote IPv6 host
+# Subnetworks are matched by repeatedly truncating
+# the last ":octetpair" from the remote IPv6 host
# address string until a match is found in the access
# table, or until further truncation is not possible.
#
# Thus, not all the ":" subnetworks will be tried.
#
# NOTE 2: The access map lookup key must be in canon-
-# ical form: do not specify unnecessary null charac-
-# ters, and do not enclose network address informa-
+# ical form: do not specify unnecessary null charac-
+# ters, and do not enclose network address informa-
# tion with "[]" characters.
#
-# NOTE 3: use the cidr lookup table type to specify
+# NOTE 3: use the cidr lookup table type to specify
# network/netmask patterns. See cidr_table(5) for
# details.
#
#
# all-numerical
# An all-numerical result is treated as OK. This for-
-# mat is generated by address-based relay authoriza-
+# mat is generated by address-based relay authoriza-
# tion schemes such as pop-before-smtp.
#
# REJECT ACTIONS
-# Postfix version 2.3 and later support enhanced status
-# codes as defined in RFC 3463. When no code is specified
-# at the beginning of the text below, Postfix inserts a
-# default enhanced status code of "5.7.1" in the case of
-# reject actions, and "4.7.1" in the case of defer actions.
+# Postfix version 2.3 and later support enhanced status
+# codes as defined in RFC 3463. When no code is specified
+# at the beginning of the text below, Postfix inserts a
+# default enhanced status code of "5.7.1" in the case of
+# reject actions, and "4.7.1" in the case of defer actions.
# See "ENHANCED STATUS CODES" below.
#
# 4NN text
#
# 5NN text
-# Reject the address etc. that matches the pattern,
+# Reject the address etc. that matches the pattern,
# and respond with the numerical three-digit code and
-# text. 4NN means "try again later", while 5NN means
+# text. 4NN means "try again later", while 5NN means
# "do not try again".
#
-# The following responses have special meaning for
+# The following responses have special meaning for
# the Postfix SMTP server:
#
# 421 text (Postfix 2.3 and later)
#
# 521 text (Postfix 2.6 and later)
-# After responding with the numerical three-
-# digit code and text, disconnect immediately
-# from the SMTP client. This frees up SMTP
-# server resources so that they can be made
+# After responding with the numerical three-
+# digit code and text, disconnect immediately
+# from the SMTP client. This frees up SMTP
+# server resources so that they can be made
# available to another SMTP client.
#
# Note: The "521" response should be used only
-# with botnets and other malware where inter-
+# with botnets and other malware where inter-
# operability is of no concern. The "send 521
-# and disconnect" behavior is NOT defined in
+# and disconnect" behavior is NOT defined in
# the SMTP standard.
#
# REJECT optional text...
-# Reject the address etc. that matches the pattern.
-# Reply with "$access_map_reject_code optional
-# text..." when the optional text is specified, oth-
+# Reject the address etc. that matches the pattern.
+# Reply with "$access_map_reject_code optional
+# text..." when the optional text is specified, oth-
# erwise reply with a generic error response message.
#
# DEFER optional text...
-# Reject the address etc. that matches the pattern.
-# Reply with "$access_map_defer_code optional
-# text..." when the optional text is specified, oth-
+# Reject the address etc. that matches the pattern.
+# Reply with "$access_map_defer_code optional
+# text..." when the optional text is specified, oth-
# erwise reply with a generic error response message.
#
# This feature is available in Postfix 2.6 and later.
#
# DEFER_IF_REJECT optional text...
-# Defer the request if some later restriction would
-# result in a REJECT action. Reply with
-# "$access_map_defer_code 4.7.1 optional text..."
-# when the optional text is specified, otherwise
+# Defer the request if some later restriction would
+# result in a REJECT action. Reply with
+# "$access_map_defer_code 4.7.1 optional text..."
+# when the optional text is specified, otherwise
# reply with a generic error response message.
#
# Prior to Postfix 2.6, the SMTP reply code is 450.
# This feature is available in Postfix 2.1 and later.
#
# DEFER_IF_PERMIT optional text...
-# Defer the request if some later restriction would
-# result in a an explicit or implicit PERMIT action.
-# Reply with "$access_map_defer_code 4.7.1 optional
-# text..." when the optional text is specified, oth-
+# Defer the request if some later restriction would
+# result in a an explicit or implicit PERMIT action.
+# Reply with "$access_map_defer_code 4.7.1 optional
+# text..." when the optional text is specified, oth-
# erwise reply with a generic error response message.
#
# Prior to Postfix 2.6, the SMTP reply code is 450.
# reject_unauth_destination, and so on).
#
# BCC user@domain
-# Send one copy of the message to the specified
+# Send one copy of the message to the specified
# recipient.
#
-# If multiple BCC actions are specified within the
-# same SMTP MAIL transaction, only the last action
+# If multiple BCC actions are specified within the
+# same SMTP MAIL transaction, only the last action
# will be used.
#
-# This feature is not part of the stable Postfix
+# This feature is not part of the stable Postfix
# release.
#
# DISCARD optional text...
-# Claim successful delivery and silently discard the
-# message. Log the optional text if specified, oth-
+# Claim successful delivery and silently discard the
+# message. Log the optional text if specified, oth-
# erwise log a generic message.
#
-# Note: this action currently affects all recipients
-# of the message. To discard only one recipient
-# without discarding the entire message, use the
+# Note: this action currently affects all recipients
+# of the message. To discard only one recipient
+# without discarding the entire message, use the
# transport(5) table to direct mail to the discard(8)
# service.
#
# This feature is available in Postfix 2.0 and later.
#
-# DUNNO Pretend that the lookup key was not found. This
-# prevents Postfix from trying substrings of the
-# lookup key (such as a subdomain name, or a network
+# DUNNO Pretend that the lookup key was not found. This
+# prevents Postfix from trying substrings of the
+# lookup key (such as a subdomain name, or a network
# address subnetwork).
#
# This feature is available in Postfix 2.0 and later.
#
# FILTER transport:destination
-# After the message is queued, send the entire mes-
+# After the message is queued, send the entire mes-
# sage through the specified external content filter.
-# The transport name specifies the first field of a
-# mail delivery agent definition in master.cf; the
-# syntax of the next-hop destination is described in
+# The transport name specifies the first field of a
+# mail delivery agent definition in master.cf; the
+# syntax of the next-hop destination is described in
# the manual page of the corresponding delivery
-# agent. More information about external content
+# agent. More information about external content
# filters is in the Postfix FILTER_README file.
#
-# Note 1: do not use $number regular expression sub-
-# stitutions for transport or destination unless you
+# Note 1: do not use $number regular expression sub-
+# stitutions for transport or destination unless you
# know that the information has a trusted origin.
#
-# Note 2: this action overrides the main.cf con-
-# tent_filter setting, and affects all recipients of
-# the message. In the case that multiple FILTER
+# Note 2: this action overrides the main.cf con-
+# tent_filter setting, and affects all recipients of
+# the message. In the case that multiple FILTER
# actions fire, only the last one is executed.
#
-# Note 3: the purpose of the FILTER command is to
-# override message routing. To override the recipi-
-# ent's transport but not the next-hop destination,
-# specify an empty filter destination (Postfix 2.7
+# Note 3: the purpose of the FILTER command is to
+# override message routing. To override the recipi-
+# ent's transport but not the next-hop destination,
+# specify an empty filter destination (Postfix 2.7
# and later), or specify a transport:destination that
-# delivers through a different Postfix instance
-# (Postfix 2.6 and earlier). Other options are using
-# the recipient-dependent transport_maps or the sen-
+# delivers through a different Postfix instance
+# (Postfix 2.6 and earlier). Other options are using
+# the recipient-dependent transport_maps or the sen-
# der-dependent sender_dependent_default_transport-
# _maps features.
#
# This feature is available in Postfix 2.0 and later.
#
# HOLD optional text...
-# Place the message on the hold queue, where it will
-# sit until someone either deletes it or releases it
-# for delivery. Log the optional text if specified,
+# Place the message on the hold queue, where it will
+# sit until someone either deletes it or releases it
+# for delivery. Log the optional text if specified,
# otherwise log a generic message.
#
-# Mail that is placed on hold can be examined with
-# the postcat(1) command, and can be destroyed or
+# Mail that is placed on hold can be examined with
+# the postcat(1) command, and can be destroyed or
# released with the postsuper(1) command.
#
-# Note: use "postsuper -r" to release mail that was
-# kept on hold for a significant fraction of $maxi-
+# Note: use "postsuper -r" to release mail that was
+# kept on hold for a significant fraction of $maxi-
# mal_queue_lifetime or $bounce_queue_lifetime, or
-# longer. Use "postsuper -H" only for mail that will
+# longer. Use "postsuper -H" only for mail that will
# not expire within a few delivery attempts.
#
-# Note: this action currently affects all recipients
+# Note: this action currently affects all recipients
# of the message.
#
# This feature is available in Postfix 2.0 and later.
#
# PREPEND headername: headervalue
-# Prepend the specified message header to the mes-
-# sage. When more than one PREPEND action executes,
-# the first prepended header appears before the sec-
+# Prepend the specified message header to the mes-
+# sage. When more than one PREPEND action executes,
+# the first prepended header appears before the sec-
# ond etc. prepended header.
#
-# Note: this action must execute before the message
-# content is received; it cannot execute in the con-
+# Note: this action must execute before the message
+# content is received; it cannot execute in the con-
# text of smtpd_end_of_data_restrictions.
#
# This feature is available in Postfix 2.1 and later.
#
# REDIRECT user@domain
-# After the message is queued, send the message to
+# After the message is queued, send the message to
# the specified address instead of the intended
# recipient(s).
#
-# Note: this action overrides the FILTER action, and
+# Note: this action overrides the FILTER action, and
# currently affects all recipients of the message.
#
# This feature is available in Postfix 2.1 and later.
#
# WARN optional text...
# Log a warning with the optional text, together with
-# client information and if available, with helo,
+# client information and if available, with helo,
# sender, recipient and protocol information.
#
# This feature is available in Postfix 2.1 and later.
#
# ENHANCED STATUS CODES
-# Postfix version 2.3 and later support enhanced status
-# codes as defined in RFC 3463. When an enhanced status
-# code is specified in an access table, it is subject to
-# modification. The following transformations are needed
-# when the same access table is used for client, helo,
-# sender, or recipient access restrictions; they happen
+# Postfix version 2.3 and later support enhanced status
+# codes as defined in RFC 3463. When an enhanced status
+# code is specified in an access table, it is subject to
+# modification. The following transformations are needed
+# when the same access table is used for client, helo,
+# sender, or recipient access restrictions; they happen
# regardless of whether Postfix replies to a MAIL FROM, RCPT
# TO or other SMTP command.
#
-# o When a sender address matches a REJECT action, the
-# Postfix SMTP server will transform a recipient DSN
-# status (e.g., 4.1.1-4.1.6) into the corresponding
+# o When a sender address matches a REJECT action, the
+# Postfix SMTP server will transform a recipient DSN
+# status (e.g., 4.1.1-4.1.6) into the corresponding
# sender DSN status, and vice versa.
#
-# o When non-address information matches a REJECT
-# action (such as the HELO command argument or the
-# client hostname/address), the Postfix SMTP server
-# will transform a sender or recipient DSN status
-# into a generic non-address DSN status (e.g.,
+# o When non-address information matches a REJECT
+# action (such as the HELO command argument or the
+# client hostname/address), the Postfix SMTP server
+# will transform a sender or recipient DSN status
+# into a generic non-address DSN status (e.g.,
# 4.0.0).
#
# REGULAR EXPRESSION TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
-# a description of regular expression lookup table syntax,
+# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
-# Each pattern is a regular expression that is applied to
+# Each pattern is a regular expression that is applied to
# the entire string being looked up. Depending on the appli-
-# cation, that string is an entire client hostname, an
+# cation, that string is an entire client hostname, an
# entire client IP address, or an entire mail address. Thus,
# no parent domain or parent network search is done,
-# user@domain mail addresses are not broken up into their
+# user@domain mail addresses are not broken up into their
# user@ and domain constituent parts, nor is user+foo broken
# up into user and foo.
#
-# Patterns are applied in the order as specified in the ta-
-# ble, until a pattern is found that matches the search
+# Patterns are applied in the order as specified in the ta-
+# ble, until a pattern is found that matches the search
# string.
#
-# Actions are the same as with indexed file lookups, with
-# the additional feature that parenthesized substrings from
+# Actions are the same as with indexed file lookups, with
+# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
# ble(5). This feature is not available up to and including
# Postfix version 2.4.
#
-# Each lookup operation uses the entire query string once.
-# Depending on the application, that string is an entire
+# Each lookup operation uses the entire query string once.
+# Depending on the application, that string is an entire
# client hostname, an entire client IP address, or an entire
-# mail address. Thus, no parent domain or parent network
-# search is done, user@domain mail addresses are not broken
-# up into their user@ and domain constituent parts, nor is
+# mail address. Thus, no parent domain or parent network
+# search is done, user@domain mail addresses are not broken
+# up into their user@ and domain constituent parts, nor is
# user+foo broken up into user and foo.
#
# Actions are the same as with indexed file lookups.
#
# EXAMPLE
-# The following example uses an indexed file, so that the
-# order of table entries does not matter. The example per-
-# mits access by the client at address 1.2.3.4 but rejects
-# all other clients in 1.2.3.0/24. Instead of hash lookup
-# tables, some systems use dbm. Use the command "postconf
-# -m" to find out what lookup tables Postfix supports on
+# The following example uses an indexed file, so that the
+# order of table entries does not matter. The example per-
+# mits access by the client at address 1.2.3.4 but rejects
+# all other clients in 1.2.3.0/24. Instead of hash lookup
+# tables, some systems use dbm. Use the command "postconf
+# -m" to find out what lookup tables Postfix supports on
# your system.
#
# /etc/postfix/main.cf:
# 1.2.3 REJECT
# 1.2.3.4 OK
#
-# Execute the command "postmap /etc/postfix/access" after
+# Execute the command "postmap /etc/postfix/access" after
# editing the file.
#
# BUGS
-# The table format does not understand quoting conventions.
+# The table format does not understand quoting conventions.
#
# SEE ALSO
# postmap(1), Postfix lookup table manager
# transport(5), transport:nexthop syntax
#
# README FILES
-# Use "postconf readme_directory" or "postconf html_direc-
+# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# SMTPD_ACCESS_README, built-in SMTP server access control
# DATABASE_README, Postfix lookup table overview
#
# LICENSE
-# The Secure Mailer license must be distributed with this
+# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
The pattern <i>domain.tld</i> also matches subdomains, but
only when the string <b>smtpd_access_maps</b> is listed in
the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a></b> con-
- figuration setting (note that this is the default
- for some versions of Postfix). Otherwise, specify
- <i>.domain.tld</i> (note the initial dot) in order to
- match subdomains.
+ figuration setting.
+
+ <i>.domain.tld</i>
+ Matches subdomains of <i>domain.tld</i>, but only when the
+ string <b>smtpd_access_maps</b> is not listed in the Post-
+ fix <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a></b> configuration
+ setting.
<i>user</i>@ Matches all mail addresses with the specified user
part.
The pattern <i>domain.tld</i> also matches subdomains, but
only when the string <b>smtpd_access_maps</b> is listed in
the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a></b> con-
- figuration setting. Otherwise, specify <i>.domain.tld</i>
- (note the initial dot) in order to match subdo-
- mains.
+ figuration setting.
+
+ <i>.domain.tld</i>
+ Matches subdomains of <i>domain.tld</i>, but only when the
+ string <b>smtpd_access_maps</b> is not listed in the Post-
+ fix <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a></b> configuration
+ setting.
<i>net.work.addr.ess</i>
<i>net.work</i>
- <i>net</i> Matches the specified IPv4 host address or subnet-
- work. An IPv4 host address is a sequence of four
+ <i>net</i> Matches the specified IPv4 host address or subnet-
+ work. An IPv4 host address is a sequence of four
decimal octets separated by ".".
- Subnetworks are matched by repeatedly truncating
+ Subnetworks are matched by repeatedly truncating
the last ".octet" from the remote IPv4 host address
- string until a match is found in the access table,
+ string until a match is found in the access table,
or until further truncation is not possible.
NOTE 1: The access map lookup key must be in canon-
- ical form: do not specify unnecessary null charac-
- ters, and do not enclose network address informa-
+ ical form: do not specify unnecessary null charac-
+ ters, and do not enclose network address informa-
tion with "[]" characters.
- NOTE 2: use the <b>cidr</b> lookup table type to specify
+ NOTE 2: use the <b>cidr</b> lookup table type to specify
network/netmask patterns. See <a href="cidr_table.5.html"><b>cidr_table</b>(5)</a> for
details.
<i>net:work</i>
- <i>net</i> Matches the specified IPv6 host address or subnet-
- work. An IPv6 host address is a sequence of three
- to eight hexadecimal octet pairs separated by ":".
+ <i>net</i> Matches the specified IPv6 host address or subnet-
+ work. An IPv6 host address is a sequence of three
+ to eight hexadecimal octet pairs separated by ":".
- Subnetworks are matched by repeatedly truncating
- the last ":octetpair" from the remote IPv6 host
+ Subnetworks are matched by repeatedly truncating
+ the last ":octetpair" from the remote IPv6 host
address string until a match is found in the access
table, or until further truncation is not possible.
Thus, not all the ":" subnetworks will be tried.
NOTE 2: The access map lookup key must be in canon-
- ical form: do not specify unnecessary null charac-
- ters, and do not enclose network address informa-
+ ical form: do not specify unnecessary null charac-
+ ters, and do not enclose network address informa-
tion with "[]" characters.
- NOTE 3: use the <b>cidr</b> lookup table type to specify
+ NOTE 3: use the <b>cidr</b> lookup table type to specify
network/netmask patterns. See <a href="cidr_table.5.html"><b>cidr_table</b>(5)</a> for
details.
<i>all-numerical</i>
An all-numerical result is treated as OK. This for-
- mat is generated by address-based relay authoriza-
+ mat is generated by address-based relay authoriza-
tion schemes such as pop-before-smtp.
<b>REJECT ACTIONS</b>
- Postfix version 2.3 and later support enhanced status
- codes as defined in <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a>. When no code is specified
- at the beginning of the <i>text</i> below, Postfix inserts a
- default enhanced status code of "5.7.1" in the case of
- reject actions, and "4.7.1" in the case of defer actions.
+ Postfix version 2.3 and later support enhanced status
+ codes as defined in <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a>. When no code is specified
+ at the beginning of the <i>text</i> below, Postfix inserts a
+ default enhanced status code of "5.7.1" in the case of
+ reject actions, and "4.7.1" in the case of defer actions.
See "ENHANCED STATUS CODES" below.
<b>4</b><i>NN text</i>
<b>5</b><i>NN text</i>
- Reject the address etc. that matches the pattern,
+ Reject the address etc. that matches the pattern,
and respond with the numerical three-digit code and
- text. <b>4</b><i>NN</i> means "try again later", while <b>5</b><i>NN</i> means
+ text. <b>4</b><i>NN</i> means "try again later", while <b>5</b><i>NN</i> means
"do not try again".
- The following responses have special meaning for
+ The following responses have special meaning for
the Postfix SMTP server:
<b>421</b> <i>text</i> (Postfix 2.3 and later)
<b>521</b> <i>text</i> (Postfix 2.6 and later)
- After responding with the numerical three-
- digit code and text, disconnect immediately
- from the SMTP client. This frees up SMTP
- server resources so that they can be made
+ After responding with the numerical three-
+ digit code and text, disconnect immediately
+ from the SMTP client. This frees up SMTP
+ server resources so that they can be made
available to another SMTP client.
Note: The "521" response should be used only
- with botnets and other malware where inter-
+ with botnets and other malware where inter-
operability is of no concern. The "send 521
- and disconnect" behavior is NOT defined in
+ and disconnect" behavior is NOT defined in
the SMTP standard.
<b>REJECT</b> <i>optional text...</i>
- Reject the address etc. that matches the pattern.
- Reply with "<b>$<a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a></b> <i>optional</i>
- <i>text...</i>" when the optional text is specified, oth-
+ Reject the address etc. that matches the pattern.
+ Reply with "<b>$<a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a></b> <i>optional</i>
+ <i>text...</i>" when the optional text is specified, oth-
erwise reply with a generic error response message.
<b>DEFER</b> <i>optional text...</i>
- Reject the address etc. that matches the pattern.
- Reply with "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a></b> <i>optional</i>
- <i>text...</i>" when the optional text is specified, oth-
+ Reject the address etc. that matches the pattern.
+ Reply with "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a></b> <i>optional</i>
+ <i>text...</i>" when the optional text is specified, oth-
erwise reply with a generic error response message.
This feature is available in Postfix 2.6 and later.
<b>DEFER_IF_REJECT</b> <i>optional text...</i>
- Defer the request if some later restriction would
- result in a REJECT action. Reply with
- "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional text...</i>"
- when the optional text is specified, otherwise
+ Defer the request if some later restriction would
+ result in a REJECT action. Reply with
+ "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional text...</i>"
+ when the optional text is specified, otherwise
reply with a generic error response message.
Prior to Postfix 2.6, the SMTP reply code is 450.
This feature is available in Postfix 2.1 and later.
<b>DEFER_IF_PERMIT</b> <i>optional text...</i>
- Defer the request if some later restriction would
- result in a an explicit or implicit PERMIT action.
- Reply with "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional</i>
- <i>text...</i>" when the optional text is specified, oth-
+ Defer the request if some later restriction would
+ result in a an explicit or implicit PERMIT action.
+ Reply with "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional</i>
+ <i>text...</i>" when the optional text is specified, oth-
erwise reply with a generic error response message.
Prior to Postfix 2.6, the SMTP reply code is 450.
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a></b>, and so on).
<b>BCC</b> <i>user@domain</i>
- Send one copy of the message to the specified
+ Send one copy of the message to the specified
recipient.
- If multiple BCC actions are specified within the
- same SMTP MAIL transaction, only the last action
+ If multiple BCC actions are specified within the
+ same SMTP MAIL transaction, only the last action
will be used.
- This feature is not part of the stable Postfix
+ This feature is not part of the stable Postfix
release.
<b>DISCARD</b> <i>optional text...</i>
- Claim successful delivery and silently discard the
- message. Log the optional text if specified, oth-
+ Claim successful delivery and silently discard the
+ message. Log the optional text if specified, oth-
erwise log a generic message.
- Note: this action currently affects all recipients
- of the message. To discard only one recipient
- without discarding the entire message, use the
+ Note: this action currently affects all recipients
+ of the message. To discard only one recipient
+ without discarding the entire message, use the
<a href="transport.5.html">transport(5)</a> table to direct mail to the <a href="discard.8.html">discard(8)</a>
service.
This feature is available in Postfix 2.0 and later.
- <b>DUNNO</b> Pretend that the lookup key was not found. This
- prevents Postfix from trying substrings of the
- lookup key (such as a subdomain name, or a network
+ <b>DUNNO</b> Pretend that the lookup key was not found. This
+ prevents Postfix from trying substrings of the
+ lookup key (such as a subdomain name, or a network
address subnetwork).
This feature is available in Postfix 2.0 and later.
<b>FILTER</b> <i>transport:destination</i>
- After the message is queued, send the entire mes-
+ After the message is queued, send the entire mes-
sage through the specified external content filter.
- The <i>transport</i> name specifies the first field of a
- mail delivery agent definition in <a href="master.5.html">master.cf</a>; the
- syntax of the next-hop <i>destination</i> is described in
+ The <i>transport</i> name specifies the first field of a
+ mail delivery agent definition in <a href="master.5.html">master.cf</a>; the
+ syntax of the next-hop <i>destination</i> is described in
the manual page of the corresponding delivery
- agent. More information about external content
+ agent. More information about external content
filters is in the Postfix <a href="FILTER_README.html">FILTER_README</a> file.
- Note 1: do not use $<i>number</i> regular expression sub-
- stitutions for <i>transport</i> or <i>destination</i> unless you
+ Note 1: do not use $<i>number</i> regular expression sub-
+ stitutions for <i>transport</i> or <i>destination</i> unless you
know that the information has a trusted origin.
- Note 2: this action overrides the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#content_filter">con</a>-</b>
- <b><a href="postconf.5.html#content_filter">tent_filter</a></b> setting, and affects all recipients of
- the message. In the case that multiple <b>FILTER</b>
+ Note 2: this action overrides the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#content_filter">con</a>-</b>
+ <b><a href="postconf.5.html#content_filter">tent_filter</a></b> setting, and affects all recipients of
+ the message. In the case that multiple <b>FILTER</b>
actions fire, only the last one is executed.
- Note 3: the purpose of the FILTER command is to
- override message routing. To override the recipi-
- ent's <i>transport</i> but not the next-hop <i>destination</i>,
- specify an empty filter <i>destination</i> (Postfix 2.7
+ Note 3: the purpose of the FILTER command is to
+ override message routing. To override the recipi-
+ ent's <i>transport</i> but not the next-hop <i>destination</i>,
+ specify an empty filter <i>destination</i> (Postfix 2.7
and later), or specify a <i>transport:destination</i> that
- delivers through a different Postfix instance
- (Postfix 2.6 and earlier). Other options are using
- the recipient-dependent <b><a href="postconf.5.html#transport_maps">transport_maps</a></b> or the sen-
+ delivers through a different Postfix instance
+ (Postfix 2.6 and earlier). Other options are using
+ the recipient-dependent <b><a href="postconf.5.html#transport_maps">transport_maps</a></b> or the sen-
der-dependent <b><a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport</a>-</b>
<b><a href="postconf.5.html#sender_dependent_default_transport_maps">_maps</a></b> features.
This feature is available in Postfix 2.0 and later.
<b>HOLD</b> <i>optional text...</i>
- Place the message on the <b>hold</b> queue, where it will
- sit until someone either deletes it or releases it
- for delivery. Log the optional text if specified,
+ Place the message on the <b>hold</b> queue, where it will
+ sit until someone either deletes it or releases it
+ for delivery. Log the optional text if specified,
otherwise log a generic message.
- Mail that is placed on hold can be examined with
- the <a href="postcat.1.html"><b>postcat</b>(1)</a> command, and can be destroyed or
+ Mail that is placed on hold can be examined with
+ the <a href="postcat.1.html"><b>postcat</b>(1)</a> command, and can be destroyed or
released with the <a href="postsuper.1.html"><b>postsuper</b>(1)</a> command.
- Note: use "<b>postsuper -r</b>" to release mail that was
- kept on hold for a significant fraction of <b>$<a href="postconf.5.html#maximal_queue_lifetime">maxi</a>-</b>
+ Note: use "<b>postsuper -r</b>" to release mail that was
+ kept on hold for a significant fraction of <b>$<a href="postconf.5.html#maximal_queue_lifetime">maxi</a>-</b>
<b><a href="postconf.5.html#maximal_queue_lifetime">mal_queue_lifetime</a></b> or <b>$<a href="postconf.5.html#bounce_queue_lifetime">bounce_queue_lifetime</a></b>, or
- longer. Use "<b>postsuper -H</b>" only for mail that will
+ longer. Use "<b>postsuper -H</b>" only for mail that will
not expire within a few delivery attempts.
- Note: this action currently affects all recipients
+ Note: this action currently affects all recipients
of the message.
This feature is available in Postfix 2.0 and later.
<b>PREPEND</b> <i>headername: headervalue</i>
- Prepend the specified message header to the mes-
- sage. When more than one PREPEND action executes,
- the first prepended header appears before the sec-
+ Prepend the specified message header to the mes-
+ sage. When more than one PREPEND action executes,
+ the first prepended header appears before the sec-
ond etc. prepended header.
- Note: this action must execute before the message
- content is received; it cannot execute in the con-
+ Note: this action must execute before the message
+ content is received; it cannot execute in the con-
text of <b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
This feature is available in Postfix 2.1 and later.
<b>REDIRECT</b> <i>user@domain</i>
- After the message is queued, send the message to
+ After the message is queued, send the message to
the specified address instead of the intended
recipient(s).
- Note: this action overrides the FILTER action, and
+ Note: this action overrides the FILTER action, and
currently affects all recipients of the message.
This feature is available in Postfix 2.1 and later.
<b>WARN</b> <i>optional text...</i>
Log a warning with the optional text, together with
- client information and if available, with helo,
+ client information and if available, with helo,
sender, recipient and protocol information.
This feature is available in Postfix 2.1 and later.
<b>ENHANCED STATUS CODES</b>
- Postfix version 2.3 and later support enhanced status
- codes as defined in <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a>. When an enhanced status
- code is specified in an access table, it is subject to
- modification. The following transformations are needed
- when the same access table is used for client, helo,
- sender, or recipient access restrictions; they happen
+ Postfix version 2.3 and later support enhanced status
+ codes as defined in <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a>. When an enhanced status
+ code is specified in an access table, it is subject to
+ modification. The following transformations are needed
+ when the same access table is used for client, helo,
+ sender, or recipient access restrictions; they happen
regardless of whether Postfix replies to a MAIL FROM, RCPT
TO or other SMTP command.
- <b>o</b> When a sender address matches a REJECT action, the
- Postfix SMTP server will transform a recipient DSN
- status (e.g., 4.1.1-4.1.6) into the corresponding
+ <b>o</b> When a sender address matches a REJECT action, the
+ Postfix SMTP server will transform a recipient DSN
+ status (e.g., 4.1.1-4.1.6) into the corresponding
sender DSN status, and vice versa.
- <b>o</b> When non-address information matches a REJECT
- action (such as the HELO command argument or the
- client hostname/address), the Postfix SMTP server
- will transform a sender or recipient DSN status
- into a generic non-address DSN status (e.g.,
+ <b>o</b> When non-address information matches a REJECT
+ action (such as the HELO command argument or the
+ client hostname/address), the Postfix SMTP server
+ will transform a sender or recipient DSN status
+ into a generic non-address DSN status (e.g.,
4.0.0).
<b>REGULAR EXPRESSION TABLES</b>
- This section describes how the table lookups change when
+ This section describes how the table lookups change when
the table is given in the form of regular expressions. For
- a description of regular expression lookup table syntax,
+ a description of regular expression lookup table syntax,
see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to
+ Each pattern is a regular expression that is applied to
the entire string being looked up. Depending on the appli-
- cation, that string is an entire client hostname, an
+ cation, that string is an entire client hostname, an
entire client IP address, or an entire mail address. Thus,
no parent domain or parent network search is done,
- <i>user@domain</i> mail addresses are not broken up into their
+ <i>user@domain</i> mail addresses are not broken up into their
<i>user@</i> and <i>domain</i> constituent parts, nor is <i>user+foo</i> broken
up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the ta-
- ble, until a pattern is found that matches the search
+ Patterns are applied in the order as specified in the ta-
+ ble, until a pattern is found that matches the search
string.
- Actions are the same as with indexed file lookups, with
- the additional feature that parenthesized substrings from
+ Actions are the same as with indexed file lookups, with
+ the additional feature that parenthesized substrings from
the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
<b>TCP-BASED TABLES</b>
- This section describes how the table lookups change when
+ This section describes how the table lookups change when
lookups are directed to a TCP-based server. For a descrip-
tion of the TCP client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_ta-</b></a>
<a href="tcp_table.5.html"><b>ble</b>(5)</a>. This feature is not available up to and including
Postfix version 2.4.
- Each lookup operation uses the entire query string once.
- Depending on the application, that string is an entire
+ Each lookup operation uses the entire query string once.
+ Depending on the application, that string is an entire
client hostname, an entire client IP address, or an entire
- mail address. Thus, no parent domain or parent network
- search is done, <i>user@domain</i> mail addresses are not broken
- up into their <i>user@</i> and <i>domain</i> constituent parts, nor is
+ mail address. Thus, no parent domain or parent network
+ search is done, <i>user@domain</i> mail addresses are not broken
+ up into their <i>user@</i> and <i>domain</i> constituent parts, nor is
<i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Actions are the same as with indexed file lookups.
<b>EXAMPLE</b>
- The following example uses an indexed file, so that the
- order of table entries does not matter. The example per-
- mits access by the client at address 1.2.3.4 but rejects
- all other clients in 1.2.3.0/24. Instead of <b>hash</b> lookup
- tables, some systems use <b>dbm</b>. Use the command "<b>postconf</b>
- <b>-m</b>" to find out what lookup tables Postfix supports on
+ The following example uses an indexed file, so that the
+ order of table entries does not matter. The example per-
+ mits access by the client at address 1.2.3.4 but rejects
+ all other clients in 1.2.3.0/24. Instead of <b>hash</b> lookup
+ tables, some systems use <b>dbm</b>. Use the command "<b>postconf</b>
+ <b>-m</b>" to find out what lookup tables Postfix supports on
your system.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
1.2.3 REJECT
1.2.3.4 OK
- Execute the command "<b>postmap /etc/postfix/access</b>" after
+ Execute the command "<b>postmap /etc/postfix/access</b>" after
editing the file.
<b>BUGS</b>
- The table format does not understand quoting conventions.
+ The table format does not understand quoting conventions.
<b>SEE ALSO</b>
<a href="postmap.1.html">postmap(1)</a>, Postfix lookup table manager
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
<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>
specifies tables with server replies indexed by <i>rbl_domain</i>.
This feature is available in Postfix 2.0 and later. </dd>
-<dt><b><a name="reject_rhsbl_client">reject_rhsbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
+<dt><b><a name="permit_dnswl_client">permit_dnswl_client <i>dnswl_domain=d.d.d.d</i></a></b></dt>
+
+<dd>Accept the request when the reversed client network address is
+listed with the A record "<i>d.d.d.d</i>" under <i>dnswl_domain</i>.
+If no "<i>=d.d.d.d</i>" is specified, accept the request when the
+reversed client network address is listed with any A record under
+<i>dnswl_domain</i>. <br> For safety, <a href="postconf.5.html#permit_dnswl_client">permit_dnswl_client</a> is silently
+ignored when it would override <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>. The
+result is DEFER_IF_REJECT when whitelist lookup fails. This feature
+is available in Postfix 2.8 and later. </dd>
+
+</dd> <dt><b><a name="reject_rhsbl_client">reject_rhsbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
<dd>Reject the request when the client hostname is listed with the
A record "<i>d.d.d.d</i>" under <i>rbl_domain</i> (Postfix version
version 2.8 and later, <a href="postconf.5.html#reject_rhsbl_reverse_client">reject_rhsbl_reverse_client</a> will usually
produce better results. </dd>
+</dd> <dt><b><a name="permit_rhswl_client">permit_rhswl_client <i>rhswl_domain=d.d.d.d</i></a></b></dt>
+
+<dd>Accept the request when the client hostname is listed with the
+A record "<i>d.d.d.d</i>" under <i>rhswl_domain</i>. If no
+"<i>=d.d.d.d</i>" is specified, accept the request when the client
+hostname is listed with any A record under <i>rhswl_domain</i>.
+<br> Caution: client name whitelisting is fragile, since the client
+name lookup can fail due to temporary outages. Client name
+whitelisting should be used only to reduce false positives in e.g.
+DNS-based blocklists, and not for making access rule exceptions.
+<br> For safety, <a href="postconf.5.html#permit_rhswl_client">permit_rhswl_client</a> is silently ignored when it
+would override <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>. The result is DEFER_IF_REJECT
+when whitelist lookup fails. This feature is available in Postfix
+2.8 and later. </dd>
+
<dt><b><a name="reject_rhsbl_reverse_client">reject_rhsbl_reverse_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
<dd>Reject the request when the unverified reverse client hostname
.sp
The pattern \fIdomain.tld\fR also matches subdomains, but only
when the string \fBsmtpd_access_maps\fR is listed in the Postfix
-\fBparent_domain_matches_subdomains\fR configuration setting
-(note that this is the default for some versions of Postfix).
-Otherwise, specify \fI.domain.tld\fR (note the initial dot) in
-order to match subdomains.
+\fBparent_domain_matches_subdomains\fR configuration setting.
+.IP \fI.domain.tld\fR
+Matches subdomains of \fIdomain.tld\fR, but only when the
+string \fBsmtpd_access_maps\fR is not listed in the Postfix
+\fBparent_domain_matches_subdomains\fR configuration setting.
.IP \fIuser\fR@
Matches all mail addresses with the specified user part.
.PP
The pattern \fIdomain.tld\fR also matches subdomains, but only
when the string \fBsmtpd_access_maps\fR is listed in the Postfix
\fBparent_domain_matches_subdomains\fR configuration setting.
-Otherwise, specify \fI.domain.tld\fR (note the initial dot) in
-order to match subdomains.
+.IP \fI.domain.tld\fR
+Matches subdomains of \fIdomain.tld\fR, but only when the
+string \fBsmtpd_access_maps\fR is not listed in the Postfix
+\fBparent_domain_matches_subdomains\fR configuration setting.
.IP \fInet.work.addr.ess\fR
.IP \fInet.work.addr\fR
.IP \fInet.work\fR
specifies the default server reply, and the rbl_reply_maps parameter
specifies tables with server replies indexed by \fIrbl_domain\fR.
This feature is available in Postfix 2.0 and later.
+.IP "\fBpermit_dnswl_client \fIdnswl_domain=d.d.d.d\fR\fR"
+Accept the request when the reversed client network address is
+listed with the A record "\fId.d.d.d\fR" under \fIdnswl_domain\fR.
+If no "\fI=d.d.d.d\fR" is specified, accept the request when the
+reversed client network address is listed with any A record under
+\fIdnswl_domain\fR.
+.br
+For safety, permit_dnswl_client is silently
+ignored when it would override reject_unauth_destination. The
+result is DEFER_IF_REJECT when whitelist lookup fails. This feature
+is available in Postfix 2.8 and later.
.IP "\fBreject_rhsbl_client \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the client hostname is listed with the
A record "\fId.d.d.d\fR" under \fIrbl_domain\fR (Postfix version
This feature is available in Postfix 2.0 and later; with Postfix
version 2.8 and later, reject_rhsbl_reverse_client will usually
produce better results.
+.IP "\fBpermit_rhswl_client \fIrhswl_domain=d.d.d.d\fR\fR"
+Accept the request when the client hostname is listed with the
+A record "\fId.d.d.d\fR" under \fIrhswl_domain\fR. If no
+"\fI=d.d.d.d\fR" is specified, accept the request when the client
+hostname is listed with any A record under \fIrhswl_domain\fR.
+.br
+Caution: client name whitelisting is fragile, since the client
+name lookup can fail due to temporary outages. Client name
+whitelisting should be used only to reduce false positives in e.g.
+DNS-based blocklists, and not for making access rule exceptions.
+.br
+For safety, permit_rhswl_client is silently ignored when it
+would override reject_unauth_destination. The result is DEFER_IF_REJECT
+when whitelist lookup fails. This feature is available in Postfix
+2.8 and later.
.IP "\fBreject_rhsbl_reverse_client \fIrbl_domain=d.d.d.d\fR\fR"
Reject the request when the unverified reverse client hostname
is listed with the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR.
s;\breject_rbl_client\b;<a href="postconf.5.html#reject_rbl_client">$&</a>;g;
s;\breject_rhsbl_client\b;<a href="postconf.5.html#reject_rhsbl_client">$&</a>;g;
s;\breject_rhsbl_reverse_client\b;<a href="postconf.5.html#reject_rhsbl_reverse_client">$&</a>;g;
+ s;\bpermit_dnswl_client\b;<a href="postconf.5.html#permit_dnswl_client">$&</a>;g;
+ s;\bpermit_rhswl_client\b;<a href="postconf.5.html#permit_rhswl_client">$&</a>;g;
# Access restrictions - helo
# .sp
# The pattern \fIdomain.tld\fR also matches subdomains, but only
# when the string \fBsmtpd_access_maps\fR is listed in the Postfix
-# \fBparent_domain_matches_subdomains\fR configuration setting
-# (note that this is the default for some versions of Postfix).
-# Otherwise, specify \fI.domain.tld\fR (note the initial dot) in
-# order to match subdomains.
+# \fBparent_domain_matches_subdomains\fR configuration setting.
+# .IP \fI.domain.tld\fR
+# Matches subdomains of \fIdomain.tld\fR, but only when the
+# string \fBsmtpd_access_maps\fR is not listed in the Postfix
+# \fBparent_domain_matches_subdomains\fR configuration setting.
# .IP \fIuser\fR@
# Matches all mail addresses with the specified user part.
# .PP
# The pattern \fIdomain.tld\fR also matches subdomains, but only
# when the string \fBsmtpd_access_maps\fR is listed in the Postfix
# \fBparent_domain_matches_subdomains\fR configuration setting.
-# Otherwise, specify \fI.domain.tld\fR (note the initial dot) in
-# order to match subdomains.
+# .IP \fI.domain.tld\fR
+# Matches subdomains of \fIdomain.tld\fR, but only when the
+# string \fBsmtpd_access_maps\fR is not listed in the Postfix
+# \fBparent_domain_matches_subdomains\fR configuration setting.
# .IP \fInet.work.addr.ess\fR
# .IP \fInet.work.addr\fR
# .IP \fInet.work\fR
specifies tables with server replies indexed by <i>rbl_domain</i>.
This feature is available in Postfix 2.0 and later. </dd>
+<dt><b><a name="permit_dnswl_client">permit_dnswl_client <i>dnswl_domain=d.d.d.d</i></a></b></dt>
+
+<dd>Accept the request when the reversed client network address is
+listed with the A record "<i>d.d.d.d</i>" under <i>dnswl_domain</i>.
+If no "<i>=d.d.d.d</i>" is specified, accept the request when the
+reversed client network address is listed with any A record under
+<i>dnswl_domain</i>. <br> For safety, permit_dnswl_client is silently
+ignored when it would override reject_unauth_destination. The
+result is DEFER_IF_REJECT when whitelist lookup fails. This feature
+is available in Postfix 2.8 and later. </dd>
+
<dt><b><a name="reject_rhsbl_client">reject_rhsbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
<dd>Reject the request when the client hostname is listed with the
version 2.8 and later, reject_rhsbl_reverse_client will usually
produce better results. </dd>
+</dd> <dt><b><a name="permit_rhswl_client">permit_rhswl_client <i>rhswl_domain=d.d.d.d</i></a></b></dt>
+
+<dd>Accept the request when the client hostname is listed with the
+A record "<i>d.d.d.d</i>" under <i>rhswl_domain</i>. If no
+"<i>=d.d.d.d</i>" is specified, accept the request when the client
+hostname is listed with any A record under <i>rhswl_domain</i>.
+<br> Caution: client name whitelisting is fragile, since the client
+name lookup can fail due to temporary outages. Client name
+whitelisting should be used only to reduce false positives in e.g.
+DNS-based blocklists, and not for making access rule exceptions.
+<br> For safety, permit_rhswl_client is silently ignored when it
+would override reject_unauth_destination. The result is DEFER_IF_REJECT
+when whitelist lookup fails. This feature is available in Postfix
+2.8 and later. </dd>
+
<dt><b><a name="reject_rhsbl_reverse_client">reject_rhsbl_reverse_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
<dd>Reject the request when the unverified reverse client hostname
#define REJECT_RHSBL_SENDER "reject_rhsbl_sender"
#define REJECT_RHSBL_RECIPIENT "reject_rhsbl_recipient"
+#define PERMIT_DNSWL_CLIENT "permit_dnswl_client"
+#define PERMIT_RHSWL_CLIENT "permit_rhswl_client"
+
#define VAR_RBL_REPLY_MAPS "rbl_reply_maps"
#define DEF_RBL_REPLY_MAPS ""
extern char *var_rbl_reply_maps;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20101103"
+#define MAIL_RELEASE_DATE "20101108"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_exp_test \
smtpd_token_test smtpd_check_test4 smtpd_check_dsn_test \
- smtpd_check_backup_test
+ smtpd_check_backup_test smtpd_dnswl_test
root_tests:
diff smtpd_token.ref smtpd_token.tmp
rm -f smtpd_token.tmp
+# This requires that the DNS server can query porcupine.org and rfc-ignorant.org
+
+smtpd_dnswl_test: smtpd_check smtpd_dnswl.in smtpd_dnswl.ref
+ ./smtpd_check <smtpd_dnswl.in >smtpd_dnswl.tmp 2>&1
+ diff smtpd_dnswl.ref smtpd_dnswl.tmp
+ rm -f smtpd_dnswl.tmp
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
}
}
+/* Support for different DNSXL lookup results. */
+
+static SMTPD_RBL_STATE dnsxl_stat_soft[1];
+
+#define SMTPD_DNSXL_STAT_SOFT(dnsxl_res) ((dnsxl_res) == dnsxl_stat_soft)
+#define SMTPD_DNXSL_STAT_HARD(dnsxl_res) ((dnsxl_res) == 0)
+#define SMTPD_DNSXL_STAT_OK(dnsxl_res) \
+ !(SMTPD_DNXSL_STAT_HARD(dnsxl_res) || SMTPD_DNSXL_STAT_SOFT(dnsxl_res))
+
/* rbl_pagein - look up an RBL lookup result */
static void *rbl_pagein(const char *query, void *unused_context)
DNS_RR *txt_list;
VSTRING *why;
int dns_status;
- SMTPD_RBL_STATE *rbl;
+ SMTPD_RBL_STATE *rbl = 0;
DNS_RR *addr_list;
MAI_HOSTADDR_STR hostaddr;
DNS_RR *rr;
*/
why = vstring_alloc(10);
dns_status = dns_lookup(query, T_A, 0, &addr_list, (VSTRING *) 0, why);
- if (dns_status != DNS_OK && dns_status != DNS_NOTFOUND)
+ if (dns_status != DNS_OK && dns_status != DNS_NOTFOUND) {
msg_warn("%s: RBL lookup error: %s", query, STR(why));
+ rbl = dnsxl_stat_soft;
+ }
vstring_free(why);
if (dns_status != DNS_OK)
- return (0);
+ return ((void *) rbl);
/*
* Save the result. Yes, we cache negative results as well as positive
{
SMTPD_RBL_STATE *rbl = (SMTPD_RBL_STATE *) data;
- if (rbl != 0) {
+ if (SMTPD_DNSXL_STAT_OK(rbl)) {
if (rbl->txt)
myfree(rbl->txt);
if (rbl->a)
/* rbl_reject_reply - format reply after RBL reject */
-static int rbl_reject_reply(SMTPD_STATE *state, SMTPD_RBL_STATE *rbl,
+static int rbl_reject_reply(SMTPD_STATE *state, const SMTPD_RBL_STATE *rbl,
const char *rbl_domain,
const char *what,
const char *reply_class)
return (0);
}
-/* reject_rbl_addr - reject if address in real-time blackhole list */
+/* find_dnsxl_addr - look up address in DNSXL */
-static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain,
- const char *addr, const char *reply_class)
+static const SMTPD_RBL_STATE *find_dnsxl_addr(SMTPD_STATE *state,
+ const char *rbl_domain,
+ const char *addr)
{
- const char *myname = "reject_rbl";
+ const char *myname = "find_dnsxl_addr";
ARGV *octets;
VSTRING *query;
int i;
struct addrinfo *res;
unsigned char *ipv6_addr;
- if (msg_verbose)
- msg_info("%s: %s %s", myname, reply_class, addr);
-
query = vstring_alloc(100);
/*
rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query));
/*
- * If the record exists, the address is blacklisted.
+ * If the record exists, match the result address.
*/
- if (rbl == 0 || (reply_addr != 0 && !rbl_match_addr(rbl, reply_addr))) {
- vstring_free(query);
+ if (SMTPD_DNSXL_STAT_OK(rbl) && reply_addr != 0
+ && !rbl_match_addr(rbl, reply_addr))
+ rbl = 0;
+ vstring_free(query);
+ return (rbl);
+}
+
+/* reject_rbl_addr - reject address in real-time blackhole list */
+
+static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain,
+ const char *addr, const char *reply_class)
+{
+ const char *myname = "reject_rbl_addr";
+ const SMTPD_RBL_STATE *rbl;
+
+ if (msg_verbose)
+ msg_info("%s: %s %s", myname, reply_class, addr);
+
+ rbl = find_dnsxl_addr(state, rbl_domain, addr);
+ if (!SMTPD_DNSXL_STAT_OK(rbl)) {
return (SMTPD_CHECK_DUNNO);
} else {
- vstring_free(query);
return (rbl_reject_reply(state, rbl, rbl_domain, addr, reply_class));
}
}
-/* reject_rbl_domain - reject if domain in real-time blackhole list */
+/* permit_dnswl_addr - permit address in DNSWL */
-static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain,
- const char *what, const char *reply_class)
+static int permit_dnswl_addr(SMTPD_STATE *state, const char *dnswl_domain,
+ const char *addr, const char *reply_class)
+{
+ const char *myname = "permit_dnswl_addr";
+ const SMTPD_RBL_STATE *dnswl_result;
+
+ if (msg_verbose)
+ msg_info("%s: %s", myname, addr);
+
+ /* Safety: don't whitelist unauthorized recipients. */
+ if (strcmp(state->where, SMTPD_CMD_RCPT) == 0 && state->recipient != 0
+ && permit_auth_destination(state, state->recipient) != SMTPD_CHECK_OK)
+ return (SMTPD_CHECK_DUNNO);
+
+ dnswl_result = find_dnsxl_addr(state, dnswl_domain, addr);
+ if (SMTPD_DNXSL_STAT_HARD(dnswl_result)) {
+ return (SMTPD_CHECK_DUNNO);
+ } else if (SMTPD_DNSXL_STAT_SOFT(dnswl_result)) {
+ /* XXX: Make configurable as dnswl_tempfail_action. */
+ DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
+ 450, "4.7.1",
+ "<%s>: %s rejected: %s",
+ addr, reply_class,
+ "Service unavailable");
+ return (SMTPD_CHECK_DUNNO);
+ } else if (SMTPD_DNSXL_STAT_OK(dnswl_result)) {
+ return (SMTPD_CHECK_OK);
+ } else {
+ /* Future proofing, in case find_dnsxl_addr() result is changed. */
+ msg_panic("%s: find_dnsxl_addr API failure", myname);
+ }
+}
+
+/* find_dnsxl_domain - reject if domain in real-time blackhole list */
+
+static const SMTPD_RBL_STATE *find_dnsxl_domain(SMTPD_STATE *state,
+ const char *rbl_domain, const char *what)
{
- const char *myname = "reject_rbl_domain";
VSTRING *query;
SMTPD_RBL_STATE *rbl;
const char *domain;
const char *reply_addr;
- if (msg_verbose)
- msg_info("%s: %s %s", myname, reply_class, what);
-
/*
* Extract the domain, tack on the RBL domain name and query the DNS for
* an A record.
rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query));
/*
- * If the record exists, the domain is blacklisted.
+ * If the record exists, match the result address.
*/
- if (rbl == 0 || (reply_addr != 0 && !rbl_match_addr(rbl, reply_addr))) {
- vstring_free(query);
+ if (SMTPD_DNSXL_STAT_OK(rbl) && reply_addr != 0
+ && !rbl_match_addr(rbl, reply_addr))
+ rbl = 0;
+ vstring_free(query);
+ return (rbl);
+}
+
+/* reject_rbl_domain - reject if domain in real-time blackhole list */
+
+static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain,
+ const char *what, const char *reply_class)
+{
+ const char *myname = "reject_rbl_domain";
+ const SMTPD_RBL_STATE *rbl;
+
+ if (msg_verbose)
+ msg_info("%s: %s %s", myname, rbl_domain, what);
+
+ rbl = find_dnsxl_domain(state, rbl_domain, what);
+ if (!SMTPD_DNSXL_STAT_OK(rbl)) {
return (SMTPD_CHECK_DUNNO);
} else {
- vstring_free(query);
return (rbl_reject_reply(state, rbl, rbl_domain, what, reply_class));
}
}
+/* permit_dnswl_domain - permit domain in DNSWL */
+
+static int permit_dnswl_domain(SMTPD_STATE *state, const char *dnswl_domain,
+ const char *what, const char *reply_class)
+{
+ const char *myname = "permit_dnswl_domain";
+ const SMTPD_RBL_STATE *dnswl_result;
+
+ if (msg_verbose)
+ msg_info("%s: %s", myname, what);
+
+ /* Safety: don't whitelist unauthorized recipients. */
+ if (strcmp(state->where, SMTPD_CMD_RCPT) == 0 && state->recipient != 0
+ && permit_auth_destination(state, state->recipient) != SMTPD_CHECK_OK)
+ return (SMTPD_CHECK_DUNNO);
+
+ dnswl_result = find_dnsxl_domain(state, dnswl_domain, what);
+ if (SMTPD_DNXSL_STAT_HARD(dnswl_result)) {
+ return (SMTPD_CHECK_DUNNO);
+ } else if (SMTPD_DNSXL_STAT_SOFT(dnswl_result)) {
+ /* XXX: Make configurable as rhswl_tempfail_action. */
+ DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
+ 450, "4.7.1",
+ "<%s>: %s rejected: %s",
+ what, reply_class,
+ "Service unavailable");
+ return (SMTPD_CHECK_DUNNO);
+ } else if (SMTPD_DNSXL_STAT_OK(dnswl_result)) {
+ return (SMTPD_CHECK_OK);
+ } else {
+ /* Future proofing, in case find_dnsxl_addr() result is changed. */
+ msg_panic("%s: find_dnsxl_addr API failure", myname);
+ }
+}
+
/* reject_maps_rbl - reject if client address in real-time blackhole list */
static int reject_maps_rbl(SMTPD_STATE *state)
else
status = reject_rbl_addr(state, *(cpp += 1), state->addr,
SMTPD_NAME_CLIENT);
+ } else if (strcasecmp(name, PERMIT_DNSWL_CLIENT) == 0) {
+ if (cpp[1] == 0)
+ msg_warn("restriction %s requires domain name argument", name);
+ else
+ status = permit_dnswl_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",
status = reject_rbl_domain(state, *cpp, state->name,
SMTPD_NAME_CLIENT);
}
+ } else if (strcasecmp(name, PERMIT_RHSWL_CLIENT) == 0) {
+ if (cpp[1] == 0)
+ msg_warn("restriction %s requires domain name argument",
+ name);
+ else {
+ cpp += 1;
+ if (strcasecmp(state->name, "unknown") != 0)
+ status = permit_dnswl_domain(state, *cpp, state->name,
+ SMTPD_NAME_CLIENT);
+ }
} else if (strcasecmp(name, REJECT_RHSBL_REVERSE_CLIENT) == 0) {
if (cpp[1] == 0)
msg_warn("restriction %s requires domain name argument",
VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code,
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code,
VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
- VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count,
+ VAR_VERIFY_POLL_COUNT, 3, &var_verify_poll_count,
VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from,
VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt,
VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code,
resp = "bad command";
switch (args->argc) {
+ /*
+ * Emtpy line.
+ */
+ case 0:
+ continue;
+
/*
* Special case: client identity.
*/
--- /dev/null
+#
+# Initialize.
+#
+#msg_verbose 1
+smtpd_delay_reject 0
+mynetworks 127.0.0.0/8,168.100.189.0/28
+mydestination porcupine.org
+relay_domains porcupine.org
+helo foobar
+
+#
+# DNSWL (by IP address)
+#
+
+# Whitelist overrides reject.
+client_restrictions permit_dnswl_client,wild.porcupine.org,reject
+client spike.porcupine.org 168.100.189.2
+
+# Whitelist does not fire - reject.
+client_restrictions permit_dnswl_client,porcupine.org,reject
+client spike.porcupine.org 168.100.189.2
+
+# Whitelist does not override reject_unauth_destination.
+client_restrictions permit
+recipient_restrictions permit_dnswl_client,wild.porcupine.org,reject_unauth_destination
+# Unauthorized destination - reject.
+rcpt rname@rdomain
+# Authorized destination - accept.
+rcpt wietse@porcupine.org
+
+#
+# RHSWL (by domain name)
+#
+
+# Whitelist overrides reject.
+client_restrictions permit_rhswl_client,dsn.rfc-ignorant.org,reject
+# Non-whitelisted client name - reject.
+client spike.porcupine.org 168.100.189.2
+# Whitelisted client name - accept.
+client example.tld 168.100.189.2
+
+# Whitelist does not override reject_unauth_destination.
+client_restrictions permit
+recipient_restrictions permit_rhswl_client,dsn.rfc-ignorant.org,reject_unauth_destination
+# Non-whitelisted client name.
+client spike.porcupine.org 168.100.189.2
+# Unauthorized destination - reject.
+rcpt rname@rdomain
+# Authorized destination - accept.
+rcpt wietse@porcupine.org
+# Whitelisted client name.
+client example.tld 168.100.189.2
+# Unauthorized destination - reject.
+rcpt rname@rdomain
+# Authorized destination - accept.
+rcpt wietse@porcupine.org
--- /dev/null
+>>> #
+>>> # Initialize.
+>>> #
+>>> #msg_verbose 1
+>>> smtpd_delay_reject 0
+OK
+>>> mynetworks 127.0.0.0/8,168.100.189.0/28
+OK
+>>> mydestination porcupine.org
+OK
+>>> relay_domains porcupine.org
+OK
+>>> helo foobar
+OK
+>>>
+>>> #
+>>> # DNSWL (by IP address)
+>>> #
+>>>
+>>> # Whitelist overrides reject.
+>>> client_restrictions permit_dnswl_client,wild.porcupine.org,reject
+OK
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>>
+>>> # Whitelist does not fire - reject.
+>>> client_restrictions permit_dnswl_client,porcupine.org,reject
+OK
+>>> client spike.porcupine.org 168.100.189.2
+./smtpd_check: <queue id>: reject: CONNECT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <spike.porcupine.org[168.100.189.2]>: Client host rejected: Access denied; proto=SMTP helo=<foobar>
+554 5.7.1 <spike.porcupine.org[168.100.189.2]>: Client host rejected: Access denied
+>>>
+>>> # Whitelist does not override reject_unauth_destination.
+>>> client_restrictions permit
+OK
+>>> recipient_restrictions permit_dnswl_client,wild.porcupine.org,reject_unauth_destination
+OK
+>>> # Unauthorized destination - reject.
+>>> rcpt rname@rdomain
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <rname@rdomain>: Relay access denied; to=<rname@rdomain> proto=SMTP helo=<foobar>
+554 5.7.1 <rname@rdomain>: Relay access denied
+>>> # Authorized destination - accept.
+>>> rcpt wietse@porcupine.org
+OK
+>>>
+>>> #
+>>> # RHSWL (by domain name)
+>>> #
+>>>
+>>> # Whitelist overrides reject.
+>>> client_restrictions permit_rhswl_client,dsn.rfc-ignorant.org,reject
+OK
+>>> # Non-whitelisted client name - reject.
+>>> client spike.porcupine.org 168.100.189.2
+./smtpd_check: <queue id>: reject: CONNECT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <spike.porcupine.org[168.100.189.2]>: Client host rejected: Access denied; proto=SMTP helo=<foobar>
+554 5.7.1 <spike.porcupine.org[168.100.189.2]>: Client host rejected: Access denied
+>>> # Whitelisted client name - accept.
+>>> client example.tld 168.100.189.2
+OK
+>>>
+>>> # Whitelist does not override reject_unauth_destination.
+>>> client_restrictions permit
+OK
+>>> recipient_restrictions permit_rhswl_client,dsn.rfc-ignorant.org,reject_unauth_destination
+OK
+>>> # Non-whitelisted client name.
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>> # Unauthorized destination - reject.
+>>> rcpt rname@rdomain
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <rname@rdomain>: Relay access denied; to=<rname@rdomain> proto=SMTP helo=<foobar>
+554 5.7.1 <rname@rdomain>: Relay access denied
+>>> # Authorized destination - accept.
+>>> rcpt wietse@porcupine.org
+OK
+>>> # Whitelisted client name.
+>>> client example.tld 168.100.189.2
+OK
+>>> # Unauthorized destination - reject.
+>>> rcpt rname@rdomain
+./smtpd_check: <queue id>: reject: RCPT from example.tld[168.100.189.2]: 554 5.7.1 <rname@rdomain>: Relay access denied; to=<rname@rdomain> proto=SMTP helo=<foobar>
+554 5.7.1 <rname@rdomain>: Relay access denied
+>>> # Authorized destination - accept.
+>>> rcpt wietse@porcupine.org
+OK