debug_peer_list = 127.0.0.1
+You can specify one or more hosts, domains, addresses or net/masks.
+
3 - Making daemon programs more verbose
=======================================
= canonical, virtual, alias, forward, include" to restore
previous behavior.
- Feature: forward_expansion_filter configuration parameter
- that controls what characters may appear in $name expansions
- of forward_path.
-
19990509
- Feature: USER, EXTENSION and DOMAIN environment variables
- are exported to shell commands (including mailbox_command).
+ Feature: USER, EXTENSION, DOMAIN, RECIPIENT (entire address)
+ and MAILBOX (address localpart) environment variables are
+ exported to shell commands (including mailbox_command).
Feature: new command_expansion_filter parameter to control
what characters may appear in message attributes that are
Bugfix: missing duplicate filter call. This caused too many
deliveries when a user is listed multiple times in an alias.
Reported by Hideyuki Suzuki, School of Engineering, University
- of Tokyo.
+ of Tokyo. Backed out on 19990512 because it caused problems.
+ Fixed 19990513 but needs further study.
Feature: it is now possible to move queue files back into
the maildrop queue, so that they can benefit from changes
Feature: made a start with integrating Joerg Henne's
dictionary extensions to remove entries and to iterate over
entries. That code is almost four months old by now.
+
+19990511
+
+ Feature: added a "undeliverable postmaster notification
+ discarded" warning when mail is dropped on the floor.
+ Requested by Michael Hasenstein, SuSE, Germany.
-Incompatible changes with snapshot-19990509:
+Incompatible changes with snapshot-19990513:
===========================================
-- The SMTP server now always delays UCE restrictions until RCPT
-TO, VRFY or ETRN command. To change back to the default specify
+- The SMTP server now delays all UCE restrictions until the RCPT
+TO, VRFY or ETRN command. This makes the restrictions more useful,
+because many SMTP clients do not expect negative responses earlier
+in the protocol. In order to restore the old behavior, specify
"smtpd_delay_reject = no" in /etc/postfix/main.cf.
- The Postfix local delivery agent no longer automatically propagates
-the address extension to aliases/include/forward addresses. Specify
+address extensions to aliases/include/forward addresses. Specify
"propagate_unmatched_extensions = canonical, virtual, alias, forward,
include" to restore the old behavior.
+- The Postfix local delivery agent no longer does $name expansion
+on words found in the mailbox_command configuration parameter. This
+makes it easier to specify shell syntax. See conf/main.cf.
+
- The luser_relay syntax has changed. You can specify one address;
it is subjected to $user, etc. expansions. See conf/main.cf.
-- File system reorganization: daemon executables are in the libexec
-subdirectory, command executables in the bin subdirectory. The
-INSTALL instructions now recommend installing daemons and commands
-into separate directories.
+- File system reorganization: daemon executables are now in the
+libexec subdirectory, command executables in the bin subdirectory.
+The INSTALL instructions now recommend installing daemons and
+commands into separate directories.
-Major changes with snapshot-19990509:
+Major changes with snapshot-19990513:
=====================================
-In addition to several little bugfixes, none related to security,
-lots of internal code cleanup, lots of new functionality, and lots
-of Solaris workarounds.
-
-- New USER, EXTENSION and DOMAIN environment variables for delivery
-to command by the local delivery agent. As you might expect, the
-information is censored. The list of acceptable characters is
-specified with the command_expansion_filter configuration parameter.
-Unacceptable characters are replaced by underscores.
+- New USER, EXTENSION, LOCAL and DOMAIN environment variables for
+delivery to command (including mailbox_command) by the local delivery
+agent. As you might expect, the information is censored. The list
+of acceptable characters is specified with the command_expansion_filter
+configuration parameter. Unacceptable characters are replaced by
+underscores.
- Specify "forward_path = /var/forward/$user" to avoid looking up
.forward files in user home directories. The default value is
- Conditional $name expansion in forward_path and luser_relay.
Available names are: $user (bare user name) $shell (user login
-shell), $home (user home directory), $recipient (everything to the
-left of @), $extension (optional address extension), $domain
-(everything to the right of @), and $recipient_delimiter. A simple
-$name expands as usual. ${name?value} expands to value when $name
-is defined. ${name:value} expands to value when $name is not
-defined. With ${name?value} and ${name:value}, the value is subject
-to another iteration of $name expansion.
+shell), $home (user home directory), $local (everything to the left
+of @), $extension (optional address extension), $domain (everything
+to the right of @), $recipient (the complete address) and
+$recipient_delimiter. A simple $name expands as usual. ${name?value}
+expands to value when $name is defined. ${name:value} expands to
+value when $name is not defined. With ${name?value} and ${name:value},
+the value is subject to another iteration of $name expansion.
- POSIX regular expression support, enabled by default on 4.4BSD,
LINUX, HP-UX, and Solaris 2.5 and later. See conf/sample-regexp.cf.
* and substitute something else so mail does not come back at us.
*/
if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) {
+ msg_warn("%s: undeliverable postmaster notification discarded",
+ queue_id);
bounce_status = 0;
}
#
# The queue_directory specifies the location of the Postfix queue.
# This is also the root directory of Postfix daemons that run chrooted.
-# The contributed source code from http://www.postfix.org/ has examples
-# for setting up Postfix chroot environments on different UNIX systems.
+# See the files in examples/chroot-setup for setting up Postfix chroot
+# environments on different UNIX systems.
#
queue_directory = /var/spool/postfix
# The mailbox_command parameter specifies the optional external
# command to use instead of mailbox delivery. The command is run as
-# the recipient with proper HOME, SHELL and LOGNAME settings.
+# the recipient with proper HOME, SHELL and LOGNAME environment settings.
# Exception: delivery for root is done as $default_user.
#
-# The following expansions are done on mailbox_command: $user (recipient
-# username), $shell (recipient shell), $home (recipient home directory),
-# $recipient (full recipient address), $extension (recipient address
-# extension), $domain (recipient domain), $mailbox (entire recipient
-# localpart), $recipient_delimiter. Specify ${name?value} or
-# ${name:value} to expand value only when $name does (does not) exist.
-#
+# Other environment variables of interest: USER (recipient username),
+# EXTENSION (address extension), DOMAIN (domain part of address),
+# and LOCAL (the address localpart).
+#
+# Unlike other Postfix configuration parameters, the mailbox_command
+# parameter is not subjected to $parameter substitutions. This is to
+# make it easier to specify shell syntax (see example below).
+#
# Avoid shell meta characters because they will force Postfix to run
# an expensive shell process. Procmail alone is expensive enough.
#
#mailbox_command = /some/where/procmail
+#mailbox_command = /some/where/procmail -a "$EXTENSION"
# The mailbox_transport specifies the optional transport in master.cf
# to use after processing aliases and .forward files. This parameter
# The following expansions are done on luser_relay: $user (recipient
# username), $shell (recipient shell), $home (recipient home directory),
# $recipient (full recipient address), $extension (recipient address
-# extension), $domain (recipient domain), $mailbox (entire recipient
+# extension), $domain (recipient domain), $local (entire recipient
# localpart), $recipient_delimiter. Specify ${name?value} or
# ${name:value} to expand value only when $name does (does not) exist.
#
# luser_relay = $user@other.host
-# luser_relay = $mailbox@other.host
-# luser_relay = admin+$mailbox
+# luser_relay = $local@other.host
+# luser_relay = admin+$local
# JUNK MAIL CONTROLS
#
hopcount_limit = 50
ignore_mx_lookup_error = no
inet_interfaces = all
-initial_destination_concurrency = 2
+initial_destination_concurrency = 5
invalid_hostname_reject_code = 501
ipc_idle = 100
ipc_timeout = 3600
mail_name = Postfix
mail_owner = postfix
mail_spool_directory = /var/mail
-mail_version = Snapshot-19990510
+mail_version = Snapshot-19990513
mailbox_command =
mailbox_transport =
maps_rbl_domains = rbl.maps.vix.com
flags=R user=cyrus argv=/cyrus/bin/deliver -e -q -m ${extension} ${user}
uucp unix - n n - - pipe
flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
+ifmail unix - n n - - pipe
+ flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
# The following expansions are done on forward_path: $user (recipient
# username), $shell (recipient shell), $home (recipient home directory),
# $recipient (full recipient address), $extension (recipient address
-# extension), $domain (recipient domain), $mailbox (entire recipient
+# extension), $domain (recipient domain), $local (entire recipient
# localpart), $recipient_delimiter. Specify ${name?value} or
# ${name:value} to expand value only when $name does (does not) exist.
#
# The following expansions are done on luser_relay: $user (recipient
# username), $shell (recipient shell), $home (recipient home directory),
# $recipient (full recipient address), $extension (recipient address
-# extension), $domain (recipient domain), $mailbox (entire recipient
+# extension), $domain (recipient domain), $local (entire recipient
# localpart), $recipient_delimiter. Specify ${name?value} or
# ${name:value} to expand value only when $name does (does not) exist.
#
# luser_relay = $user@other.host
-# luser_relay = $mailbox@other.host
-# luser_relay = admin+$mailbox
+# luser_relay = $local@other.host
+# luser_relay = admin+$local
# The mail_spool_directory parameter specifies the directory where
# UNIX-style mailboxes are kept. The default setting depends on the
# The mailbox_command parameter specifies the optional external
# command to use instead of mailbox delivery. The command is run
-# as the recipient with proper HOME, SHELL and LOGNAME settings.
+# as the recipient with proper HOME, SHELL and LOGNAME environment settings.
# Exception: delivery for root is done as $default_user.
#
-# The following expansions are done on mailbox_command: $user (recipient
-# username), $shell (recipient shell), $home (recipient home directory),
-# $recipient (full recipient address), $extension (recipient address
-# extension), $domain (recipient domain), $mailbox (entire recipient
-# localpart), $recipient_delimiter. Specify ${name?value} or
-# ${name:value} to expand value only when $name does (does not) exist.
+# Other environment variables of interest: USER (recipient username),
+# EXTENSION (address extension), DOMAIN (domain part of address),
+# and LOCAL (the address localpart).
+#
+# Unlike other Postfix configuration parameters, the mailbox_command
+# parameter is not subjected to $parameter substitutions. This is to
+# make it easier to specify shell syntax (see example below).
#
# Avoid shell meta characters because they will force Postfix to run
# an expensive shell process. Procmail alone is expensive enough.
#
# mailbox_command = /some/where/procmail
+# mailbox_command = /some/where/procmail -a "$EXTENSION"
mailbox_command =
# The mailbox_transport specifies the optional transport in master.cf
/* recognized in \fBpattern\fR, with the corresponding bit mask
/* given in parentheses:
/* .IP "canonical (EXP_PROP_CANONICAL)"
-/* Propagate unmatched address extensions tothe right-hand side
-/* canonical map entries.
+/* Propagate unmatched address extensions to the right-hand side
+/* of canonical table entries (not: regular expressions).
/* .IP "virtual (EXP_PROP_VIRTUAL)
-/* Propagate unmatched address extensions tothe right-hand side
-/* canonical map entries.
+/* Propagate unmatched address extensions to the right-hand side
+/* of virtual table entries (not: regular expressions).
/* .IP "alias (EXP_PROP_ALIAS)
-/* Propagate unmatched address extensions tothe right-hand side
-/* canonical map entries.
+/* Propagate unmatched address extensions to the right-hand side
+/* of alias database entries.
/* .IP "forward (EXP_PROP_FORWARD)"
-/* Propagate unmatched address extensions tothe right-hand side
-/* canonical map entries.
+/* Propagate unmatched address extensions to the right-hand side
+/* of .forward file entries.
/* .IP "include (EXP_PROP_INCLUDE)"
-/* Propagate unmatched address extensions tothe right-hand side
-/* canonical map entries.
+/* Propagate unmatched address extensions to the right-hand side
+/* of :include: file entries.
/* DIAGNOSTICS
/* Panic: inappropriate use.
/* LICENSE
* Queue manager: default destination concurrency levels.
*/
#define VAR_INIT_DEST_CON "initial_destination_concurrency"
-#define DEF_INIT_DEST_CON 2
+#define DEF_INIT_DEST_CON 5
extern int var_init_dest_concurrency;
#define VAR_DEST_CON_LIMIT "default_destination_concurrency_limit"
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19990510"
+#define DEF_MAIL_VERSION "Snapshot-19990513"
extern char *var_mail_version;
/* LICENSE
interpolation of <b>$user</b> (recipient username), <b>$home</b> (recip-
ient home directory), <b>$shell</b> (recipient shell), <b>$recipient</b>
(complete recipient address), <b>$extension</b> (recipient
- address extension), <b>$domain</b> (recipient domain), <b>mailbox</b>
+ address extension), <b>$domain</b> (recipient domain), <b>local</b>
(entire recipient address localpart) and <b>$recipient</b><i>_</i><b>delim-</b>
<b>iter.</b> The forms <i>${name?value}</i> and <i>${name:value}</i> expand
conditionally to <i>value</i> when <i>$name</i> is (is not) defined.
<b>LOGNAME</b>
The bare recipient name.
- The <b>PATH</b> environment variable is always reset to a system-
- dependent default path, and the <b>TZ</b> (time zone) environment
- variable is always passed on without change.
+ <b>LOCAL</b> The entire recipient address localpart (text to the
+ left of the rightmost @ character).
- The current working directory is the mail queue directory.
+ <b>RECIPIENT</b>
+ The entire recipient address.
- The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
- lope header to each message, prepends a <b>Delivered-To:</b>
+ The <b>PATH</b> environment variable is always reset to a system-
+ dependent default path, and the <b>TZ</b> (time zone) environment
LOCAL(8) LOCAL(8)
- header with the recipient envelope address, prepends a
- <b>Return-Path:</b> header with the sender envelope address, and
+ variable is always passed on without change.
+
+ The current working directory is the mail queue directory.
+
+ The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
+ lope header to each message, prepends a <b>Delivered-To:</b>
+ header with the recipient envelope address, prepends a
+ <b>Return-Path:</b> header with the sender envelope address, and
appends an empty line.
<b>EXTERNAL</b> <b>FILE</b> <b>DELIVERY</b>
- The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
- delivery to external files. The default setting (<b>alias,</b>
- <b>forward</b>) forbids file destinations in <b>:include:</b> files.
+ The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
+ delivery to external files. The default setting (<b>alias,</b>
+ <b>forward</b>) forbids file destinations in <b>:include:</b> files.
Specify a pathname ending in <b>/</b> for <b>qmail</b>-compatible
<b>maildir</b> delivery.
The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
- lope header to each message, prepends a <b>Delivered-To:</b>
- header with the recipient envelope address, prepends a >
- character to lines beginning with "<b>From</b> ", and appends an
- empty line. The envelope sender address is available in
- the <b>Return-Path:</b> header. When the destination is a regu-
+ lope header to each message, prepends a <b>Delivered-To:</b>
+ header with the recipient envelope address, prepends a >
+ character to lines beginning with "<b>From</b> ", and appends an
+ empty line. The envelope sender address is available in
+ the <b>Return-Path:</b> header. When the destination is a regu-
lar file, it is locked for exclusive access while delivery
is in progress. In case of problems, an attempt is made to
truncate a regular file to its original length.
In the case of <b>maildir</b> delivery, the local daemon prepends
- a <b>Delivered-To:</b> header with the envelope recipient
- address. The envelope sender address is available in the
+ a <b>Delivered-To:</b> header with the envelope recipient
+ address. The envelope sender address is available in the
<b>Return-Path:</b> header.
<b>ADDRESS</b> <b>EXTENSION</b>
- The optional <b>recipient</b><i>_</i><b>delimiter</b> configuration parameter
- specifies how to separate address extensions from local
+ The optional <b>recipient</b><i>_</i><b>delimiter</b> configuration parameter
+ specifies how to separate address extensions from local
recipient names.
- For example, with "<b>recipient</b><i>_</i><b>delimiter</b> <b>=</b> <b>+</b>", mail for
- <i>name</i>+<i>foo</i> is delivered to the alias <i>name</i>+<i>foo</i> or to the
- alias <i>name</i>, to the destinations listed in ~<i>name</i>/.<b>for-</b>
+ For example, with "<b>recipient</b><i>_</i><b>delimiter</b> <b>=</b> <b>+</b>", mail for
+ <i>name</i>+<i>foo</i> is delivered to the alias <i>name</i>+<i>foo</i> or to the
+ alias <i>name</i>, to the destinations listed in ~<i>name</i>/.<b>for-</b>
<b>ward</b>+<i>foo</i> or in ~<i>name</i>/.<b>forward</b>, to the mailbox owned by the
user <i>name</i>, or it is sent back as undeliverable.
- In all cases the <b>local</b> daemon prepends a `<b>Delivered-To:</b>
+ In all cases the <b>local</b> daemon prepends a `<b>Delivered-To:</b>
<i>name</i>+<i>foo</i>' header line.
<b>DELIVERY</b> <b>RIGHTS</b>
- Deliveries to external files and external commands are
+ Deliveries to external files and external commands are
made with the rights of the receiving user on whose behalf
- the delivery is made. In the absence of a user context,
- the <b>local</b> daemon uses the owner rights of the <b>:include:</b>
+ the delivery is made. In the absence of a user context,
+ the <b>local</b> daemon uses the owner rights of the <b>:include:</b>
file or alias database. When those files are owned by the
superuser, delivery is made with the rights specified with
the <b>default</b><i>_</i><b>privs</b> configuration parameter.
-<b>STANDARDS</b>
- RFC 822 (ARPA Internet Text Messages)
-
-<b>DIAGNOSTICS</b>
- Problems and transactions are logged to <b>syslogd</b>(8).
-
4
LOCAL(8) LOCAL(8)
- Corrupted message files are marked so that the queue man-
- ager can move them to the <b>corrupt</b> queue afterwards.
+<b>STANDARDS</b>
+ RFC 822 (ARPA Internet Text Messages)
+
+<b>DIAGNOSTICS</b>
+ Problems and transactions are logged to <b>syslogd</b>(8). Cor-
+ rupted message files are marked so that the queue manager
+ can move them to the <b>corrupt</b> queue afterwards.
- Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
- the postmaster is notified of bounces and of other trou-
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
ble.
<b>BUGS</b>
- For security reasons, the message delivery status of
- external commands or of external files is never check-
+ For security reasons, the message delivery status of
+ external commands or of external files is never check-
pointed to file. As a result, the program may occasionally
deliver more than once to a command or external file. Bet-
ter safe than sorry.
- Mutually-recursive aliases or ~/.<b>forward</b> files are not
- detected early. The resulting mail forwarding loop is
+ Mutually-recursive aliases or ~/.<b>forward</b> files are not
+ detected early. The resulting mail forwarding loop is
broken by the use of the <b>Delivered-To:</b> message header.
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
- to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values. Use the <b>postfix</b> <b>reload</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change.
<b>Miscellaneous</b>
ject to <i>$name</i> expansion.
<b>local</b><i>_</i><b>command</b><i>_</i><b>shell</b>
- Shell to use for external command execution (for
- example, /some/where/smrsh -c). When a shell is
+ Shell to use for external command execution (for
+ example, /some/where/smrsh -c). When a shell is
specified, it is invoked even when the command con-
- tains no shell built-in commands or meta charac-
+ tains no shell built-in commands or meta charac-
ters.
<b>owner</b><i>_</i><b>request</b><i>_</i><b>special</b>
<b>Mailbox</b> <b>delivery</b>
<b>fallback</b><i>_</i><b>transport</b>
Message transport for recipients that are not found
- in the UNIX passwd database. This parameter over-
- rides <b>luser</b><i>_</i><b>relay</b>.
-
- <b>home</b><i>_</i><b>mailbox</b>
- Pathname of a mailbox relative to a user's home
LOCAL(8) LOCAL(8)
+ in the UNIX passwd database. This parameter over-
+ rides <b>luser</b><i>_</i><b>relay</b>.
+
+ <b>home</b><i>_</i><b>mailbox</b>
+ Pathname of a mailbox relative to a user's home
directory. Specify a path ending in <b>/</b> for maildir-
style delivery.
<b>luser</b><i>_</i><b>relay</b>
- Destination (<i>@domain</i> or <i>address</i>) for non-existent
- users. The <i>address</i> is subjected to <i>$name</i> expan-
+ Destination (<i>@domain</i> or <i>address</i>) for non-existent
+ users. The <i>address</i> is subjected to <i>$name</i> expan-
sion.
<b>mail</b><i>_</i><b>spool</b><i>_</i><b>directory</b>
- Directory with UNIX-style mailboxes. The default
+ Directory with UNIX-style mailboxes. The default
pathname is system dependent.
<b>mailbox</b><i>_</i><b>command</b>
- External command to use for mailbox delivery. The
+ External command to use for mailbox delivery. The
command executes with the recipient privileges
- (exception: root). The string is subject to $name
+ (exception: root). The string is subject to $name
expansions.
<b>mailbox</b><i>_</i><b>transport</b>
- Message transport to use for mailbox delivery to
+ Message transport to use for mailbox delivery to
all local recipients, whether or not they are found
- in the UNIX passwd database. This parameter over-
- rides all other configuration parameters that con-
+ in the UNIX passwd database. This parameter over-
+ rides all other configuration parameters that con-
trol mailbox delivery, including <b>luser</b><i>_</i><b>relay</b>.
<b>Locking</b> <b>controls</b>
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
- Limit the number of attempts to acquire an exclu-
+ Limit the number of attempts to acquire an exclu-
sive lock on a mailbox or external file.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
- Time in seconds between successive attempts to
+ Time in seconds between successive attempts to
acquire an exclusive lock.
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
<b>Resource</b> <b>controls</b>
<b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>
- Limit the amount of time for delivery to external
+ Limit the amount of time for delivery to external
command.
<b>duplicate</b><i>_</i><b>filter</b><i>_</i><b>limit</b>
- Limit the size of the duplicate filter for results
+ Limit the size of the duplicate filter for results
from alias etc. expansion.
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
- Limit the amount of memory used for processing a
+ Limit the amount of memory used for processing a
partial input line.
- <b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
- Limit the number of parallel deliveries to the same
- user. The default limit is taken from the
- <b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
-
6
LOCAL(8) LOCAL(8)
+ <b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
+ Limit the number of parallel deliveries to the same
+ user. The default limit is taken from the
+ <b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
+
<b>local</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the number of recipients per message deliv-
- ery. The default limit is taken from the
+ Limit the number of recipients per message deliv-
+ ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Security</b> <b>controls</b>
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>commands</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
command.
<b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b>
- Restrict the usage of mail delivery to external
+ Restrict the usage of mail delivery to external
file.
<b>command</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
- What characters are allowed to appear in $name
- expansions of mailbox_command. Illegal characters
+ What characters are allowed to appear in $name
+ expansions of mailbox_command. Illegal characters
are replaced by underscores.
<b>default</b><i>_</i><b>privs</b>
- Default rights for delivery to external file or
+ Default rights for delivery to external file or
command.
<b>HISTORY</b>
- The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
Daniel Bernstein.
- The <i>maildir</i> structure appears in the <b>qmail</b> system by
+ The <i>maildir</i> structure appears in the <b>qmail</b> system by
Daniel Bernstein.
<b>SEE</b> <b>ALSO</b>
<a href="qmgr.8.html">qmgr(8)</a> queue manager
<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>
-
-
-
-
-
7
port <b>2025</b>. Instead of a numerical port a symbolic name may be
used. Specify [] around the destination in order to disable MX lookups.
+ The error mailer can be used to bounce mail:
+
+ <b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliverable</b>
+
+ This causes all mail for <i>user</i>@<i>anything</i><b>foo.org</b>
+ to be bounced.
+
<b>CONFIGURATION</b> <b>PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant
to this topic. See the Postfix <b>main.cf</b> file for syntax
The Secure Mailer license must be distributed with this
software.
+
+
+
+ 2
+
+
+
+
+
+TRANSPORT(5) TRANSPORT(5)
+
+
<b>AUTHOR(S)</b>
Wietse Venema
IBM T.J. Watson Research
- 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
</pre> </body> </html>
/* output is captured for diagnostics purposes.
/* Duplicate commands for the same recipient are suppressed.
/* A limited amount of information is exported via the environment:
-/* HOME, SHELL, LOGNAME, USER, EXTENSION, and DOMAIN. The exported
+/* HOME, SHELL, LOGNAME, USER, EXTENSION, DOMAIN, RECIPIENT (entire
+/* address) and LOCAL (just the local part). The exported
/* information is censored with var_cmd_filter.
/*
/* Arguments:
env = argv_alloc(1);
if (usr_attr.home)
argv_add(env, "HOME", usr_attr.home, ARGV_END);
- argv_add(env, "LOGNAME", state.msg_attr.user, ARGV_END);
- argv_add(env, "USER", state.msg_attr.user, ARGV_END);
+ argv_add(env,
+ "LOGNAME", state.msg_attr.user,
+ "USER", state.msg_attr.user,
+ "RECIPIENT", state.msg_attr.recipient,
+ "LOCAL", state.msg_attr.local,
+ ARGV_END);
if (usr_attr.shell)
argv_add(env, "SHELL", usr_attr.shell, ARGV_END);
if (state.msg_attr.domain)
char *saved_forward_path;
char *lhs;
char *next;
- const char *forward_path;
int expand_status;
/*
MSG_LOG_STATE(myname, state);
/*
- * Skip this module if per-user forwarding is disabled. XXX We need to
- * extend the mail_conf_XXX() interface to request no expansion of $names
- * in the given value or in the default value.
+ * Skip this module if per-user forwarding is disabled.
*/
- if ((forward_path = mail_conf_lookup(VAR_FORWARD_PATH)) == 0)
- forward_path = DEF_FORWARD_PATH;
- if (*forward_path == 0)
+ if (*var_forward_path == 0)
return (NO);
- /*
- * DUPLICATE/LOOP ELIMINATION
- *
- * If this user includes (an alias of) herself in her own .forward file,
- * deliver to the user instead.
- */
- if (been_here(state.dup_filter, "forward %s", state.msg_attr.local))
- return (NO);
- state.msg_attr.exp_from = state.msg_attr.local;
-
/*
* Skip non-existing users. The mailbox delivery routine will catch the
* error.
* be this user and 2) mail forwarded to other local users will be
* resubmitted as a new queue file.
*/
- state.msg_attr.owner = state.msg_attr.recipient;
+ state.msg_attr.owner = state.msg_attr.user;
/*
* Search the forward_path for an existing forward file.
status = 0;
path = vstring_alloc(100);
- saved_forward_path = mystrdup(forward_path);
+ saved_forward_path = mystrdup(var_forward_path);
next = saved_forward_path;
lookup_status = -1;
* .forward file as the user. Ignore files that aren't regular files,
* files that are owned by the wrong user, or files that have world write
* permission enabled.
+ *
+ * DUPLICATE/LOOP ELIMINATION
+ *
+ * If this user includes (an alias of) herself in her own .forward file,
+ * deliver to the user instead.
*/
- if (lookup_status >= 0) {
+ if (lookup_status >= 0
+ && been_here(state.dup_filter, "forward %s", STR(path)) == 0) {
+ state.msg_attr.exp_from = state.msg_attr.local;
if (S_ISREG(st.st_mode) == 0) {
msg_warn("file %s is not a regular file", STR(path));
} else if (st.st_uid != 0 && st.st_uid != usr_attr.uid) {
/* \fB$user\fR (recipient username), \fB$home\fR (recipient home
/* directory), \fB$shell\fR (recipient shell), \fB$recipient\fR
/* (complete recipient address), \fB$extension\fR (recipient address
-/* extension), \fB$domain\fR (recipient domain), \fBmailbox\fR
+/* extension), \fB$domain\fR (recipient domain), \fBlocal\fR
/* (entire recipient address localpart) and
/* \fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and
/* \fI${name:value}\fR expand conditionally to \fIvalue\fR when
/* The recipient address domain part.
/* .IP \fBLOGNAME\fR
/* The bare recipient name.
+/* .IP \fBLOCAL\fR
+/* The entire recipient address localpart (text to the left of the
+/* rightmost @ character).
+/* .IP \fBRECIPIENT\fR
+/* The entire recipient address.
/* .PP
/* The \fBPATH\fR environment variable is always reset to a
/* system-dependent default path, and the \fBTZ\fR (time zone)
VAR_ALLOW_FILES, DEF_ALLOW_FILES, &var_allow_files, 0, 0,
VAR_RCPT_FDELIM, DEF_RCPT_FDELIM, &var_rcpt_fdelim, 0, 0,
VAR_LOCAL_CMD_SHELL, DEF_LOCAL_CMD_SHELL, &var_local_cmd_shell, 0, 0,
- VAR_LUSER_RELAY, DEF_LUSER_RELAY, &var_luser_relay, 0, 0,
VAR_MAIL_SPOOL_DIR, DEF_MAIL_SPOOL_DIR, &var_mail_spool_dir, 0, 0,
VAR_MAILBOX_TRANSP, DEF_MAILBOX_TRANSP, &var_mailbox_transport, 0, 0,
VAR_FALLBACK_TRANSP, DEF_FALLBACK_TRANSP, &var_fallback_transport, 0, 0,
/* The recipient address extension.
/* .IP home
/* The recipient home directory.
-/* .IP mailbox
-/* The full recipient address localpart.
+/* .IP local
+/* The entire recipient address localpart.
/* .IP recipient
-/* The full recipient address.
+/* The entire recipient address.
/* .IP recipient_delimiter
/* The recipient delimiter.
/* .IP shell
return (local->usr_attr->shell);
} else if (STREQ(name, "domain")) {
return (local->state->msg_attr.domain);
+ } else if (STREQ(name, "local")) {
+ return (local->state->msg_attr.local);
} else if (STREQ(name, "mailbox")) {
return (local->state->msg_attr.local);
} else if (STREQ(name, "recipient")) {
* recipient domain is local, so we only have to compare local parts.
*/
if (state.msg_attr.owner != 0
- && strncasecmp(state.msg_attr.owner, state.msg_attr.recipient,
- strlen(state.msg_attr.local) + 1) != 0)
+ && strcasecmp(state.msg_attr.owner, state.msg_attr.user) != 0)
return (deliver_indirect(state));
/*
/*
* Duplicate filter.
*/
- if (been_here(state.dup_filter, "recipient %s", state.msg_attr.recipient))
+ if (been_here(state.dup_filter, "recipient %d %s",
+ state.level, state.msg_attr.recipient))
return (0);
/*
state.msg_attr.user = mystrdup(state.msg_attr.local);
if (*var_rcpt_delim) {
state.msg_attr.extension =
- split_addr(state.msg_attr.local, *var_rcpt_delim);
+ split_addr(state.msg_attr.user, *var_rcpt_delim);
if (state.msg_attr.extension && strchr(state.msg_attr.extension, '/')) {
msg_warn("%s: address with illegal extension: %s",
state.msg_attr.queue_id, state.msg_attr.local);
*/
tok822_rewrite(addr, REWRITE_CANON);
tok822_resolve(addr, &reply);
- state.msg_attr.recipient = STR(reply.recipient);
/*
* Splice in the optional unmatched address extension.
} else {
ext_len = strlen(state.msg_attr.unmatched);
VSTRING_SPACE(reply.recipient, ext_len + 2);
+ if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0)
+ msg_panic("%s: recipient @ botch", myname);
memmove(ratsign + ext_len + 1, ratsign, strlen(ratsign) + 1);
*ratsign = *var_rcpt_delim;
memcpy(ratsign + 1, state.msg_attr.unmatched, ext_len);
VSTRING_SKIP(reply.recipient);
}
}
+ state.msg_attr.recipient = STR(reply.recipient);
/*
* Delivery to a local or non-local address. For a while there was some
This directs mail for \fIuser\fR@\fBfoo.org\fR to host \fBbar.org\fR
port \fB2025\fR. Instead of a numerical port a symbolic name may be
used. Specify [] around the destination in order to disable MX lookups.
+
+The error mailer can be used to bounce mail:
+
+.ti +5
+\fB\&.foo.org error:mail for *.foo.org is not deliverable\fR
+
+This causes all mail for \fIuser\fR@\fIanything\fBfoo.org\fR
+to be bounced.
.SH CONFIGURATION PARAMETERS
.na
.nf
\fB$user\fR (recipient username), \fB$home\fR (recipient home
directory), \fB$shell\fR (recipient shell), \fB$recipient\fR
(complete recipient address), \fB$extension\fR (recipient address
-extension), \fB$domain\fR (recipient domain), \fBmailbox\fR
+extension), \fB$domain\fR (recipient domain), \fBlocal\fR
(entire recipient address localpart) and
\fB$recipient_delimiter.\fR The forms \fI${name?value}\fR and
\fI${name:value}\fR expand conditionally to \fIvalue\fR when
The recipient address domain part.
.IP \fBLOGNAME\fR
The bare recipient name.
+.IP \fBLOCAL\fR
+The entire recipient address localpart (text to the left of the
+rightmost @ character).
+.IP \fBRECIPIENT\fR
+The entire recipient address.
.PP
The \fBPATH\fR environment variable is always reset to a
system-dependent default path, and the \fBTZ\fR (time zone)
sent(message->queue_id, recipient->address,
"none", message->arrival_time, "discarded");
deliver_completed(message->fp, recipient->offset);
+ msg_warn("%s: undeliverable postmaster notification discarded",
+ message->queue_id);
continue;
}
}
* postmaster notices, this may be the only trace left that service was
* rejected. Print the request, client name/address, and response.
*/
- msg_info("%s: reject: %s from %s: %s",
- state->queue_id, state->where,
- state->namaddr, STR(error_text));
-
- /*
- * Log from/to information if available, for the benefit of the local
- * sysadmin.
- */
- if (state->sender) {
- msg_info(state->recipient ?
- "%s: reject: %s from %s: from=<%s> to=<%s>" :
- "%s: reject: %s from %s: from=<%s>",
- state->queue_id, state->where, state->namaddr,
- state->sender, state->recipient);
- }
+ msg_info(state->recipient ? "reject: %s from %s: %s; from=<%s> to=<%s>"
+ : state->sender ? "reject: %s from %s: %s; from=<%s>"
+ : "reject: %s from %s: %s",
+ state->where, state->namaddr, STR(error_text),
+ state->sender, state->recipient);
return (SMTPD_CHECK_REJECT);
}
if (msg_verbose)
msg_info("%s: %s %s %s", myname, table, value, datum);
+ /*
+ * DUNNO means skip this table.
+ */
+ if (strcasecmp(value, "DUNNO") == 0)
+ return (SMTPD_CHECK_DUNNO);
+
/*
* REJECT means NO. Generate a generic error response.
*/
/*
* Initialize.
*/
+ if (state->name == 0 && state->addr == 0)
+ return (0);
status = setjmp(smtpd_check_buf);
if (status != 0)
return (0);
/*
* Initialize.
*/
+ if (helohost == 0)
+ return (0);
status = setjmp(smtpd_check_buf);
if (status != 0)
return (0);
/*
* Initialize.
*/
+ if (sender == 0)
+ return (0);
status = setjmp(smtpd_check_buf);
if (status != 0)
return (0);
char *saved_recipient = state->recipient;
char *err;
+ /*
+ * Initialize.
+ */
+ if (recipient == 0)
+ return (0);
+
+ /*
+ * Minor kluge so that we can delegate work to the generic routine and so
+ * that we can syslog the recipient with the reject messages.
+ */
+ state->recipient = mystrdup(recipient);
+
+#define SMTPD_CHECK_RCPT_RETURN(x) { \
+ myfree(state->recipient); \
+ state->recipient = saved_recipient; \
+ return (x); \
+ }
+
/*
* Apply delayed restrictions.
*/
if ((err = smtpd_check_client(state)) != 0
|| (err = smtpd_check_helo(state, state->helo_name)) != 0
|| (err = smtpd_check_mail(state, state->sender)) != 0)
- return (err);
+ SMTPD_CHECK_RCPT_RETURN(err);
/*
- * Initialize.
+ * More initialization.
*/
status = setjmp(smtpd_check_buf);
if (status != 0)
- return (0);
+ SMTPD_CHECK_RCPT_RETURN(0);
/*
- * Apply restrictions in the order as specified. Minor kluge so that we
- * can delegate work to the generic routine.
+ * Apply restrictions in the order as specified.
*/
- state->recipient = mystrdup(recipient);
for (cpp = rcpt_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) {
status = check_mail_access(state, name, recipient,
if (status != 0)
break;
}
- myfree(state->recipient);
- state->recipient = saved_recipient;
- return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
+ SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
}
/* smtpd_check_etrn - validate ETRN request */
/*
* Initialize.
*/
+ if (domain == 0)
+ return (0);
status = setjmp(smtpd_check_buf);
if (status != 0)
return (0);
>>> client_restrictions permit_mynetworks,reject_unknown_client,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
-./smtpd_check: <queue id>: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
+./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> client random.bad.domain 123.123.123.123
-./smtpd_check: <queue id>: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client friend.bad.domain 123.123.123.123
OK
>>> client bad.domain 123.123.123.123
-./smtpd_check: <queue id>: reject: CONNECT from bad.domain[123.123.123.123]: 554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: reject: CONNECT from bad.domain[123.123.123.123]: 554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client wzv.win.tue.nl 131.155.210.17
OK
>>> client aa.win.tue.nl 131.155.210.18
-./smtpd_check: <queue id>: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
+./smtpd_check: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
>>> client_restrictions permit_mynetworks
OK
>>> client unknown 131.155.210.17
OK
>>> helo foo.
-./smtpd_check: <queue id>: reject: HELO from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
+./smtpd_check: reject: HELO from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client foo 123.123.123.123
OK
>>> helo foo.
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Helo command rejected: Host not found
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Helo command rejected: Host not found
450 <foo.>: Helo command rejected: Host not found
>>> helo foo
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo>: Helo command rejected: Host not found
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo>: Helo command rejected: Host not found
450 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
OK
>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
554 <random.bad.domain>: Helo command rejected: match bad.domain
>>> helo friend.bad.domain
OK
OK
>>> helo 123.123.123.123
./smtpd_check: warning: valid_hostname: numeric hostname: 123.123.123.123
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <123.123.123.123>: Helo command rejected: Host not found
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <123.123.123.123>: Helo command rejected: Host not found
450 <123.123.123.123>: Helo command rejected: Host not found
>>> helo_restrictions permit_naked_ip_address,reject_invalid_hostname,reject_unknown_hostname
OK
>>> client unknown 131.155.210.17
OK
>>> mail foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
-./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: from=<foo@watson.ibm.com>
+./smtpd_check: reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> mail foo@watson.ibm.com
OK
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain>
450 <foo@bad.domain>: Sender address rejected: Domain not found
>>> sender_restrictions hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail Reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <Reject@this.address>: Sender address rejected: match reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<Reject@this.address>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <Reject@this.address>: Sender address rejected: match reject@this.address; from=<Reject@this.address>
554 <Reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@Bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@Bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@Bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@Bad.domain>: Sender address rejected: match bad.domain; from=<foo@Bad.domain>
554 <foo@Bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> client unknown 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
-./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
-./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
-./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: from=<foo@friend.bad.domain>
+./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com; from=<foo@friend.bad.domain>
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
>>> #
>>> # Hybrids
>>> client foo 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> helo bad.domain
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo@friend.bad.domain>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain>
554 <bad.domain>: Helo command rejected: match bad.domain
>>> rcpt foo@porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@porcupine.org>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain> to=<foo@porcupine.org>
554 <bad.domain>: Helo command rejected: match bad.domain
>>> helo 131.155.210.17
./smtpd_check: warning: valid_hostname: numeric hostname: 131.155.210.17
>>> recipient_restrictions check_sender_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> rcpt foo@porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@bad.domain> to=<foo@porcupine.org>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> to=<foo@porcupine.org>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> rcpt wietse@wzv.win.tue.nl
OK
>>> rcpt wietse@trouble.org
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <wietse@trouble.org>: Recipient address rejected: Access denied
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@friend.bad.domain> to=<wietse@trouble.org>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <wietse@trouble.org>: Recipient address rejected: Access denied; from=<foo@friend.bad.domain> to=<wietse@trouble.org>
554 <wietse@trouble.org>: Recipient address rejected: Access denied
>>> rcpt wietse@porcupine.org
OK
>>> mail foo@good.domain
OK
>>> rcpt foo@porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@good.domain> to=<foo@porcupine.org>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@good.domain> to=<foo@porcupine.org>
554 <bad.domain>: Helo command rejected: match bad.domain
>>> helo good.domain
OK
>>> mail foo@bad.domain
OK
>>> rcpt foo@porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@bad.domain> to=<foo@porcupine.org>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> to=<foo@porcupine.org>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> #
>>> # FQDN restrictions
>>> helo foo.bar
OK
>>> helo foo
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 504 <foo>: Helo command rejected: need fully-qualified hostname
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo@bad.domain>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 504 <foo>: Helo command rejected: need fully-qualified hostname; from=<foo@bad.domain>
504 <foo>: Helo command rejected: need fully-qualified hostname
>>> mail foo@foo.bar.
OK
>>> mail foo@foo.bar
OK
>>> mail foo@foo
-./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 504 <foo@foo>: Sender address rejected: need fully-qualified address
-./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: from=<foo@foo>
+./smtpd_check: reject: MAIL from foo[131.155.210.17]: 504 <foo@foo>: Sender address rejected: need fully-qualified address; from=<foo@foo>
504 <foo@foo>: Sender address rejected: need fully-qualified address
>>> mail foo
-./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 504 <foo>: Sender address rejected: need fully-qualified address
-./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: MAIL from foo[131.155.210.17]: 504 <foo>: Sender address rejected: need fully-qualified address; from=<foo>
504 <foo>: Sender address rejected: need fully-qualified address
>>> rcpt foo@foo.bar.
OK
>>> rcpt foo@foo.bar
OK
>>> rcpt foo@foo
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 504 <foo@foo>: Recipient address rejected: need fully-qualified address
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo> to=<foo@foo>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 504 <foo@foo>: Recipient address rejected: need fully-qualified address; from=<foo> to=<foo@foo>
504 <foo@foo>: Recipient address rejected: need fully-qualified address
>>> rcpt foo
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 504 <foo>: Recipient address rejected: need fully-qualified address
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo> to=<foo>
+./smtpd_check: reject: RCPT from foo[131.155.210.17]: 504 <foo>: Recipient address rejected: need fully-qualified address; from=<foo> to=<foo>
504 <foo>: Recipient address rejected: need fully-qualified address
>>> #
>>> # Numerical HELO checks
>>> helo [321.255.255.255]
./smtpd_check: reject_invalid_hostaddr: [321.255.255.255]
./smtpd_check: warning: valid_hostaddr: invalid octet value: 321.255.255.255
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[321.255.255.255]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[321.255.255.255]>: Helo command rejected: invalid ip address; from=<foo>
501 <[321.255.255.255]>: Helo command rejected: invalid ip address
>>> helo [0.255.255.255]
./smtpd_check: reject_invalid_hostaddr: [0.255.255.255]
./smtpd_check: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[0.255.255.255]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[0.255.255.255]>: Helo command rejected: invalid ip address; from=<foo>
501 <[0.255.255.255]>: Helo command rejected: invalid ip address
>>> helo [1.2.3.321]
./smtpd_check: reject_invalid_hostaddr: [1.2.3.321]
./smtpd_check: warning: valid_hostaddr: invalid octet value: 1.2.3.321
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.321]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.321]>: Helo command rejected: invalid ip address; from=<foo>
501 <[1.2.3.321]>: Helo command rejected: invalid ip address
>>> helo [1.2.3]
./smtpd_check: reject_invalid_hostaddr: [1.2.3]
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3]>: Helo command rejected: invalid ip address; from=<foo>
501 <[1.2.3]>: Helo command rejected: invalid ip address
>>> helo [1.2.3.4.5]
./smtpd_check: reject_invalid_hostaddr: [1.2.3.4.5]
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address; from=<foo>
501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address
>>> helo [1..2.3.4]
./smtpd_check: reject_invalid_hostaddr: [1..2.3.4]
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1..2.3.4
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1..2.3.4]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1..2.3.4]>: Helo command rejected: invalid ip address; from=<foo>
501 <[1..2.3.4]>: Helo command rejected: invalid ip address
>>> helo [.1.2.3.4]
./smtpd_check: reject_invalid_hostaddr: [.1.2.3.4]
./smtpd_check: warning: valid_hostaddr: misplaced dot: .1.2.3.4
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[.1.2.3.4]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[.1.2.3.4]>: Helo command rejected: invalid ip address; from=<foo>
501 <[.1.2.3.4]>: Helo command rejected: invalid ip address
>>> helo [1.2.3.4.5.]
./smtpd_check: reject_invalid_hostaddr: [1.2.3.4.5.]
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address; from=<foo>
501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address
>>> helo 1.2.3.4
./smtpd_check: reject_invalid_hostaddr: 1.2.3.4
>>> helo 321.255.255.255
./smtpd_check: reject_invalid_hostaddr: 321.255.255.255
./smtpd_check: warning: valid_hostaddr: invalid octet value: 321.255.255.255
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <321.255.255.255>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <321.255.255.255>: Helo command rejected: invalid ip address; from=<foo>
501 <321.255.255.255>: Helo command rejected: invalid ip address
>>> helo 0.255.255.255
./smtpd_check: reject_invalid_hostaddr: 0.255.255.255
./smtpd_check: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <0.255.255.255>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <0.255.255.255>: Helo command rejected: invalid ip address; from=<foo>
501 <0.255.255.255>: Helo command rejected: invalid ip address
>>> helo 1.2.3.321
./smtpd_check: reject_invalid_hostaddr: 1.2.3.321
./smtpd_check: warning: valid_hostaddr: invalid octet value: 1.2.3.321
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.321>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.321>: Helo command rejected: invalid ip address; from=<foo>
501 <1.2.3.321>: Helo command rejected: invalid ip address
>>> helo 1.2.3
./smtpd_check: reject_invalid_hostaddr: 1.2.3
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3>: Helo command rejected: invalid ip address; from=<foo>
501 <1.2.3>: Helo command rejected: invalid ip address
>>> helo 1.2.3.4.5
./smtpd_check: reject_invalid_hostaddr: 1.2.3.4.5
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5>: Helo command rejected: invalid ip address; from=<foo>
501 <1.2.3.4.5>: Helo command rejected: invalid ip address
>>> helo 1..2.3.4
./smtpd_check: reject_invalid_hostaddr: 1..2.3.4
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1..2.3.4
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1..2.3.4>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1..2.3.4>: Helo command rejected: invalid ip address; from=<foo>
501 <1..2.3.4>: Helo command rejected: invalid ip address
>>> helo .1.2.3.4
./smtpd_check: reject_invalid_hostaddr: .1.2.3.4
./smtpd_check: warning: valid_hostaddr: misplaced dot: .1.2.3.4
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <.1.2.3.4>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <.1.2.3.4>: Helo command rejected: invalid ip address; from=<foo>
501 <.1.2.3.4>: Helo command rejected: invalid ip address
>>> helo 1.2.3.4.5.
./smtpd_check: reject_invalid_hostaddr: 1.2.3.4.5.
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address
-./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
+./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address; from=<foo>
501 <1.2.3.4.5.>: Helo command rejected: invalid ip address
>>> client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
-./smtpd_check: <queue id>: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
+./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> client random.bad.domain 123.123.123.123
-./smtpd_check: <queue id>: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client friend.bad.domain 123.123.123.123
OK
>>> client bad.domain 123.123.123.123
-./smtpd_check: <queue id>: reject: CONNECT from bad.domain[123.123.123.123]: 554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: reject: CONNECT from bad.domain[123.123.123.123]: 554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client wzv.win.tue.nl 131.155.210.17
OK
>>> client aa.win.tue.nl 131.155.210.18
-./smtpd_check: <queue id>: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
+./smtpd_check: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
>>> client_restrictions permit_mynetworks
OK
>>> client unknown 131.155.210.17
OK
>>> helo foo.
-./smtpd_check: <queue id>: reject: HELO from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
+./smtpd_check: reject: HELO from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client foo 123.123.123.123
OK
>>> helo foo.
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Helo command rejected: Host not found
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Helo command rejected: Host not found
450 <foo.>: Helo command rejected: Host not found
>>> helo foo
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo>: Helo command rejected: Host not found
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo>: Helo command rejected: Host not found
450 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
OK
>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
554 <random.bad.domain>: Helo command rejected: match bad.domain
>>> helo friend.bad.domain
OK
>>> client unknown 131.155.210.17
OK
>>> mail foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
-./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: from=<foo@watson.ibm.com>
+./smtpd_check: reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> mail foo@watson.ibm.com
OK
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found; from=<foo@bad.domain>
450 <foo@bad.domain>: Sender address rejected: Domain not found
>>> sender_restrictions check_sender_access,hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail Reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <Reject@this.address>: Sender address rejected: match reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<Reject@this.address>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <Reject@this.address>: Sender address rejected: match reject@this.address; from=<Reject@this.address>
554 <Reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@Bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@Bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@Bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@Bad.domain>: Sender address rejected: match bad.domain; from=<foo@Bad.domain>
554 <foo@Bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> client unknown 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
-./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
-./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
+./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied; from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_recipient_access,hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
-./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
+./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
-./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
-./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: from=<foo@friend.bad.domain>
+./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com; from=<foo@friend.bad.domain>
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
>>> #
>>> # unknown sender/recipient domain
>>> rcpt wietse@porcupine.org
OK
>>> rcpt wietse@no.recipient.domain
-./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.recipient.domain>: Recipient address rejected: Domain not found
-./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: from=<wietse@porcupine.org> to=<wietse@no.recipient.domain>
+./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.recipient.domain>: Recipient address rejected: Domain not found; from=<wietse@porcupine.org> to=<wietse@no.recipient.domain>
554 <wietse@no.recipient.domain>: Recipient address rejected: Domain not found
>>> mail wietse@no.sender.domain
OK
>>> rcpt wietse@porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.sender.domain>: Sender address rejected: Domain not found
-./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: from=<wietse@no.sender.domain> to=<wietse@porcupine.org>
+./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.sender.domain>: Sender address rejected: Domain not found; from=<wietse@no.sender.domain> to=<wietse@porcupine.org>
554 <wietse@no.sender.domain>: Sender address rejected: Domain not found
* Utility library.
*/
#include <vstream.h>
-#include <vstring.h>
/*
* Generic dictionary interface - in reality, a dictionary extends this
return status;
}
-
-
/* dict_db_close - close data base */
static void dict_db_close(DICT *dict)
dict_ldap->server_host =
mystrdup((char *) get_mail_conf_str(vstring_str(config_param),
- "localhost", 0, 0));
+ "localhost", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->server_host);
vstring_sprintf(config_param, "%s_result_attribute", ldapsource);
dict_ldap->result_attribute =
mystrdup((char *) get_mail_conf_str(vstring_str(config_param),
- "maildrop", 0, 0));
+ "maildrop", 0, 0));
if (msg_verbose)
msg_info("%s: %s is %s", myname, vstring_str(config_param),
dict_ldap->result_attribute);
if (ret < 0) {
if (ret == PCRE_ERROR_NOSUBSTRING)
msg_fatal("regexp %s, line %d: replace index out of range",
- ctxt->dict_name, ctxt->lineno);
+ ctxt->dict_name, ctxt->lineno);
else
msg_fatal("regexp %s, line %d: pcre_get_substring error: %d",
- ctxt->dict_name, ctxt->lineno, ret);
+ ctxt->dict_name, ctxt->lineno, ret);
}
- if (*pp == 0)
+ if (*pp == 0) {
+ myfree((char *) pp);
return (MAC_PARSE_UNDEF);
+ }
vstring_strcat(ctxt->buf, pp);
+ myfree((char *) pp);
+ return (0);
} else
/* Straight text - duplicate with no substitution */
vstring_strcat(ctxt->buf, vstring_str(buf));
if (pcre_list->replace)
myfree((char *) pcre_list->replace);
}
+ myfree(dict_pcre->map);
myfree((char *) dict_pcre);
}
+++ /dev/null
-/* mac_expand_update_va - update engine */
-
-static MAC_EXP *mac_expand_update_va(MAC_EXP *mc, int key, va_list ap)
-{
- HTABLE_INFO **ht_info;
- HTABLE_INFO **ht;
- HTABLE *table;
- char *name;
- char *value;
-
-#define HTABLE_CLOBBER(t, n, v) do { \
- HTABLE_INFO *_ht; \
- if ((_ht = htable_locate(t, n)) != 0) \
- _ht->value = v; \
- else \
- htable_enter(t, n, v); \
- } while(0);
-
- /*
- * Optionally create expansion context.
- */
- if (mc == 0) {
- mc = (MAC_EXP *) mymalloc(sizeof(*mc));
- mc->table = htable_create(0);
- mc->result = 0;
- mc->flags = 0;
- mc->filter = 0;
- mc->clobber = '_';
- mc->level = 0;
- }
-
- /*
- * Stash away the attributes.
- */
- for ( /* void */ ; key != 0; key = va_arg(ap, int)) {
- switch (key) {
- case MAC_EXP_ARG_ATTR:
- name = va_arg(ap, char *);
- value = va_arg(ap, char *);
- HTABLE_CLOBBER(mc->table, name, value);
- break;
- case MAC_EXP_ARG_TABLE:
- table = va_arg(ap, HTABLE *);
- ht_info = htable_list(table);
- for (ht = ht_info; *ht; ht++)
- HTABLE_CLOBBER(mc->table, ht[0]->key, ht[0]->value);
- myfree((char *) ht_info);
- break;
- case MAC_EXP_ARG_FILTER:
- mc->filter = va_arg(ap, char *);
- break;
- case MAC_EXP_ARG_CLOBBER:
- mc->clobber = va_arg(ap, int);
- break;
- }
- }
- return (mc);
-}
-
-/* mac_expand_update - update or create macro expansion context */
-
-MAC_EXP *mac_expand_update(MAC_EXP *mc, int key,...)
-{
- va_list ap;
-
- va_start(ap, key);
- mc = mac_expand_update(mc, key, ap);
- va_end(ap);
- return (mc);
-}
-
-/* .IP key
-/* The attribute information is specified as a null-terminated list.
-/* Attributes are defined left to right; only the last definition
-/* of an attribute is remembered.
-/* The following keys are understood (types of arguments indicated
-/* in parentheses):
-/* .RS
-/* .IP "MAC_EXP_ARG_ATTR (char *, char *)"
-/* The next two arguments specify an attribute name and its attribute
-/* string value. Specify a null string value for an attribute that is
-/* known but unset. Attribute string values are not copied.
-/* .IP "MAC_EXP_ARG_TABLE (HTABLE *)"
-/* The next argument is a hash table with attribute names and values.
-/* Specify a null string value for an attribute that is known but unset.
-/* Attribute string values are not copied.
-/* .RE
-/* .IP MAC_EXP_ARG_END
-/* A manifest constant that indicates the end of the argument list.
stat=2 result=|name1-value||
<< $(name1
unknown: warning: truncated macro reference: "$(name1"
-stat=1 result=name1-value
+stat=1 result=
<< $(name )
unknown: warning: macro name syntax error: "name "
stat=1 result=
if (*ep == close_paren[pp - open_paren])
level--;
}
+ if (status & MAC_PARSE_ERROR)
+ break;
vstring_strncat(buf, vp, level > 0 ? ep - vp : ep - vp - 1);
vp = ep;
} else { /* plain $x */