-TSMFICTX
-TSMTPD_CMD
-TSMTPD_DEFER
+-TSMTPD_PROXY
-TSMTPD_RBL_EXPAND_CONTEXT
-TSMTPD_RBL_STATE
-TSMTPD_RCPTMAP_ST
the Postfix SMTP server. This a last-resort tool to fix bad
command syntax that Postfix would otherwise reject. See
examples in the postconf(5) manual page. File: smtpd/smtpd.c.
+
+20091026
+
+ Cleanup: changed parameter evaluation order so that the
+ multi_instance_wrapper parameter value is evaluated after
+ the command and daemon directory parameters. File:
+ global/mail_params.h.
+
+20091101
+
+ Performance: specify "smtpd_proxy_options = speed_adjust"
+ to receive an entire message before sending it through a
+ before-queue content filter. This reduces the number of
+ simultaneous content filtering processes, and thus, the
+ system memory requirements. Files: smtpd/smtpd.[hc],
+ smtpd/smtpd_proxy.[hc].
+
+20091103-4
+
+ Cleaned up the speed-adjust code, streamlined the error
+ handling, and updated documentation. Files: smtpd/smtpd.[hc],
+ smtpd/smtpd_proxy.[hc], proto/SMTPD_PROXY_README.html.
+
+20091105
+
+ Cleaning up after speed_adjust introduction: smtpd segfault
+ caused by an incomplete API change; refined the queue space
+ check; release scratch space immediately after delivering
+ mail to the before-queue filter. Files: smtpd.c, smtpd_proxy.c.
W\bWA\bAR\bRN\bNI\bIN\bNG\bG
-The before-queue content filtering feature described in this document is
-suitable only for low-traffic sites. See the "Pros and Cons" section below for
-details.
+The before-queue content filtering feature described in this document limits
+the amount of mail that a site can handle. See the "Pros and Cons" section
+below for details.
T\bTh\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx b\bbe\bef\bfo\bor\bre\be-\b-q\bqu\bue\beu\bue\be c\bco\bon\bnt\bte\ben\bnt\bt f\bfi\bil\blt\bte\ber\br f\bfe\bea\bat\btu\bur\bre\be
system load increases, fewer and fewer CPU cycles remain available to
answer within the deadline, and eventually you either have to stop
accepting mail or you have to stop filtering mail. It is for this reason
- that the before-queue content filter can be used only on low-traffic sites.
+ that the before-queue content filter limits the amount of mail that a site
+ can handle.
- * Con: Content filtering software can use lots of memory resources. In order
- to not run out of memory you have to reduce the number of before-filter
- SMTP server processes so that a burst of mail will not drive your system
- into the ground with too many content filter processes. This, in turn,
- means that SMTP clients have to wait for a long time before they receive
- service.
+ * Con: Content filtering software can use lots of memory resources. You have
+ to reduce the number of simultaneous content filter processes so that a
+ burst of mail will not drive your system into the ground.
+
+ o With Postfix versions 2.7 and later, SMTP clients will experience an
+ increase in the delay between the time the client sends "end-of-
+ message" and the time the Postfix SMTP server replies (here, the number
+ of before-filter SMTP server processes can be larger than the number of
+ filter processes).
+
+ o With Postfix versions before 2.7, SMTP clients will experience an
+ increase in the delay before they can receive service (here, the number
+ of before-filter SMTP server processes is always equal to the number of
+ filter processes).
C\bCo\bon\bnf\bfi\big\bgu\bur\bri\bin\bng\bg t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP p\bpa\bas\bss\bs-\b-t\bth\bhr\bro\bou\bug\bgh\bh p\bpr\bro\box\bxy\by f\bfe\bea\bat\btu\bur\bre\be
smtp inet n - n - 20 smtpd
-o smtpd_proxy_filter=127.0.0.1:10025
-o smtpd_client_connection_count_limit=10
+ # Postfix 2.7 and later performance feature.
+ # -o smtpd_proxy_options=speed_adjust
#
# After-filter SMTP server. Receive mail from the content filter
# on localhost port 10026.
Note: this setting is available in Postfix version 2.2 and later. Earlier
Postfix versions will ignore it.
- * The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the before filter SMTP
+ * The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the before-filter SMTP
server that it should give incoming mail to the content filter that listens
on localhost TCP port 10025.
- * Postfix 2.3 supports both TCP and UNIX-domain filters. The above filter
+ * The "-o smtpd_proxy_options=speed_adjust" tells the before-filter SMTP
+ server that it should receive an entire email message before it connects to
+ a content filter. This reduces the number of simultaneous filter processes.
+
+ NOTE 1: When this option is turned on, a content filter must not
+ selectively reject recipients of a multi-recipient message. Rejecting all
+ recipients is OK, as is accepting all recipients.
+
+ NOTE 2: This feature increases the minimum amount of free queue space by
+ $message_size_limit. The extra space is needed to save the message to a
+ temporary file.
+
+ * Postfix >= 2.3 supports both TCP and UNIX-domain filters. The above filter
could be specified as "inet:127.0.0.1:10025". To specify a UNIX-domain
filter, specify "unix:pathname". A relative pathname is interpreted
relative to the Postfix queue directory.
* The "-o smtpd_authorized_xforward_hosts=127.0.0.0/8" allows the after-
filter SMTP server to receive remote SMTP client information from the
- before filter SMTP server, so that the after-filter Postfix daemons log the
+ before-filter SMTP server, so that the after-filter Postfix daemons log the
remote SMTP client information instead of logging localhost[127.0.0.1].
* The other after-filter SMTP server settings avoid duplication of work that
If you upgrade from Postfix 2.5 or earlier, read RELEASE_NOTES-2.6
before proceeding.
+Major changes with snapshot 20091109
+====================================
+
+Improved before-queue filter performance. With "smtpd_proxy_options
+= speed_adjust", the Postfix SMTP server receives the entire message
+before it connects to a before-queue content filter. This means you
+can run more SMTP server processes with the same number of running
+content filter processes, and thus, handle more mail. This feature
+is off by default until it is proven to create no new problems.
+
+This addresses a concern of people in Europe who want to reject all
+bad mail with a before-queue filter. The alternative, an after-queue
+filter, means they would have to discard bad mail (which is illegal)
+or bounce bad mail (which violates good network citizenship).
+
+NOTE 1: When this feature is turned on, a filter cannot selectively
+reject recipients of a multi-recipient message. Rejecting all
+recipients is OK, as is deferring all recipients, or accepting all
+recipients of the same multi-recipient message.
+
+NOTE 2: This feature increases the minimum amount of free queue
+space by $message_size_limit. The extra space is needed to save the
+message to a temporary file.
+
+To keep the performance overhead low, the same temporary file is
+reused with successive mail transactions (the file is of course
+truncated before reuse, so there is no information leakage).
+
Incompatibility with snapshot 20091008
======================================
<h2>WARNING </h2>
-<p> The before-queue content filtering feature described in
-this document is suitable only for low-traffic sites. See the "<a
-href="#pros_cons">Pros and Cons</a>" section below for details.
+<p> The before-queue content filtering feature described in this
+document limits the amount of mail that a site can handle. See the
+"<a href="#pros_cons">Pros and Cons</a>" section below for details.
</p>
<h2>The Postfix before-queue content filter feature</h2>
cycles remain available to answer within the deadline, and eventually
you either have to stop accepting mail or you have to stop filtering
mail. It is for this reason that the before-queue content filter
-can be used only on low-traffic sites. </p>
+limits the amount of mail that a site can handle. </p>
<li> <p> Con: Content filtering software can use lots of memory
-resources. In order to not run out of memory you have to reduce
-the number of before-filter SMTP server processes so that a burst
-of mail will not drive your system into the ground with too many
-content filter processes. This, in turn, means that SMTP clients
-have to wait for a long time before they receive service. </p>
+resources. You have to reduce the number of simultaneous content
+filter processes so that a burst of mail will not drive your system
+into the ground. </p>
+
+<ul>
+
+<li> <p> With Postfix versions 2.7 and later, SMTP clients will
+experience an increase in the delay between the time the client
+sends "end-of-message" and the time the Postfix SMTP server replies
+(here, the number of before-filter SMTP server processes can be
+larger than the number of filter processes). </p>
+
+<li> <p> With Postfix versions before 2.7, SMTP clients will
+experience an increase in the delay before they can receive service
+(here, the number of before-filter SMTP server processes is always
+equal to the number of filter processes). </p>
+
+</ul>
</ul>
smtp inet n - n - 20 smtpd
-o <a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a>=127.0.0.1:10025
-o <a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a>=10
+ # Postfix 2.7 and later performance feature.
+ # -o <a href="postconf.5.html#smtpd_proxy_options">smtpd_proxy_options</a>=speed_adjust
#
# After-filter SMTP server. Receive mail from the content filter
# on localhost port 10026.
later. Earlier Postfix versions will ignore it. </p>
<li> <p> The "-o <a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a>=127.0.0.1:10025" tells the
- before filter SMTP server that it should give incoming mail to
+ before-filter SMTP server that it should give incoming mail to
the content filter that listens on localhost TCP port 10025.
- <li> <p> Postfix 2.3 supports both TCP and UNIX-domain filters.
+ <li> <p> The "-o <a href="postconf.5.html#smtpd_proxy_options">smtpd_proxy_options</a>=speed_adjust" tells the
+ before-filter SMTP server that it should receive an entire email
+ message before it connects to a content filter. This reduces
+ the number of simultaneous filter processes. </p>
+
+ <p> NOTE 1: When this option is turned on, a content filter must
+ not <i>selectively</i> reject recipients of a multi-recipient
+ message. Rejecting all recipients is OK, as is accepting all
+ recipients. </p>
+
+ <p> NOTE 2: This feature increases the minimum amount of free
+ queue space by $<a href="postconf.5.html#message_size_limit">message_size_limit</a>. The extra space is needed
+ to save the message to a temporary file. </p>
+
+ <li> <p> Postfix ≥ 2.3 supports both TCP and UNIX-domain filters.
The above filter could be specified as "inet:127.0.0.1:10025".
To specify a UNIX-domain filter, specify "unix:<i>pathname</i>".
A relative pathname is interpreted relative to the Postfix queue
<li> <p> The "-o <a href="postconf.5.html#smtpd_authorized_xforward_hosts">smtpd_authorized_xforward_hosts</a>=127.0.0.0/8"
allows the after-filter SMTP server to receive remote SMTP
- client information from the before filter SMTP server, so that
+ client information from the before-filter SMTP server, so that
the after-filter Postfix daemons log the remote SMTP client
information instead of logging localhost[127.0.0.1]. </p>
</p>
<p> Specify the name of a "<a href="DATABASE_README.html">type:table</a>" lookup table. The search
-string is the SMTP command as received from the SMTP client. The
-only change made is to remove initial whitespace and the trailing
-<CR><LF> characters. The result value is executed by the Postfix
-SMTP server. </p>
+string is the SMTP command as received from the SMTP client, except
+that initial whitespace and the trailing <CR><LF> are removed. The
+result value is executed by the Postfix SMTP server. </p>
<p> Examples: </p>
</pre>
<pre>
- # Work around clients that enclose addresses in single quotes.
+ # Work around clients that send RCPT TO:<'user@domain'>.
# WARNING: do not lose the parameters that follow the address.
/^RCPT\s+TO:\s*<'([^[:space:]]+)'>(.*)/ RCPT TO:<$1>$2
</pre>
and later. </p>
+</DD>
+
+<DT><b><a name="smtpd_proxy_options">smtpd_proxy_options</a>
+(default: empty)</b></DT><DD>
+
+<p>
+List of options that control how the Postfix SMTP server
+communicates with a before-queue content filter. Specify zero or
+more of the following, separated by comma or whitespace. </p>
+
+<dl>
+
+<dt><b>speed_adjust</b></dt>
+
+<dd> Do not connect to a before-queue content filter until an entire
+message has been received. This reduces the number of simultaneous
+before-queue content filter processes. </p>
+
+<p> NOTE 1: A filter must not <i>selectively</i> reject recipients
+of a multi-recipient message. Rejecting all recipients is OK, as
+is accepting all recipients. </p>
+
+<p> NOTE 2: This feature increases the minimum amount of free queue
+space by $<a href="postconf.5.html#message_size_limit">message_size_limit</a>. The extra space is needed to save the
+message to a temporary file. </p> </dd>
+
+</dl>
+
+<p>
+This feature is available in Postfix 2.7 and later.
+</p>
+
+
</DD>
<DT><b><a name="smtpd_proxy_timeout">smtpd_proxy_timeout</a>
rejecting the address as invalid.
<b><a href="postconf.5.html#smtpd_command_filter">smtpd_command_filter</a> (empty)</b>
- A mechanism to substitute incoming SMTP commands by
- other commands.
+ A mechanism to substitute incoming SMTP commands.
<b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
- Request that the Postfix SMTP server rejects mail
- from unknown sender addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
+ Request that the Postfix SMTP server rejects mail
+ from unknown sender addresses, even when no
+ explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
is specified.
<b><a href="postconf.5.html#smtpd_sasl_exceptions_networks">smtpd_sasl_exceptions_networks</a> (empty)</b>
- What remote SMTP clients the Postfix SMTP server
+ What remote SMTP clients the Postfix SMTP server
will not offer AUTH support to.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">smtpd_discard_ehlo_keyword_address_maps</a> (empty)</b>
- Lookup tables, indexed by the remote SMTP client
- address, with case insensitive lists of EHLO key-
- words (pipelining, starttls, auth, etc.) that the
+ Lookup tables, indexed by the remote SMTP client
+ address, with case insensitive lists of EHLO key-
+ words (pipelining, starttls, auth, etc.) that the
SMTP server will not send in the EHLO response to a
remote SMTP client.
<b><a href="postconf.5.html#smtpd_discard_ehlo_keywords">smtpd_discard_ehlo_keywords</a> (empty)</b>
- A case insensitive list of EHLO keywords (pipelin-
- ing, starttls, auth, etc.) that the SMTP server
+ A case insensitive list of EHLO keywords (pipelin-
+ ing, starttls, auth, etc.) that the SMTP server
will not send in the EHLO response to a remote SMTP
client.
<b><a href="postconf.5.html#smtpd_delay_open_until_valid_rcpt">smtpd_delay_open_until_valid_rcpt</a> (yes)</b>
- Postpone the start of an SMTP mail transaction
+ Postpone the start of an SMTP mail transaction
until a valid RCPT TO command is received.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_session_ids</a> (yes)</b>
- Force the Postfix SMTP server to issue a TLS ses-
- sion id, even when TLS session caching is turned
+ Force the Postfix SMTP server to issue a TLS ses-
+ sion id, even when TLS session caching is turned
off (<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> is empty).
Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#tcp_windowsize">tcp_windowsize</a> (0)</b>
- An optional workaround for routers that break TCP
+ An optional workaround for routers that break TCP
window scaling.
<b>ADDRESS REWRITING CONTROLS</b>
- See the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document for a detailed
+ See the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document for a detailed
discussion of Postfix address rewriting.
<b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
- Enable or disable recipient validation, built-in
+ Enable or disable recipient validation, built-in
content filtering, or address mapping.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> (<a href="postconf.5.html#permit_inet_interfaces">permit_inet_interfaces</a>)</b>
Rewrite message header addresses in mail from these
- clients and update incomplete addresses with the
+ clients and update incomplete addresses with the
domain name in $<a href="postconf.5.html#myorigin">myorigin</a> or $<a href="postconf.5.html#mydomain">mydomain</a>; either don't
- rewrite message headers from other clients at all,
- or rewrite message headers and update incomplete
- addresses with the domain specified in the
+ rewrite message headers from other clients at all,
+ or rewrite message headers and update incomplete
+ addresses with the domain specified in the
<a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter.
<b>AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS</b>
- As of version 1.0, Postfix can be configured to send new
- mail to an external content filter AFTER the mail is
- queued. This content filter is expected to inject mail
- back into a (Postfix or other) MTA for further delivery.
+ As of version 1.0, Postfix can be configured to send new
+ mail to an external content filter AFTER the mail is
+ queued. This content filter is expected to inject mail
+ back into a (Postfix or other) MTA for further delivery.
See the <a href="FILTER_README.html">FILTER_README</a> document for details.
<b><a href="postconf.5.html#content_filter">content_filter</a> (empty)</b>
- The name of a mail delivery transport that filters
+ The name of a mail delivery transport that filters
mail after it is queued.
<b>BEFORE QUEUE EXTERNAL CONTENT INSPECTION CONTROLS</b>
- As of version 2.1, the Postfix SMTP server can be config-
- ured to send incoming mail to a real-time SMTP-based con-
+ As of version 2.1, the Postfix SMTP server can be config-
+ ured to send incoming mail to a real-time SMTP-based con-
tent filter BEFORE mail is queued. This content filter is
- expected to inject mail back into Postfix. See the
- <a href="SMTPD_PROXY_README.html">SMTPD_PROXY_README</a> document for details on how to config-
+ expected to inject mail back into Postfix. See the
+ <a href="SMTPD_PROXY_README.html">SMTPD_PROXY_README</a> document for details on how to config-
ure and operate this feature.
<b><a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a> (empty)</b>
- The hostname and TCP port of the mail filtering
+ The hostname and TCP port of the mail filtering
proxy server.
<b><a href="postconf.5.html#smtpd_proxy_ehlo">smtpd_proxy_ehlo</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
How the Postfix SMTP server announces itself to the
proxy filter.
+ <b><a href="postconf.5.html#smtpd_proxy_options">smtpd_proxy_options</a> (empty)</b>
+ List of options that control how the Postfix SMTP
+ server communicates with a before-queue content
+ filter.
+
<b><a href="postconf.5.html#smtpd_proxy_timeout">smtpd_proxy_timeout</a> (100s)</b>
The time limit for connecting to a proxy filter and
for sending or receiving information.
<b>BEFORE QUEUE MILTER CONTROLS</b>
As of version 2.3, Postfix supports the Sendmail version 8
- Milter (mail filter) protocol. These content filters run
- outside Postfix. They can inspect the SMTP command stream
- and the message content, and can request modifications
- before mail is queued. For details see the <a href="MILTER_README.html">MILTER_README</a>
+ Milter (mail filter) protocol. These content filters run
+ outside Postfix. They can inspect the SMTP command stream
+ and the message content, and can request modifications
+ before mail is queued. For details see the <a href="MILTER_README.html">MILTER_README</a>
document.
<b><a href="postconf.5.html#smtpd_milters">smtpd_milters</a> (empty)</b>
A list of Milter (mail filter) applications for new
- mail that arrives via the Postfix <a href="smtpd.8.html"><b>smtpd</b>(8)</a> server.
+ mail that arrives via the Postfix <a href="smtpd.8.html"><b>smtpd</b>(8)</a> server.
<b><a href="postconf.5.html#milter_protocol">milter_protocol</a> (6)</b>
- The mail filter protocol version and optional pro-
- tocol extensions for communication with a Milter
- application; prior to Postfix 2.6 the default pro-
+ The mail filter protocol version and optional pro-
+ tocol extensions for communication with a Milter
+ application; prior to Postfix 2.6 the default pro-
tocol is 2.
<b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b>
- The default action when a Milter (mail filter)
+ The default action when a Milter (mail filter)
application is unavailable or mis-configured.
<b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
cations.
<b><a href="postconf.5.html#milter_connect_timeout">milter_connect_timeout</a> (30s)</b>
- The time limit for connecting to a Milter (mail
- filter) application, and for negotiating protocol
+ The time limit for connecting to a Milter (mail
+ filter) application, and for negotiating protocol
options.
<b><a href="postconf.5.html#milter_command_timeout">milter_command_timeout</a> (30s)</b>
- The time limit for sending an SMTP command to a
+ The time limit for sending an SMTP command to a
Milter (mail filter) application, and for receiving
the response.
<b><a href="postconf.5.html#milter_content_timeout">milter_content_timeout</a> (300s)</b>
- The time limit for sending message content to a
+ The time limit for sending message content to a
Milter (mail filter) application, and for receiving
the response.
<b><a href="postconf.5.html#milter_connect_macros">milter_connect_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter)
- applications after completion of an SMTP connec-
+ The macros that are sent to Milter (mail filter)
+ applications after completion of an SMTP connec-
tion.
<b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter)
+ The macros that are sent to Milter (mail filter)
applications after the SMTP HELO or EHLO command.
<b><a href="postconf.5.html#milter_mail_macros">milter_mail_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter)
+ The macros that are sent to Milter (mail filter)
applications after the SMTP MAIL FROM command.
<b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter)
+ The macros that are sent to Milter (mail filter)
applications after the SMTP RCPT TO command.
<b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to version 4 or higher
- Milter (mail filter) applications after the SMTP
+ The macros that are sent to version 4 or higher
+ Milter (mail filter) applications after the SMTP
DATA command.
<b><a href="postconf.5.html#milter_unknown_command_macros">milter_unknown_command_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to version 3 or higher
- Milter (mail filter) applications after an unknown
+ The macros that are sent to version 3 or higher
+ Milter (mail filter) applications after an unknown
SMTP command.
<b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter)
+ The macros that are sent to Milter (mail filter)
applications after the end of the message header.
<b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter)
+ The macros that are sent to Milter (mail filter)
applications after the message end-of-data.
<b>GENERAL CONTENT INSPECTION CONTROLS</b>
- The following parameters are applicable for both built-in
+ The following parameters are applicable for both built-in
and external content filters.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
- Enable or disable recipient validation, built-in
+ Enable or disable recipient validation, built-in
content filtering, or address mapping.
<b>EXTERNAL CONTENT INSPECTION CONTROLS</b>
- The following parameters are applicable for both before-
+ The following parameters are applicable for both before-
queue and after-queue content filtering.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_xforward_hosts">smtpd_authorized_xforward_hosts</a> (empty)</b>
- What SMTP clients are allowed to use the XFORWARD
+ What SMTP clients are allowed to use the XFORWARD
feature.
<b>SASL AUTHENTICATION CONTROLS</b>
- Postfix SASL support (<a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a>) can be used to authenti-
- cate remote SMTP clients to the Postfix SMTP server, and
- to authenticate the Postfix SMTP client to a remote SMTP
+ Postfix SASL support (<a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a>) can be used to authenti-
+ cate remote SMTP clients to the Postfix SMTP server, and
+ to authenticate the Postfix SMTP client to a remote SMTP
server. See the <a href="SASL_README.html">SASL_README</a> document for details.
<b><a href="postconf.5.html#broken_sasl_auth_clients">broken_sasl_auth_clients</a> (no)</b>
- Enable inter-operability with SMTP clients that
- implement an obsolete version of the AUTH command
+ Enable inter-operability with SMTP clients that
+ implement an obsolete version of the AUTH command
(<a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a>).
<b><a href="postconf.5.html#smtpd_sasl_auth_enable">smtpd_sasl_auth_enable</a> (no)</b>
- Enable SASL authentication in the Postfix SMTP
+ Enable SASL authentication in the Postfix SMTP
server.
<b><a href="postconf.5.html#smtpd_sasl_local_domain">smtpd_sasl_local_domain</a> (empty)</b>
- The name of the Postfix SMTP server's local SASL
+ The name of the Postfix SMTP server's local SASL
authentication realm.
<b><a href="postconf.5.html#smtpd_sasl_security_options">smtpd_sasl_security_options</a> (noanonymous)</b>
- Postfix SMTP server SASL security options; as of
- Postfix 2.3 the list of available features depends
- on the SASL server implementation that is selected
+ Postfix SMTP server SASL security options; as of
+ Postfix 2.3 the list of available features depends
+ on the SASL server implementation that is selected
with <b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b>.
<b><a href="postconf.5.html#smtpd_sender_login_maps">smtpd_sender_login_maps</a> (empty)</b>
- Optional lookup table with the SASL login names
+ Optional lookup table with the SASL login names
that own sender (MAIL FROM) addresses.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_sasl_exceptions_networks">smtpd_sasl_exceptions_networks</a> (empty)</b>
- What remote SMTP clients the Postfix SMTP server
+ What remote SMTP clients the Postfix SMTP server
will not offer AUTH support to.
Available in Postfix version 2.1 and 2.2:
<b>smtpd_sasl_application_name (smtpd)</b>
- The application name that the Postfix SMTP server
+ The application name that the Postfix SMTP server
uses for SASL server initialization.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_sasl_authenticated_header">smtpd_sasl_authenticated_header</a> (no)</b>
- Report the SASL authenticated user name in the
+ Report the SASL authenticated user name in the
<a href="smtpd.8.html"><b>smtpd</b>(8)</a> Received message header.
<b><a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a> (smtpd)</b>
- Implementation-specific information that the Post-
- fix SMTP server passes through to the SASL plug-in
- implementation that is selected with
+ Implementation-specific information that the Post-
+ fix SMTP server passes through to the SASL plug-in
+ implementation that is selected with
<b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b>.
<b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a> (cyrus)</b>
- The SASL plug-in type that the Postfix SMTP server
+ The SASL plug-in type that the Postfix SMTP server
should use for authentication.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#cyrus_sasl_config_path">cyrus_sasl_config_path</a> (empty)</b>
- Search path for Cyrus SASL application configura-
- tion files, currently used only to locate the
+ Search path for Cyrus SASL application configura-
+ tion files, currently used only to locate the
$<a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a>.conf file.
<b>STARTTLS SUPPORT CONTROLS</b>
- Detailed information about STARTTLS configuration may be
+ Detailed information about STARTTLS configuration may be
found in the <a href="TLS_README.html">TLS_README</a> document.
<b><a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> (empty)</b>
- The SMTP TLS security level for the Postfix SMTP
- server; when a non-empty value is specified, this
+ The SMTP TLS security level for the Postfix SMTP
+ server; when a non-empty value is specified, this
overrides the obsolete parameters <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> and
<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>.
<b><a href="postconf.5.html#smtpd_sasl_tls_security_options">smtpd_sasl_tls_security_options</a> ($<a href="postconf.5.html#smtpd_sasl_security_options">smtpd_sasl_secu</a>-</b>
<b><a href="postconf.5.html#smtpd_sasl_security_options">rity_options</a>)</b>
- The SASL authentication security options that the
- Postfix SMTP server uses for TLS encrypted SMTP
+ The SASL authentication security options that the
+ Postfix SMTP server uses for TLS encrypted SMTP
sessions.
<b><a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> (300s)</b>
- The time limit for Postfix SMTP server write and
- read operations during TLS startup and shutdown
+ The time limit for Postfix SMTP server write and
+ read operations during TLS startup and shutdown
handshake procedures.
<b><a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> (empty)</b>
- A file containing (PEM format) CA certificates of
- root CAs trusted to sign either remote SMTP client
+ A file containing (PEM format) CA certificates of
+ root CAs trusted to sign either remote SMTP client
certificates or intermediate CA certificates.
<b><a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> (empty)</b>
A directory containing (PEM format) CA certificates
- of root CAs trusted to sign either remote SMTP
- client certificates or intermediate CA certifi-
+ of root CAs trusted to sign either remote SMTP
+ client certificates or intermediate CA certifi-
cates.
<b><a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_session_ids</a> (yes)</b>
- Force the Postfix SMTP server to issue a TLS ses-
- sion id, even when TLS session caching is turned
+ Force the Postfix SMTP server to issue a TLS ses-
+ sion id, even when TLS session caching is turned
off (<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> is empty).
<b><a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> (no)</b>
- Ask a remote SMTP client for a client certificate.
+ Ask a remote SMTP client for a client certificate.
<b><a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> (no)</b>
When TLS encryption is optional in the Postfix SMTP
- server, do not announce or accept SASL authentica-
+ server, do not announce or accept SASL authentica-
tion over unencrypted connections.
<b><a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a> (9)</b>
- The verification depth for remote SMTP client cer-
+ The verification depth for remote SMTP client cer-
tificates.
<b><a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> (empty)</b>
- File with the Postfix SMTP server RSA certificate
+ File with the Postfix SMTP server RSA certificate
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a> (empty)</b>
SMTP server cipher list at all TLS security levels.
<b><a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> (empty)</b>
- File with the Postfix SMTP server DSA certificate
+ File with the Postfix SMTP server DSA certificate
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> (empty)</b>
- File with DH parameters that the Postfix SMTP
+ File with DH parameters that the Postfix SMTP
server should use with EDH ciphers.
<b><a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> (empty)</b>
- File with DH parameters that the Postfix SMTP
+ File with DH parameters that the Postfix SMTP
server should use with EDH ciphers.
<b><a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b>
- File with the Postfix SMTP server DSA private key
+ File with the Postfix SMTP server DSA private key
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> ($<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b>
- File with the Postfix SMTP server RSA private key
+ File with the Postfix SMTP server RSA private key
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> (0)</b>
- Enable additional Postfix SMTP server logging of
+ Enable additional Postfix SMTP server logging of
TLS activity.
<b><a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_mandatory_ciphers</a> (medium)</b>
- The minimum TLS cipher grade that the Postfix SMTP
+ The minimum TLS cipher grade that the Postfix SMTP
server will use with mandatory TLS encryption.
<b><a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_mandatory_exclude_ciphers</a> (empty)</b>
- Additional list of ciphers or cipher types to
- exclude from the SMTP server cipher list at manda-
+ Additional list of ciphers or cipher types to
+ exclude from the SMTP server cipher list at manda-
tory TLS security levels.
<b><a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> (SSLv3, TLSv1)</b>
- The SSL/TLS protocols accepted by the Postfix SMTP
+ The SSL/TLS protocols accepted by the Postfix SMTP
server with mandatory TLS encryption.
<b><a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> (no)</b>
Request that the Postfix SMTP server produces
Received: message headers that include information
- about the protocol and cipher used, as well as the
- client CommonName and client certificate issuer
+ about the protocol and cipher used, as well as the
+ client CommonName and client certificate issuer
CommonName.
<b><a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a> (no)</b>
- With mandatory TLS encryption, require a trusted
- remote SMTP client certificate in order to allow
+ With mandatory TLS encryption, require a trusted
+ remote SMTP client certificate in order to allow
TLS connections to proceed.
<b><a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> (empty)</b>
- Name of the file containing the optional Postfix
+ Name of the file containing the optional Postfix
SMTP server TLS session cache.
<b><a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> (3600s)</b>
sion cache information.
<b><a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a> (no)</b>
- Run the Postfix SMTP server in the non-standard
- "wrapper" mode, instead of using the STARTTLS com-
+ Run the Postfix SMTP server in the non-standard
+ "wrapper" mode, instead of using the STARTTLS com-
mand.
<b><a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> (32)</b>
- The number of pseudo-random bytes that an <a href="smtp.8.html"><b>smtp</b>(8)</a>
- or <a href="smtpd.8.html"><b>smtpd</b>(8)</a> process requests from the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a>
- server in order to seed its internal pseudo random
+ The number of pseudo-random bytes that an <a href="smtp.8.html"><b>smtp</b>(8)</a>
+ or <a href="smtpd.8.html"><b>smtpd</b>(8)</a> process requests from the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a>
+ server in order to seed its internal pseudo random
number generator (PRNG).
<b><a href="postconf.5.html#tls_high_cipherlist">tls_high_cipherlist</a></b>
ciphers.
<b><a href="postconf.5.html#tls_low_cipherlist">tls_low_cipherlist</a> (ALL:!EXPORT:+RC4:@STRENGTH)</b>
- The OpenSSL cipherlist for "LOW" or higher grade
+ The OpenSSL cipherlist for "LOW" or higher grade
ciphers.
<b><a href="postconf.5.html#tls_export_cipherlist">tls_export_cipherlist</a> (ALL:+RC4:@STRENGTH)</b>
ciphers.
<b><a href="postconf.5.html#tls_null_cipherlist">tls_null_cipherlist</a> (eNULL:!aNULL)</b>
- The OpenSSL cipherlist for "NULL" grade ciphers
+ The OpenSSL cipherlist for "NULL" grade ciphers
that provide authentication without encryption.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> (md5)</b>
- The message digest algorithm used to construct
+ The message digest algorithm used to construct
client-certificate fingerprints for
<b><a href="postconf.5.html#check_ccert_access">check_ccert_access</a></b> and <b><a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a></b>.
Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> (empty)</b>
- List of TLS protocols that the Postfix SMTP server
- will exclude or include with opportunistic TLS
+ List of TLS protocols that the Postfix SMTP server
+ will exclude or include with opportunistic TLS
encryption.
<b><a href="postconf.5.html#smtpd_tls_ciphers">smtpd_tls_ciphers</a> (export)</b>
- The minimum TLS cipher grade that the Postfix SMTP
- server will use with opportunistic TLS encryption.
+ The minimum TLS cipher grade that the Postfix SMTP
+ server will use with opportunistic TLS encryption.
<b><a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a> (empty)</b>
File with the Postfix SMTP server ECDSA certificate
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> (see 'postconf -d' output)</b>
- The Postfix SMTP server security grade for
+ The Postfix SMTP server security grade for
ephemeral elliptic-curve Diffie-Hellman (EECDH) key
exchange.
imally strong ephemeral ECDH key exchange.
<b>OBSOLETE STARTTLS CONTROLS</b>
- The following configuration parameters exist for compati-
+ The following configuration parameters exist for compati-
bility with Postfix versions before 2.3. Support for these
will be removed in a future release.
<b><a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> (no)</b>
- Opportunistic TLS: announce STARTTLS support to
- SMTP clients, but do not require that clients use
+ Opportunistic TLS: announce STARTTLS support to
+ SMTP clients, but do not require that clients use
TLS encryption.
<b><a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> (no)</b>
- Mandatory TLS: announce STARTTLS support to SMTP
- clients, and require that clients use TLS encryp-
+ Mandatory TLS: announce STARTTLS support to SMTP
+ clients, and require that clients use TLS encryp-
tion.
<b><a href="postconf.5.html#smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> (empty)</b>
server TLS cipher list.
<b>VERP SUPPORT CONTROLS</b>
- With VERP style delivery, each recipient of a message
+ With VERP style delivery, each recipient of a message
receives a customized copy of the message with his/her own
- recipient address encoded in the envelope sender address.
+ recipient address encoded in the envelope sender address.
The <a href="VERP_README.html">VERP_README</a> file describes configuration and operation
- details of Postfix support for variable envelope return
+ details of Postfix support for variable envelope return
path addresses. VERP style delivery is requested with the
- SMTP XVERP command or with the "sendmail -V" command-line
- option and is available in Postfix version 1.1 and later.
+ SMTP XVERP command or with the "sendmail -V" command-line
+ option and is available in Postfix version 1.1 and later.
<b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a> (+=)</b>
The two default VERP delimiter characters.
<b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
- The characters Postfix accepts as VERP delimiter
- characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
+ The characters Postfix accepts as VERP delimiter
+ characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
and in SMTP commands.
Available in Postfix version 1.1 and 2.0:
<b><a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- What SMTP clients are allowed to specify the XVERP
+ What SMTP clients are allowed to specify the XVERP
command.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_verp_clients">smtpd_authorized_verp_clients</a> ($<a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a>)</b>
- What SMTP clients are allowed to specify the XVERP
+ What SMTP clients are allowed to specify the XVERP
command.
<b>TROUBLE SHOOTING CONTROLS</b>
- The <a href="DEBUG_README.html">DEBUG_README</a> document describes how to debug parts of
- the Postfix mail system. The methods vary from making the
- software log a lot of detail, to running some daemon pro-
+ The <a href="DEBUG_README.html">DEBUG_README</a> document describes how to debug parts of
+ the Postfix mail system. The methods vary from making the
+ software log a lot of detail, to running some daemon pro-
cesses under control of a call tracer or debugger.
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ The increment in verbose logging level when a
+ remote client or server matches a pattern in the
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
<b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
- Optional list of remote client or server hostname
- or network address patterns that cause the verbose
- logging level to increase by the amount specified
+ Optional list of remote client or server hostname
+ or network address patterns that cause the verbose
+ logging level to increase by the amount specified
in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
<b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
<b><a href="postconf.5.html#internal_mail_filter_classes">internal_mail_filter_classes</a> (empty)</b>
- What categories of Postfix-generated mail are sub-
- ject to before-queue content inspection by
+ What categories of Postfix-generated mail are sub-
+ ject to before-queue content inspection by
<a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a>, <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>.
<b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a> (empty)</b>
- What SMTP clients are allowed to use the XCLIENT
+ What SMTP clients are allowed to use the XCLIENT
feature.
<b>KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS</b>
- As of Postfix version 2.0, the SMTP server rejects mail
- for unknown recipients. This prevents the mail queue from
- clogging up with undeliverable MAILER-DAEMON messages.
- Additional information on this topic is in the
+ As of Postfix version 2.0, the SMTP server rejects mail
+ for unknown recipients. This prevents the mail queue from
+ clogging up with undeliverable MAILER-DAEMON messages.
+ Additional information on this topic is in the
<a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a> and <a href="ADDRESS_CLASS_README.html">ADDRESS_CLASS_README</a> documents.
<b><a href="postconf.5.html#show_user_unknown_table_name">show_user_unknown_table_name</a> (yes)</b>
- Display the name of the recipient table in the
+ Display the name of the recipient table in the
"User unknown" responses.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for message
+ Optional address mapping lookup tables for message
headers and envelopes.
<b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, local-</b>
<b>host)</b>
- The list of domains that are delivered via the
+ The list of domains that are delivered via the
$<a href="postconf.5.html#local_transport">local_transport</a> mail delivery transport.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
<b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
- The Internet protocols Postfix will attempt to use
+ The Internet protocols Postfix will attempt to use
when making or accepting connections.
<b><a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> (<a href="proxymap.8.html">proxy</a>:unix:passwd.byname</b>
<b>$<a href="postconf.5.html#alias_maps">alias_maps</a>)</b>
- Lookup tables with all names or addresses of local
- recipients: a recipient address is local when its
- domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
+ Lookup tables with all names or addresses of local
+ recipients: a recipient address is local when its
+ domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
<b><a href="postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
- when a recipient address is local, and
- $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a list of lookup
+ The numerical Postfix SMTP server response code
+ when a recipient address is local, and
+ $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a list of lookup
tables that does not match the recipient.
- Parameters concerning known/unknown recipients of relay
+ Parameters concerning known/unknown recipients of relay
destinations:
<b><a href="postconf.5.html#relay_domains">relay_domains</a> ($<a href="postconf.5.html#mydestination">mydestination</a>)</b>
- What destination domains (and subdomains thereof)
+ What destination domains (and subdomains thereof)
this system will relay mail to.
<b><a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> (empty)</b>
- Optional lookup tables with all valid addresses in
+ Optional lookup tables with all valid addresses in
the domains that match $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#unknown_relay_recipient_reject_code">unknown_relay_recipient_reject_code</a> (550)</b>
The numerical Postfix SMTP server reply code when a
- recipient address matches $<a href="postconf.5.html#relay_domains">relay_domains</a>, and
- <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies a list of lookup
+ recipient address matches $<a href="postconf.5.html#relay_domains">relay_domains</a>, and
+ <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies a list of lookup
tables that does not match the recipient address.
- Parameters concerning known/unknown recipients in virtual
+ Parameters concerning known/unknown recipients in virtual
alias domains:
<b><a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> ($<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>)</b>
Postfix is final destination for the specified list
- of virtual alias domains, that is, domains for
- which all addresses are aliased to addresses in
+ of virtual alias domains, that is, domains for
+ which all addresses are aliased to addresses in
other local or remote domains.
<b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
- Optional lookup tables that alias specific mail
- addresses or domains to other local or remote
+ Optional lookup tables that alias specific mail
+ addresses or domains to other local or remote
address.
<b><a href="postconf.5.html#unknown_virtual_alias_reject_code">unknown_virtual_alias_reject_code</a> (550)</b>
The SMTP server reply code when a recipient address
- matches $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, and $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
- <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of lookup tables
+ matches $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, and $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
+ <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of lookup tables
that does not match the recipient address.
- Parameters concerning known/unknown recipients in virtual
+ Parameters concerning known/unknown recipients in virtual
mailbox domains:
<b><a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> ($<a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a>)</b>
Postfix is final destination for the specified list
- of domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">vir</a>-
+ of domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">vir</a>-
<a href="postconf.5.html#virtual_transport">tual_transport</a> mail delivery transport.
<b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> (empty)</b>
- Optional lookup tables with all valid addresses in
+ Optional lookup tables with all valid addresses in
the domains that match $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
<b><a href="postconf.5.html#unknown_virtual_mailbox_reject_code">unknown_virtual_mailbox_reject_code</a> (550)</b>
The SMTP server reply code when a recipient address
- matches $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, and $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
+ matches $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, and $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
<a href="postconf.5.html#virtual_mailbox_maps">tual_mailbox_maps</a> specifies a list of lookup tables
that does not match the recipient address.
<b>RESOURCE AND RATE CONTROLS</b>
- The following parameters limit resource usage by the SMTP
+ The following parameters limit resource usage by the SMTP
server and/or control client request rates.
<b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
- Upon input, long lines are chopped up into pieces
- of at most this length; upon delivery, long lines
+ Upon input, long lines are chopped up into pieces
+ of at most this length; upon delivery, long lines
are reconstructed.
<b><a href="postconf.5.html#queue_minfree">queue_minfree</a> (0)</b>
- The minimal amount of free space in bytes in the
+ The minimal amount of free space in bytes in the
queue file system that is needed to receive mail.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
- The maximal size in bytes of a message, including
+ The maximal size in bytes of a message, including
envelope information.
<b><a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a> (1000)</b>
- The maximal number of recipients that the Postfix
+ The maximal number of recipients that the Postfix
SMTP server accepts per message delivery request.
<b><a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> (normal: 300s, stress: 10s)</b>
- The time limit for sending a Postfix SMTP server
- response and for receiving a remote SMTP client
+ The time limit for sending a Postfix SMTP server
+ response and for receiving a remote SMTP client
request.
<b><a href="postconf.5.html#smtpd_history_flush_threshold">smtpd_history_flush_threshold</a> (100)</b>
- The maximal number of lines in the Postfix SMTP
- server command history before it is flushed upon
+ The maximal number of lines in the Postfix SMTP
+ server command history before it is flushed upon
receipt of EHLO, RSET, or end of DATA.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_peername_lookup">smtpd_peername_lookup</a> (yes)</b>
Attempt to look up the remote SMTP client hostname,
- and verify that the name matches the client IP
+ and verify that the name matches the client IP
address.
The per SMTP client connection count and request rate lim-
its are implemented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> ser-
- vice, and are available in Postfix version 2.2 and later.
+ vice, and are available in Postfix version 2.2 and later.
<b><a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a> (50)</b>
- How many simultaneous connections any client is
+ How many simultaneous connections any client is
allowed to make to this service.
<b><a href="postconf.5.html#smtpd_client_connection_rate_limit">smtpd_client_connection_rate_limit</a> (0)</b>
The maximal number of connection attempts any
- client is allowed to make to this service per time
+ client is allowed to make to this service per time
unit.
<b><a href="postconf.5.html#smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a> (0)</b>
- The maximal number of message delivery requests
- that any client is allowed to make to this service
+ The maximal number of message delivery requests
+ that any client is allowed to make to this service
per time unit, regardless of whether or not Postfix
actually accepts those messages.
<b><a href="postconf.5.html#smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a> (0)</b>
- The maximal number of recipient addresses that any
- client is allowed to send to this service per time
+ The maximal number of recipient addresses that any
+ client is allowed to send to this service per time
unit, regardless of whether or not Postfix actually
accepts those recipients.
<b><a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- Clients that are excluded from connection count,
+ Clients that are excluded from connection count,
connection rate, or SMTP request rate restrictions.
Available in Postfix version 2.3 and later:
tiate with this service per time unit.
<b>TARPIT CONTROLS</b>
- When a remote SMTP client makes errors, the Postfix SMTP
- server can insert delays before responding. This can help
- to slow down run-away software. The behavior is con-
- trolled by an error counter that counts the number of
- errors within an SMTP session that a client makes without
+ When a remote SMTP client makes errors, the Postfix SMTP
+ server can insert delays before responding. This can help
+ to slow down run-away software. The behavior is con-
+ trolled by an error counter that counts the number of
+ errors within an SMTP session that a client makes without
delivering mail.
<b><a href="postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time</a> (1s)</b>
With Postfix version 2.1 and later: the SMTP server
- response delay after a client has made more than
- $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> errors, and fewer than
- $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without delivering
+ response delay after a client has made more than
+ $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> errors, and fewer than
+ $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without delivering
mail.
<b><a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> (10)</b>
- The number of errors a remote SMTP client is
- allowed to make without delivering mail before the
+ The number of errors a remote SMTP client is
+ allowed to make without delivering mail before the
Postfix SMTP server slows down all its responses.
<b><a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> (normal: 20, stress: 1)</b>
- The maximal number of errors a remote SMTP client
+ The maximal number of errors a remote SMTP client
is allowed to make without delivering mail.
<b><a href="postconf.5.html#smtpd_junk_command_limit">smtpd_junk_command_limit</a> (normal: 100, stress: 1)</b>
- The number of junk commands (NOOP, VRFY, ETRN or
+ The number of junk commands (NOOP, VRFY, ETRN or
RSET) that a remote SMTP client can send before the
- Postfix SMTP server starts to increment the error
+ Postfix SMTP server starts to increment the error
counter with each junk command.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_recipient_overshoot_limit">smtpd_recipient_overshoot_limit</a> (1000)</b>
- The number of recipients that a remote SMTP client
- can send in excess of the limit specified with
+ The number of recipients that a remote SMTP client
+ can send in excess of the limit specified with
$<a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a>, before the Postfix SMTP
- server increments the per-session error count for
+ server increments the per-session error count for
each excess recipient.
<b>ACCESS POLICY DELEGATION CONTROLS</b>
- As of version 2.1, Postfix can be configured to delegate
- access policy decisions to an external server that runs
- outside Postfix. See the file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
+ As of version 2.1, Postfix can be configured to delegate
+ access policy decisions to an external server that runs
+ outside Postfix. See the file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
more information.
<b><a href="postconf.5.html#smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a> (300s)</b>
- The time after which an idle SMTPD policy service
+ The time after which an idle SMTPD policy service
connection is closed.
<b><a href="postconf.5.html#smtpd_policy_service_max_ttl">smtpd_policy_service_max_ttl</a> (1000s)</b>
connection is closed.
<b><a href="postconf.5.html#smtpd_policy_service_timeout">smtpd_policy_service_timeout</a> (100s)</b>
- The time limit for connecting to, writing to or
+ The time limit for connecting to, writing to or
receiving from a delegated SMTPD policy server.
<b>ACCESS CONTROLS</b>
- The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
+ The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
all the SMTP server access control features.
<b><a href="postconf.5.html#smtpd_delay_reject">smtpd_delay_reject</a> (yes)</b>
- Wait until the RCPT TO command before evaluating
+ Wait until the RCPT TO command before evaluating
$<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a>, $smtpd_helo_restric-
tions and $<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a>, or wait until
- the ETRN command before evaluating
+ the ETRN command before evaluating
$<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> and $smtpd_helo_restric-
tions.
- <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
+ <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
<b>put)</b>
What Postfix features match subdomains of
"domain.tld" automatically, instead of requiring an
explicit ".domain.tld" pattern.
<b><a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> (empty)</b>
- Optional SMTP server access restrictions in the
+ Optional SMTP server access restrictions in the
context of a client SMTP connection request.
<b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b>
Require that a remote SMTP client introduces itself
- at the beginning of an SMTP session with the HELO
+ at the beginning of an SMTP session with the HELO
or EHLO command.
<b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server
+ Optional restrictions that the Postfix SMTP server
applies in the context of the SMTP HELO command.
<b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server
+ Optional restrictions that the Postfix SMTP server
applies in the context of the MAIL FROM command.
<b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b>
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b>
The access restrictions that the Postfix SMTP
- server applies in the context of the RCPT TO com-
+ server applies in the context of the RCPT TO com-
mand.
<b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
- Optional SMTP server access restrictions in the
+ Optional SMTP server access restrictions in the
context of a client ETRN request.
<b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b>
- Forward mail with sender-specified routing
- (user[@%!]remote[@%!]site) from untrusted clients
+ Forward mail with sender-specified routing
+ (user[@%!]remote[@%!]site) from untrusted clients
to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b>
- User-defined aliases for groups of access restric-
+ User-defined aliases for groups of access restric-
tions.
<b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b><><b>)</b>
- The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
+ The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
instead of the null sender address.
<b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b>
Restrict the use of the <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a> SMTP
- access feature to only domains whose primary MX
+ access feature to only domains whose primary MX
hosts match the listed networks.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b>
- Optional access restrictions that the Postfix SMTP
+ Optional access restrictions that the Postfix SMTP
server applies in the context of the SMTP DATA com-
mand.
<b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b>
- What characters are allowed in $name expansions of
+ What characters are allowed in $name expansions of
RBL reply templates.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
- Request that the Postfix SMTP server rejects mail
- from unknown sender addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
+ Request that the Postfix SMTP server rejects mail
+ from unknown sender addresses, even when no
+ explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
is specified.
<b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b>
- Request that the Postfix SMTP server rejects mail
+ Request that the Postfix SMTP server rejects mail
for unknown recipient addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
+ explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
tion is specified.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b>
- Optional access restrictions that the Postfix SMTP
- server applies in the context of the SMTP END-OF-
+ Optional access restrictions that the Postfix SMTP
+ server applies in the context of the SMTP END-OF-
DATA command.
<b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
- Postfix version 2.1 introduces sender and recipient
- address verification. This feature is implemented by
- sending probe email messages that are not actually deliv-
- ered. This feature is requested via the reject_unveri-
- fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
- restrictions. The status of verification probes is main-
+ Postfix version 2.1 introduces sender and recipient
+ address verification. This feature is implemented by
+ sending probe email messages that are not actually deliv-
+ ered. This feature is requested via the reject_unveri-
+ fied_sender and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
+ restrictions. The status of verification probes is main-
tained by the <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VER</a>-
- <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
+ <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
and operate the Postfix sender/recipient address verifica-
tion service.
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (3)</b>
- How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
- the completion of an address verification request
+ How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
+ the completion of an address verification request
in progress.
<b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b>
- The delay between queries for the completion of an
+ The delay between queries for the completion of an
address verification request in progress.
<b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> ($<a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a>)</b>
- The sender address to use in address verification
+ The sender address to use in address verification
probes; prior to Postfix 2.5 the default was "post-
master".
<b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a recipient address is rejected by the
+ The numerical Postfix SMTP server response code
+ when a recipient address is rejected by the
<a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction.
<b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response when a
+ The numerical Postfix SMTP server response when a
recipient address is rejected by the reject_unveri-
fied_recipient restriction.
Available in Postfix version 2.6 and later:
<b><a href="postconf.5.html#unverified_sender_defer_code">unverified_sender_defer_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a sender address probe fails due to a tempo-
+ The numerical Postfix SMTP server response code
+ when a sender address probe fails due to a tempo-
rary error condition.
<b><a href="postconf.5.html#unverified_recipient_defer_code">unverified_recipient_defer_code</a> (450)</b>
- The numerical Postfix SMTP server response when a
- recipient address probe fails due to a temporary
+ The numerical Postfix SMTP server response when a
+ recipient address probe fails due to a temporary
error condition.
<b><a href="postconf.5.html#unverified_sender_reject_reason">unverified_sender_reject_reason</a> (empty)</b>
<b><a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unver</a>-
- <a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
+ <a href="postconf.5.html#reject_unverified_sender">ified_sender</a> fails due to a temporary error condi-
tion.
<b><a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
dition.
<b>ACCESS CONTROL RESPONSES</b>
- The following parameters control numerical SMTP reply
+ The following parameters control numerical SMTP reply
codes and/or text responses.
<b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b>
an <a href="access.5.html"><b>access</b>(5)</a> map "reject" action.
<b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "defer" restriction.
<b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
- The numerical Postfix SMTP server response code
- when the client HELO or EHLO command parameter is
- rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
+ The numerical Postfix SMTP server response code
+ when the client HELO or EHLO command parameter is
+ rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
restriction.
<b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>, <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>,
<a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a> or <a href="postconf.5.html#reject_rhsbl_recipient">reject_rhsbl_recipient</a>
<b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
The numerical Postfix SMTP server reply code when a
- client request is rejected by the
+ client request is rejected by the
<a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
<a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
restriction.
<b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a request is rejected by the <b>reject_plain-</b>
+ The numerical Postfix SMTP server response code
+ when a request is rejected by the <b>reject_plain-</b>
<b>text_session</b> restriction.
<b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "reject" restriction.
<b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a client request is rejected by the
+ The numerical Postfix SMTP server response code
+ when a client request is rejected by the
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
<b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a sender or recipient address is rejected by
+ The numerical Postfix SMTP server response code
+ when a sender or recipient address is rejected by
the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
<b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a client without valid address <=> name map-
+ The numerical Postfix SMTP server response code
+ when a client without valid address <=> name map-
ping is rejected by the reject_unknown_client_host-
name restriction.
<b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when the hostname specified with the HELO or EHLO
- command is rejected by the
+ The numerical Postfix SMTP server response code
+ when the hostname specified with the HELO or EHLO
+ command is rejected by the
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
- The default SMTP server response template for a
- request that is rejected by an RBL-based restric-
+ The default SMTP server response template for a
+ request that is rejected by an RBL-based restric-
tion.
<b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
<b><a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> (450)</b>
The numerical Postfix SMTP server response code for
- an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
+ an <a href="access.5.html"><b>access</b>(5)</a> map "defer" action, including
"<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" or "<a href="postconf.5.html#defer_if_reject">defer_if_reject</a>".
<b><a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a> (<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>)</b>
The Postfix SMTP server's action when a reject-type
- restriction fails due to a temporary error condi-
+ restriction fails due to a temporary error condi-
tion.
<b><a href="postconf.5.html#unknown_helo_hostname_tempfail_action">unknown_helo_hostname_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_temp</a>-</b>
<b><a href="postconf.5.html#reject_tempfail_action">fail_action</a>)</b>
- The Postfix SMTP server's action when
+ The Postfix SMTP server's action when
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> fails due to an tempo-
rary error condition.
<b><a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b>
- The Postfix SMTP server's action when
+ The Postfix SMTP server's action when
<a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
- <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
+ <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> fail due to a tem-
porary error condition.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
- The location of all postfix administrative com-
+ The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
and most Postfix daemon processes.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of incoming connections that a
- Postfix daemon process will service before termi-
+ The maximal number of incoming connections that a
+ Postfix daemon process will service before termi-
nating voluntarily.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
The internet hostname of this mail system.
<b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
- The list of "trusted" SMTP clients that have more
+ The list of "trusted" SMTP clients that have more
privileges than "strangers".
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
sions (user+foo).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
- The text that follows the 220 status code in the
+ The text that follows the 220 status code in the
SMTP greeting banner.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
- List of commands that causes the Postfix SMTP
- server to immediately terminate the session with a
+ List of commands that causes the Postfix SMTP
+ server to immediately terminate the session with a
221 code.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> (no)</b>
- Enable logging of the remote SMTP client port in
+ Enable logging of the remote SMTP client port in
addition to the hostname and IP address.
<b>SEE ALSO</b>
<a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
<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>
invalid command syntax that would otherwise be rejected by Postfix.
.PP
Specify the name of a "type:table" lookup table. The search
-string is the SMTP command as received from the SMTP client. The
-only change made is to remove initial whitespace and the trailing
-<CR><LF> characters. The result value is executed by the Postfix
-SMTP server.
+string is the SMTP command as received from the SMTP client, except
+that initial whitespace and the trailing <CR><LF> are removed. The
+result value is executed by the Postfix SMTP server.
.PP
Examples:
.PP
.nf
.na
.ft C
- # Work around clients that enclose addresses in single quotes.
+ # Work around clients that send RCPT TO:<'user@domain'>.
# WARNING: do not lose the parameters that follow the address.
/^RCPT\es+TO:\es*<'([^[:space:]]+)'>(.*)/ RCPT TO:<$1>$2
.fi
.PP
The "inet:" and "unix:" prefixes are available in Postfix 2.3
and later.
+.SH smtpd_proxy_options (default: empty)
+List of options that control how the Postfix SMTP server
+communicates with a before-queue content filter. Specify zero or
+more of the following, separated by comma or whitespace.
+.IP "\fBspeed_adjust\fR"
+Do not connect to a before-queue content filter until an entire
+message has been received. This reduces the number of simultaneous
+before-queue content filter processes.
+.PP
+NOTE 1: A filter must not \fIselectively\fR reject recipients
+of a multi-recipient message. Rejecting all recipients is OK, as
+is accepting all recipients.
+.PP
+NOTE 2: This feature increases the minimum amount of free queue
+space by $message_size_limit. The extra space is needed to save the
+message to a temporary file.
+.PP
+This feature is available in Postfix 2.7 and later.
.SH smtpd_proxy_timeout (default: 100s)
The time limit for connecting to a proxy filter and for sending or
receiving information. When a connection fails the client gets a
local hostname were specified, instead of rejecting the address as
invalid.
.IP "\fBsmtpd_command_filter (empty)\fR"
-A mechanism to substitute incoming SMTP commands by other
-commands.
+A mechanism to substitute incoming SMTP commands.
.IP "\fBsmtpd_reject_unlisted_sender (no)\fR"
Request that the Postfix SMTP server rejects mail from unknown
sender addresses, even when no explicit reject_unlisted_sender
The hostname and TCP port of the mail filtering proxy server.
.IP "\fBsmtpd_proxy_ehlo ($myhostname)\fR"
How the Postfix SMTP server announces itself to the proxy filter.
+.IP "\fBsmtpd_proxy_options (empty)\fR"
+List of options that control how the Postfix SMTP server
+communicates with a before-queue content filter.
.IP "\fBsmtpd_proxy_timeout (100s)\fR"
The time limit for connecting to a proxy filter and for sending or
receiving information.
s;\bsmtpd_proxy_ehlo\b;<a href="postconf.5.html#smtpd_proxy_ehlo">$&</a>;g;
s;\bsmtpd_proxy_filter\b;<a href="postconf.5.html#smtpd_proxy_filter">$&</a>;g;
s;\bsmtpd_proxy_timeout\b;<a href="postconf.5.html#smtpd_proxy_timeout">$&</a>;g;
+ s;\bsmtpd_proxy_options\b;<a href="postconf.5.html#smtpd_proxy_options">$&</a>;g;
s;\bsmtpd_recip[-</bB>]*\n* *[<bB>]*ient_limit\b;<a href="postconf.5.html#smtpd_recipient_limit">$&</a>;g;
s;\bsmtpd_recip[-</bB>]*\n* *[<bB>]*ient_restrictions\b;<a href="postconf.5.html#smtpd_recipient_restrictions">$&</a>;g;
s;\bsmtpd_reject_unlisted_recip[-</bB>]*\n* *[<bB>]*ient\b;<a href="postconf.5.html#smtpd_reject_unlisted_recipient">$&</a>;g;
<h2>WARNING </h2>
-<p> The before-queue content filtering feature described in
-this document is suitable only for low-traffic sites. See the "<a
-href="#pros_cons">Pros and Cons</a>" section below for details.
+<p> The before-queue content filtering feature described in this
+document limits the amount of mail that a site can handle. See the
+"<a href="#pros_cons">Pros and Cons</a>" section below for details.
</p>
<h2>The Postfix before-queue content filter feature</h2>
cycles remain available to answer within the deadline, and eventually
you either have to stop accepting mail or you have to stop filtering
mail. It is for this reason that the before-queue content filter
-can be used only on low-traffic sites. </p>
+limits the amount of mail that a site can handle. </p>
<li> <p> Con: Content filtering software can use lots of memory
-resources. In order to not run out of memory you have to reduce
-the number of before-filter SMTP server processes so that a burst
-of mail will not drive your system into the ground with too many
-content filter processes. This, in turn, means that SMTP clients
-have to wait for a long time before they receive service. </p>
+resources. You have to reduce the number of simultaneous content
+filter processes so that a burst of mail will not drive your system
+into the ground. </p>
+
+<ul>
+
+<li> <p> With Postfix versions 2.7 and later, SMTP clients will
+experience an increase in the delay between the time the client
+sends "end-of-message" and the time the Postfix SMTP server replies
+(here, the number of before-filter SMTP server processes can be
+larger than the number of filter processes). </p>
+
+<li> <p> With Postfix versions before 2.7, SMTP clients will
+experience an increase in the delay before they can receive service
+(here, the number of before-filter SMTP server processes is always
+equal to the number of filter processes). </p>
+
+</ul>
</ul>
smtp inet n - n - 20 smtpd
-o smtpd_proxy_filter=127.0.0.1:10025
-o smtpd_client_connection_count_limit=10
+ # Postfix 2.7 and later performance feature.
+ # -o smtpd_proxy_options=speed_adjust
#
# After-filter SMTP server. Receive mail from the content filter
# on localhost port 10026.
later. Earlier Postfix versions will ignore it. </p>
<li> <p> The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the
- before filter SMTP server that it should give incoming mail to
+ before-filter SMTP server that it should give incoming mail to
the content filter that listens on localhost TCP port 10025.
- <li> <p> Postfix 2.3 supports both TCP and UNIX-domain filters.
+ <li> <p> The "-o smtpd_proxy_options=speed_adjust" tells the
+ before-filter SMTP server that it should receive an entire email
+ message before it connects to a content filter. This reduces
+ the number of simultaneous filter processes. </p>
+
+ <p> NOTE 1: When this option is turned on, a content filter must
+ not <i>selectively</i> reject recipients of a multi-recipient
+ message. Rejecting all recipients is OK, as is accepting all
+ recipients. </p>
+
+ <p> NOTE 2: This feature increases the minimum amount of free
+ queue space by $message_size_limit. The extra space is needed
+ to save the message to a temporary file. </p>
+
+ <li> <p> Postfix ≥ 2.3 supports both TCP and UNIX-domain filters.
The above filter could be specified as "inet:127.0.0.1:10025".
To specify a UNIX-domain filter, specify "unix:<i>pathname</i>".
A relative pathname is interpreted relative to the Postfix queue
<li> <p> The "-o smtpd_authorized_xforward_hosts=127.0.0.0/8"
allows the after-filter SMTP server to receive remote SMTP
- client information from the before filter SMTP server, so that
+ client information from the before-filter SMTP server, so that
the after-filter Postfix daemons log the remote SMTP client
information instead of logging localhost[127.0.0.1]. </p>
This feature is available in Postfix 2.1 and later.
</p>
+%PARAM smtpd_proxy_options
+
+<p>
+List of options that control how the Postfix SMTP server
+communicates with a before-queue content filter. Specify zero or
+more of the following, separated by comma or whitespace. </p>
+
+<dl>
+
+<dt><b>speed_adjust</b></dt>
+
+<dd> Do not connect to a before-queue content filter until an entire
+message has been received. This reduces the number of simultaneous
+before-queue content filter processes. </p>
+
+<p> NOTE 1: A filter must not <i>selectively</i> reject recipients
+of a multi-recipient message. Rejecting all recipients is OK, as
+is accepting all recipients. </p>
+
+<p> NOTE 2: This feature increases the minimum amount of free queue
+space by $message_size_limit. The extra space is needed to save the
+message to a temporary file. </p> </dd>
+
+</dl>
+
+<p>
+This feature is available in Postfix 2.7 and later.
+</p>
+
%CLASS smtpd-proxy SMTP Proxy filter
<p>
</p>
<p> Specify the name of a "type:table" lookup table. The search
-string is the SMTP command as received from the SMTP client. The
-only change made is to remove initial whitespace and the trailing
-<CR><LF> characters. The result value is executed by the Postfix
-SMTP server. </p>
+string is the SMTP command as received from the SMTP client, except
+that initial whitespace and the trailing <CR><LF> are removed. The
+result value is executed by the Postfix SMTP server. </p>
<p> Examples: </p>
</pre>
<pre>
- # Work around clients that enclose addresses in single quotes.
+ # Work around clients that send RCPT TO:<'user@domain'>.
# WARNING: do not lose the parameters that follow the address.
/^RCPT\s+TO:\s*<'([^[:space:]]+)'>(.*)/ RCPT TO:<$1>$2
</pre>
#ifndef NO_TRUNCATE
if ((flags & MAIL_COPY_TOFILE) != 0)
if (corrupt_error || read_error || write_error)
- ftruncate(vstream_fileno(dst), orig_length);
+ /* Complain about ignored "undo" errors? So sue me. */
+ (void) ftruncate(vstream_fileno(dst), orig_length);
#endif
write_error |= vstream_fclose(dst);
VAR_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY, &var_syslog_facility, 1, 0,
VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 1, 0,
VAR_MULTI_CONF_DIRS, DEF_MULTI_CONF_DIRS, &var_multi_conf_dirs, 0, 0,
- VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0,
+ /* multi_instance_wrapper may have dependencies but not dependents. */
VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0,
VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0,
0,
VAR_PROXYMAP_SERVICE, DEF_PROXYMAP_SERVICE, &var_proxymap_service, 1, 0,
VAR_PROXYWRITE_SERVICE, DEF_PROXYWRITE_SERVICE, &var_proxywrite_service, 1, 0,
VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0,
+ /* multi_instance_wrapper may have dependencies but not dependents. */
+ VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0,
0,
};
static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
#define DEF_SMTPD_PROXY_TMOUT "100s"
extern int var_smtpd_proxy_tmout;
+#define VAR_SMTPD_PROXY_OPTS "smtpd_proxy_options"
+#define DEF_SMTPD_PROXY_OPTS ""
+extern char *var_smtpd_proxy_opts;
+
/*
* Transparency options for mail input interfaces and for the cleanup server
* behind them. These should turn off stuff we don't want to happen, because
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20091023"
+#define MAIL_RELEASE_DATE "20091109"
#define MAIL_VERSION_NUMBER "2.7"
#ifdef SNAPSHOT
int alone = 0;
int zerolimit = 0;
WATCHDOG *watchdog;
+ char *oname_val;
char *oname;
char *oval;
const char *err;
service_name = optarg;
break;
case 'o':
- if ((err = split_nameval(mystrdup(optarg), &oname, &oval)) != 0)
+ oname_val = mystrdup(optarg);
+ if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
redo_syslog_init = 1;
+ myfree(oname_val);
break;
case 's':
if ((socket_count = atoi(optarg)) <= 0)
int alone = 0;
int zerolimit = 0;
WATCHDOG *watchdog;
+ char *oname_val;
char *oname;
char *oval;
const char *err;
service_name = optarg;
break;
case 'o':
- if ((err = split_nameval(mystrdup(optarg), &oname, &oval)) != 0)
+ oname_val = mystrdup(optarg);
+ if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
redo_syslog_init = 1;
+ myfree(oname_val);
break;
case 's':
if ((socket_count = atoi(optarg)) <= 0)
int alone = 0;
int zerolimit = 0;
WATCHDOG *watchdog;
+ char *oname_val;
char *oname;
char *oval;
const char *err;
service_name = optarg;
break;
case 'o':
- if ((err = split_nameval(mystrdup(optarg), &oname, &oval)) != 0)
+ oname_val = mystrdup(optarg);
+ if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
redo_syslog_init = 1;
+ myfree(oname_val);
break;
case 's':
if ((socket_count = atoi(optarg)) <= 0)
int alone = 0;
int zerolimit = 0;
WATCHDOG *watchdog;
+ char *oname_val;
char *oname;
char *oval;
const char *err;
service_name = optarg;
break;
case 'o':
- if ((err = split_nameval(mystrdup(optarg), &oname, &oval)) != 0)
+ oname_val = mystrdup(optarg);
+ if ((err = split_nameval(oname_val, &oname, &oval)) != 0)
msg_fatal("invalid \"-o %s\" option value: %s", optarg, err);
mail_conf_update(oname, oval);
if (strcmp(oname, VAR_SYSLOG_NAME) == 0)
redo_syslog_init = 1;
+ myfree(oname_val);
break;
case 's':
if ((socket_count = atoi(optarg)) <= 0)
smtpd_milter.o: ../../include/quote_821_local.h
smtpd_milter.o: ../../include/quote_flags.h
smtpd_milter.o: ../../include/resolve_clnt.h
+smtpd_milter.o: ../../include/split_at.h
smtpd_milter.o: ../../include/sys_defs.h
smtpd_milter.o: ../../include/tls.h
smtpd_milter.o: ../../include/vbuf.h
smtpd_proxy.o: ../../include/mail_error.h
smtpd_proxy.o: ../../include/mail_params.h
smtpd_proxy.o: ../../include/mail_proto.h
+smtpd_proxy.o: ../../include/mail_queue.h
smtpd_proxy.o: ../../include/mail_stream.h
smtpd_proxy.o: ../../include/milter.h
smtpd_proxy.o: ../../include/msg.h
smtpd_proxy.o: ../../include/myaddrinfo.h
+smtpd_proxy.o: ../../include/mymalloc.h
smtpd_proxy.o: ../../include/name_code.h
smtpd_proxy.o: ../../include/name_mask.h
smtpd_proxy.o: ../../include/rec_type.h
+smtpd_proxy.o: ../../include/record.h
smtpd_proxy.o: ../../include/smtp_stream.h
smtpd_proxy.o: ../../include/stringops.h
smtpd_proxy.o: ../../include/sys_defs.h
/* local hostname were specified, instead of rejecting the address as
/* invalid.
/* .IP "\fBsmtpd_command_filter (empty)\fR"
-/* A mechanism to substitute incoming SMTP commands by other
-/* commands.
+/* A mechanism to substitute incoming SMTP commands.
/* .IP "\fBsmtpd_reject_unlisted_sender (no)\fR"
/* Request that the Postfix SMTP server rejects mail from unknown
/* sender addresses, even when no explicit reject_unlisted_sender
/* The hostname and TCP port of the mail filtering proxy server.
/* .IP "\fBsmtpd_proxy_ehlo ($myhostname)\fR"
/* How the Postfix SMTP server announces itself to the proxy filter.
+/* .IP "\fBsmtpd_proxy_options (empty)\fR"
+/* List of options that control how the Postfix SMTP server
+/* communicates with a before-queue content filter.
/* .IP "\fBsmtpd_proxy_timeout (100s)\fR"
/* The time limit for connecting to a proxy filter and for sending or
/* receiving information.
char *var_smtpd_proxy_filt;
int var_smtpd_proxy_tmout;
char *var_smtpd_proxy_ehlo;
+char *var_smtpd_proxy_opts;
char *var_input_transp;
int var_smtpd_policy_tmout;
int var_smtpd_policy_idle;
char *var_unv_rcpt_tf_act;
char *var_unv_from_tf_act;
+int smtpd_proxy_opts;
+
/*
* Silly little macros.
*/
*/
if (state->proxy_mail) {
smtpd_check_rewrite(state);
- if (smtpd_proxy_open(state, var_smtpd_proxy_filt,
- var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
- state->proxy_mail) != 0) {
- smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+ if (smtpd_proxy_create(state, smtpd_proxy_opts, var_smtpd_proxy_filt,
+ var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
+ state->proxy_mail) != 0) {
+ smtpd_chat_reply(state, "%s", STR(state->proxy->buffer));
+ smtpd_proxy_free(state);
return (-1);
}
}
}
/*
- * Check the queue file space, if applicable.
+ * Check the queue file space, if applicable. The optional before-filter
+ * speed-adjust buffers use disk space. However, we don't know if they
+ * compete for storage space with the after-filter queue, so we can't
+ * simply bump up the free space requirement to 2.5 * message_size_limit.
*/
- if (!USE_SMTPD_PROXY(state)) {
+ if (!USE_SMTPD_PROXY(state)
+ || (smtpd_proxy_opts & SMTPD_PROXY_FLAG_SPEED_ADJUST)) {
if (SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_queue(state)) != 0) {
/* XXX Reset access map side effects. */
VSTRING_RESET(state->instance);
VSTRING_TERMINATE(state->instance);
- /*
- * Try to be nice. Don't bother when we lost the connection. Don't bother
- * waiting for a reply, it just increases latency.
- */
- if (state->proxy) {
- (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, SMTPD_CMD_QUIT);
- smtpd_proxy_close(state);
- }
+ if (state->proxy)
+ smtpd_proxy_free(state);
if (state->xforward.flags)
smtpd_xforward_reset(state);
if (state->prepend)
static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
{
+ SMTPD_PROXY *proxy;
const char *err;
int narg;
char *arg;
* the recipient then we can have a proxy connection without having
* accepted a recipient.
*/
- if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK,
- "%s", STR(state->buffer)) != 0) {
- smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+ proxy = state->proxy;
+ if (proxy != 0 && proxy->cmd(state, SMTPD_PROX_WANT_OK,
+ "%s", STR(state->buffer)) != 0) {
+ smtpd_chat_reply(state, "%s", STR(proxy->buffer));
return (-1);
}
static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
{
+ SMTPD_PROXY *proxy;
const char *err;
char *start;
int len;
smtpd_chat_reply(state, "%s", err);
return (-1);
}
- if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_MORE,
- "%s", STR(state->buffer)) != 0) {
- smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+ proxy = state->proxy;
+ if (proxy != 0 && proxy->cmd(state, SMTPD_PROX_WANT_MORE,
+ "%s", STR(state->buffer)) != 0) {
+ smtpd_chat_reply(state, "%s", STR(proxy->buffer));
return (-1);
}
* operation. We want to avoid massive code duplication within tons of
* if-else clauses.
*/
- if (state->proxy) {
- out_stream = state->proxy;
- out_record = smtpd_proxy_rec_put;
- out_fprintf = smtpd_proxy_rec_fprintf;
+ if (proxy) {
+ out_stream = proxy->stream;
+ out_record = proxy->rec_put;
+ out_fprintf = proxy->rec_fprintf;
out_error = CLEANUP_STAT_PROXY;
} else {
out_stream = state->cleanup;
* Suppress our own Received: header in the unlikely case that we are an
* intermediate proxy.
*/
- if (!state->proxy || state->xforward.flags == 0) {
+ if (!proxy || state->xforward.flags == 0) {
out_fprintf(out_stream, REC_TYPE_NORM,
"Received: from %s (%s [%s])",
state->helo_name ? state->helo_name : state->name,
out_record(out_stream, REC_TYPE_NORM, "", 0);
}
if (prev_rec_type != REC_TYPE_CONT && *start == '.'
- && (state->proxy == 0 ? (++start, --len) == 0 : len == 1))
+ && (proxy == 0 ? (++start, --len) == 0 : len == 1))
break;
if (state->err == CLEANUP_STAT_OK) {
if (var_message_limit > 0 && var_message_limit - state->act_size < len + 2) {
&& SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_eod(state)) != 0) {
smtpd_chat_reply(state, "%s", err);
- if (state->proxy) {
+ if (proxy) {
smtpd_proxy_close(state);
} else {
mail_stream_cleanup(state->dest);
/*
* Send the end of DATA and finish the proxy connection. Set the
* CLEANUP_STAT_PROXY error flag in case of trouble.
- *
- * XXX The low-level proxy output routines should set "state" error
- * attributes. This requires making "state" a context attribute of the
- * VSTREAM.
*/
- if (state->proxy) {
+ if (proxy) {
if (state->err == CLEANUP_STAT_OK) {
- (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, ".");
+ (void) proxy->cmd(state, SMTPD_PROX_WANT_ANY, ".");
if (state->err == CLEANUP_STAT_OK &&
- *STR(state->proxy_buffer) != '2')
+ *STR(proxy->buffer) != '2')
state->err = CLEANUP_STAT_CONT;
- } else if (state->err != CLEANUP_STAT_SIZE) {
- state->err |= CLEANUP_STAT_PROXY;
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
}
}
state->error_count = 0;
state->error_mask = 0;
state->junk_cmds = 0;
- if (state->queue_id)
+ if (proxy)
+ smtpd_chat_reply(state, "%s", STR(proxy->buffer));
+ else
smtpd_chat_reply(state,
"250 2.0.0 Ok: queued as %s", state->queue_id);
- else
- smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
} else if (why && IS_SMTP_REJECT(STR(why))) {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "%s", STR(why));
} else if ((state->err & CLEANUP_STAT_CONT) != 0) {
state->error_mask |= MAIL_ERROR_POLICY;
detail = cleanup_stat_detail(CLEANUP_STAT_CONT);
- if (state->proxy_buffer) {
- smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+ if (proxy) {
+ smtpd_chat_reply(state, "%s", STR(proxy->buffer));
} else if (why && LEN(why) > 0) {
/* Allow address-specific DSN status in header/body_checks. */
smtpd_chat_reply(state, "%d %s", detail->smtp, STR(why));
detail->smtp, detail->dsn, detail->text);
} else if ((state->err & CLEANUP_STAT_PROXY) != 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
- smtpd_chat_reply(state, "%s", STR(state->proxy_buffer));
+ smtpd_chat_reply(state, "%s", STR(proxy->buffer));
} else {
state->error_mask |= MAIL_ERROR_SOFTWARE;
detail = cleanup_stat_detail(CLEANUP_STAT_BAD);
smtpd_input_transp_mask =
input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
+ /*
+ * Initialize before-queue filter options: do we want speed-matching
+ * support so that the entire message is received before we contact a
+ * before-queue content filter?
+ */
+ if (*var_smtpd_proxy_filt)
+ smtpd_proxy_opts =
+ smtpd_proxy_parse_opts(VAR_SMTPD_PROXY_OPTS, var_smtpd_proxy_opts);
+
/*
* Sendmail mail filters.
*
VAR_VERP_CLIENTS, DEF_VERP_CLIENTS, &var_verp_clients, 0, 0,
VAR_SMTPD_PROXY_FILT, DEF_SMTPD_PROXY_FILT, &var_smtpd_proxy_filt, 0, 0,
VAR_SMTPD_PROXY_EHLO, DEF_SMTPD_PROXY_EHLO, &var_smtpd_proxy_ehlo, 0, 0,
+ VAR_SMTPD_PROXY_OPTS, DEF_SMTPD_PROXY_OPTS, &var_smtpd_proxy_opts, 0, 0,
VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0,
VAR_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0,
VAR_XFORWARD_HOSTS, DEF_XFORWARD_HOSTS, &var_xforward_hosts, 0, 0,
char *domain; /* rewrite context */
} SMTPD_XFORWARD_ATTR;
-typedef struct SMTPD_STATE {
+typedef struct {
int flags; /* see below */
int err; /* cleanup server/queue file errors */
VSTREAM *client; /* SMTP client handle */
/*
* Pass-through proxy client.
*/
- VSTREAM *proxy; /* proxy handle */
- VSTRING *proxy_buffer; /* proxy query/reply buffer */
+ struct SMTPD_PROXY *proxy;
char *proxy_mail; /* owned by mail_cmd() */
- int proxy_xforward_features; /* XFORWARD proxy state */
/*
* XFORWARD server state.
*/
extern MILTERS *smtpd_milters;
+ /*
+ * Message size multiplication factor for free space check.
+ */
+extern double smtpd_space_multf;
+
/* LICENSE
/* .ad
/* .fi
const char *txt; /* randomly selected trimmed TXT rr */
} SMTPD_RBL_EXPAND_CONTEXT;
+ /*
+ * Multiplication factor for free space check. Free space must be at least
+ * smtpd_space_multf * message_size_limit.
+ */
+double smtpd_space_multf = 1.5;
+
/* policy_client_register - register policy service endpoint */
static void policy_client_register(const char *name)
(unsigned long) var_queue_minfree,
(unsigned long) var_message_limit);
if (BLOCKS(var_queue_minfree) >= fsbuf.block_free
- || BLOCKS(var_message_limit) >= fsbuf.block_free / 1.5) {
+ || BLOCKS(var_message_limit) >= fsbuf.block_free / smtpd_space_multf) {
(void) smtpd_check_reject(state, MAIL_ERROR_RESOURCE,
452, "4.3.1",
"Insufficient system storage");
msg_warn("not enough free space in mail queue: %lu bytes < "
- "1.5*message size limit",
- (unsigned long) fsbuf.block_free * fsbuf.block_size);
+ "%g*message size limit",
+ (unsigned long) fsbuf.block_free * fsbuf.block_size,
+ smtpd_space_multf);
return (STR(error_text));
}
return (0);
/*
/* typedef struct {
/* .in +4
-/* /* other fields... */
-/* VSTREAM *proxy; /* connection to SMTP proxy */
-/* VSTRING *proxy_buffer; /* last SMTP proxy response */
+/* VSTREAM *stream; /* SMTP proxy or replay log */
+/* VSTRING *buffer; /* last SMTP proxy response */
/* /* other fields... */
/* .in -4
-/* } SMTPD_STATE;
+/* } SMTPD_PROXY;
/*
-/* int smtpd_proxy_open(state, service, timeout, ehlo_name, mail_from)
+/* int smtpd_proxy_create(state, flags, service, timeout,
+/* ehlo_name, mail_from)
/* SMTPD_STATE *state;
+/* int flags;
/* const char *service;
/* int timeout;
/* const char *ehlo_name;
/* const char *mail_from;
/*
-/* int smtpd_proxy_cmd(state, expect, format, ...)
+/* int proxy->cmd(state, expect, format, ...)
+/* SMTPD_PROXY *proxy;
/* SMTPD_STATE *state;
/* int expect;
-/* cont char *format;
+/* const char *format;
+/*
+/* void smtpd_proxy_disconnect(state)
+/* SMTPD_STATE *state;
/*
-/* void smtpd_proxy_close(state)
+/* void smtpd_proxy_free(state)
/* SMTPD_STATE *state;
+/*
+/* int smtpd_proxy_parse_opts(param_name, param_val)
+/* const char *param_name;
+/* const char *param_val;
/* RECORD-LEVEL ROUTINES
-/* int smtpd_proxy_rec_put(stream, rec_type, data, len)
-/* VSTREAM *stream;
+/* int proxy->rec_put(proxy->stream, rec_type, data, len)
+/* SMTPD_PROXY *proxy;
/* int rec_type;
/* const char *data;
/* ssize_t len;
/*
-/* int smtpd_proxy_rec_fprintf(stream, rec_type, format, ...)
-/* VSTREAM *stream;
+/* int proxy->rec_fprintf(proxy->stream, rec_type, format, ...)
+/* SMTPD_PROXY *proxy;
/* int rec_type;
/* cont char *format;
/* DESCRIPTION
/* The functions in this module implement a pass-through proxy
/* client.
/*
-/* In order to minimize the intrusiveness of pass-through proxying, 1) the
-/* proxy server must support the same MAIL FROM/RCPT syntax that Postfix
-/* supports, 2) the record-level routines for message content proxying
-/* have the same interface as the routines that are used for non-proxied
-/* mail.
+/* In order to minimize the intrusiveness of pass-through
+/* proxying, 1) the proxy server must support the same MAIL
+/* FROM/RCPT syntax that Postfix supports, 2) the record-level
+/* routines for message content proxying have the same interface
+/* as the routines that are used for non-proxied mail.
+/*
+/* smtpd_proxy_create() takes a description of a before-queue
+/* filter. Depending on flags, it either arranges to buffer
+/* up commands and message content until the entire message
+/* is received, or it immediately connects to the proxy service,
+/* sends EHLO, sends client information with the XFORWARD
+/* command if possible, sends the MAIL FROM command, and
+/* receives the reply.
+/* A non-zero result value means trouble: either the proxy is
+/* unavailable, or it did not send the expected reply.
+/* All results are reported via the proxy->buffer field in a
+/* form that can be sent to the SMTP client. An unexpected
+/* 2xx or 3xx proxy server response is replaced by a generic
+/* error response to avoid support problems.
+/* In case of error, smtpd_proxy_create() updates the
+/* state->error_mask and state->err fields, and leaves the the
+/* proxy handle in an unconnected state. Destroy the handle
+/* after reporting the error reply in the proxy->buffer field.
+/*
+/* proxy->cmd() formats and either buffers up the command and
+/* expected response until the entire message is received, or
+/* it immediately sends the specified command to the proxy
+/* server, and receives the proxy server reply.
+/* A non-zero result value means trouble: either the proxy is
+/* unavailable, or it did not send the expected reply.
+/* All results are reported via the proxy->buffer field in a
+/* form that can be sent to the SMTP client. An unexpected
+/* 2xx or 3xx proxy server response is replaced by a generic
+/* error response to avoid support problems.
+/* In case of error, proxy->cmd() updates the state->error_mask
+/* and state->err fields.
/*
-/* smtpd_proxy_open() connects to the proxy service, sends EHLO, sends
-/* client information with the XFORWARD command if possible, sends
-/* the MAIL FROM command, and receives the reply. A non-zero result means
-/* trouble: either the proxy is unavailable, or it did not send the
-/* expected reply.
-/* The result is reported via the state->proxy_buffer field in a form
-/* that can be sent to the SMTP client. In case of error, the
-/* state->error_mask and state->err fields are updated.
-/* A state->proxy_buffer field is created automatically; this field
-/* persists beyond the end of a proxy session.
+/* smtpd_proxy_disconnect() disconnects from a proxy server.
+/* The last proxy server reply or error description remains
+/* available via the proxy->buffer field.
/*
-/* smtpd_proxy_cmd() formats and sends the specified command to the
-/* proxy server, and receives the proxy server reply. A non-zero result
-/* means trouble: either the proxy is unavailable, or it did not send the
-/* expected reply.
-/* All results are reported via the state->proxy_buffer field in a form
-/* that can be sent to the SMTP client. In case of error, the
-/* state->error_mask and state->err fields are updated.
+/* smtpd_proxy_free() destroys a proxy server handle and resets
+/* the state->proxy field.
/*
-/* smtpd_proxy_close() disconnects from a proxy server and resets
-/* the state->proxy field. The last proxy server reply or error
-/* description remains available via state->proxy-reply.
+/* smtpd_proxy_parse_opts() parses main.cf processing options.
/*
-/* smtpd_proxy_rec_put() is a rec_put() clone that passes arbitrary
-/* message content records to the proxy server. The data is expected
-/* to be in SMTP dot-escaped form. All errors are reported as a
-/* REC_TYPE_ERROR result value.
+/* proxy->rec_put() is a rec_put() clone that either buffers
+/* up arbitrary message content records until the entire message
+/* is received, or that immediately sends it to the proxy
+/* server.
+/* All data is expected to be in SMTP dot-escaped form.
+/* All errors are reported as a REC_TYPE_ERROR result value,
+/* with the state->error_mask, state->err and proxy-buffer
+/* fields given appropriate values.
/*
-/* smtpd_proxy_rec_fprintf() is a rec_fprintf() clone that formats
-/* message content and sends it to the proxy server. Leading dots are
-/* not escaped. All errors are reported as a REC_TYPE_ERROR result
-/* value.
+/* proxy->rec_fprintf() is a rec_fprintf() clone that formats
+/* message content and either buffers up the record until the
+/* entire message is received, or that immediately sends it
+/* to the proxy server.
+/* All data is expected to be in SMTP dot-escaped form.
+/* All errors are reported as a REC_TYPE_ERROR result value,
+/* with the state->error_mask, state->err and proxy-buffer
+/* fields given appropriate values.
/*
/* Arguments:
+/* .IP flags
+/* Zero, or SMTPD_PROXY_FLAG_SPEED_ADJUST to buffer up the entire
+/* message before contacting a before-queue content filter.
+/* Note: when this feature is requested, the before-queue
+/* filter MUST use the same 2xx, 4xx or 5xx reply code for all
+/* recipients of a multi-recipient message.
/* .IP server
/* The SMTP proxy server host:port. The host or host: part is optional.
+/* This argument is not duplicated.
/* .IP timeout
/* Time limit for connecting to the proxy server and for
/* sending and receiving proxy server commands and replies.
/* .IP ehlo_name
/* The EHLO Hostname that will be sent to the proxy server.
+/* This argument is not duplicated.
/* .IP mail_from
-/* The MAIL FROM command.
+/* The MAIL FROM command. This argument is not duplicated.
/* .IP state
/* SMTP server state.
/* .IP expect
/* SEE ALSO
/* smtpd(8) Postfix smtp server
/* DIAGNOSTICS
+/* Panic: internal API violations.
+/*
/* Fatal errors: memory allocation problem.
/*
/* Warnings: unexpected response from proxy server, unable
-/* to connect to proxy server, proxy server read/write error.
+/* to connect to proxy server, proxy server read/write error,
+/* proxy speed-adjust buffer read/write error.
/* LICENSE
/* .ad
/* .fi
/* System library. */
#include <sys_defs.h>
+#include <sys/stat.h>
#include <ctype.h>
+#include <unistd.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#include <stringops.h>
#include <connect.h>
#include <name_code.h>
+#include <mymalloc.h>
/* Global library. */
#include <mail_proto.h>
#include <mail_params.h> /* null_format_string */
#include <xtext.h>
+#include <record.h>
+#include <mail_queue.h>
/* Application-specific. */
#define SMTPD_PROXY_XFORWARD_DOMAIN (1<<5) /* origin type */
#define SMTPD_PROXY_XFORWARD_PORT (1<<6) /* client port */
+ /*
+ * Spead-matching: we use an unlinked file for transient storage.
+ */
+static VSTREAM *smtpd_proxy_replay_stream;
+
+ /*
+ * Forward declarations.
+ */
+static void smtpd_proxy_fake_server_reply(SMTPD_STATE *, int);
+static int smtpd_proxy_rdwr_error(SMTPD_STATE *, int);
+static int smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
+static int smtpd_proxy_rec_put(VSTREAM *, int, const char *, ssize_t);
+
/*
* SLMs.
*/
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
-#define SMTPD_PROXY_CONNECT null_format_string
+#define SMTPD_PROXY_CONN_FMT null_format_string
#define STREQ(x, y) (strcmp((x), (y)) == 0)
-/* smtpd_xforward_flush - flush forwarding information */
+/* smtpd_proxy_xforward_flush - flush forwarding information */
-static int smtpd_xforward_flush(SMTPD_STATE *state, VSTRING *buf)
+static int smtpd_proxy_xforward_flush(SMTPD_STATE *state, VSTRING *buf)
{
int ret;
return (0);
}
-/* smtpd_xforward - send forwarding information */
+/* smtpd_proxy_xforward_send - send forwarding information */
-static int smtpd_xforward(SMTPD_STATE *state, VSTRING *buf, const char *name,
- int value_available, const char *value)
+static int smtpd_proxy_xforward_send(SMTPD_STATE *state, VSTRING *buf,
+ const char *name,
+ int value_available,
+ const char *value)
{
size_t new_len;
int ret;
* Flush the buffer if we need to, and store the attribute.
*/
if (VSTRING_LEN(buf) > 0 && VSTRING_LEN(buf) + new_len > PAYLOAD_LIMIT)
- if ((ret = smtpd_xforward_flush(state, buf)) < 0)
+ if ((ret = smtpd_proxy_xforward_flush(state, buf)) < 0)
return (ret);
vstring_sprintf_append(buf, " %s=%s", name, STR(state->expand_buf));
return (0);
}
-/* smtpd_proxy_open - open proxy connection */
+/* smtpd_proxy_connect - open proxy connection */
-int smtpd_proxy_open(SMTPD_STATE *state, const char *service,
- int timeout, const char *ehlo_name,
- const char *mail_from)
+static int smtpd_proxy_connect(SMTPD_STATE *state)
{
+ SMTPD_PROXY *proxy = state->proxy;
int fd;
char *lines;
char *words;
VSTRING *buf;
int bad;
char *word;
- static const NAME_CODE xforward_features[] = {
+ static const NAME_CODE known_xforward_features[] = {
XFORWARD_NAME, SMTPD_PROXY_XFORWARD_NAME,
XFORWARD_ADDR, SMTPD_PROXY_XFORWARD_ADDR,
XFORWARD_PORT, SMTPD_PROXY_XFORWARD_PORT,
XFORWARD_DOMAIN, SMTPD_PROXY_XFORWARD_DOMAIN,
0, 0,
};
- const CLEANUP_STAT_DETAIL *detail;
+ int server_xforward_features;
int (*connect_fn) (const char *, int, int);
const char *endpoint;
- /*
- * This buffer persists beyond the end of a proxy session so we can
- * inspect the last command's reply.
- */
- if (state->proxy_buffer == 0)
- state->proxy_buffer = vstring_alloc(10);
-
/*
* Find connection method (default inet)
*/
- if (strncasecmp("unix:", service, 5) == 0) {
- endpoint = service + 5;
+ if (strncasecmp("unix:", proxy->service_name, 5) == 0) {
+ endpoint = proxy->service_name + 5;
connect_fn = unix_connect;
} else {
- if (strncasecmp("inet:", service, 5) == 0)
- endpoint = service + 5;
+ if (strncasecmp("inet:", proxy->service_name, 5) == 0)
+ endpoint = proxy->service_name + 5;
else
- endpoint = service;
+ endpoint = proxy->service_name;
connect_fn = inet_connect;
}
/*
* Connect to proxy.
*/
- if ((fd = connect_fn(endpoint, BLOCKING, timeout)) < 0) {
- state->error_mask |= MAIL_ERROR_SOFTWARE;
- state->err |= CLEANUP_STAT_PROXY;
- msg_warn("connect to proxy service %s: %m", service);
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
- return (-1);
- }
- state->proxy = vstream_fdopen(fd, O_RDWR);
- vstream_control(state->proxy, VSTREAM_CTL_PATH, service, VSTREAM_CTL_END);
- smtp_timeout_setup(state->proxy, timeout);
+ if ((fd = connect_fn(endpoint, BLOCKING, proxy->timeout)) < 0)
+ return (smtpd_proxy_rdwr_error(state, 0));
+ proxy->service_stream = vstream_fdopen(fd, O_RDWR);
+ /* Needed by our DATA-phase record emulation routines. */
+ vstream_control(proxy->service_stream, VSTREAM_CTL_CONTEXT,
+ (char *) state, VSTREAM_CTL_END);
+ smtp_timeout_setup(proxy->service_stream, proxy->timeout);
/*
* Get server greeting banner.
*
* If this fails then we have a problem because the proxy should always
* accept our connection. Make up our own response instead of passing
- * back the greeting banner: the proxy open might be delayed to the point
- * that the client expects a MAIL FROM or RCPT TO reply.
- */
- if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONNECT) != 0) {
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
+ * back a negative greeting banner: the proxy open is delayed to the
+ * point that the client expects a MAIL FROM or RCPT TO reply.
+ */
+ if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, SMTPD_PROXY_CONN_FMT)) {
+ smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
smtpd_proxy_close(state);
return (-1);
}
/*
* Send our own EHLO command. If this fails then we have a problem
* because the proxy should always accept our EHLO command. Make up our
- * own response instead of passing back the EHLO reply: the proxy open
- * might be delayed to the point that the client expects a MAIL FROM or
+ * own response instead of passing back a negative EHLO reply: the proxy
+ * open is delayed to the point that the client expects a MAIL FROM or
* RCPT TO reply.
*/
- if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s", ehlo_name) != 0) {
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
+ if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "EHLO %s",
+ proxy->ehlo_name)) {
+ smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
smtpd_proxy_close(state);
return (-1);
}
/*
* Parse the EHLO reply and see if we can forward logging information.
*/
- state->proxy_xforward_features = 0;
- lines = STR(state->proxy_buffer);
+ server_xforward_features = 0;
+ lines = STR(proxy->buffer);
while ((words = mystrtok(&lines, "\n")) != 0) {
if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t")) != 0) {
if (strcasecmp(word, XFORWARD_CMD) == 0)
while ((word = mystrtok(&words, " \t")) != 0)
- state->proxy_xforward_features |=
- name_code(xforward_features, NAME_CODE_FLAG_NONE, word);
+ server_xforward_features |=
+ name_code(known_xforward_features,
+ NAME_CODE_FLAG_NONE, word);
}
}
/*
* Send XFORWARD attributes. For robustness, explicitly specify what SMTP
- * session attributes are known and unknown.
+ * session attributes are known and unknown. Make up our own response
+ * instead of passing back a negative XFORWARD reply: the proxy open is
+ * delayed to the point that the client expects a MAIL FROM or RCPT TO
+ * reply.
*/
- if (state->proxy_xforward_features) {
+ if (server_xforward_features) {
buf = vstring_alloc(100);
- bad = 0;
- if (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_NAME)
- bad = smtpd_xforward(state, buf, XFORWARD_NAME,
- IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state)),
- FORWARD_NAME(state));
- if (bad == 0
- && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_ADDR))
- bad = smtpd_xforward(state, buf, XFORWARD_ADDR,
- IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)),
- FORWARD_ADDR(state));
- if (bad == 0
- && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_PORT))
- bad = smtpd_xforward(state, buf, XFORWARD_PORT,
- IS_AVAIL_CLIENT_PORT(FORWARD_PORT(state)),
- FORWARD_PORT(state));
- if (bad == 0
- && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_HELO))
- bad = smtpd_xforward(state, buf, XFORWARD_HELO,
- IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state)),
- FORWARD_HELO(state));
- if (bad == 0
- && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_PROTO))
- bad = smtpd_xforward(state, buf, XFORWARD_PROTO,
- IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state)),
- FORWARD_PROTO(state));
- if (bad == 0
- && (state->proxy_xforward_features & SMTPD_PROXY_XFORWARD_DOMAIN))
- bad = smtpd_xforward(state, buf, XFORWARD_DOMAIN, 1,
+ bad =
+ (((server_xforward_features & SMTPD_PROXY_XFORWARD_NAME)
+ && smtpd_proxy_xforward_send(state, buf, XFORWARD_NAME,
+ IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state)),
+ FORWARD_NAME(state)))
+ || ((server_xforward_features & SMTPD_PROXY_XFORWARD_ADDR)
+ && smtpd_proxy_xforward_send(state, buf, XFORWARD_ADDR,
+ IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state)),
+ FORWARD_ADDR(state)))
+ || ((server_xforward_features & SMTPD_PROXY_XFORWARD_PORT)
+ && smtpd_proxy_xforward_send(state, buf, XFORWARD_PORT,
+ IS_AVAIL_CLIENT_PORT(FORWARD_PORT(state)),
+ FORWARD_PORT(state)))
+ || ((server_xforward_features & SMTPD_PROXY_XFORWARD_HELO)
+ && smtpd_proxy_xforward_send(state, buf, XFORWARD_HELO,
+ IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state)),
+ FORWARD_HELO(state)))
+ || ((server_xforward_features & SMTPD_PROXY_XFORWARD_PROTO)
+ && smtpd_proxy_xforward_send(state, buf, XFORWARD_PROTO,
+ IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state)),
+ FORWARD_PROTO(state)))
+ || ((server_xforward_features & SMTPD_PROXY_XFORWARD_DOMAIN)
+ && smtpd_proxy_xforward_send(state, buf, XFORWARD_DOMAIN, 1,
STREQ(FORWARD_DOMAIN(state), MAIL_ATTR_RWR_LOCAL) ?
- XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE);
- if (bad == 0)
- bad = smtpd_xforward_flush(state, buf);
+ XFORWARD_DOM_LOCAL : XFORWARD_DOM_REMOTE))
+ || smtpd_proxy_xforward_flush(state, buf));
vstring_free(buf);
if (bad) {
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
+ smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
smtpd_proxy_close(state);
return (-1);
}
* have a problem because the proxy should always accept any MAIL FROM
* command that was accepted by us.
*/
- if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "%s", mail_from) != 0) {
+ if (smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, "%s",
+ proxy->mail_from) != 0) {
+ /* NOT: smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY); */
smtpd_proxy_close(state);
return (-1);
}
return (0);
}
+/* smtpd_proxy_fake_server_reply - produce generic error response */
+
+static void smtpd_proxy_fake_server_reply(SMTPD_STATE *state, int status)
+{
+ const CLEANUP_STAT_DETAIL *detail;
+
+ /*
+ * Either we have no server reply (connection refused), or we have an
+ * out-of-protocol server reply, so we make up a generic server error
+ * response instead.
+ */
+ detail = cleanup_stat_detail(status);
+ vstring_sprintf(state->proxy->buffer,
+ "%d %s Error: %s",
+ detail->smtp, detail->dsn, detail->text);
+}
+
+/* smtpd_proxy_replay_rdwr_error - report replay log I/O error */
+
+static int smtpd_proxy_replay_rdwr_error(SMTPD_STATE *state)
+{
+
+ /*
+ * Log an appropriate warning message.
+ */
+ msg_warn("proxy speed-adjust log I/O error: %m");
+
+ /*
+ * Set the appropriate flags and server reply.
+ */
+ state->error_mask |= MAIL_ERROR_RESOURCE;
+ /* Update state->err in case we are past the client's DATA command. */
+ state->err |= CLEANUP_STAT_PROXY;
+ smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
+ return (-1);
+}
+
/* smtpd_proxy_rdwr_error - report proxy communication error */
-static int smtpd_proxy_rdwr_error(VSTREAM *stream, int err)
+static int smtpd_proxy_rdwr_error(SMTPD_STATE *state, int err)
{
+ const char *myname = "smtpd_proxy_rdwr_error";
+ SMTPD_PROXY *proxy = state->proxy;
+
+ /*
+ * Sanity check.
+ */
+ if (err != 0 && err != SMTP_ERR_NONE && proxy == 0)
+ msg_panic("%s: proxy error %d without proxy handle", myname, err);
+
+ /*
+ * Log an appropriate warning message.
+ */
switch (err) {
- case SMTP_ERR_EOF:
- msg_warn("lost connection with proxy %s", VSTREAM_PATH(stream));
- return (err);
+ case 0:
+ case SMTP_ERR_NONE:
+ break;
+ case SMTP_ERR_EOF:
+ msg_warn("lost connection with proxy %s", proxy->service_name);
+ break;
case SMTP_ERR_TIME:
- msg_warn("timeout talking to proxy %s", VSTREAM_PATH(stream));
- return (err);
+ msg_warn("timeout talking to proxy %s", proxy->service_name);
+ break;
default:
- msg_panic("smtpd_proxy_rdwr_error: unknown proxy %s stream error %d",
- VSTREAM_PATH(stream), err);
+ msg_panic("%s: unknown proxy %s error %d",
+ myname, proxy->service_name, err);
+ }
+
+ /*
+ * Set the appropriate flags and server reply.
+ */
+ state->error_mask |= MAIL_ERROR_SOFTWARE;
+ /* Update state->err in case we are past the client's DATA command. */
+ state->err |= CLEANUP_STAT_PROXY;
+ smtpd_proxy_fake_server_reply(state, CLEANUP_STAT_PROXY);
+ return (-1);
+}
+
+/* smtpd_proxy_replay_send - replay saved SMTP session from speed-match log */
+
+static int smtpd_proxy_replay_send(SMTPD_STATE *state)
+{
+ const char *myname = "smtpd_proxy_replay_send";
+ static VSTRING *replay_buf = 0;
+ SMTPD_PROXY *proxy = state->proxy;
+ int rec_type;
+ int expect = SMTPD_PROX_WANT_BAD;
+
+ /*
+ * Sanity check.
+ */
+ if (smtpd_proxy_replay_stream == 0)
+ msg_panic("%s: no before-queue filter speed-adjust log", myname);
+
+ /*
+ * Errors first.
+ */
+ if (vstream_ferror(smtpd_proxy_replay_stream)
+ || vstream_feof(smtpd_proxy_replay_stream)
+ || vstream_fflush(smtpd_proxy_replay_stream))
+ /* NOT: fsync(vstream_fileno(smtpd_proxy_replay_stream)) */
+ return (smtpd_proxy_replay_rdwr_error(state));
+
+ /*
+ * Delayed connection to the before-queue filter.
+ */
+ if (smtpd_proxy_connect(state) < 0)
+ return (-1);
+
+ /*
+ * Replay the speed-match log. We do sanity check record content, but we
+ * don't implement a protocol state engine here, since we are reading
+ * from a file that we just wrote ourselves.
+ */
+ if (replay_buf == 0)
+ replay_buf = vstring_alloc(100);
+ if (vstream_fseek(smtpd_proxy_replay_stream, (off_t) 0, SEEK_SET) < 0)
+ return (smtpd_proxy_replay_rdwr_error(state));
+
+ for (;;) {
+ switch (rec_type = rec_get(smtpd_proxy_replay_stream, replay_buf,
+ REC_FLAG_NONE)) {
+
+ /*
+ * Message content.
+ */
+ case REC_TYPE_NORM:
+ case REC_TYPE_CONT:
+ if (smtpd_proxy_rec_put(proxy->service_stream, rec_type,
+ STR(replay_buf), LEN(replay_buf)) < 0)
+ return (-1);
+ break;
+
+ /*
+ * Expected server reply type.
+ */
+ case REC_TYPE_RCPT:
+ if (!alldig(STR(replay_buf))
+ || (expect = atoi(STR(replay_buf))) == SMTPD_PROX_WANT_BAD)
+ msg_panic("%s: malformed server reply type: %s",
+ myname, STR(replay_buf));
+ break;
+
+ /*
+ * Client command, or void. Bail out on the first negative proxy
+ * response. This is OK, because the filter must use the same
+ * reply code for all recipients of a multi-recipient message.
+ */
+ case REC_TYPE_FROM:
+ if (expect == SMTPD_PROX_WANT_BAD)
+ msg_panic("%s: missing server reply type", myname);
+ if (smtpd_proxy_cmd(state, expect, *STR(replay_buf) ? "%s" :
+ SMTPD_PROXY_CONN_FMT, STR(replay_buf)) < 0)
+ return (-1);
+ expect = SMTPD_PROX_WANT_BAD;
+ break;
+
+ /*
+ * End of replay log.
+ */
+ case REC_TYPE_EOF:
+ return (0);
+
+ /*
+ * Errors.
+ */
+ case REC_TYPE_ERROR:
+ return (smtpd_proxy_replay_rdwr_error(state));
+ default:
+ msg_panic("%s: unexpected record type; %d", myname, rec_type);
+ }
}
}
-/* smtpd_proxy_cmd_error - report unexpected proxy reply */
+/* smtpd_proxy_save_cmd - save SMTP command + expected response to replay log */
-static void smtpd_proxy_cmd_error(SMTPD_STATE *state, const char *fmt,
- va_list ap)
+static int smtpd_proxy_save_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
{
+ va_list ap;
+
+ /*
+ * Errors first.
+ */
+ if (vstream_ferror(smtpd_proxy_replay_stream)
+ || vstream_feof(smtpd_proxy_replay_stream))
+ return (smtpd_proxy_replay_rdwr_error(state));
+
+ /*
+ * Save the expected reply first, so that the replayer can safely
+ * overwrite the input buffer with the command.
+ */
+ rec_fprintf(smtpd_proxy_replay_stream, REC_TYPE_RCPT, "%d", expect);
+
+ /*
+ * The command can be omitted at the start of an SMTP session. This is
+ * not documented as part of the official interface because it is used
+ * only internally to this module. Use an explicit null string in case
+ * the SMTPD_PROXY_CONN_FMT implementation details change.
+ */
+ if (fmt == SMTPD_PROXY_CONN_FMT)
+ fmt = "";
+
+ /*
+ * Save the command to the replay log, and send it to the before-queue
+ * filter after we have received the entire message.
+ */
+ va_start(ap, fmt);
+ rec_vfprintf(smtpd_proxy_replay_stream, REC_TYPE_FROM, fmt, ap);
+ va_end(ap);
+
+ /*
+ * If we just saved the "." command, replay the log.
+ */
+ return (strcmp(fmt, ".") ? 0 : smtpd_proxy_replay_send(state));
+}
+
+/* smtpd_proxy_cmd_warn - report unexpected proxy reply */
+
+static void smtpd_proxy_cmd_warn(SMTPD_STATE *state, const char *fmt,
+ va_list ap)
+{
+ SMTPD_PROXY *proxy = state->proxy;
VSTRING *buf;
/*
* because it is used only internally to this module.
*/
buf = vstring_alloc(100);
- vstring_vsprintf(buf, fmt == SMTPD_PROXY_CONNECT ?
+ vstring_vsprintf(buf, fmt == SMTPD_PROXY_CONN_FMT ?
"connection request" : fmt, ap);
- msg_warn("proxy %s rejected \"%s\": \"%s\"", VSTREAM_PATH(state->proxy),
- STR(buf), STR(state->proxy_buffer));
+ msg_warn("proxy %s rejected \"%s\": \"%s\"",
+ proxy->service_name, STR(buf), STR(proxy->buffer));
vstring_free(buf);
}
/* smtpd_proxy_cmd - send command to proxy, receive reply */
-int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
+static int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
{
+ SMTPD_PROXY *proxy = state->proxy;
va_list ap;
char *cp;
int last_char;
int err = 0;
static VSTRING *buffer = 0;
- const CLEANUP_STAT_DETAIL *detail;
/*
* Errors first. Be prepared for delayed errors from the DATA phase.
*/
- if (vstream_ferror(state->proxy)
- || vstream_feof(state->proxy)
- || ((err = vstream_setjmp(state->proxy)) != 0
- && smtpd_proxy_rdwr_error(state->proxy, err))) {
- state->error_mask |= MAIL_ERROR_SOFTWARE;
- state->err |= CLEANUP_STAT_PROXY;
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
- return (-1);
+ if (vstream_ferror(proxy->service_stream)
+ || vstream_feof(proxy->service_stream)
+ || (err = vstream_setjmp(proxy->service_stream)) != 0) {
+ return (smtpd_proxy_rdwr_error(state, err));
}
/*
* not documented as part of the official interface because it is used
* only internally to this module.
*/
- if (fmt != SMTPD_PROXY_CONNECT) {
+ if (fmt != SMTPD_PROXY_CONN_FMT) {
/*
* Format the command.
*/
va_start(ap, fmt);
- vstring_vsprintf(state->proxy_buffer, fmt, ap);
+ vstring_vsprintf(proxy->buffer, fmt, ap);
va_end(ap);
/*
* what the program is trying to do.
*/
if (msg_verbose)
- msg_info("> %s: %s", VSTREAM_PATH(state->proxy),
- STR(state->proxy_buffer));
+ msg_info("> %s: %s", proxy->service_name, STR(proxy->buffer));
/*
* Send the command to the proxy server. Since we're going to read a
* reply immediately, there is no need to flush buffers.
*/
- smtp_fputs(STR(state->proxy_buffer), LEN(state->proxy_buffer),
- state->proxy);
+ smtp_fputs(STR(proxy->buffer), LEN(proxy->buffer),
+ proxy->service_stream);
}
/*
* Early return if we don't want to wait for a server reply (such as
- * after sending QUIT.
+ * after sending QUIT).
*/
if (expect == SMTPD_PROX_WANT_NONE)
return (0);
* Censor out non-printable characters in server responses and save
* complete multi-line responses if possible.
*/
- VSTRING_RESET(state->proxy_buffer);
+ VSTRING_RESET(proxy->buffer);
if (buffer == 0)
buffer = vstring_alloc(10);
for (;;) {
- last_char = smtp_get(buffer, state->proxy, var_line_limit);
+ last_char = smtp_get(buffer, proxy->service_stream, var_line_limit);
printable(STR(buffer), '?');
if (last_char != '\n')
msg_warn("%s: response longer than %d: %.30s...",
- VSTREAM_PATH(state->proxy), var_line_limit,
+ proxy->service_name, var_line_limit,
STR(buffer));
if (msg_verbose)
- msg_info("< %s: %.100s", VSTREAM_PATH(state->proxy),
- STR(buffer));
+ msg_info("< %s: %.100s", proxy->service_name, STR(buffer));
/*
* Defend against a denial of service attack by limiting the amount
* of multi-line text that we are willing to store.
*/
- if (LEN(state->proxy_buffer) < var_line_limit) {
- if (VSTRING_LEN(state->proxy_buffer))
- VSTRING_ADDCH(state->proxy_buffer, '\n');
- vstring_strcat(state->proxy_buffer, STR(buffer));
+ if (LEN(proxy->buffer) < var_line_limit) {
+ if (VSTRING_LEN(proxy->buffer))
+ VSTRING_ADDCH(proxy->buffer, '\n');
+ vstring_strcat(proxy->buffer, STR(buffer));
}
/*
break;
}
msg_warn("received garbage from proxy %s: %.100s",
- VSTREAM_PATH(state->proxy), STR(buffer));
+ proxy->service_name, STR(buffer));
}
/*
* Log a warning in case the proxy does not send the expected response.
* Silently accept any response when the client expressed no expectation.
*
- * Don't pass through misleading 2xx replies. It confuses naive users and
- * SMTP clients, and creates support problems.
+ * Starting with Postfix 2.6 we don't pass through unexpected 2xx or 3xx
+ * proxy replies. They are a source of support problems, so we replace
+ * them by generic server error replies.
*/
- if (expect != SMTPD_PROX_WANT_ANY && expect != *STR(state->proxy_buffer)) {
+ if (expect != SMTPD_PROX_WANT_ANY && expect != *STR(proxy->buffer)) {
va_start(ap, fmt);
- smtpd_proxy_cmd_error(state, fmt, ap);
+ smtpd_proxy_cmd_warn(state, fmt, ap);
va_end(ap);
- if (*STR(state->proxy_buffer) == SMTPD_PROX_WANT_OK
- || *STR(state->proxy_buffer) == SMTPD_PROX_WANT_MORE) {
- state->error_mask |= MAIL_ERROR_SOFTWARE;
- state->err |= CLEANUP_STAT_PROXY;
- detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
- vstring_sprintf(state->proxy_buffer,
- "%d %s Error: %s",
- detail->smtp, detail->dsn, detail->text);
+ if (*STR(proxy->buffer) == SMTPD_PROX_WANT_OK
+ || *STR(proxy->buffer) == SMTPD_PROX_WANT_MORE) {
+ smtpd_proxy_rdwr_error(state, 0);
}
return (-1);
} else {
}
}
+/* smtpd_proxy_save_rec_put - save message content to replay log */
+
+static int smtpd_proxy_save_rec_put(VSTREAM *stream, int rec_type,
+ const char *data, ssize_t len)
+{
+ const char *myname = "smtpd_proxy_save_rec_put";
+ int ret;
+
+#define VSTREAM_TO_SMTPD_STATE(s) ((SMTPD_STATE *) vstream_context(s))
+
+ /*
+ * Sanity check.
+ */
+ if (stream == 0)
+ msg_panic("%s: attempt to use closed stream", myname);
+
+ /*
+ * Send one content record. Errors and results must be as with rec_put().
+ */
+ if (rec_type == REC_TYPE_NORM || rec_type == REC_TYPE_CONT)
+ ret = rec_put(stream, rec_type, data, len);
+ else
+ msg_panic("%s: need REC_TYPE_NORM or REC_TYPE_CONT", myname);
+
+ /*
+ * Errors last.
+ */
+ if (ret != rec_type) {
+ (void) smtpd_proxy_replay_rdwr_error(VSTREAM_TO_SMTPD_STATE(stream));
+ return (REC_TYPE_ERROR);
+ }
+ return (rec_type);
+}
+
/* smtpd_proxy_rec_put - send message content, rec_put() clone */
-int smtpd_proxy_rec_put(VSTREAM *stream, int rec_type,
- const char *data, ssize_t len)
+static int smtpd_proxy_rec_put(VSTREAM *stream, int rec_type,
+ const char *data, ssize_t len)
{
- int err;
+ const char *myname = "smtpd_proxy_rec_put";
+ int err = 0;
/*
* Errors first.
*/
- if (vstream_ferror(stream) || vstream_feof(stream))
+ if (vstream_ferror(stream) || vstream_feof(stream)
+ || (err = vstream_setjmp(stream)) != 0) {
+ (void) smtpd_proxy_rdwr_error(VSTREAM_TO_SMTPD_STATE(stream), err);
return (REC_TYPE_ERROR);
- if ((err = vstream_setjmp(stream)) != 0)
- return (smtpd_proxy_rdwr_error(stream, err), REC_TYPE_ERROR);
+ }
/*
* Send one content record. Errors and results must be as with rec_put().
else if (rec_type == REC_TYPE_CONT)
smtp_fwrite(data, len, stream);
else
- msg_panic("smtpd_proxy_rec_put: need REC_TYPE_NORM or REC_TYPE_CONT");
+ msg_panic("%s: need REC_TYPE_NORM or REC_TYPE_CONT", myname);
+ return (rec_type);
+}
+
+/* smtpd_proxy_save_rec_fprintf - save message content to replay log */
+
+static int smtpd_proxy_save_rec_fprintf(VSTREAM *stream, int rec_type,
+ const char *fmt,...)
+{
+ const char *myname = "smtpd_proxy_save_rec_fprintf";
+ va_list ap;
+ int ret;
+
+ /*
+ * Sanity check.
+ */
+ if (stream == 0)
+ msg_panic("%s: attempt to use closed stream", myname);
+
+ /*
+ * Save one content record. Errors and results must be as with
+ * rec_fprintf().
+ */
+ va_start(ap, fmt);
+ if (rec_type == REC_TYPE_NORM)
+ ret = rec_vfprintf(stream, rec_type, fmt, ap);
+ else
+ msg_panic("%s: need REC_TYPE_NORM", myname);
+ va_end(ap);
+
+ /*
+ * Errors last.
+ */
+ if (ret != rec_type) {
+ (void) smtpd_proxy_replay_rdwr_error(VSTREAM_TO_SMTPD_STATE(stream));
+ return (REC_TYPE_ERROR);
+ }
return (rec_type);
}
/* smtpd_proxy_rec_fprintf - send message content, rec_fprintf() clone */
-int smtpd_proxy_rec_fprintf(VSTREAM *stream, int rec_type,
- const char *fmt,...)
+static int smtpd_proxy_rec_fprintf(VSTREAM *stream, int rec_type,
+ const char *fmt,...)
{
+ const char *myname = "smtpd_proxy_rec_fprintf";
va_list ap;
- int err;
+ int err = 0;
/*
* Errors first.
*/
- if (vstream_ferror(stream) || vstream_feof(stream))
+ if (vstream_ferror(stream) || vstream_feof(stream)
+ || (err = vstream_setjmp(stream)) != 0) {
+ (void) smtpd_proxy_rdwr_error(VSTREAM_TO_SMTPD_STATE(stream), err);
return (REC_TYPE_ERROR);
- if ((err = vstream_setjmp(stream)) != 0)
- return (smtpd_proxy_rdwr_error(stream, err), REC_TYPE_ERROR);
+ }
/*
* Send one content record. Errors and results must be as with
if (rec_type == REC_TYPE_NORM)
smtp_vprintf(stream, fmt, ap);
else
- msg_panic("smtpd_proxy_rec_fprintf: need REC_TYPE_NORM");
+ msg_panic("%s: need REC_TYPE_NORM", myname);
va_end(ap);
return (rec_type);
}
-/* smtpd_proxy_close - close proxy connection */
+#ifndef NO_TRUNCATE
+
+/* smtpd_proxy_replay_setup - prepare the replay logfile */
+
+static int smtpd_proxy_replay_setup(SMTPD_STATE *state)
+{
+ const char *myname = "smtpd_proxy_replay_setup";
+ struct stat st;
+
+ /*
+ * Where possible reuse an existing replay logfile, because creating a
+ * file is expensive compared to reading or writing. For security reasons
+ * we must truncate the file before reuse. For performance reasons we
+ * should truncate the file immediately after the end of a mail
+ * transaction. We enforce the security guarantee here by requiring that
+ * the file is emtpy when it is reused. This is less expensive than
+ * truncating the file redundantly.
+ */
+ if (smtpd_proxy_replay_stream != 0) {
+ if (vstream_fseek(smtpd_proxy_replay_stream, (off_t) 0, SEEK_SET) < 0) {
+ msg_warn("seek before-queue filter speed-adjust log: %m");
+ (void) vstream_fclose(smtpd_proxy_replay_stream);
+ smtpd_proxy_replay_stream = 0;
+ } else if (fstat(vstream_fileno(smtpd_proxy_replay_stream), &st) < 0) {
+ msg_warn("fstat before-queue filter speed-adjust log: %m");
+ (void) vstream_fclose(smtpd_proxy_replay_stream);
+ smtpd_proxy_replay_stream = 0;
+ } else {
+ if (st.st_size > 0)
+ msg_panic("%s: non-empty before-queue filter speed-adjust log",
+ myname);
+ vstream_clearerr(smtpd_proxy_replay_stream);
+ if (msg_verbose)
+ msg_info("%s: reuse speed-adjust stream fd=%d", myname,
+ vstream_fileno(smtpd_proxy_replay_stream));
+ /* Here, smtpd_proxy_replay_stream != 0 */
+ }
+ }
+
+ /*
+ * Create a new replay logfile.
+ */
+ if (smtpd_proxy_replay_stream == 0) {
+ smtpd_proxy_replay_stream = mail_queue_enter(MAIL_QUEUE_INCOMING, 0,
+ (struct timeval *) 0);
+ if (smtpd_proxy_replay_stream == 0)
+ return (smtpd_proxy_replay_rdwr_error(state));
+ if (unlink(VSTREAM_PATH(smtpd_proxy_replay_stream)) < 0)
+ msg_warn("remove before-queue filter speed-adjust log %s: %m",
+ VSTREAM_PATH(smtpd_proxy_replay_stream));
+ if (msg_verbose)
+ msg_info("%s: new speed-adjust stream fd=%d", myname,
+ vstream_fileno(smtpd_proxy_replay_stream));
+ }
+
+ /*
+ * Needed by our DATA-phase record emulation routines.
+ */
+ vstream_control(smtpd_proxy_replay_stream, VSTREAM_CTL_CONTEXT,
+ (char *) state, VSTREAM_CTL_END);
+ return (0);
+}
+
+#endif
+
+/* smtpd_proxy_create - set up smtpd proxy handle */
+
+int smtpd_proxy_create(SMTPD_STATE *state, int flags, const char *service,
+ int timeout, const char *ehlo_name,
+ const char *mail_from)
+{
+ SMTPD_PROXY *proxy;
+
+ /*
+ * When an operation has many arguments it is safer to use named
+ * parameters, and have the compiler enforce the argument count.
+ */
+#define SMTPD_PROXY_ALLOC(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
+ ((p) = (SMTPD_PROXY *) mymalloc(sizeof(*(p))), (p)->a1, (p)->a2, \
+ (p)->a3, (p)->a4, (p)->a5, (p)->a6, (p)->a7, (p)->a8, (p)->a9, \
+ (p)->a10, (p)->a11, (p))
+
+ /*
+ * Connect to the before-queue filter immediately.
+ */
+ if ((flags & SMTPD_PROXY_FLAG_SPEED_ADJUST) == 0) {
+ state->proxy =
+ SMTPD_PROXY_ALLOC(proxy, stream = 0, buffer = vstring_alloc(10),
+ cmd = smtpd_proxy_cmd,
+ rec_fprintf = smtpd_proxy_rec_fprintf,
+ rec_put = smtpd_proxy_rec_put,
+ flags = flags, service_stream = 0,
+ service_name = service, timeout = timeout,
+ ehlo_name = ehlo_name, mail_from = mail_from);
+ if (smtpd_proxy_connect(state) < 0) {
+ /* NOT: smtpd_proxy_free(state); we still need proxy->buffer. */
+ return (-1);
+ }
+ proxy->stream = proxy->service_stream;
+ return (0);
+ }
+
+ /*
+ * Connect to the before-queue filter after we receive the entire
+ * message. Open the replay logfile early to simplify code. The file is
+ * reused for multiple mail transactions, so there is no need to minimize
+ * its life time.
+ */
+ else {
+#ifdef NO_TRUNCATE
+ msg_panic("smtpd_proxy_create: speed-adjust support is not available");
+#else
+ if (smtpd_proxy_replay_setup(state) < 0)
+ return (-1);
+ state->proxy =
+ SMTPD_PROXY_ALLOC(proxy, stream = smtpd_proxy_replay_stream,
+ buffer = vstring_alloc(10),
+ cmd = smtpd_proxy_save_cmd,
+ rec_fprintf = smtpd_proxy_save_rec_fprintf,
+ rec_put = smtpd_proxy_save_rec_put,
+ flags = flags, service_stream = 0,
+ service_name = service, timeout = timeout,
+ ehlo_name = ehlo_name, mail_from = mail_from);
+ return (0);
+#endif
+ }
+}
+
+/* smtpd_proxy_close - close proxy connection without destroying handle */
void smtpd_proxy_close(SMTPD_STATE *state)
{
- (void) vstream_fclose(state->proxy);
+ SMTPD_PROXY *proxy = state->proxy;
+
+ /*
+ * XXX We can't send QUIT if the stream is still good, because that would
+ * overwrite the last server reply in proxy->buffer. We probably should
+ * just bite the bullet and allocate separate buffers for sending and
+ * receiving.
+ */
+ if (proxy->service_stream != 0) {
+#if 0
+ if (vstream_feof(proxy->service_stream) == 0
+ && vstream_ferror(proxy->service_stream) == 0)
+ (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE,
+ SMTPD_CMD_QUIT);
+#endif
+ (void) vstream_fclose(proxy->service_stream);
+ if (proxy->stream == proxy->service_stream)
+ proxy->stream = 0;
+ proxy->service_stream = 0;
+ }
+}
+
+/* smtpd_proxy_free - destroy smtpd proxy handle */
+
+void smtpd_proxy_free(SMTPD_STATE *state)
+{
+ SMTPD_PROXY *proxy = state->proxy;
+
+ /*
+ * Clean up.
+ */
+ if (proxy->service_stream != 0)
+ (void) smtpd_proxy_close(state);
+ if (proxy->buffer != 0)
+ vstring_free(proxy->buffer);
+ myfree((char *) proxy);
state->proxy = 0;
+
+ /*
+ * Reuse the replay logfile if possible. For security reasons we must
+ * truncate the replay logfile before reuse. For performance reasons we
+ * should truncate the replay logfile immediately after the end of a mail
+ * transaction. We truncate the file here, and enforce the security
+ * guarantee by requiring that the file is empty when it is reused.
+ */
+ if (smtpd_proxy_replay_stream == 0)
+ return;
+ if (vstream_ferror(smtpd_proxy_replay_stream)) {
+ (void) vstream_fclose(smtpd_proxy_replay_stream);
+ smtpd_proxy_replay_stream = 0;
+ return;
+ }
+ if (ftruncate(vstream_fileno(smtpd_proxy_replay_stream), (off_t) 0) < 0) {
+ msg_warn("truncate before-queue filter speed-adjust log: %m");
+ (void) vstream_fclose(smtpd_proxy_replay_stream);
+ smtpd_proxy_replay_stream = 0;
+ return;
+ }
+}
+
+/* smtpd_proxy_parse_opts - parse main.cf options */
+
+int smtpd_proxy_parse_opts(const char *param_name, const char *param_val)
+{
+ static const NAME_MASK proxy_opts_table[] = {
+ SMTPD_PROXY_NAME_SPEED_ADJUST, SMTPD_PROXY_FLAG_SPEED_ADJUST,
+ 0, 0,
+ };
+ int flags;
+
+ /*
+ * The optional before-filter speed-adjust buffers use disk space.
+ * However, we don't know if they compete for storage space with the
+ * after-filter queue, so we can't simply bump up the free space
+ * requirement to 2.5 * message_size_limit.
+ */
+ flags = name_mask(param_name, proxy_opts_table, param_val);
+ if (flags & SMTPD_PROXY_FLAG_SPEED_ADJUST) {
+#ifdef NO_TRUNCATE
+ msg_warn("smtpd_proxy %s support is not available",
+ SMTPD_PROXY_NAME_SPEED_ADJUST);
+ flags &= ~SMTPD_PROXY_FLAG_SPEED_ADJUST;
+#endif
+ }
+ return (flags);
}
/*
* Application-specific.
*/
+typedef int PRINTFPTRLIKE(3, 4) (*SMTPD_PROXY_CMD_FN) (SMTPD_STATE *, int, const char *,...);
+typedef int PRINTFPTRLIKE(3, 4) (*SMTPD_PROXY_REC_FPRINTF_FN) (VSTREAM *, int, const char *,...);
+typedef int (*SMTPD_PROXY_REC_PUT_FN) (VSTREAM *, int, const char *, ssize_t);
+
+typedef struct SMTPD_PROXY {
+ /* Public. */
+ VSTREAM *stream;
+ VSTRING *buffer; /* proxy query/reply buffer */
+ SMTPD_PROXY_CMD_FN cmd;
+ SMTPD_PROXY_REC_FPRINTF_FN rec_fprintf;
+ SMTPD_PROXY_REC_PUT_FN rec_put;
+ /* Private. */
+ int flags;
+ VSTREAM *service_stream;
+ const char *service_name;
+ int timeout;
+ const char *ehlo_name;
+ const char *mail_from;
+} SMTPD_PROXY;
+
+#define SMTPD_PROXY_FLAG_SPEED_ADJUST (1<<0)
+
+#define SMTPD_PROXY_NAME_SPEED_ADJUST "speed_adjust"
+
+#define SMTPD_PROX_WANT_BAD 0xff /* Do not use */
#define SMTPD_PROX_WANT_NONE '\0' /* Do not receive reply */
#define SMTPD_PROX_WANT_ANY '0' /* Expect any reply */
#define SMTPD_PROX_WANT_OK '2' /* Expect 2XX reply */
#define SMTPD_PROX_WANT_MORE '3' /* Expect 3XX reply */
-extern int smtpd_proxy_open(SMTPD_STATE *, const char *, int, const char *, const char *);
-extern int PRINTFLIKE(3, 4) smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
-extern int smtpd_proxy_rec_put(VSTREAM *, int, const char *, ssize_t);
-extern int PRINTFLIKE(3, 4) smtpd_proxy_rec_fprintf(VSTREAM *, int, const char *,...);
+extern int smtpd_proxy_create(SMTPD_STATE *, int, const char *, int, const char *, const char *);
extern void smtpd_proxy_close(SMTPD_STATE *);
+extern void smtpd_proxy_free(SMTPD_STATE *);
+extern int smtpd_proxy_parse_opts(const char *, const char *);
/* LICENSE
/* .ad
state->expand_buf = 0;
state->prepend = 0;
state->proxy = 0;
- state->proxy_buffer = 0;
state->proxy_mail = 0;
- state->proxy_xforward_features = 0;
state->saved_filter = 0;
state->saved_redirect = 0;
state->saved_bcc = 0;
vstring_free(state->defer_if_reject.reason);
if (state->expand_buf)
vstring_free(state->expand_buf);
- if (state->proxy_buffer)
- vstring_free(state->proxy_buffer);
if (state->instance)
vstring_free(state->instance);
if (state->dsn_buf)
#include <smtpd.h>
-/* smtpd_xforward_init - initialize XCLIENT attributes */
+/* smtpd_xforward_init - initialize xforward attributes */
void smtpd_xforward_init(SMTPD_STATE *state)
{
/* Leave domain context at zero. */
}
-/* smtpd_xforward_reset - reset XCLIENT attributes */
+/* smtpd_xforward_reset - reset xforward attributes */
void smtpd_xforward_reset(SMTPD_STATE *state)
{
/*
/* The TLS layer to network interface is realized with a BIO pair:
/*
-/* Postfix | TLS layer
+/* Postfix SMTP layer | TLS layer
/* |
/* smtp/smtpd |
/* /\ || |
/* | || \/
/* | BIO pair (internal_bio)
/* | BIO pair (network_bio)
-/* | /\ ||
+/* Postfix socket layer | /\ ||
/* | || \/
/* socket read/write <===> BIO read/write
/* /\ || |
#endif
#ifndef SCANFLIKE
-#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || __GNUC__ == 3
+#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || __GNUC__ >= 3
#define SCANFLIKE(x,y) __attribute__ ((format (scanf, (x), (y))))
#else
#define SCANFLIKE(x,y)
#endif
+#endif
+
+ /*
+ * Some gcc implementations don't grok these attributes with pointer to
+ * function. Again, wild guess of what is supported. To override, specify
+ * #define PRINTPTRFLIKE in the system-dependent sections above.
+ */
+#ifndef PRINTFPTRLIKE
+#if (__GNUC__ >= 3) /* XXX Rough estimate */
+#define PRINTFPTRLIKE(x,y) PRINTFLIKE(x,y)
+#else
+#define PRINTFPTRLIKE(x,y)
+#endif
#endif
/*