added support for read timeouts, and added a missing exception
handler for the 220 server greeting. File: smtpstone/smtp-sink.c.
+20050506
+
+ Cleanup: with "REJECT 4.X.Y ..." actions in header/body_checks,
+ change the SMTP server reply code from 550 into 450, instead
+ of having the SMTP server change the DSN into 5.X.Y. File:
+ smtpd/smtpd.c.
+
+20050510
+
+ Usability: when reporting a sender address problem, transform
+ a recipient DSN status (e.g., 4.1.1-4.1.6) into the
+ corresponding sender DSN status, and vice versa; and when
+ reporting a non-address problem, transform a sender or
+ recipient DSN status into a generic non-address DSN status
+ (e.g., 4.0.0). This transformation may be needed when the
+ same access table or RBL reply template are used for client,
+ helo, sender, or recipient restrictions; or when the same
+ error mailer information is used for senders or recipients.
+ Files: smtpd/smtpd_check.c, smtpd/smtpd_dsn_fix.[hc].
+
Open problems:
Med: disable header address rewriting after XCLIENT?
I\bIn\bnt\btr\bro\bod\bdu\buc\bct\bti\bio\bon\bn
Postfix 2.2 introduces support for the IPv6 (IP version 6) protocol. IPv6
-support older Postfix versions was available as an add-on patch. The section
-"Compatibility with Postfix <2.2 IPv6 support" below discusses the differences
-between these implementations.
+support for older Postfix versions was available as an add-on patch. The
+section "Compatibility with Postfix <2.2 IPv6 support" below discusses the
+differences between these implementations.
The main feature of interest is that IPv6 uses 128-bit IP addresses instead of
the 32-bit addresses used by IPv4. It can therefore accommodate a much larger
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
+Major changes with snapshot 20050510
+====================================
+
+This release improves usability of DSN (enhanced status codes) in
+Postfix access tables, RBL reply templates and in transport maps
+that use the error(8) delivery agent.
+
+- When the SMTP server rejects a sender address, it transforms a
+ recipient DSN status (e.g., 4.1.1-4.1.6) into the corresponding
+ sender DSN status, and vice versa.
+
+- When the SMTP server rejects non-address information (such as the
+ HELO command parameter or the client hostname/address), it
+ transforms a sender or recipient DSN status into a generic
+ non-address DSN status (e.g., 4.0.0).
+
+These transformations are needed when the same access table or RBL
+reply template are used for client, helo, sender, or recipient
+restrictions; or when the same error(8) mailer information is used
+for both senders and recipients.
+
Incompatibility with snapshot 20050503
======================================
# codes. 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.
+# 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".
#
# REJECT optional text...
-# Reject the address etc. that matches the pattern.
-# Reply with $reject_code optional text... when the
-# optional text is specified, otherwise reply with a
+# Reject the address etc. that matches the pattern.
+# Reply with $reject_code optional text... when the
+# optional text is specified, otherwise reply with a
# generic error response message.
#
# DEFER_IF_REJECT optional text...
-# Defer the request if some later restriction would
+# Defer the request if some later restriction would
# result in a REJECT action. Reply with "450 optional
# text... when the optional text is specified, other-
# wise reply with a generic error response message.
# 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 "450 optional text... when the optional
-# text is specified, otherwise reply with a generic
+# Defer the request if some later restriction would
+# result in a an explicit or implicit PERMIT action.
+# Reply with "450 optional text... when the optional
+# text is specified, otherwise reply with a generic
# error response message.
#
# This feature is available in Postfix 2.1 and later.
# reject_unauth_destination, and so on).
#
# 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
+# Note: this action currently affects all recipients
# of the message.
#
# 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:destination syntax is described in
-# the transport(5) manual page. More information
-# about external content filters is in the Postfix
+# The transport:destination syntax is described in
+# the transport(5) manual page. More information
+# about external content filters is in the Postfix
# FILTER_README file.
#
-# Note: this action overrides the main.cf con-
+# Note: this action overrides the main.cf con-
# tent_filter setting, and currently affects all
# recipients of the message.
#
# 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.
#
-# 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-
+# Prepend the specified message header to the mes-
# sage. When this action is used multiple times, the
-# first prepended header appears before the second
+# first prepended header appears before the second
# etc. prepended header.
#
-# Note: this action does not support multi-line mes-
+# Note: this action does not support multi-line mes-
# sage headers.
#
# 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
+# When an enhanced status code is specified in an access ta-
+# ble, it is subject to modification. The following trans-
+# formations are needed when the same access table is used
+# for client, helo, sender, or recipient access restric-
+# tions:
+#
+# o When rejecting a sender address, the Postfix SMTP
+# server will transform a recipient DSN status (e.g.,
+# 4.1.1-4.1.6) into the corresponding sender DSN sta-
+# tus, and vice versa.
+#
+# o When rejecting non-address information (such as the
+# HELO command argument or the client host-
+# name/address), the Postfix SMTP server will trans-
+# form 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
# the table is given in the form of regular expressions. For
<h2>Introduction</h2>
<p> Postfix 2.2 introduces support for the IPv6 (IP version 6)
-protocol. IPv6 support older Postfix versions was available as an
-add-on patch. The section "<a href="#compat">Compatibility with
+protocol. IPv6 support for older Postfix versions was available as
+an add-on patch. The section "<a href="#compat">Compatibility with
Postfix <2.2 IPv6 support</a>" below discusses the differences
between these implementations. </p>
codes. 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.
+ 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".
<b>REJECT</b> <i>optional text...</i>
- Reject the address etc. that matches the pattern.
- Reply with <i>$reject</i><b>_</b><i>code optional text...</i> when the
- optional text is specified, otherwise reply with a
+ Reject the address etc. that matches the pattern.
+ Reply with <i>$reject</i><b>_</b><i>code optional text...</i> when the
+ optional text is specified, otherwise reply with a
generic error response message.
<b>DEFER_IF_REJECT</b> <i>optional text...</i>
- Defer the request if some later restriction would
+ Defer the request if some later restriction would
result in a REJECT action. Reply with "<b>450</b> <i>optional</i>
<i>text...</i> when the optional text is specified, other-
wise reply with a generic error response message.
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>450</b> <i>optional text...</i> when the optional
- text is specified, otherwise reply with a generic
+ Defer the request if some later restriction would
+ result in a an explicit or implicit PERMIT action.
+ Reply with "<b>450</b> <i>optional text...</i> when the optional
+ text is specified, otherwise reply with a generic
error response message.
This feature is available in Postfix 2.1 and later.
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a></b>, and so on).
<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
+ Note: this action currently affects all recipients
of the message.
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:destination</i> syntax is described in
- the <a href="transport.5.html"><b>transport</b>(5)</a> manual page. More information
- about external content filters is in the Postfix
+ The <i>transport:destination</i> syntax is described in
+ the <a href="transport.5.html"><b>transport</b>(5)</a> manual page. More information
+ about external content filters is in the Postfix
<a href="FILTER_README.html">FILTER_README</a> file.
- Note: this action overrides the <b>main.cf <a href="postconf.5.html#content_filter">con</a>-</b>
+ Note: this action overrides the <b>main.cf <a href="postconf.5.html#content_filter">con</a>-</b>
<b><a href="postconf.5.html#content_filter">tent_filter</a></b> setting, and currently affects all
recipients of the message.
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.
- 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-
+ Prepend the specified message header to the mes-
sage. When this action is used multiple times, the
- first prepended header appears before the second
+ first prepended header appears before the second
etc. prepended header.
- Note: this action does not support multi-line mes-
+ Note: this action does not support multi-line mes-
sage headers.
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>
+ When an enhanced status code is specified in an access ta-
+ ble, it is subject to modification. The following trans-
+ formations are needed when the same access table is used
+ for client, helo, sender, or recipient access restric-
+ tions:
+
+ <b>o</b> When rejecting a sender address, the Postfix SMTP
+ server will transform a recipient DSN status (e.g.,
+ 4.1.1-4.1.6) into the corresponding sender DSN sta-
+ tus, and vice versa.
+
+ <b>o</b> When rejecting non-address information (such as the
+ HELO command argument or the client host-
+ name/address), the Postfix SMTP server will trans-
+ form 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
the table is given in the form of regular expressions. For
Instead of $name you can also specify ${name} or $(name).
</p>
+<p> Note: when an enhanced status code is specified in an RBL reply
+template, it is subject to modification. The following transformations
+are needed when the same RBL reply template is used for client,
+helo, sender, or recipient access restrictions. </p>
+
+<ul>
+
+<li> <p> When rejecting a sender address, 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. </p>
+
+<li> <p> When rejecting non-address information (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). </p>
+
+</ul>
+
</DD>
<b>-6</b> Support IPv6 only. This option is not available
when Postfix is built without IPv6 support.
+ <b>-8</b> Do not announce 8BITMIME support.
+
<b>-a</b> Do not announce SASL authentication support.
<b>-c</b> Display a running counter that is updated whenever
Wait <i>delay</i> seconds before responding to a DATA com-
mand.
- <b>-8</b> Do not announce 8BITMIME support.
-
[<b>inet:</b>][<i>host</i>]:<i>port</i>
Listen on network interface <i>host</i> (default: any
interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
.IP \fB-6\fR
Support IPv6 only. This option is not available when
Postfix is built without IPv6 support.
+.IP \fB-8\fR
+Do not announce 8BITMIME support.
.IP \fB-a\fR
Do not announce SASL authentication support.
.IP \fB-c\fR
Show the SMTP conversations.
.IP "\fB-w \fIdelay\fR"
Wait \fIdelay\fR seconds before responding to a DATA command.
-.IP \fB-8\fR
-Do not announce 8BITMIME support.
.IP [\fBinet:\fR][\fIhost\fR]:\fIport\fR
Listen on network interface \fIhost\fR (default: any interface)
TCP port \fIport\fR. Both \fIhost\fR and \fIport\fR may be
When no code is specified at the beginning of the \fItext\fR
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.
+defer actions. See "ENHANCED STATUS CODES" below.
.IP "\fB4\fINN text\fR"
.IP "\fB5\fINN text\fR"
Reject the address etc. that matches the pattern, and respond with
and if available, with helo, sender, recipient and protocol information.
.sp
This feature is available in Postfix 2.1 and later.
+.SH "ENHANCED STATUS CODES"
+.na
+.nf
+.ad
+.fi
+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:
+.IP \(bu
+When rejecting a sender address, 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.
+.IP \(bu
+When rejecting non-address information (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).
.SH "REGULAR EXPRESSION TABLES"
.na
.nf
Expands to `text' if $name is empty.
.PP
Instead of $name you can also specify ${name} or $(name).
+.PP
+Note: when an enhanced status code is specified in an RBL reply
+template, it is subject to modification. The following transformations
+are needed when the same RBL reply template is used for client,
+helo, sender, or recipient access restrictions.
+.IP \(bu
+When rejecting a sender address, 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.
+.IP \(bu
+When rejecting non-address information (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).
.SH default_recipient_limit (default: 10000)
The default per-transport upper limit on the number of in-memory
recipients. These limits take priority over the global
<h2>Introduction</h2>
<p> Postfix 2.2 introduces support for the IPv6 (IP version 6)
-protocol. IPv6 support older Postfix versions was available as an
-add-on patch. The section "<a href="#compat">Compatibility with
+protocol. IPv6 support for older Postfix versions was available as
+an add-on patch. The section "<a href="#compat">Compatibility with
Postfix <2.2 IPv6 support</a>" below discusses the differences
between these implementations. </p>
# When no code is specified at the beginning of the \fItext\fR
# 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.
+# defer actions. See "ENHANCED STATUS CODES" below.
# .IP "\fB4\fINN text\fR"
# .IP "\fB5\fINN text\fR"
# Reject the address etc. that matches the pattern, and respond with
# and if available, with helo, sender, recipient and protocol information.
# .sp
# This feature is available in Postfix 2.1 and later.
+# ENHANCED STATUS CODES
+# .ad
+# .fi
+# 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:
+# .IP \(bu
+# When rejecting a sender address, 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.
+# .IP \(bu
+# When rejecting non-address information (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
# .ad
# .fi
Instead of $name you can also specify ${name} or $(name).
</p>
+<p> Note: when an enhanced status code is specified in an RBL reply
+template, it is subject to modification. The following transformations
+are needed when the same RBL reply template is used for client,
+helo, sender, or recipient access restrictions. </p>
+
+<ul>
+
+<li> <p> When rejecting a sender address, 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. </p>
+
+<li> <p> When rejecting non-address information (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). </p>
+
+</ul>
+
%PARAM smtpd_expansion_filter see "postconf -d" output
<p>
}
}
nvtable_update(state->attr, attr_name, attr_value);
- myfree(sbuf);
cleanup_out(state, type, buf, len);
+ myfree(sbuf);
return;
} else {
cleanup_out(state, type, buf, len);
if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) != 0)
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ENCODING, encoding);
- if (state->return_receipt)
- cleanup_out_string(state, REC_TYPE_RRTO, state->return_receipt);
- if (state->errors_to)
- cleanup_out_string(state, REC_TYPE_ERTO, state->errors_to);
state->flags |= CLEANUP_FLAG_INRCPT;
}
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20050504"
+#define MAIL_RELEASE_DATE "20050510"
#define MAIL_VERSION_NUMBER "2.3"
#define VAR_MAIL_VERSION "mail_version"
SHELL = /bin/sh
SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
- smtpd_xforward.c
+ smtpd_xforward.c smtpd_dsn_fix.c
OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
- smtpd_xforward.o
+ smtpd_xforward.o smtpd_dsn_fix.c
HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
- smtpd_sasl_glue.h smtpd_proxy.h
+ smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h
TESTSRC = smtpd_token_test.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
../../libexec/$(PROG): $(PROG)
cp $(PROG) ../../libexec
-SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o smtpd_xforward.o
+SMTPD_CHECK_OBJ = smtpd_state.o smtpd_peer.o smtpd_xforward.o smtpd_dsn_fix.o
smtpd_token: smtpd_token.c $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
tidy: clean
tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_exp_test \
- smtpd_token_test smtpd_check_test4
+ smtpd_token_test smtpd_check_test4 smtpd_check_dsn
smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref smtpd_check_access
../postmap/postmap hash:smtpd_check_access
diff smtpd_exp.ref smtpd_exp.tmp
rm -f smtpd_exp.tmp smtpd_check_access.*
+smtpd_check_dsn_test: smtpd_check smtpd_check_dsn.in smtpd_check_dsn.ref smtpd_check_access
+ ../postmap/postmap hash:smtpd_check_access
+ ./smtpd_check <smtpd_check_dsn.in >smtpd_check.tmp 2>&1
+ diff smtpd_check_dsn.ref smtpd_check.tmp
+ rm -f smtpd_check.tmp smtpd_check_access.*
+
smtpd_token_test: smtpd_token smtpd_token.in smtpd_token.ref
./smtpd_token <smtpd_token.in >smtpd_token.tmp 2>&1
diff smtpd_token.ref smtpd_token.tmp
smtpd_check.o: smtpd.h
smtpd_check.o: smtpd_check.c
smtpd_check.o: smtpd_check.h
+smtpd_check.o: smtpd_dsn_fix.h
smtpd_check.o: smtpd_sasl_glue.h
+smtpd_dsn_fix.o: ../../include/msg.h
+smtpd_dsn_fix.o: ../../include/sys_defs.h
+smtpd_dsn_fix.o: smtpd_dsn_fix.c
+smtpd_dsn_fix.o: smtpd_dsn_fix.h
smtpd_peer.o: ../../include/argv.h
smtpd_peer.o: ../../include/attr.h
smtpd_peer.o: ../../include/inet_proto.h
int out_error;
char **cpp;
CLEANUP_STAT_DETAIL *detail;
+ int smtp_code;
#ifdef USE_TLS
VSTRING *peer_CN;
if (state->proxy_buffer) {
smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
} else if (why && LEN(why) > 0) {
- smtpd_chat_reply(state, "%d %s", detail->smtp, STR(why));
+ /* Allow address-specific DSN status in header/body_checks. */
+ smtp_code = (STR(why)[0] == '5' ? (detail->smtp % 100) + 500 :
+ STR(why)[0] == '4' ? (detail->smtp % 100) + 400 :
+ detail->smtp);
+ smtpd_chat_reply(state, "%d %s", smtp_code, STR(why));
} else {
smtpd_chat_reply(state, "%d %s Error: %s",
detail->smtp, detail->dsn, detail->text);
>>> # check_sender_access specific
>>> #
>>> mail <>
-./smtpd_check: <queue id>: reject: MAIL from bar.duno.com[44.33.44.33]: 550 5.0.0 <>: Sender address rejected: Go away postmaster; from=<> proto=SMTP helo=<foo.duuno.com>
-550 5.0.0 <>: Sender address rejected: Go away postmaster
+./smtpd_check: <queue id>: reject: MAIL from bar.duno.com[44.33.44.33]: 550 5.7.1 <>: Sender address rejected: Go away postmaster; from=<> proto=SMTP helo=<foo.duuno.com>
+550 5.7.1 <>: Sender address rejected: Go away postmaster
#include "smtpd.h"
#include "smtpd_sasl_glue.h"
#include "smtpd_check.h"
+#include "smtpd_dsn_fix.h"
#define RESTRICTION_SEPARATORS ", \t\r\n"
static int check_recipient_rcpt_maps(SMTPD_STATE *, const char *);
static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *);
- /*
- * Reject context.
- */
-#define SMTPD_NAME_CLIENT "Client host"
-#define SMTPD_NAME_CCERT "Client certificate"
-#define SMTPD_NAME_HELO "Helo command"
-#define SMTPD_NAME_SENDER "Sender address"
-#define SMTPD_NAME_RECIPIENT "Recipient address"
-#define SMTPD_NAME_ETRN "Etrn command"
-#define SMTPD_NAME_DATA "Data command"
-#define SMTPD_NAME_EOD "End-of-data"
-
/*
* YASLM.
*/
if (STREQUAL(value, "REJECT", cmd_len)) {
dsn_split(&dp, "5.7.1", cmd_text);
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
- var_access_map_code, DSN_CODE(dp.dsn),
+ var_access_map_code,
+ smtpd_dsn_fix(DSN_CODE(dp.dsn), reply_class),
"<%s>: %s rejected: %s",
reply_name, reply_class,
*dp.text ? dp.text : "Access denied"));
if (STREQUAL(value, DEFER_IF_PERMIT, cmd_len)) {
dsn_split(&dp, "4.7.1", cmd_text);
DEFER_IF_PERMIT3(state, MAIL_ERROR_POLICY,
- 450, DSN_CODE(dp.dsn),
+ 450, smtpd_dsn_fix(DSN_CODE(dp.dsn), reply_class),
"<%s>: %s rejected: %s",
reply_name, reply_class,
*dp.text ? dp.text : "Service unavailable");
if (STREQUAL(value, DEFER_IF_REJECT, cmd_len)) {
dsn_split(&dp, "4.7.1", cmd_text);
DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
- 450, DSN_CODE(dp.dsn),
+ 450, smtpd_dsn_fix(DSN_CODE(dp.dsn), reply_class),
"<%s>: %s rejected: %s",
reply_name, reply_class,
*dp.text ? dp.text : "Service unavailable");
def_dsn[0] = value[0];
dsn_split(&dp, def_dsn, cmd_text);
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
- code, DSN_CODE(dp.dsn),
+ code,
+ smtpd_dsn_fix(DSN_CODE(dp.dsn), reply_class),
"<%s>: %s rejected: %s",
reply_name, reply_class,
*dp.text ? dp.text : "Access denied"));
code = atoi(STR(why));
dsn_split(&dp, "4.7.1", STR(why) + 4);
result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
- code, DSN_CODE(dp.dsn),
+ code,
+ smtpd_dsn_fix(DSN_CODE(dp.dsn), reply_class),
"%s", *dp.text ?
dp.text : "Service unavailable");
}
return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
(reply->flags & RESOLVE_CLASS_ALIAS) ?
var_virt_alias_code : 550,
- DSN_CODE(dp.dsn),
+ smtpd_dsn_fix(DSN_CODE(dp.dsn), reply_class),
"<%s>: %s rejected: %s",
recipient, reply_class,
dp.text));
if (*addr && strchr(addr, '@') == 0)
msg_fatal("%s: address rewriting is disabled", addr);
vstring_strcpy(result, addr);
+ return (result);
}
/* resolve_clnt_query - stub */
>>> 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 5.0.0 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
-554 5.0.0 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: <queue id>: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 5.7.1 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
+554 5.7.1 <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 5.0.0 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
-554 5.0.0 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: <queue id>: reject: CONNECT from bad.domain[123.123.123.123]: 554 5.7.1 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
+554 5.7.1 <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 5.0.0 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210; proto=SMTP
-554 5.0.0 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
+./smtpd_check: <queue id>: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 5.7.1 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210; proto=SMTP
+554 5.7.1 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
>>> client_restrictions permit_mynetworks
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 5.0.0 <random.bad.domain>: Helo command rejected: match bad.domain; proto=SMTP helo=<random.bad.domain>
-554 5.0.0 <random.bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 5.7.1 <random.bad.domain>: Helo command rejected: match bad.domain; proto=SMTP helo=<random.bad.domain>
+554 5.7.1 <random.bad.domain>: Helo command rejected: match bad.domain
>>> helo friend.bad.domain
OK
>>> helo_restrictions reject_invalid_hostname,reject_unknown_hostname
>>> 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 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <Reject@this.address>: Sender address rejected: match reject@this.address; from=<Reject@this.address> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <Reject@this.address>: Sender address rejected: match reject@this.address
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <Reject@this.address>: Sender address rejected: match reject@this.address; from=<Reject@this.address> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <foo@Bad.domain>: Sender address rejected: match bad.domain; from=<foo@Bad.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <foo@Bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@Bad.domain>: Sender address rejected: match bad.domain; from=<foo@Bad.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
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 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <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 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<123.123.123.123>
-554 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<123.123.123.123>
+554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
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 5.0.0 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain> proto=SMTP helo=<bad.domain>
-554 5.0.0 <bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 554 5.7.1 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain> proto=SMTP helo=<bad.domain>
+554 5.7.1 <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 5.0.0 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain> to=<foo@porcupine.org> proto=SMTP helo=<bad.domain>
-554 5.0.0 <bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@friend.bad.domain> to=<foo@porcupine.org> proto=SMTP helo=<bad.domain>
+554 5.7.1 <bad.domain>: Helo command rejected: match bad.domain
>>> helo 131.155.210.17
OK
>>> rcpt foo@porcupine.org
>>> 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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<131.155.210.17>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<131.155.210.17>
+554 5.7.1 <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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> to=<foo@porcupine.org> proto=SMTP helo=<131.155.210.17>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> to=<foo@porcupine.org> proto=SMTP helo=<131.155.210.17>
+554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> rcpt foo@porcupine.org
>>> mail foo@good.domain
OK
>>> rcpt foo@porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.0.0 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@good.domain> to=<foo@porcupine.org> proto=SMTP helo=<bad.domain>
-554 5.0.0 <bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <bad.domain>: Helo command rejected: match bad.domain; from=<foo@good.domain> to=<foo@porcupine.org> proto=SMTP helo=<bad.domain>
+554 5.7.1 <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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> to=<foo@porcupine.org> proto=SMTP helo=<good.domain>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> to=<foo@porcupine.org> proto=SMTP helo=<good.domain>
+554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> #
>>> # FQDN restrictions
>>> #
>>> 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 5.0.0 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
-554 5.0.0 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: <queue id>: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 5.7.1 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
+554 5.7.1 <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 5.0.0 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
-554 5.0.0 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
+./smtpd_check: <queue id>: reject: CONNECT from bad.domain[123.123.123.123]: 554 5.7.1 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain; proto=SMTP
+554 5.7.1 <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 5.0.0 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210; proto=SMTP
-554 5.0.0 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
+./smtpd_check: <queue id>: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 5.7.1 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210; proto=SMTP
+554 5.7.1 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
>>> client_restrictions permit_mynetworks
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 5.0.0 <random.bad.domain>: Helo command rejected: match bad.domain; proto=SMTP helo=<random.bad.domain>
-554 5.0.0 <random.bad.domain>: Helo command rejected: match bad.domain
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 5.7.1 <random.bad.domain>: Helo command rejected: match bad.domain; proto=SMTP helo=<random.bad.domain>
+554 5.7.1 <random.bad.domain>: Helo command rejected: match bad.domain
>>> helo friend.bad.domain
OK
>>> #
>>> 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 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <Reject@this.address>: Sender address rejected: match reject@this.address; from=<Reject@this.address> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <Reject@this.address>: Sender address rejected: match reject@this.address
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <Reject@this.address>: Sender address rejected: match reject@this.address; from=<Reject@this.address> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <foo@Bad.domain>: Sender address rejected: match bad.domain; from=<foo@Bad.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <foo@Bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@Bad.domain>: Sender address rejected: match bad.domain; from=<foo@Bad.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
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 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <bad-sender@any.domain>: Sender address rejected: match bad-sender@; from=<bad-sender@any.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <reject@this.address>: Sender address rejected: match reject@this.address
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <reject@this.address>: Sender address rejected: match reject@this.address; from=<reject@this.address> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <foo@bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@bad.domain>: Sender address rejected: match bad.domain; from=<foo@bad.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <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 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<friend.bad.domain>
-554 5.0.0 <foo@random.bad.domain>: Sender address rejected: match bad.domain
+./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain; from=<foo@random.bad.domain> proto=SMTP helo=<friend.bad.domain>
+554 5.7.1 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> #
./smtpd_check: <queue id>: reject: MAIL from localhost[127.0.0.1]: 554 5.7.1 <rejecttext@bad.domain>: Sender address rejected: text; from=<rejecttext@bad.domain> proto=SMTP
554 5.7.1 <rejecttext@bad.domain>: Sender address rejected: text
>>> mail filter@filter.domain
-./smtpd_check: warning: access map hash:./smtpd_check_access entry "filter@filter.domain" has FILTER entry without value
+./smtpd_check: warning: access table hash:./smtpd_check_access entry "filter@filter.domain" has FILTER entry without value
OK
>>> mail filtertext@filter.domain
-./smtpd_check: warning: access map hash:./smtpd_check_access entry "filtertext@filter.domain" requires transport:destination
+./smtpd_check: warning: access table hash:./smtpd_check_access entry "filtertext@filter.domain" requires transport:destination
OK
>>> mail filtertexttext@filter.domain
./smtpd_check: <queue id>: filter: MAIL from localhost[127.0.0.1]: <filtertexttext@filter.domain>: Sender address triggers FILTER text:text; from=<filtertexttext@filter.domain> proto=SMTP
10.10.10.10 reject mail server 10.10.10.10
spike.porcupine.org reject name server spike.porcupine.org
241 reject class E subnet
+4.1.1_dsn reject 4.1.1 reject
+4.1.2_dsn reject 4.1.2 reject
+4.1.3_dsn reject 4.1.3 reject
+4.1.4_dsn reject 4.1.4 reject
+4.1.5_dsn reject 4.1.5 reject
+4.1.6_dsn reject 4.1.6 reject
+4.1.7_dsn reject 4.1.7 reject
+4.1.8_dsn reject 4.1.8 reject
+4.4.0_dsn reject 4.4.0 reject
+user@4.1.1_dsn reject 4.1.1 reject
+user@4.1.2_dsn reject 4.1.2 reject
+user@4.1.3_dsn reject 4.1.3 reject
+user@4.1.4_dsn reject 4.1.4 reject
+user@4.1.5_dsn reject 4.1.5 reject
+user@4.1.6_dsn reject 4.1.6 reject
+user@4.1.7_dsn reject 4.1.7 reject
+user@4.1.8_dsn reject 4.1.8 reject
+user@4.4.0_dsn reject 4.4.0 reject
--- /dev/null
+#
+# Initialize.
+#
+#! ../bin/postmap smtpd_check_access
+#msg_verbose 1
+smtpd_delay_reject 0
+mynetworks 127.0.0.0/8,168.100.189.0/28
+#
+# Test the client restrictions.
+#
+client_restrictions hash:./smtpd_check_access
+client 4.1.1_dsn 1.2.3.4
+client 4.1.2_dsn 1.2.3.4
+client 4.1.3_dsn 1.2.3.4
+client 4.1.4_dsn 1.2.3.4
+client 4.1.5_dsn 1.2.3.4
+client 4.1.6_dsn 1.2.3.4
+client 4.1.7_dsn 1.2.3.4
+client 4.1.8_dsn 1.2.3.4
+client 4.4.0_dsn 1.2.3.4
+client dummy dummy
+#
+# Test the helo restrictions
+#
+helo_restrictions hash:./smtpd_check_access
+helo 4.1.1_dsn
+helo 4.1.2_dsn
+helo 4.1.3_dsn
+helo 4.1.4_dsn
+helo 4.1.5_dsn
+helo 4.1.6_dsn
+helo 4.1.7_dsn
+helo 4.1.8_dsn
+helo 4.4.0_dsn
+#
+# Test the sender restrictions
+#
+sender_restrictions hash:./smtpd_check_access
+mail user@4.1.1_dsn
+mail user@4.1.2_dsn
+mail user@4.1.3_dsn
+mail user@4.1.4_dsn
+mail user@4.1.5_dsn
+mail user@4.1.6_dsn
+mail user@4.1.7_dsn
+mail user@4.1.8_dsn
+mail user@4.4.0_dsn
+#
+# Test the recipient restrictions
+#
+recipient_restrictions hash:./smtpd_check_access
+rcpt user@4.1.1_dsn
+rcpt user@4.1.2_dsn
+rcpt user@4.1.3_dsn
+rcpt user@4.1.4_dsn
+rcpt user@4.1.5_dsn
+rcpt user@4.1.6_dsn
+rcpt user@4.1.7_dsn
+rcpt user@4.1.8_dsn
+rcpt user@4.4.0_dsn
--- /dev/null
+>>> #
+>>> # Initialize.
+>>> #
+>>> #! ../bin/postmap smtpd_check_access
+>>> #msg_verbose 1
+>>> smtpd_delay_reject 0
+OK
+>>> mynetworks 127.0.0.0/8,168.100.189.0/28
+OK
+>>> #
+>>> # Test the client restrictions.
+>>> #
+>>> client_restrictions hash:./smtpd_check_access
+OK
+>>> client 4.1.1_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.1 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.1_dsn[1.2.3.4]: 554 5.0.0 <4.1.1_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.1_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.2_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.2 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.2_dsn[1.2.3.4]: 554 5.0.0 <4.1.2_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.2_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.3_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.3 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.3_dsn[1.2.3.4]: 554 5.0.0 <4.1.3_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.3_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.4_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.4 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.4_dsn[1.2.3.4]: 554 5.0.0 <4.1.4_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.4_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.5_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.5 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.5_dsn[1.2.3.4]: 554 5.0.0 <4.1.5_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.5_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.6_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.6 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.6_dsn[1.2.3.4]: 554 5.0.0 <4.1.6_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.6_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.7_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.7 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.7_dsn[1.2.3.4]: 554 5.0.0 <4.1.7_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.7_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.1.8_dsn 1.2.3.4
+./smtpd_check: mapping DSN status 4.1.8 into Client host status 4.0.0
+./smtpd_check: <queue id>: reject: CONNECT from 4.1.8_dsn[1.2.3.4]: 554 5.0.0 <4.1.8_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.0.0 <4.1.8_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client 4.4.0_dsn 1.2.3.4
+./smtpd_check: <queue id>: reject: CONNECT from 4.4.0_dsn[1.2.3.4]: 554 5.4.0 <4.4.0_dsn[1.2.3.4]>: Client host rejected: reject; proto=SMTP
+554 5.4.0 <4.4.0_dsn[1.2.3.4]>: Client host rejected: reject
+>>> client dummy dummy
+OK
+>>> #
+>>> # Test the helo restrictions
+>>> #
+>>> helo_restrictions hash:./smtpd_check_access
+OK
+>>> helo 4.1.1_dsn
+./smtpd_check: mapping DSN status 4.1.1 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.1_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.1_dsn>
+554 5.0.0 <4.1.1_dsn>: Helo command rejected: reject
+>>> helo 4.1.2_dsn
+./smtpd_check: mapping DSN status 4.1.2 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.2_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.2_dsn>
+554 5.0.0 <4.1.2_dsn>: Helo command rejected: reject
+>>> helo 4.1.3_dsn
+./smtpd_check: mapping DSN status 4.1.3 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.3_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.3_dsn>
+554 5.0.0 <4.1.3_dsn>: Helo command rejected: reject
+>>> helo 4.1.4_dsn
+./smtpd_check: mapping DSN status 4.1.4 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.4_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.4_dsn>
+554 5.0.0 <4.1.4_dsn>: Helo command rejected: reject
+>>> helo 4.1.5_dsn
+./smtpd_check: mapping DSN status 4.1.5 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.5_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.5_dsn>
+554 5.0.0 <4.1.5_dsn>: Helo command rejected: reject
+>>> helo 4.1.6_dsn
+./smtpd_check: mapping DSN status 4.1.6 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.6_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.6_dsn>
+554 5.0.0 <4.1.6_dsn>: Helo command rejected: reject
+>>> helo 4.1.7_dsn
+./smtpd_check: mapping DSN status 4.1.7 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.7_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.7_dsn>
+554 5.0.0 <4.1.7_dsn>: Helo command rejected: reject
+>>> helo 4.1.8_dsn
+./smtpd_check: mapping DSN status 4.1.8 into Helo command status 4.0.0
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.0.0 <4.1.8_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.1.8_dsn>
+554 5.0.0 <4.1.8_dsn>: Helo command rejected: reject
+>>> helo 4.4.0_dsn
+./smtpd_check: <queue id>: reject: HELO from dummy[dummy]: 554 5.4.0 <4.4.0_dsn>: Helo command rejected: reject; proto=SMTP helo=<4.4.0_dsn>
+554 5.4.0 <4.4.0_dsn>: Helo command rejected: reject
+>>> #
+>>> # Test the sender restrictions
+>>> #
+>>> sender_restrictions hash:./smtpd_check_access
+OK
+>>> mail user@4.1.1_dsn
+./smtpd_check: mapping DSN status 4.1.1 into Sender address status 4.1.0
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.1_dsn>: Sender address rejected: reject; from=<user@4.1.1_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.0 <user@4.1.1_dsn>: Sender address rejected: reject
+>>> mail user@4.1.2_dsn
+./smtpd_check: mapping DSN status 4.1.2 into Sender address status 4.1.8
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.8 <user@4.1.2_dsn>: Sender address rejected: reject; from=<user@4.1.2_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.8 <user@4.1.2_dsn>: Sender address rejected: reject
+>>> mail user@4.1.3_dsn
+./smtpd_check: mapping DSN status 4.1.3 into Sender address status 4.1.7
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.3_dsn>: Sender address rejected: reject; from=<user@4.1.3_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.7 <user@4.1.3_dsn>: Sender address rejected: reject
+>>> mail user@4.1.4_dsn
+./smtpd_check: mapping DSN status 4.1.4 into Sender address status 4.1.0
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.4_dsn>: Sender address rejected: reject; from=<user@4.1.4_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.0 <user@4.1.4_dsn>: Sender address rejected: reject
+>>> mail user@4.1.5_dsn
+./smtpd_check: mapping DSN status 4.1.5 into Sender address status 4.1.0
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.5_dsn>: Sender address rejected: reject; from=<user@4.1.5_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.0 <user@4.1.5_dsn>: Sender address rejected: reject
+>>> mail user@4.1.6_dsn
+./smtpd_check: mapping DSN status 4.1.6 into Sender address status 4.1.0
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.0 <user@4.1.6_dsn>: Sender address rejected: reject; from=<user@4.1.6_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.0 <user@4.1.6_dsn>: Sender address rejected: reject
+>>> mail user@4.1.7_dsn
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.7 <user@4.1.7_dsn>: Sender address rejected: reject; from=<user@4.1.7_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.7 <user@4.1.7_dsn>: Sender address rejected: reject
+>>> mail user@4.1.8_dsn
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.1.8 <user@4.1.8_dsn>: Sender address rejected: reject; from=<user@4.1.8_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.8 <user@4.1.8_dsn>: Sender address rejected: reject
+>>> mail user@4.4.0_dsn
+./smtpd_check: <queue id>: reject: MAIL from dummy[dummy]: 554 5.4.0 <user@4.4.0_dsn>: Sender address rejected: reject; from=<user@4.4.0_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.4.0 <user@4.4.0_dsn>: Sender address rejected: reject
+>>> #
+>>> # Test the recipient restrictions
+>>> #
+>>> recipient_restrictions hash:./smtpd_check_access
+OK
+>>> rcpt user@4.1.1_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.1 <user@4.1.1_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.1_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.1 <user@4.1.1_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.2_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.2 <user@4.1.2_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.2_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.2 <user@4.1.2_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.3_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.3 <user@4.1.3_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.3_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.3 <user@4.1.3_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.4_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.4 <user@4.1.4_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.4_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.4 <user@4.1.4_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.5_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.5 <user@4.1.5_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.5_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.5 <user@4.1.5_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.6_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.6 <user@4.1.6_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.6_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.6 <user@4.1.6_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.7_dsn
+./smtpd_check: mapping DSN status 4.1.7 into Recipient address status 4.1.3
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.3 <user@4.1.7_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.7_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.3 <user@4.1.7_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.1.8_dsn
+./smtpd_check: mapping DSN status 4.1.8 into Recipient address status 4.1.2
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.1.2 <user@4.1.8_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.1.8_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.1.2 <user@4.1.8_dsn>: Recipient address rejected: reject
+>>> rcpt user@4.4.0_dsn
+./smtpd_check: <queue id>: reject: RCPT from dummy[dummy]: 554 5.4.0 <user@4.4.0_dsn>: Recipient address rejected: reject; from=<user@4.4.0_dsn> to=<user@4.4.0_dsn> proto=SMTP helo=<4.4.0_dsn>
+554 5.4.0 <user@4.4.0_dsn>: Recipient address rejected: reject
--- /dev/null
+/*++
+/* NAME
+/* smtpd_dsn_fix 3
+/* SUMMARY
+/* fix DSN status
+/* SYNOPSIS
+/* #include <smtpd_dsn_fix.h>
+/*
+/* const char *smtpd_dsn_fix(status, reply_class)
+/* const char *status;
+/* const char *reply_class;
+/* DESCRIPTION
+/* smtpd_dsn_fix() transforms DSN status codes according to the
+/* status information that is actually being reported. The
+/* following transformations are implemented:
+/* .IP \(bu
+/* Transform a recipient address DSN into a sender address DSN
+/* when reporting sender address status information, and vice
+/* versa. This transformation may be needed because some Postfix
+/* access control features don't know whether the address being
+/* rejected is a sender or recipient. Examples are smtpd access
+/* tables, rbl reply templates, and the error mailer.
+/* .IP \(bu
+/* Transform a sender or recipient address DSN into a non-address
+/* DSN when reporting non-address status information. For
+/* example, if something rejects HELO with DSN status 4.1.1
+/* (unknown recipient address), then we send the more neutral
+/* 4.0.0 DSN instead. This transformation is needed when the
+/* same smtpd access map entry or rbl reply template is used
+/* for both address and non-address information.
+/* .PP
+/* No transformation is done when reporting a non-address DSN
+/* when reporting sender or recipient address status information,
+/* as there are many legitimate instances of such usage.
+/*
+/* It is left up to the caller to update the initial DSN digit
+/* appropriately; in Postfix this is done as late as possible,
+/* because hard rejects may be changed into soft rejects for
+/* all kinds of reasons.
+/*
+/* Arguments:
+/* .IP status
+/* A DSN status as per RFC 3463.
+/* .IP reply_class
+/* SMTPD_NAME_SENDER, SMTPD_NAME_RECIPIENT or some other
+/* null-terminated string.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+/* System library. */
+
+#include <sys_defs.h>
+#include <ctype.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* Global library. */
+
+/* Application-specific. */
+
+#include <smtpd_dsn_fix.h>
+
+struct dsn_map {
+ const char *micro_code; /* Final digits in mailbox D.S.N. */
+ const char *sender_dsn; /* Replacement sender D.S.N. */
+ const char *rcpt_dsn; /* Replacement recipient D.S.N. */
+};
+
+static struct dsn_map dsn_map[] = {
+ /* - Sender - Recipient */
+ "1", "4.1.0", "4.1.1", /* 4.1.1: Bad dest mbox addr */
+ "2", "4.1.8", "4.1.2", /* 4.1.2: Bad dest system addr */
+ "3", "4.1.7", "4.1.3", /* 4.1.3: Bad dest mbox addr syntax */
+ "4", "4.1.0", "4.1.4", /* 4.1.4: Dest mbox addr ambiguous */
+ "5", "4.1.0", "4.1.5", /* 4.1.5: Dest mbox addr valid */
+ "6", "4.1.0", "4.1.6", /* 4.1.6: Mailbox has moved */
+ "7", "4.1.7", "4.1.3", /* 4.1.7: Bad sender mbox addr syntax */
+ "8", "4.1.8", "4.1.2", /* 4.1.8: Bad sender system addr */
+ 0, "4.1.0", "4.1.0", /* Default mapping */
+};
+
+/* smtpd_dsn_fix - fix DSN status */
+
+const char *smtpd_dsn_fix(const char *status, const char *reply_class)
+{
+ struct dsn_map *dp;
+ const char *result = status;
+
+ if (ISDIGIT(status[0]) && strncmp(status + 1, ".1.", 3) == 0) {
+
+ /*
+ * Fix recipient address DSN while rejecting a sender address. Don't
+ * let future recipient-specific DSN codes slip past us.
+ */
+ if (strcmp(reply_class, SMTPD_NAME_SENDER) == 0) {
+ for (dp = dsn_map; dp->micro_code != 0; dp++)
+ if (strcmp(status + 4, dp->micro_code) == 0)
+ break;
+ result = dp->sender_dsn;
+ }
+
+ /*
+ * Fix sender address DSN while rejecting a recipient address. Don't
+ * let future sender-specific DSN codes slip past us.
+ */
+ else if (strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0) {
+ for (dp = dsn_map; dp->micro_code != 0; dp++)
+ if (strcmp(status + 4, dp->micro_code) == 0)
+ break;
+ result = dp->rcpt_dsn;
+ }
+
+ /*
+ * Fix address-specific DSN while rejecting a non-address.
+ */
+ else {
+ result = "4.0.0";
+ }
+
+ /*
+ * Give them a clue of what is going on.
+ */
+ if (strcmp(status + 2, result + 2) != 0)
+ msg_info("mapping DSN status %s into %s status %c%s",
+ status, reply_class, status[0], result + 1);
+ return (result);
+ } else {
+ return (status);
+ }
+}
--- /dev/null
+/*++
+/* NAME
+/* smtpd_check 3h
+/* SUMMARY
+/* SMTP client request filtering
+/* SYNOPSIS
+/* #include "smtpd.h"
+/* #include "smtpd_check_int.h"
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Internal interface.
+ */
+#define SMTPD_NAME_CLIENT "Client host"
+#define SMTPD_NAME_CCERT "Client certificate"
+#define SMTPD_NAME_HELO "Helo command"
+#define SMTPD_NAME_SENDER "Sender address"
+#define SMTPD_NAME_RECIPIENT "Recipient address"
+#define SMTPD_NAME_ETRN "Etrn command"
+#define SMTPD_NAME_DATA "Data command"
+#define SMTPD_NAME_EOD "End-of-data"
+
+extern const char *smtpd_dsn_fix(const char *, const char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
>>> mail sname@sdomain
OK
>>> rcpt rname@rdomain
-./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
-554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
+554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld
>>> #
>>> # Check MX access
>>> #
vstream_printf("Token value: %s\n", tok_argv[i].strval);
}
}
+ vstring_free(vp);
exit(0);
}
/* .IP \fB-6\fR
/* Support IPv6 only. This option is not available when
/* Postfix is built without IPv6 support.
+/* .IP \fB-8\fR
+/* Do not announce 8BITMIME support.
/* .IP \fB-a\fR
/* Do not announce SASL authentication support.
/* .IP \fB-c\fR
/* Show the SMTP conversations.
/* .IP "\fB-w \fIdelay\fR"
/* Wait \fIdelay\fR seconds before responding to a DATA command.
-/* .IP \fB-8\fR
-/* Do not announce 8BITMIME support.
/* .IP [\fBinet:\fR][\fIhost\fR]:\fIport\fR
/* Listen on network interface \fIhost\fR (default: any interface)
/* TCP port \fIport\fR. Both \fIhost\fR and \fIport\fR may be
static void usage(char *myname)
{
- msg_fatal("usage: %s [-acCeFLpPv8] [-f commands] [-h hostname] [-n count] [-q commands] [-r commands] [-s commands] [-w delay] [host]:port backlog", myname);
+ msg_fatal("usage: %s [-468acCeEFLpPv] [-f commands] [-h hostname] [-n count] [-q commands] [-r commands] [-s commands] [-w delay] [host]:port backlog", myname);
}
int main(int argc, char **argv)
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "46acCeEf:Fh:Ln:pPq:r:s:t:vw:8")) > 0) {
+ while ((ch = GETOPT(argc, argv, "468acCeEf:Fh:Ln:pPq:r:s:t:vw:")) > 0) {
switch (ch) {
case '4':
protocols = INET_PROTO_NAME_IPV4;
case '6':
protocols = INET_PROTO_NAME_IPV6;
break;
+ case '8':
+ disable_8bitmime = 1;
+ break;
case 'a':
disable_saslauth = 1;
break;
if ((fixed_delay = atoi(optarg)) <= 0)
usage(argv[0]);
break;
- case '8':
- disable_8bitmime = 1;
- break;
default:
usage(argv[0]);
}
tls_mgr.o: tls_mgr.h
tls_misc.o: ../../include/msg.h
tls_misc.o: ../../include/mymalloc.h
+tls_misc.o: ../../include/stringops.h
tls_misc.o: ../../include/sys_defs.h
tls_misc.o: ../../include/vbuf.h
tls_misc.o: ../../include/vstream.h
fullname.o: sys_defs.h
fullname.o: vbuf.h
fullname.o: vstring.h
+gccw.o: gccw.c
get_domainname.o: get_domainname.c
get_domainname.o: get_domainname.h
get_domainname.o: get_hostname.h