-TDICT_ENV
-TDICT_FAIL
-TDICT_HT
+-TDICT_INLINE
-TDICT_LDAP
-TDICT_LMDB
-TDICT_MC
Cleanup: don't write back-to-back queue file pointer records
when the "add recipient" action was a NOOP (e.g., because
the recipient was a duplicate). File: cleanup/cleanup_milter.c.
+
+20141120
+
+ Documentation: COMPATIBILITY_README now has "purpose of
+ this document" section, plus a separate section for turning
+ off the safety net. File: proto/COMPATIBILITY_README.html
+
+20131121
+
+ Cleanup: replace mua_mumble with msa_mumble in master.cf
+ submission and smtps service parameter overrides. File:
+ proto/BUILTIN_FILTER_README.html.
+
+ Feature: "static:{ text with whitespace }". This could be
+ used as check_mumble_access static:{reject text...} at the
+ end of smtpd_mumble_restrictions. Files: util/dict_static.c,
+ util/Makefile.in, util/dict_static_test.ref,
+ proto/DATABASE_README.html. postconf/postconf.c (manpage).
+
+20141126
+
+ Feature: "inline:{key=value, { key = text with comma/space}}
+ avoids the need to create a database for just a few entries.
+ Files: util/dict_inline.[hc], mantools/postlink,
+ proto/DATABASE_README.html. postconf/postconf.c (manpage),
+ util/dict_inline.[hc], util/dict_open.c, util/Makefile.in,
+ util/dict_inline_test.ref.
+
+ Cleanup: report nullmx DNS records as "domain does not
+ accept mail", instead of "invalid DNS response". The Postfix
+ SMTP client already bounced mail for such domains, and the
+ Postfix SMTP server already rejected such domains with
+ reject_unknown_sender/recipient_domain. This introduces a
+ new SMTP server configuration parameter nullmx_reject_code
+ (default: 556). Files: src/dns/dns_lookup.[hc], dns/Makefile,in,
+ dns/nullmx_test.ref, src/smtp/smtp_addr.c, src/smtpd/smtpd_check.c,
+ smtpd/smtpd_check_nullmx.in, smtpd/smtpd_check_nullmx.ref,
+ mantools/postlink, proto/postconf.proto, smtpd/smtpd.c.
+
+ Cleanup: added some missing libdns tests: dns/Makefile,in,
+ dns/mxonly_test,ref, dns/nxdomain_test.ref
+
+ Cleanup: libglobal "make test" had suffered from bitrot.
+ Files: global/mime_state.c, global/header_body_checks.c.
* FORWARD_SECRECY_README: TLS Forward Secrecy
* IPV6_README: IP Version 6 Support
* IPV6_README: IP Version 6 Support
- * SMTPUTF8_README: SMTPUTF8 support
- * COMPATIBILITY_README: Backwards-Compatibility Support
+ * SMTPUTF8_README: SMTPUTF8 Support
+ * COMPATIBILITY_README: Backwards-Compatibility Safety Net
* INSTALL: Installation from source code
P\bPr\bro\bob\bbl\ble\bem\bm s\bso\bol\blv\bvi\bin\bng\bg
for the submission and smtps services.
/etc/postfix/main.cf:
- mua_cleanup_service_name = mua_cleanup
- mua_header_checks = pcre:/etc/postfix/mua_header_checks
- mua_body_checks = pcre:/etc/postfix/mua_body_checks
+ msa_cleanup_service_name = msa_cleanup
+ msa_header_checks = pcre:/etc/postfix/msa_header_checks
+ msa_body_checks = pcre:/etc/postfix/msa_body_checks
-Next, we define mua_cleanup as a dedicated cleanup service that will be used
+Next, we define msa_cleanup as a dedicated cleanup service that will be used
only by the submission and smtps services. This service uses the header_checks
and body_checks overrides that were defined above.
# (yes) (yes) (yes) (never) (100)
# =================================================================
smtp inet n - n - - smtpd
- mua_cleanup unix n - n - 0 cleanup
- -o header_checks=$mua_header_checks
- -o body_checks=$mua_body_checks
+ msa_cleanup unix n - n - 0 cleanup
+ -o header_checks=$msa_header_checks
+ -o body_checks=$msa_body_checks
submission inet n - n - - smtpd
- -o cleanup_service_name=$mua_cleanup_service_name
+ -o cleanup_service_name=$msa_cleanup_service_name
-o syslog_name=postfix/submission
...[see sample master.cf file for more]...
smtps inet n - n - - smtpd
- -o cleanup_service_name=$mua_cleanup_service_name
+ -o cleanup_service_name=$msa_cleanup_service_name
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
...[see sample master.cf file for more]...
-By keeping the "mua_xxx" parameter settings in main.cf, you keep your master.cf
+By keeping the "msa_xxx" parameter settings in main.cf, you keep your master.cf
file simple, and you minimize the amount of duplication.
C\bCo\bon\bnf\bfi\big\bgu\bur\bri\bin\bng\bg h\bhe\bea\bad\bde\ber\br/\b/b\bbo\bod\bdy\by c\bch\bhe\bec\bck\bks\bs f\bfo\bor\br m\bma\bai\bil\bl t\bto\bo s\bso\bom\bme\be d\bdo\bom\bma\bai\bin\bns\bs o\bon\bnl\bly\by
-P\bPo\bos\bst\btf\bfi\bix\bx B\bBa\bac\bck\bkw\bwa\bar\brd\bds\bs-\b-C\bCo\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by S\bSu\bup\bpp\bpo\bor\brt\bt
+P\bPo\bos\bst\btf\bfi\bix\bx B\bBa\bac\bck\bkw\bwa\bar\brd\bds\bs-\b-C\bCo\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by S\bSa\baf\bft\bty\by N\bNe\bet\bt
-------------------------------------------------------------------------------
+P\bPu\bur\brp\bpo\bos\bse\be o\bof\bf t\bth\bhi\bis\bs d\bdo\boc\bcu\bum\bme\ben\bnt\bt
+
+Postfix 2.12 introduces a safety net that runs Postfix programs with backwards-
+compatible default settings after an upgrade. The safety net will log a warning
+whenever a "new" default setting could have an negative effect on your mail
+flow.
+
+This document provides information on the following topics:
+
+ * Detailed descriptions of Postfix backwards-compatibility warnings.
+
+ * What backwards-compatible settings you may have to make permanent in
+ main.cf or master.cf.
+
+ * How to turn off Postfix backwards-compatibility warnings.
+
O\bOv\bve\ber\brv\bvi\bie\bew\bw
-Postfix 2.12 introduces a safety net that causes Postfix programs to run with
-backwards-compatible default settings after an upgrade to a newer Postfix
-version. Backwards compatibility is turned on when the main.cf
-compatibility_level value is less than the Postfix built-in value.
+With backwards compatibility turned on, Postfix logs a message whenever a
+backwards-compatible default setting may be required for continuity of service.
+Based on this logging the system administrator can decide if any backwards-
+compatible settings need to be made permanent in main.cf or master.cf, before
+turning off the backwards-compatibility safety net as described at the end of
+this document.
-With backwards compatibility turned on, Postfix looks for settings that are
-left at their implicit default value, and logs a message when a backwards-
-compatible default setting is required for continuity of service. The following
-messages may be logged:
+The following messages may be logged:
* Using backwards-compatible default setting append_dot_mydomain=yes
or master.cf, as detailed in the sections that follow.
When no more backwards-compatible settings need to be made permanent, the
-administrator should turn off backwards compatibility by updating the
-compatibility_level setting in main.cf.
-
- # p\bpo\bos\bst\btc\bco\bon\bnf\bf c\bco\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by_\b_l\ble\bev\bve\bel\bl=\b=N\bN
- # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
-
-For N specify the number that is logged in your postfix(1) warning message:
-
- warning: To disable backwards compatibility use "postconf
- compatibility_level=N" and "postfix reload"
-
-Sites that don't care about backwards compatibility may set
-"compatibility_level = 9999" at their own risk.
+system administrator should turn off the backwards-compatibility safety net as
+described at the end of this document.
U\bUs\bsi\bin\bng\bg b\bba\bac\bck\bkw\bwa\bar\brd\bds\bs-\b-c\bco\bom\bmp\bpa\bat\bti\bib\bbl\ble\be d\bde\bef\bfa\bau\bul\blt\bt s\bse\bet\btt\bti\bin\bng\bg a\bap\bpp\bpe\ben\bnd\bd_\b_d\bdo\bot\bt_\b_m\bmy\byd\bdo\bom\bma\bai\bin\bn=\b=y\bye\bes\bs
# p\bpo\bos\bst\btc\bco\bon\bnf\bf s\bsm\bmt\btp\bpu\but\btf\bf8\b8_\b_e\ben\bna\bab\bbl\ble\be=\b=n\bno\bo
# p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+T\bTu\bur\brn\bni\bin\bng\bg o\bof\bff\bf t\bth\bhe\be b\bba\bac\bck\bkw\bwa\bar\brd\bds\bs-\b-c\bco\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by s\bsa\baf\bfe\bet\bty\by n\bne\bet\bt
+
+Backwards compatibility is turned off by updating the compatibility_level
+setting in main.cf.
+
+ # p\bpo\bos\bst\btc\bco\bon\bnf\bf c\bco\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by_\b_l\ble\bev\bve\bel\bl=\b=N\bN
+ # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+
+For N specify the number that is logged in your postfix(1) warning message:
+
+ warning: To disable backwards compatibility use "postconf
+ compatibility_level=N" and "postfix reload"
+
+Sites that don't care about backwards compatibility may set
+"compatibility_level = 9999" at their own risk.
+
are created with the postmap(1) or postalias(1) command, and private
databases are maintained by Postfix daemons. The database name as used
in "hash:table" is the database file name without the ".db" suffix.
+ inline (read-only)
+ A non-shared, in-memory lookup table. Example: "inline:{ key=value,
+ { key = text with whitespace or comma }}". Key-value pairs are
+ separated by whitespace or comma; whitespace after "{" and before "}"
+ is ignored. Inline tables eliminate the need to create a database file
+ for just a few fixed elements. See also the static: map type.
i\bin\bnt\bte\ber\brn\bna\bal\bl
A non-shared, in-memory hash table. Its content are lost when a process
terminates.
s\bst\bta\bat\bti\bic\bc (read-only)
A table that always returns its name as the lookup result. For example,
"static:foobar" always returns the string "foobar" as lookup result.
+ Specify "static:{ text with whitespace }" when the result contains
+ whitespace; this form ignores whitespace after "{" and before "}". See
+ also the inline: map type.
t\btc\bcp\bp
TCP/IP client. The protocol is described in tcp_table(5). The lookup
table name is "tcp:host:port" where "host" specifies a symbolic
(mantools/srctoman - makedefs | nroff -man | less) with information
about build options that are not described in the INSTALL instructions.
+Major changes with snapshot 20141126
+====================================
+
+Nullmx support (MX records with a null hostname). This change affects
+error messages only. The Postfix SMTP client already bounced mail
+for such domains, and the Postfix SMTP server already rejected such
+domains with reject_unknown_sender/recipient_domain. This introduces
+a new SMTP server configuration parameter nullmx_reject_code (default:
+556).
+
+Major changes with snapshot 20141119
+====================================
+
+Support for BCC actions in header/body_checks and milter_header_checks.
+There is no limit on the number of BCC actions that may be specified,
+other than the implicit limit due to finite storage. BCC support
+will not be implemented in Postfix delivery agents.
+
+It works in the same way as always_bcc and sender/recipient_bcc_maps:
+there can be only one address per action, recipients are added with
+the NOTIFY=NONE delivery status notification option, and duplicate
+recipients are ignored (with the same delivery status notification
+options).
+
Major changes with snapshot 20141011
====================================
Things to do after the stable release:
+ Log command=good/bad statistics in postscreen?
+
+ Implement smtpd_client_auth_rate limit?
+
Make the access map BCC action consistent with header_checks.
+ smtpd_checks tests either must use a DNS dummy resolver
+ (override the res_search API) or all names must be under
+ porcupine.org (but that does not work for address->name
+ lookups, and cannot simulate some errors).
+
Find a way to show non-default OPT, DEBUG etc. settings at
the top of the makedefs.out file.
- Inline table for quick tests. Short form example: inline:{
- name1=value1, name2=value2 } would instantiate a table with
- tuples (name1, value1) and (name2, value2). Long form example
- allows space around =, and space/comma in values: inline:{
- { name1 = value1 }, { name2 = value2 } }.
-
Update smtputf8_enable in postconf(5)
Clobber ORCPT when sender is owner-mumble?
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- mua_cleanup_service_name = mua_cleanup
- mua_header_checks = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/mua_header_checks
- mua_body_checks = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/mua_body_checks
+ msa_cleanup_service_name = msa_cleanup
+ msa_header_checks = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/msa_header_checks
+ msa_body_checks = <a href="pcre_table.5.html">pcre</a>:/etc/postfix/msa_body_checks
</pre>
</blockquote>
-<p> Next, we define mua_cleanup as a dedicated cleanup service that
+<p> Next, we define msa_cleanup as a dedicated cleanup service that
will be used only by the submission and smtps services. This service
uses the <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a> overrides that were defined
above. </p>
# (yes) (yes) (yes) (never) (100)
# =================================================================
smtp inet n - n - - smtpd
- mua_cleanup unix n - n - 0 cleanup
- -o <a href="postconf.5.html#header_checks">header_checks</a>=$mua_header_checks
- -o <a href="postconf.5.html#body_checks">body_checks</a>=$mua_body_checks
+ msa_cleanup unix n - n - 0 cleanup
+ -o <a href="postconf.5.html#header_checks">header_checks</a>=$msa_header_checks
+ -o <a href="postconf.5.html#body_checks">body_checks</a>=$msa_body_checks
submission inet n - n - - smtpd
- -o <a href="postconf.5.html#cleanup_service_name">cleanup_service_name</a>=$mua_cleanup_service_name
+ -o <a href="postconf.5.html#cleanup_service_name">cleanup_service_name</a>=$msa_cleanup_service_name
-o <a href="postconf.5.html#syslog_name">syslog_name</a>=postfix/submission
<i>...[see sample <a href="master.5.html">master.cf</a> file for more]...</i>
smtps inet n - n - - smtpd
- -o <a href="postconf.5.html#cleanup_service_name">cleanup_service_name</a>=$mua_cleanup_service_name
+ -o <a href="postconf.5.html#cleanup_service_name">cleanup_service_name</a>=$msa_cleanup_service_name
-o <a href="postconf.5.html#syslog_name">syslog_name</a>=postfix/smtps
-o <a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a>=yes
<i>...[see sample <a href="master.5.html">master.cf</a> file for more]...</i>
</pre>
</blockquote>
-<p> By keeping the "mua_xxx" parameter settings in <a href="postconf.5.html">main.cf</a>, you
+<p> By keeping the "msa_xxx" parameter settings in <a href="postconf.5.html">main.cf</a>, you
keep your <a href="master.5.html">master.cf</a> file simple, and you minimize the amount
of duplication. </p>
<head>
-<title>Postfix Backwards-Compatibility Support</title>
+<title>Postfix Backwards-Compatibility Safty Net</title>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<body>
<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
-Backwards-Compatibility Support</h1>
+Backwards-Compatibility Safty Net</h1>
<hr>
-<h2>Overview </h2>
+<h2>Purpose of this document </h2>
-<p> Postfix 2.12 introduces a safety net that causes Postfix programs
-to run with backwards-compatible default settings after an upgrade
-to a newer Postfix version. Backwards compatibility is turned on
-when the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#compatibility_level">compatibility_level</a> value is less than the Postfix
-built-in value. </p>
+<p> Postfix 2.12 introduces a safety net that runs Postfix programs
+with backwards-compatible default settings after an upgrade. The
+safety net will log a warning whenever a "new" default setting could
+have an negative effect on your mail flow. </p>
-<p> With backwards compatibility turned on, Postfix looks for
-settings that are left at their implicit default value, and logs a
-message when a backwards-compatible default setting is required for
-continuity of service. The following messages may be logged: </p>
+<p>This document provides information on the following topics: </p>
+
+<ul>
+
+<li> <p> <a href="#overview">Detailed descriptions</a> of Postfix
+backwards-compatibility warnings.
+
+<li> <p> What backwards-compatible settings you may have to make
+permanent in <a href="postconf.5.html">main.cf</a> or <a href="master.5.html">master.cf</a>. </p>
+
+<li> <p> <a href="#turnoff">How to turn off</a> Postfix
+backwards-compatibility warnings. </p>
+
+</ul>
+
+<h2> <a name="overview"> Overview </a> </h2>
+
+<p> With backwards compatibility turned on, Postfix logs a message
+whenever a backwards-compatible default setting may be required for
+continuity of service. Based on this logging the system administrator
+can decide if any backwards-compatible settings need to be made
+permanent in main.cf or master.cf, before <a href="#turnoff">turning
+off the backwards-compatibility safety net</a> as described at the
+end of this document. </p>
+
+<p> The following messages may be logged: </p>
<ul>
sections that follow. </p>
<p> When no more backwards-compatible settings need to be made
-permanent, the administrator should turn off backwards compatibility
-by updating the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting in <a href="postconf.5.html">main.cf</a>. </p>
-
-<blockquote>
-<pre>
-# <b>postconf <a href="postconf.5.html#compatibility_level">compatibility_level</a>=<i>N</i></b>
-# <b>postfix reload</b>
-</pre>
-</blockquote>
-
-<p> For <i>N</i> specify the number that is logged in your <a href="postfix.1.html">postfix(1)</a>
-warning message: </p>
-
-<blockquote>
-<pre>
-warning: To disable backwards compatibility use "postconf <a href="postconf.5.html#compatibility_level">compatibility_level</a>=<i>N</i>" and "postfix reload"
-</pre>
-</blockquote>
-
-<p> Sites that don't care about backwards compatibility may set
-"<a href="postconf.5.html#compatibility_level">compatibility_level</a> = 9999" at their own risk. </p>
+permanent, the system administrator should <a href="#turnoff">turn
+off the backwards-compatibility safety net</a> as described at the
+end of this document. </p>
<h2> <a name="append_dot_mydomain"> Using backwards-compatible default
setting append_dot_mydomain=yes</a> </h2>
</pre>
</blockquote>
+<h2> <a name="turnoff">Turning off the backwards-compatibility safety net</a> </h2>
+
+<p> Backwards compatibility is turned off by updating the
+<a href="postconf.5.html#compatibility_level">compatibility_level</a> setting in <a href="postconf.5.html">main.cf</a>. </p>
+
+<blockquote>
+<pre>
+# <b>postconf <a href="postconf.5.html#compatibility_level">compatibility_level</a>=<i>N</i></b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p> For <i>N</i> specify the number that is logged in your <a href="postfix.1.html">postfix(1)</a>
+warning message: </p>
+
+<blockquote>
+<pre>
+warning: To disable backwards compatibility use "postconf <a href="postconf.5.html#compatibility_level">compatibility_level</a>=<i>N</i>" and "postfix reload"
+</pre>
+</blockquote>
+
+<p> Sites that don't care about backwards compatibility may set
+"<a href="postconf.5.html#compatibility_level">compatibility_level</a> = 9999" at their own risk. </p>
+
</body>
</html>
name as used in "<a href="DATABASE_README.html#types">hash</a>:table" is the database file name without the
".db" suffix. </dd>
+<dt> <b></b>inline (read-only) </dt>
+
+<dd> A non-shared, in-memory lookup table. Example: "<a href="DATABASE_README.html#types">inline</a>:{
+<i>key=value</i>, { <i>key = text with whitespace or comma</i> }}".
+Key-value pairs are separated by whitespace or comma; whitespace
+after "{" and before "}" is ignored. Inline tables eliminate the
+need to create a database file for just a few fixed elements. See
+also the <a href="DATABASE_README.html#types">static</a>: map type. </dd>
+
<dt> <b>internal</b> </dt>
<dd> A non-shared, in-memory hash table. Its content are lost when
<dd> A table that always returns its name as the lookup result.
For example, "<a href="DATABASE_README.html#types">static</a>:foobar" always returns the string "foobar" as
-lookup result. </dd>
+lookup result. Specify "<a href="DATABASE_README.html#types">static</a>:{ <i>text with whitespace</i> }"
+when the result contains whitespace; this form ignores whitespace
+after "{" and before "}". See also the <a href="DATABASE_README.html#types">inline</a>: map type. </dd>
<dt> <b>tcp</b> </dt>
<li> <a href="IPV6_README.html"> IP Version 6 Support </a>
-<li> <a href="SMTPUTF8_README.html"> SMTPUTF8 support </a>
+<li> <a href="SMTPUTF8_README.html"> SMTPUTF8 Support </a>
-<li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Support</a>
+<li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Safety Net</a>
<li> <a href="INSTALL.html"> Installation from source code </a>
<b>hash</b> An indexed file type based on hashing. Available on sys-
tems with support for Berkeley DB databases.
+ <b>inline</b> (read-only)
+ A non-shared, in-memory lookup table. Example: "<b><a href="DATABASE_README.html#types">inline</a>:{</b>
+ <i>key</i><b>=</b><i>value</i><b>, {</b> <i>key</i> <b>=</b> <i>text with whitespace or comma</i> <b>}}</b>".
+ Key-value pairs are separated by whitespace or comma;
+ whitespace after "{" and before "}" is ignored. Inline
+ tables eliminate the need to create a database file for
+ just a few fixed elements. See also the <i><a href="DATABASE_README.html#types">static</a>:</i> map
+ type.
+
<b>internal</b>
A non-shared, in-memory hash table. Its content are lost
when a process terminates.
<b>static</b> (read-only)
A table that always returns its name as lookup result.
For example, <b><a href="DATABASE_README.html#types">static</a>:foobar</b> always returns the string <b>foo-</b>
- <b>bar</b> as lookup result.
+ <b>bar</b> as lookup result. Specify "<b><a href="DATABASE_README.html#types">static</a>:{</b> <i>text with white-</i>
+ <i>space</i> <b>}</b>" when the result contains whitespace; this form
+ ignores whitespace after "{" and before "}". See also the
+ <i><a href="DATABASE_README.html#types">inline</a>:</i> map.
<b>tcp</b> (read-only)
TCP/IP client. The protocol is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
<b>texthash</b> (read-only)
- Produces similar results as <a href="DATABASE_README.html#types">hash</a>: files, except that you
- don't need to run the <a href="postmap.1.html"><b>postmap</b>(1)</a> command before you can
- use the file, and that it does not detect changes after
+ Produces similar results as <a href="DATABASE_README.html#types">hash</a>: files, except that you
+ don't need to run the <a href="postmap.1.html"><b>postmap</b>(1)</a> command before you can
+ use the file, and that it does not detect changes after
the file is read.
<b>unionmap</b> (read-only)
- A table that sends each query to multiple lookup tables
- and that concatenates all found results, separated by
+ A table that sends each query to multiple lookup tables
+ and that concatenates all found results, separated by
comma. The table name syntax is the same as for <b>pipemap</b>.
<b>unix</b> (read-only)
- A limited view of the UNIX authentication database. The
+ A limited view of the UNIX authentication database. The
following tables are implemented:
<b>unix:passwd.byname</b>
- The table is the UNIX password database. The key
- is a login name. The result is a password file
+ The table is the UNIX password database. The key
+ is a login name. The result is a password file
entry in <b>passwd</b>(5) format.
<b>unix:group.byname</b>
The table is the UNIX group database. The key is a
- group name. The result is a group file entry in
+ group name. The result is a group file entry in
<b>group</b>(5) format.
- Other table types may exist depending on how Postfix was built.
+ Other table types may exist depending on how Postfix was built.
- <b>-M</b> Show <a href="master.5.html"><b>master.cf</b></a> file contents instead of <a href="postconf.5.html"><b>main.cf</b></a> file contents.
+ <b>-M</b> Show <a href="master.5.html"><b>master.cf</b></a> file contents instead of <a href="postconf.5.html"><b>main.cf</b></a> file contents.
Specify <b>-Mf</b> to fold long lines for human readability.
Specify zero or more arguments, each with a <i>service-name</i> or <i>ser-</i>
- <i>vice-name/service-type</i> pair, where <i>service-name</i> is the first
- field of a <a href="master.5.html">master.cf</a> entry and <i>service-type</i> is one of (<b>inet</b>,
+ <i>vice-name/service-type</i> pair, where <i>service-name</i> is the first
+ field of a <a href="master.5.html">master.cf</a> entry and <i>service-type</i> is one of (<b>inet</b>,
<b>unix</b>, <b>fifo</b>, or <b>pass</b>).
- If <i>service-name</i> or <i>service-name/service-type</i> is specified, only
- the matching <a href="master.5.html">master.cf</a> entries will be output. For example,
- "<b>postconf -Mf smtp</b>" will output all services named "smtp", and
- "<b>postconf -Mf smtp/inet</b>" will output only the smtp service that
- listens on the network. Trailing service type fields that are
+ If <i>service-name</i> or <i>service-name/service-type</i> is specified, only
+ the matching <a href="master.5.html">master.cf</a> entries will be output. For example,
+ "<b>postconf -Mf smtp</b>" will output all services named "smtp", and
+ "<b>postconf -Mf smtp/inet</b>" will output only the smtp service that
+ listens on the network. Trailing service type fields that are
omitted will be handled as "*" wildcard fields.
This feature is available with Postfix 2.9 and later. The syntax
- was changed from "<i>name.type</i>" to "<i>name/type</i>", and "*" wildcard
+ was changed from "<i>name.type</i>" to "<i>name/type</i>", and "*" wildcard
support was added with Postfix 2.11.
<b>-n</b> Show only configuration parameters that have explicit <i>name=value</i>
- settings in <a href="postconf.5.html"><b>main.cf</b></a>. Specify <b>-nf</b> to fold long lines for human
+ settings in <a href="postconf.5.html"><b>main.cf</b></a>. Specify <b>-nf</b> to fold long lines for human
readability (Postfix 2.9 and later).
<b>-o</b> <i>name=value</i>
This feature is available with Postfix 2.11 and later.
- <b>-P</b> Show <a href="master.5.html"><b>master.cf</b></a> service parameter settings (by default all ser-
+ <b>-P</b> Show <a href="master.5.html"><b>master.cf</b></a> service parameter settings (by default all ser-
vices and all parameters). formatted as one "<i>ser-</i>
- <i>vice/type/parameter=value</i>" per line. Specify <b>-Pf</b> to fold long
+ <i>vice/type/parameter=value</i>" per line. Specify <b>-Pf</b> to fold long
lines.
- Specify one or more "<i>service/type/parameter</i>" instances on the
- <a href="postconf.1.html"><b>postconf</b>(1)</a> command line to limit the output to parameters of
- interest. Trailing parameter name or service type fields that
+ Specify one or more "<i>service/type/parameter</i>" instances on the
+ <a href="postconf.1.html"><b>postconf</b>(1)</a> command line to limit the output to parameters of
+ interest. Trailing parameter name or service type fields that
are omitted will be handled as "*" wildcard fields.
This feature is available with Postfix 2.11 and later.
<b>-t</b> [<i>template</i><b>_</b><i>file</i>]
- Display the templates for text that appears at the beginning of
- delivery status notification (DSN) messages, without expanding
+ Display the templates for text that appears at the beginning of
+ delivery status notification (DSN) messages, without expanding
$<b>name</b> expressions.
To override the built-in templates, specify a template file name
- at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line, or specify a file
+ at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line, or specify a file
name in <a href="postconf.5.html"><b>main.cf</b></a> with the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter.
- To force selection of the built-in templates, specify an empty
- template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line (in shell
+ To force selection of the built-in templates, specify an empty
+ template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line (in shell
language: "").
This feature is available with Postfix 2.3 and later.
- <b>-v</b> Enable verbose logging for debugging purposes. Multiple <b>-v</b>
+ <b>-v</b> Enable verbose logging for debugging purposes. Multiple <b>-v</b>
options make the software increasingly verbose.
- <b>-x</b> Expand <i>$name</i> in <a href="postconf.5.html"><b>main.cf</b></a> or <a href="master.5.html"><b>master.cf</b></a> parameter values. The
+ <b>-x</b> Expand <i>$name</i> in <a href="postconf.5.html"><b>main.cf</b></a> or <a href="master.5.html"><b>master.cf</b></a> parameter values. The
expansion is recursive.
This feature is available with Postfix 2.10 and later.
- <b>-X</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and remove the parameters
+ <b>-X</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and remove the parameters
named on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line. Specify a list of param-
eter names, not "<i>name=value</i>" pairs.
- With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
- or more service entries as specified with "<i>service/type</i>" on the
+ With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
+ or more service entries as specified with "<i>service/type</i>" on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
- With <b>-P</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
+ With <b>-P</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and remove one
or more service parameter settings (-o parameter=value settings)
as specied with "<i>service/type/parameter</i>" on the <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
mand line.
into place. Specify quotes to protect special characters on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
- There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
+ There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
tion.
- This feature is available with Postfix 2.10 and later. Support
+ This feature is available with Postfix 2.10 and later. Support
for -M and -P was added with Postfix 2.11.
<b>-#</b> Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration file, and comment out the parame-
eters revert to their default values. Specify a list of parame-
ter names, not "<i>name=value</i>" pairs.
- With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and comment out
- one or more service entries as specified with "<i>service/type</i>" on
+ With <b>-M</b>, edit the <a href="master.5.html"><b>master.cf</b></a> configuration file, and comment out
+ one or more service entries as specified with "<i>service/type</i>" on
the <a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
In all cases the file is copied to a temporary file then renamed
into place. Specify quotes to protect special characters on the
<a href="postconf.1.html"><b>postconf</b>(1)</a> command line.
- There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
+ There is no <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the reverse opera-
tion.
- This feature is available with Postfix 2.6 and later. Support
+ This feature is available with Postfix 2.6 and later. Support
for -M was added with Postfix 2.11.
<b>DIAGNOSTICS</b>
Directory with Postfix configuration files.
<b>CONFIGURATION PARAMETERS</b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
gram.
- The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
+ The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
more details including examples.
<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 <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
- Pathname of a configuration file with bounce message templates.
+ Pathname of a configuration file with bounce message templates.
<b>FILES</b>
/etc/postfix/<a href="postconf.5.html">main.cf</a>, Postfix configuration parameters
<p> Large delay values are rounded off to an integral number seconds;
delay values below the <a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> are logged
-as "0", and small delay values are logged with at most two-digit
+as "0", and delay values under 100s are logged with at most two-digit
precision. </p>
<p> The format of the "delays=a/b/c/d" logging is as follows: </p>
</pre>
+</DD>
+
+<DT><b><a name="nullmx_reject_code">nullmx_reject_code</a>
+(default: 556)</b></DT><DD>
+
+<p> The numerical reply code when the Postfix SMTP server rejects
+a sender or recipient address because its domain has a nullmx DNS
+record (an MX record with an empty hostname). This is one of the
+possible replies from <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> and
+<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a>. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+
</DD>
<DT><b><a name="owner_request_special">owner_request_special</a>
record or 2) a malformed MX record such as a record with
a zero-length MX hostname (Postfix version 2.3 and later). <br> The
<a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies the numerical
-response code for rejected requests (default: 450). The response
+response code for rejected requests (default: 450). The <a href="postconf.5.html#nullmx_reject_code">nullmx_reject_code</a>
+parameter specifies the response code for domains with a nullmx
+DNS record (default: 556, Postfix 2.12 and later). The response
is always 450 in case of a temporary DNS error. <br> The
<a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> parameter specifies the action
after a temporary DNS error (default: <a href="postconf.5.html#defer_if_permit">defer_if_permit</a>). </dd>
record, or 2) a malformed MX record such as a record with
a zero-length MX hostname (Postfix version 2.3 and later). <br> The
<a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> parameter specifies the numerical
-response code for rejected requests (default: 450). The response
+response code for rejected requests (default: 450). The <a href="postconf.5.html#nullmx_reject_code">nullmx_reject_code</a>
+parameter specifies the response code for domains with a nullmx
+DNS record (default 556, Postfix 2.12 and later). The response
is always 450 in case of a temporary DNS error. <br> The
<a href="postconf.5.html#unknown_address_tempfail_action">unknown_address_tempfail_action</a> parameter specifies the action
after a temporary DNS error (default: <a href="postconf.5.html#defer_if_permit">defer_if_permit</a>). </dd>
<p>
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. The response is
-always 450 in case of a temporary DNS error.
+or <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction. The <a href="postconf.5.html#nullmx_reject_code">nullmx_reject_code</a>
+is used for domains with a nullmx DNS record (Postfix 2.12 and
+later). The response is always 450 in case of a temporary DNS
+error.
</p>
<p>
<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 temporary error condition.
+ Available in Postfix version 2.12 and later:
+
+ <b><a href="postconf.5.html#nullmx_reject_code">nullmx_reject_code</a> (556)</b>
+ The numerical reply code when the Postfix SMTP server rejects a
+ sender or recipient address because its domain has a nullmx DNS
+ record (an MX record with an empty hostname).
+
<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 <a href="master.5.html">master.cf</a> con-
.IP \fBhash\fR
An indexed file type based on hashing. Available on systems
with support for Berkeley DB databases.
+.IP "\fBinline\fR (read-only)"
+A non-shared, in-memory lookup table. Example: "\fBinline:{
+\fIkey\fB=\fIvalue\fB, { \fIkey\fB = \fItext with whitespace
+or comma\fB }}\fR". Key-value pairs are separated by
+whitespace or comma; whitespace after "{" and before "}"
+is ignored. Inline tables eliminate the need to create a
+database file for just a few fixed elements. See also the
+\fIstatic:\fR map type.
.IP \fBinternal\fR
A non-shared, in-memory hash table. Its content are lost
when a process terminates.
.IP "\fBstatic\fR (read-only)"
A table that always returns its name as lookup result. For
example, \fBstatic:foobar\fR always returns the string
-\fBfoobar\fR as lookup result.
+\fBfoobar\fR as lookup result. Specify "\fBstatic:{ \fItext
+with whitespace\fB }\fR" when the result contains whitespace;
+this form ignores whitespace after "{" and before "}". See
+also the \fIinline:\fR map.
.IP "\fBtcp\fR (read-only)"
TCP/IP client. The protocol is described in \fBtcp_table\fR(5).
.IP "\fBtexthash\fR (read-only)"
.PP
Large delay values are rounded off to an integral number seconds;
delay values below the delay_logging_resolution_limit are logged
-as "0", and small delay values are logged with at most two-digit
+as "0", and delay values under 100s are logged with at most two-digit
precision.
.PP
The format of the "delays=a/b/c/d" logging is as follows:
.fi
.ad
.ft R
+.SH nullmx_reject_code (default: 556)
+The numerical reply code when the Postfix SMTP server rejects
+a sender or recipient address because its domain has a nullmx DNS
+record (an MX record with an empty hostname). This is one of the
+possible replies from reject_unknown_sender_domain and
+reject_unknown_recipient_domain.
+.PP
+This feature is available in Postfix 2.12 and later.
.SH owner_request_special (default: yes)
Give special treatment to owner-listname and listname-request
address localparts: don't split such addresses when the
.br
The
unknown_address_reject_code parameter specifies the numerical
-response code for rejected requests (default: 450). The response
+response code for rejected requests (default: 450). The nullmx_reject_code
+parameter specifies the response code for domains with a nullmx
+DNS record (default: 556, Postfix 2.12 and later). The response
is always 450 in case of a temporary DNS error.
.br
The
.br
The
unknown_address_reject_code parameter specifies the numerical
-response code for rejected requests (default: 450). The response
+response code for rejected requests (default: 450). The nullmx_reject_code
+parameter specifies the response code for domains with a nullmx
+DNS record (default 556, Postfix 2.12 and later). The response
is always 450 in case of a temporary DNS error.
.br
The
.SH unknown_address_reject_code (default: 450)
The numerical Postfix SMTP server response code when a sender or
recipient address is rejected by the reject_unknown_sender_domain
-or reject_unknown_recipient_domain restriction. The response is
-always 450 in case of a temporary DNS error.
+or reject_unknown_recipient_domain restriction. The nullmx_reject_code
+is used for domains with a nullmx DNS record (Postfix 2.12 and
+later). The response is always 450 in case of a temporary DNS
+error.
.PP
Do not change this unless you have a complete understanding of RFC 5321.
.SH unknown_address_tempfail_action (default: $reject_tempfail_action)
The Postfix SMTP server's action when reject_unknown_sender_domain
or reject_unknown_recipient_domain fail due to a temporary error
condition.
+.PP
+Available in Postfix version 2.12 and later:
+.IP "\fBnullmx_reject_code (556)\fR"
+The numerical reply code when the Postfix SMTP server rejects
+a sender or recipient address because its domain has a nullmx DNS
+record (an MX record with an empty hostname).
.SH "MISCELLANEOUS CONTROLS"
.na
.nf
s;\bno_address_mappings\b;<a href="postconf.5.html#no_address_mappings">$&</a>;g;
s;\bno_header_body_checks\b;<a href="postconf.5.html#no_header_body_checks">$&</a>;g;
s;\bno_milters\b;<a href="postconf.5.html#no_milters">$&</a>;g;
+ s;\bnullmx_reject_code\b;<a href="postconf.5.html#nullmx_reject_code">$&</a>;g;
s;\brecip[-</bB>]*\n* *[<bB>]*i[-</bB>]*\n* *[<bB>]*ent_bcc_maps\b;<a href="postconf.5.html#recipient_bcc_maps">$&</a>;g;
s;\brecip[-</bB>]*\n* *[<bB>]*i[-</bB>]*\n* *[<bB>]*ent_canoni[-</bB>]*\n* *[<bB>]*cal_classes\b;<a href="postconf.5.html#recipient_canonical_classes">$&</a>;g;
s;\brecip[-</bB>]*\n* *[<bB>]*i[-</bB>]*\n* *[<bB>]*ent_canoni[-</bB>]*\n* *[<bB>]*cal_maps\b;<a href="postconf.5.html#recipient_canonical_maps">$&</a>;g;
s/\b(texthash):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
#s/\b(unix):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
s/\b(unionmap):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
+ s/\b(inline):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
# Do nice links for smtp:host:port etc.
<blockquote>
<pre>
/etc/postfix/main.cf:
- mua_cleanup_service_name = mua_cleanup
- mua_header_checks = pcre:/etc/postfix/mua_header_checks
- mua_body_checks = pcre:/etc/postfix/mua_body_checks
+ msa_cleanup_service_name = msa_cleanup
+ msa_header_checks = pcre:/etc/postfix/msa_header_checks
+ msa_body_checks = pcre:/etc/postfix/msa_body_checks
</pre>
</blockquote>
-<p> Next, we define mua_cleanup as a dedicated cleanup service that
+<p> Next, we define msa_cleanup as a dedicated cleanup service that
will be used only by the submission and smtps services. This service
uses the header_checks and body_checks overrides that were defined
above. </p>
# (yes) (yes) (yes) (never) (100)
# =================================================================
smtp inet n - n - - smtpd
- mua_cleanup unix n - n - 0 cleanup
- -o header_checks=$mua_header_checks
- -o body_checks=$mua_body_checks
+ msa_cleanup unix n - n - 0 cleanup
+ -o header_checks=$msa_header_checks
+ -o body_checks=$msa_body_checks
submission inet n - n - - smtpd
- -o cleanup_service_name=$mua_cleanup_service_name
+ -o cleanup_service_name=$msa_cleanup_service_name
-o syslog_name=postfix/submission
<i>...[see sample master.cf file for more]...</i>
smtps inet n - n - - smtpd
- -o cleanup_service_name=$mua_cleanup_service_name
+ -o cleanup_service_name=$msa_cleanup_service_name
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
<i>...[see sample master.cf file for more]...</i>
</pre>
</blockquote>
-<p> By keeping the "mua_xxx" parameter settings in main.cf, you
+<p> By keeping the "msa_xxx" parameter settings in main.cf, you
keep your master.cf file simple, and you minimize the amount
of duplication. </p>
<head>
-<title>Postfix Backwards-Compatibility Support</title>
+<title>Postfix Backwards-Compatibility Safty Net</title>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<body>
<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
-Backwards-Compatibility Support</h1>
+Backwards-Compatibility Safty Net</h1>
<hr>
-<h2>Overview </h2>
+<h2>Purpose of this document </h2>
-<p> Postfix 2.12 introduces a safety net that causes Postfix programs
-to run with backwards-compatible default settings after an upgrade
-to a newer Postfix version. Backwards compatibility is turned on
-when the main.cf compatibility_level value is less than the Postfix
-built-in value. </p>
+<p> Postfix 2.12 introduces a safety net that runs Postfix programs
+with backwards-compatible default settings after an upgrade. The
+safety net will log a warning whenever a "new" default setting could
+have an negative effect on your mail flow. </p>
-<p> With backwards compatibility turned on, Postfix looks for
-settings that are left at their implicit default value, and logs a
-message when a backwards-compatible default setting is required for
-continuity of service. The following messages may be logged: </p>
+<p>This document provides information on the following topics: </p>
+
+<ul>
+
+<li> <p> <a href="#overview">Detailed descriptions</a> of Postfix
+backwards-compatibility warnings.
+
+<li> <p> What backwards-compatible settings you may have to make
+permanent in main.cf or master.cf. </p>
+
+<li> <p> <a href="#turnoff">How to turn off</a> Postfix
+backwards-compatibility warnings. </p>
+
+</ul>
+
+<h2> <a name="overview"> Overview </a> </h2>
+
+<p> With backwards compatibility turned on, Postfix logs a message
+whenever a backwards-compatible default setting may be required for
+continuity of service. Based on this logging the system administrator
+can decide if any backwards-compatible settings need to be made
+permanent in main.cf or master.cf, before <a href="#turnoff">turning
+off the backwards-compatibility safety net</a> as described at the
+end of this document. </p>
+
+<p> The following messages may be logged: </p>
<ul>
sections that follow. </p>
<p> When no more backwards-compatible settings need to be made
-permanent, the administrator should turn off backwards compatibility
-by updating the compatibility_level setting in main.cf. </p>
-
-<blockquote>
-<pre>
-# <b>postconf compatibility_level=<i>N</i></b>
-# <b>postfix reload</b>
-</pre>
-</blockquote>
-
-<p> For <i>N</i> specify the number that is logged in your postfix(1)
-warning message: </p>
-
-<blockquote>
-<pre>
-warning: To disable backwards compatibility use "postconf compatibility_level=<i>N</i>" and "postfix reload"
-</pre>
-</blockquote>
-
-<p> Sites that don't care about backwards compatibility may set
-"compatibility_level = 9999" at their own risk. </p>
+permanent, the system administrator should <a href="#turnoff">turn
+off the backwards-compatibility safety net</a> as described at the
+end of this document. </p>
<h2> <a name="append_dot_mydomain"> Using backwards-compatible default
setting append_dot_mydomain=yes</a> </h2>
</pre>
</blockquote>
+<h2> <a name="turnoff">Turning off the backwards-compatibility safety net</a> </h2>
+
+<p> Backwards compatibility is turned off by updating the
+compatibility_level setting in main.cf. </p>
+
+<blockquote>
+<pre>
+# <b>postconf compatibility_level=<i>N</i></b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p> For <i>N</i> specify the number that is logged in your postfix(1)
+warning message: </p>
+
+<blockquote>
+<pre>
+warning: To disable backwards compatibility use "postconf compatibility_level=<i>N</i>" and "postfix reload"
+</pre>
+</blockquote>
+
+<p> Sites that don't care about backwards compatibility may set
+"compatibility_level = 9999" at their own risk. </p>
+
</body>
</html>
name as used in "hash:table" is the database file name without the
".db" suffix. </dd>
+<dt> <b></b>inline (read-only) </dt>
+
+<dd> A non-shared, in-memory lookup table. Example: "inline:{
+<i>key=value</i>, { <i>key = text with whitespace or comma</i> }}".
+Key-value pairs are separated by whitespace or comma; whitespace
+after "{" and before "}" is ignored. Inline tables eliminate the
+need to create a database file for just a few fixed elements. See
+also the static: map type. </dd>
+
<dt> <b>internal</b> </dt>
<dd> A non-shared, in-memory hash table. Its content are lost when
<dd> A table that always returns its name as the lookup result.
For example, "static:foobar" always returns the string "foobar" as
-lookup result. </dd>
+lookup result. Specify "static:{ <i>text with whitespace</i> }"
+when the result contains whitespace; this form ignores whitespace
+after "{" and before "}". See also the inline: map type. </dd>
<dt> <b>tcp</b> </dt>
record or 2) a malformed MX record such as a record with
a zero-length MX hostname (Postfix version 2.3 and later). <br> The
unknown_address_reject_code parameter specifies the numerical
-response code for rejected requests (default: 450). The response
+response code for rejected requests (default: 450). The nullmx_reject_code
+parameter specifies the response code for domains with a nullmx
+DNS record (default: 556, Postfix 2.12 and later). The response
is always 450 in case of a temporary DNS error. <br> The
unknown_address_tempfail_action parameter specifies the action
after a temporary DNS error (default: defer_if_permit). </dd>
record, or 2) a malformed MX record such as a record with
a zero-length MX hostname (Postfix version 2.3 and later). <br> The
unknown_address_reject_code parameter specifies the numerical
-response code for rejected requests (default: 450). The response
+response code for rejected requests (default: 450). The nullmx_reject_code
+parameter specifies the response code for domains with a nullmx
+DNS record (default 556, Postfix 2.12 and later). The response
is always 450 in case of a temporary DNS error. <br> The
unknown_address_tempfail_action parameter specifies the action
after a temporary DNS error (default: defer_if_permit). </dd>
<p>
The numerical Postfix SMTP server response code when a sender or
recipient address is rejected by the reject_unknown_sender_domain
-or reject_unknown_recipient_domain restriction. The response is
-always 450 in case of a temporary DNS error.
+or reject_unknown_recipient_domain restriction. The nullmx_reject_code
+is used for domains with a nullmx DNS record (Postfix 2.12 and
+later). The response is always 450 in case of a temporary DNS
+error.
</p>
<p>
<p> Large delay values are rounded off to an integral number seconds;
delay values below the delay_logging_resolution_limit are logged
-as "0", and small delay values are logged with at most two-digit
+as "0", and delay values under 100s are logged with at most two-digit
precision. </p>
<p> The format of the "delays=a/b/c/d" logging is as follows: </p>
header names is limited only by available memory. </p>
<p> This feature is available in Postfix 2.12 and later. </p>
+
+%PARAM nullmx_reject_code 556
+
+<p> The numerical reply code when the Postfix SMTP server rejects
+a sender or recipient address because its domain has a nullmx DNS
+record (an MX record with an empty hostname). This is one of the
+possible replies from reject_unknown_sender_domain and
+reject_unknown_recipient_domain. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
test: $(TESTPROG)
tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \
- dns_rr_eq_sa_test
+ dns_rr_eq_sa_test nullmx_test nxdomain_test mxonly_test
root_tests:
diff dns_rr_eq_sa.ref dns_rr_eq_sa.tmp
rm -f dns_rr_eq_sa.tmp
+nullmx_test: test_dns_lookup nullmx_test.ref
+ (set -e; \
+ $(SHLIB_ENV) ./test_dns_lookup mx,a nullmx.porcupine.org; \
+ ) >nullmx_test.tmp 2>&1 || exit 0
+ diff nullmx_test.ref nullmx_test.tmp
+ rm -f nullmx_test.tmp
+
+nxdomain_test: test_dns_lookup nxdomain_test.ref
+ (set -e; \
+ $(SHLIB_ENV) ./test_dns_lookup mx,a nxdomain.porcupine.org; \
+ ) >nxdomain_test.tmp 2>&1 || exit 0
+ diff nxdomain_test.ref nxdomain_test.tmp
+ rm -f nxdomain_test.tmp
+
+mxonly_test: test_dns_lookup mxonly_test.ref
+ (set -e; \
+ $(SHLIB_ENV) ./test_dns_lookup mx,a porcupine.org | sort; \
+ ) >mxonly_test.tmp 2>&1 || exit 0
+ diff mxonly_test.ref mxonly_test.tmp
+ rm -f mxonly_test.tmp
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
*/
#define DNS_REQ_FLAG_STOP_OK (1<<0)
#define DNS_REQ_FLAG_STOP_INVAL (1<<1)
+#define DNS_REQ_FLAG_STOP_UNAVAIL (1<<2)
#define DNS_REQ_FLAG_NONE (0)
/*
* Status codes. Failures must have negative codes so they will not collide
* with valid counts of answer records etc.
*/
+#define DNS_UNAVAIL (-6) /* query ok, service unavailable */
#define DNS_INVAL (-5) /* query ok, malformed reply */
#define DNS_FAIL (-4) /* query failed, don't retry */
#define DNS_NOTFOUND (-3) /* query ok, data not found */
/* .IP DNS_REQ_FLAG_STOP_INVAL
/* Invoke dns_lookup() for the resource types in the order as
/* specified, and return when dns_lookup() returns DNS_INVAL.
+/* .IP DNS_REQ_FLAG_STOP_UNAVAIL
+/* Invoke dns_lookup() for the resource types in the order as
+/* specified, and return when dns_lookup() returns DNS_UNAVAIL.
/* .IP DNS_REQ_FLAG_STOP_OK
/* Invoke dns_lookup() for the resource types in the order as
/* specified, and return when dns_lookup() returns DNS_OK.
/* The DNS query succeeded.
/* .IP DNS_NOTFOUND
/* The DNS query succeeded; the requested information was not found.
+/* .IP DNS_UNAVAIL
+/* The DNS query succeeded; the requested service is unavailable.
+/* This is returned when the list argument is not a null
+/* pointer, and an MX lookup result contains a null server
+/* name (so-called "nullmx" record).
/* .IP DNS_INVAL
/* The DNS query succeeded; the result failed the valid_hostname() test.
/*
GETSHORT(pref, pos);
if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
return (DNS_RETRY);
+ /* Don't even think of returning an invalid hostname to the caller. */
+ if (*temp == 0)
+ return (DNS_UNAVAIL); /* XXX TODO: return descriptive text here */
if (!valid_rr_name(temp, "resource data", fixed->type, reply))
return (DNS_INVAL);
data_len = strlen(temp) + 1;
resource_found++;
rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
*rrlist = dns_rr_append(*rrlist, rr);
+ } else if (status == DNS_UNAVAIL) {
+ CORRUPT(status); /* XXX TODO: use better name here */
} else if (not_found_status != DNS_RETRY)
not_found_status = status;
} else
vstring_sprintf(why, "Name service error for name=%s type=%s: "
"Malformed or unexpected name server reply",
name, dns_strtype(type));
- /* FALLTHROUGH */
+ return (status);
+ case DNS_UNAVAIL:
+ if (why)
+ vstring_sprintf(why, type == T_MX ? /* XXX TODO: move this */
+ "Domain %s does not accept mail (null %s)" :
+ "Domain %s does not provide %s service",
+ name, dns_strtype(type));
+ h_errno = NO_DATA;
+ return (status);
case DNS_OK:
return (status);
case DNS_RECURSE:
} else if (status == DNS_INVAL) {
if (lflags & DNS_REQ_FLAG_STOP_INVAL)
break;
+ } else if (status == DNS_UNAVAIL) {
+ if (lflags & DNS_REQ_FLAG_STOP_UNAVAIL)
+ break;
} else if (status == DNS_RETRY) {
soft_err = 1;
}
} else if (status == DNS_INVAL) {
if (lflags & DNS_REQ_FLAG_STOP_INVAL)
break;
+ } else if (status == DNS_UNAVAIL) {
+ if (lflags & DNS_REQ_FLAG_STOP_UNAVAIL)
+ break;
} else if (status == DNS_RETRY) {
soft_err = 1;
}
--- /dev/null
+./test_dns_lookup: lookup porcupine.org type MX flags 2097152
+./test_dns_lookup: dns_query: porcupine.org (MX): OK
+./test_dns_lookup: dns_get_answer: type MX for porcupine.org
+./test_dns_lookup: dns_get_answer: type MX for porcupine.org
+./test_dns_lookup: dns_get_answer: type MX for porcupine.org
+./test_dns_lookup: lookup porcupine.org type A flags 2097152
+./test_dns_lookup: dns_query: porcupine.org (A): Host found but no data record of requested type
+porcupine.org: ad: 0, ttl: 3600 pref: 10 MX: spike.porcupine.org
+porcupine.org: ad: 0, ttl: 3600 pref: 20 MX: fist.porcupine.org
+porcupine.org: ad: 0, ttl: 3600 pref: 30 MX: m1.porcupine.org
+porcupine.org: fqdn: porcupine.org
--- /dev/null
+./test_dns_lookup: lookup nullmx.porcupine.org type MX flags 2097152
+./test_dns_lookup: dns_query: nullmx.porcupine.org (MX): OK
+./test_dns_lookup: dns_get_answer: type MX for nullmx.porcupine.org
+./test_dns_lookup: lookup nullmx.porcupine.org type A flags 2097152
+./test_dns_lookup: dns_query: nullmx.porcupine.org (A): OK
+./test_dns_lookup: dns_get_answer: type A for nullmx.porcupine.org
+nullmx.porcupine.org: fqdn: nullmx.porcupine.org
+nullmx.porcupine.org: ad: 0, ttl: 3600 A: 168.100.189.13
--- /dev/null
+./test_dns_lookup: lookup nxdomain.porcupine.org type MX flags 2097152
+./test_dns_lookup: dns_query: nxdomain.porcupine.org (MX): Host not found
+./test_dns_lookup: lookup nxdomain.porcupine.org type A flags 2097152
+./test_dns_lookup: dns_query: nxdomain.porcupine.org (A): Host not found
+./test_dns_lookup: fatal: Host or domain name not found. Name service error for name=nxdomain.porcupine.org type=A: Host not found (rcode=3)
argv_free(types_argv);
name = argv[2];
msg_verbose = 1;
- switch (dns_lookup_rv(name, RES_DEBUG | RES_USE_DNSSEC, &rr, fqdn, why,
+ switch (dns_lookup_rv(name, RES_USE_DNSSEC, &rr, fqdn, why,
&rcode, DNS_REQ_FLAG_NONE, types)) {
default:
msg_fatal("%s (rcode=%d)", vstring_str(why), rcode);
#include <vstream.h>
#include <msg_vstream.h>
#include <rec_streamlf.h>
+#include <mail_params.h>
typedef struct {
HBC_CHECKS *header_checks;
int var_header_limit = 2000;
int var_mime_maxdepth = 20;
int var_mime_bound_len = 2000;
+char *var_drop_hdrs = DEF_DROP_HDRS;
int main(int argc, char **argv)
{
#define DEF_UNK_ADDR_CODE 450
extern int var_unk_addr_code;
+#define VAR_NULLMX_RCODE "nullmx_reject_code"
+#define DEF_NULLMX_RCODE 556
+extern int var_nullmx_rcode;
+
#define VAR_UNK_ADDR_TF_ACT "unknown_address_tempfail_action"
#define DEF_UNK_ADDR_TF_ACT "$" VAR_REJECT_TMPF_ACT
extern char *var_unk_addr_tf_act;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20141119"
+#define MAIL_RELEASE_DATE "20141126"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT
int var_header_limit = 2000;
int var_mime_maxdepth = 20;
int var_mime_bound_len = 2000;
+char *var_drop_hdrs = DEF_DROP_HDRS;
int main(int unused_argc, char **argv)
{
/* .IP \fBhash\fR
/* An indexed file type based on hashing. Available on systems
/* with support for Berkeley DB databases.
+/* .IP "\fBinline\fR (read-only)"
+/* A non-shared, in-memory lookup table. Example: "\fBinline:{
+/* \fIkey\fB=\fIvalue\fB, { \fIkey\fB = \fItext with whitespace
+/* or comma\fB }}\fR". Key-value pairs are separated by
+/* whitespace or comma; whitespace after "{" and before "}"
+/* is ignored. Inline tables eliminate the need to create a
+/* database file for just a few fixed elements. See also the
+/* \fIstatic:\fR map type.
/* .IP \fBinternal\fR
/* A non-shared, in-memory hash table. Its content are lost
/* when a process terminates.
/* .IP "\fBstatic\fR (read-only)"
/* A table that always returns its name as lookup result. For
/* example, \fBstatic:foobar\fR always returns the string
-/* \fBfoobar\fR as lookup result.
+/* \fBfoobar\fR as lookup result. Specify "\fBstatic:{ \fItext
+/* with whitespace\fB }\fR" when the result contains whitespace;
+/* this form ignores whitespace after "{" and before "}". See
+/* also the \fIinline:\fR map.
/* .IP "\fBtcp\fR (read-only)"
/* TCP/IP client. The protocol is described in \fBtcp_table\fR(5).
/* .IP "\fBtexthash\fR (read-only)"
case DNS_INVAL:
dsb_status(state->why, "5.4.4");
break;
+ case DNS_UNAVAIL:
+ dsb_status(state->why, "5.1.0");
+ break;
case DNS_FAIL:
dsb_status(state->why, "5.4.3");
break;
if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(aname, misc_flags, why);
break;
+ case DNS_UNAVAIL:
+ dsb_status(why, "5.1.0");
+ break;
case DNS_FAIL:
dsb_status(why, "5.4.3");
if (var_ign_mx_lookup_err)
tests: smtpd_check_test smtpd_check_test2 smtpd_acl_test smtpd_exp_test \
smtpd_token_test smtpd_check_test4 smtpd_check_dsn_test \
smtpd_check_backup_test smtpd_dnswl_test smtpd_error_test \
- smtpd_server_test
+ smtpd_server_test smtpd_nullmx_test
root_tests:
diff smtpd_server.ref smtpd_server.tmp
rm -f smtpd_server.tmp smtpd_check_access.*
+smtpd_nullmx_test: smtpd_check smtpd_nullmx.in smtpd_nullmx.ref
+ $(SHLIB_ENV) ../postmap/postmap hash:smtpd_check_access
+ $(SHLIB_ENV) ./smtpd_check <smtpd_nullmx.in >smtpd_nullmx.tmp 2>&1
+ diff smtpd_nullmx.ref smtpd_nullmx.tmp
+ rm -f smtpd_nullmx.tmp smtpd_check_access.*
+
smtpd_check_dsn_test: smtpd_check smtpd_check_dsn.in smtpd_check_dsn.ref smtpd_check_access
$(SHLIB_ENV) ../postmap/postmap hash:smtpd_check_access
$(SHLIB_ENV) ./smtpd_check <smtpd_check_dsn.in >smtpd_check.tmp 2>&1
/* The Postfix SMTP server's action when reject_unknown_sender_domain
/* or reject_unknown_recipient_domain fail due to a temporary error
/* condition.
+/* .PP
+/* Available in Postfix version 2.12 and later:
+/* .IP "\fBnullmx_reject_code (556)\fR"
+/* The numerical reply code when the Postfix SMTP server rejects
+/* a sender or recipient address because its domain has a nullmx DNS
+/* record (an MX record with an empty hostname).
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
bool var_smtpd_peername_lookup;
int var_plaintext_code;
+int var_nullmx_rcode;
bool var_smtpd_delay_open;
char *var_smtpd_milters;
int var_milt_conn_time;
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0,
VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0,
+ VAR_NULLMX_RCODE, DEF_NULLMX_RCODE, &var_nullmx_rcode, 0, 0,
VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0,
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
if (dummy)
dns_rr_free(dummy);
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
+ /* We don't care about DNS_UNAVAIL. */
if (dns_status != DNS_RETRY)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
var_unk_name_code, "4.7.1",
}
#endif
-#define MAILHOST_LOOKUP_FLAGS (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL)
+#define MAILHOST_LOOKUP_FLAGS \
+ (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL | DNS_REQ_FLAG_STOP_UNAVAIL)
dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0,
(VSTRING *) 0, MAILHOST_LOOKUP_FLAGS,
if (dummy)
dns_rr_free(dummy);
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
+ if (dns_status == DNS_UNAVAIL)
+ return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
+ var_nullmx_rcode,
+ strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
+ "4.7.0" : "4.1.0",
+ "<%s>: %s rejected: "
+ "Domain %s does not accept mail",
+ reply_name, reply_class, name));
if (dns_status != DNS_RETRY)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
var_unk_addr_code,
*/
dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0,
DNS_REQ_FLAG_NONE, inet_proto_info()->dns_atype_list);
+ /* DNS_UNAVAIL is not applicable here. */
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
450, "4.4.4",
SMTPD_CHECK_OK : SMTPD_CHECK_DUNNO);
#endif
if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
+ /* We don't care about DNS_UNAVAIL. */
if (dns_status == DNS_RETRY)
DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
450, "4.4.4",
} else {
dns_status = dns_lookup(domain, type, 0, &server_list,
(VSTRING *) 0, (VSTRING *) 0);
+ if (dns_status == DNS_UNAVAIL)
+ return (SMTPD_CHECK_DUNNO);
if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) {
if (type == T_MX) {
server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
#endif
char *var_mynetworks = "";
char *var_notify_classes = "";
+char *var_smtpd_policy_def_action = "";
/*
* String-valued configuration parameters.
int var_smtpd_policy_tmout;
int var_smtpd_policy_idle;
int var_smtpd_policy_ttl;
+int var_smtpd_policy_req_limit;
+int var_smtpd_policy_try_limit;
+int var_smtpd_policy_try_delay;
int var_smtpd_rej_unl_from;
int var_smtpd_rej_unl_rcpt;
int var_plaintext_code;
bool var_smtpd_peername_lookup;
bool var_smtpd_client_port_log;
+int var_nullmx_rcode;
+
+#define int_table test_int_table
static const INT_TABLE int_table[] = {
"msg_verbose", 0, &msg_verbose,
VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code,
VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup,
VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log,
+ VAR_NULLMX_RCODE, DEF_NULLMX_RCODE, &var_nullmx_rcode,
0,
};
if (strcasecmp(args->argv[0], VAR_MYDEST) == 0) {
UPDATE_STRING(var_mydest, args->argv[1]);
resolve_local_init();
+ smtpd_resolve_init(100);
resp = 0;
break;
}
if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_DOMS) == 0) {
UPDATE_STRING(var_virt_alias_doms, args->argv[1]);
UPDATE_LIST(virt_alias_doms, var_virt_alias_doms);
+ smtpd_resolve_init(100);
resp = 0;
break;
}
if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_DOMS) == 0) {
UPDATE_STRING(var_virt_mailbox_doms, args->argv[1]);
UPDATE_LIST(virt_mailbox_doms, var_virt_mailbox_doms);
+ smtpd_resolve_init(100);
resp = 0;
break;
}
}
if (strcasecmp(args->argv[0], VAR_MYNETWORKS) == 0) {
/* NOT: UPDATE_STRING */
- namadr_list_free(mynetworks);
- mynetworks =
+ namadr_list_free(mynetworks_curr);
+ mynetworks_curr =
namadr_list_init(MATCH_FLAG_RETURN
| match_parent_style(VAR_MYNETWORKS),
args->argv[1]);
+ smtpd_resolve_init(100);
resp = 0;
break;
}
relay_domains =
domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
args->argv[1]);
+ smtpd_resolve_init(100);
resp = 0;
break;
}
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 4.7.1 <foo>: Helo command rejected: Host not found; proto=SMTP helo=<foo>
450 4.7.1 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
-./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 5.7.1 <spike.porcupine.org>: Helo command rejected: name server spike.porcupine.org; proto=SMTP helo=<spike.porcupine.org>
-554 5.7.1 <spike.porcupine.org>: Helo command rejected: name server spike.porcupine.org
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 5.7.1 <spike.porcupine.org>: Helo command rejected: ns or mx server spike.porcupine.org; proto=SMTP helo=<spike.porcupine.org>
+554 5.7.1 <spike.porcupine.org>: Helo command rejected: ns or mx server spike.porcupine.org
>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
64.94.110.11 reject Verisign wild-card
topica.com reject
10.10.10.10 reject mail server 10.10.10.10
-spike.porcupine.org reject name server spike.porcupine.org
+spike.porcupine.org reject ns or mx server spike.porcupine.org
241 reject class E subnet
4.1.1_dsn reject 4.1.1 reject
4.1.2_dsn reject 4.1.2 reject
--- /dev/null
+#
+# Initialize.
+#
+#! ../bin/postmap smtpd_check_access
+#msg_verbose 1
+#smtpd_delay_reject 0
+#mynetworks 127.0.0.0/8,168.100.189.0/28
+#relay_domains porcupine.org
+#maps_rbl_domains dnsbltest.porcupine.org
+#rbl_reply_maps hash:smtpd_check_access
+#helo foobar
+#
+# reject_unknown_helo_hostname
+#
+smtpd_delay_reject 0
+helo_restrictions reject_unknown_helo_hostname
+client spike.porcupine.org 168.100.189.2
+mail sname@sdomain
+rcpt rname@rdomain
+helo nxdomain.porcupine.org
+helo nullmx.porcupine.org
+helo spike.porcupine.org
+#
+# reject_unknown_sender_domain
+#
+smtpd_delay_reject 0
+sender_restrictions reject_unknown_sender_domain
+client spike.porcupine.org 168.100.189.2
+helo spike.porcupine.org
+rcpt rname@rdomain
+mail sname@nxdomain.porcupine.org
+mail sname@nullmx.porcupine.org
+mail sname@spike.porcupine.org
+#
+# reject_unknown_recipient_domain
+#
+smtpd_delay_reject 0
+sender_restrictions permit
+recipient_restrictions reject_unknown_recipient_domain
+relay_restrictions reject_unauth_destination
+client spike.porcupine.org 168.100.189.2
+helo spike.porcupine.org
+mail sname@sdomain
+relay_domains nxdomain.porcupine.org
+rcpt rname@nxdomain.porcupine.org
+relay_domains nullmx.porcupine.org
+rcpt rname@nullmx.porcupine.org
+relay_domains spike.porcupine.org
+rcpt rname@spike.porcupine.org
+#
+# check_mx_access
+#
+smtpd_delay_reject 0
+sender_restrictions check_sender_mx_access,hash:smtpd_check_access
+client spike.porcupine.org 168.100.189.2
+mail sname@nxdomain.porcupine.org
+mail sname@nullmx.porcupine.org
+mail sname@spike.porcupine.org
--- /dev/null
+>>> #
+>>> # Initialize.
+>>> #
+>>> #! ../bin/postmap smtpd_check_access
+>>> #msg_verbose 1
+>>> #smtpd_delay_reject 0
+>>> #mynetworks 127.0.0.0/8,168.100.189.0/28
+>>> #relay_domains porcupine.org
+>>> #maps_rbl_domains dnsbltest.porcupine.org
+>>> #rbl_reply_maps hash:smtpd_check_access
+>>> #helo foobar
+>>> #
+>>> # reject_unknown_helo_hostname
+>>> #
+>>> smtpd_delay_reject 0
+OK
+>>> helo_restrictions reject_unknown_helo_hostname
+OK
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>> mail sname@sdomain
+OK
+>>> rcpt rname@rdomain
+OK
+>>> helo nxdomain.porcupine.org
+./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.189.2]: 450 4.7.1 <nxdomain.porcupine.org>: Helo command rejected: Host not found; from=<sname@sdomain> proto=SMTP helo=<nxdomain.porcupine.org>
+450 4.7.1 <nxdomain.porcupine.org>: Helo command rejected: Host not found
+>>> helo nullmx.porcupine.org
+OK
+>>> helo spike.porcupine.org
+OK
+>>> #
+>>> # reject_unknown_sender_domain
+>>> #
+>>> smtpd_delay_reject 0
+OK
+>>> sender_restrictions reject_unknown_sender_domain
+OK
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>> helo spike.porcupine.org
+OK
+>>> rcpt rname@rdomain
+OK
+>>> mail sname@nxdomain.porcupine.org
+./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.189.2]: 450 4.1.8 <sname@nxdomain.porcupine.org>: Sender address rejected: Domain not found; from=<sname@nxdomain.porcupine.org> proto=SMTP helo=<spike.porcupine.org>
+450 4.1.8 <sname@nxdomain.porcupine.org>: Sender address rejected: Domain not found
+>>> mail sname@nullmx.porcupine.org
+./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.189.2]: 556 5.7.0 <sname@nullmx.porcupine.org>: Sender address rejected: Domain nullmx.porcupine.org does not accept mail; from=<sname@nullmx.porcupine.org> proto=SMTP helo=<spike.porcupine.org>
+556 5.7.0 <sname@nullmx.porcupine.org>: Sender address rejected: Domain nullmx.porcupine.org does not accept mail
+>>> mail sname@spike.porcupine.org
+OK
+>>> #
+>>> # reject_unknown_recipient_domain
+>>> #
+>>> smtpd_delay_reject 0
+OK
+>>> sender_restrictions permit
+OK
+>>> recipient_restrictions reject_unknown_recipient_domain
+OK
+>>> relay_restrictions reject_unauth_destination
+OK
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>> helo spike.porcupine.org
+OK
+>>> mail sname@sdomain
+OK
+>>> relay_domains nxdomain.porcupine.org
+OK
+>>> rcpt rname@nxdomain.porcupine.org
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 450 4.1.2 <rname@nxdomain.porcupine.org>: Recipient address rejected: Domain not found; from=<sname@sdomain> to=<rname@nxdomain.porcupine.org> proto=SMTP helo=<spike.porcupine.org>
+450 4.1.2 <rname@nxdomain.porcupine.org>: Recipient address rejected: Domain not found
+>>> relay_domains nullmx.porcupine.org
+OK
+>>> rcpt rname@nullmx.porcupine.org
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 556 5.1.0 <rname@nullmx.porcupine.org>: Recipient address rejected: Domain nullmx.porcupine.org does not accept mail; from=<sname@sdomain> to=<rname@nullmx.porcupine.org> proto=SMTP helo=<spike.porcupine.org>
+556 5.1.0 <rname@nullmx.porcupine.org>: Recipient address rejected: Domain nullmx.porcupine.org does not accept mail
+>>> relay_domains spike.porcupine.org
+OK
+>>> rcpt rname@spike.porcupine.org
+OK
+>>> #
+>>> # check_mx_access
+>>> #
+>>> smtpd_delay_reject 0
+OK
+>>> sender_restrictions check_sender_mx_access,hash:smtpd_check_access
+OK
+>>> client spike.porcupine.org 168.100.189.2
+OK
+>>> mail sname@nxdomain.porcupine.org
+./smtpd_check: warning: Unable to look up MX host nxdomain.porcupine.org for Sender address sname@nxdomain.porcupine.org: hostname nor servname provided, or not known
+OK
+>>> mail sname@nullmx.porcupine.org
+OK
+>>> mail sname@spike.porcupine.org
+./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <sname@spike.porcupine.org>: Sender address rejected: ns or mx server spike.porcupine.org; from=<sname@spike.porcupine.org> proto=SMTP helo=<spike.porcupine.org>
+554 5.7.1 <sname@spike.porcupine.org>: Sender address rejected: ns or mx server spike.porcupine.org
/* are always resolved in local rewriting context.
/*
/* smtpd_resolve_init() initializes the cache and must
-/* called once before the cache can be used.
+/* called before the cache can be used. This function may also
+/* be called to flush the cache after an address class update.
/*
/* smtpd_resolve_addr() resolves one address or returns
/* a known result from cache.
* Sanity check.
*/
if (smtpd_resolve_cache)
- msg_panic("smtpd_resolve_init: multiple initialization");
+ ctable_free(smtpd_resolve_cache);
/*
* Initialize the resolved address cache. Note: the cache persists across
554 5.7.1 <foo@ns1.topica.com>: Recipient address rejected: Access denied
>>> #rcpt foo@verisign-wildcard.com
>>> rcpt foo@1.2.3.porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <foo@1.2.3.porcupine.org>: Recipient address rejected: name server spike.porcupine.org; from=<foo@ns1.topica.com> to=<foo@1.2.3.porcupine.org> proto=SMTP helo=<example.tld>
-554 5.7.1 <foo@1.2.3.porcupine.org>: Recipient address rejected: name server spike.porcupine.org
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 <foo@1.2.3.porcupine.org>: Recipient address rejected: ns or mx server spike.porcupine.org; from=<foo@ns1.topica.com> to=<foo@1.2.3.porcupine.org> proto=SMTP helo=<example.tld>
+554 5.7.1 <foo@1.2.3.porcupine.org>: Recipient address rejected: ns or mx server spike.porcupine.org
>>> #
>>> # Check A access
>>> #
dict_sockmap.c line_number.c recv_pass_attr.c pass_accept.c \
poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \
valid_utf8_hostname.c midna.c argv_splitq.c balpar.c dict_union.c \
- extpar.c
+ extpar.c dict_inline.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
dict_sockmap.o line_number.o recv_pass_attr.o pass_accept.o \
poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \
valid_utf8_hostname.o midna.o argv_splitq.o balpar.o dict_union.o \
- extpar.o
+ extpar.o dict_inline.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
edit_file.h dict_cache.h dict_thash.h ip_match.h nbbio.h base32_code.h \
dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \
slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \
- valid_utf8_hostname.h midna.h dict_union.h
+ valid_utf8_hostname.h midna.h dict_union.h dict_inline.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
myaddrinfo_test format_tv_test ip_match_test name_mask_tests \
- base32_code_test dict_thash_test surrogate_test timecmp_test
+ base32_code_test dict_thash_test surrogate_test timecmp_test \
+ dict_static_test dict_inline_test
root_tests:
diff surrogate.ref surrogate.tmp
rm -f surrogate.tmp
+dict_static_test: dict_open dict_static.ref
+ (set -e; \
+ (echo get foo; echo get bar) | $(SHLIB_ENV) \
+ ./dict_open static:fooxx read; \
+ $(SHLIB_ENV) ./dict_open static:'{ foo xx ' read </dev/null; \
+ $(SHLIB_ENV) ./dict_open static:'{ foo xx }x' read </dev/null; \
+ (echo get foo; echo get bar) | $(SHLIB_ENV) \
+ ./dict_open static:'{ foo xx }' read; \
+ ) >dict_static.tmp 2>&1
+ diff dict_static.ref dict_static.tmp
+ rm -f dict_static.tmp
+
+dict_inline_test: dict_open dict_inline.ref
+ (set -e; \
+ $(SHLIB_ENV) ./dict_open inline:'{ }' read </dev/null; \
+ $(SHLIB_ENV) ./dict_open inline:'{ foo = xx }' read </dev/null; \
+ $(SHLIB_ENV) ./dict_open inline:'{ foo=xx }x' read </dev/null; \
+ $(SHLIB_ENV) ./dict_open inline:'{ foo=xx x' read </dev/null; \
+ $(SHLIB_ENV) ./dict_open inline:'{ foo=xx {x=y}x}' read </dev/null; \
+ (echo get foo; echo get bar; echo get baz) | $(SHLIB_ENV) \
+ ./dict_open inline:'{ foo=xx, { bar = lotsa stuff }}' read; \
+ ) >dict_inline.tmp 2>&1
+ diff dict_inline.ref dict_inline.tmp
+ rm -f dict_inline.tmp
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
dict_ht.o: vbuf.h
dict_ht.o: vstream.h
dict_ht.o: vstring.h
+dict_inline.o: argv.h
+dict_inline.o: dict.h
+dict_inline.o: dict_inline.c
+dict_inline.o: dict_inline.h
+dict_inline.o: htable.h
+dict_inline.o: msg.h
+dict_inline.o: myflock.h
+dict_inline.o: mymalloc.h
+dict_inline.o: stringops.h
+dict_inline.o: sys_defs.h
+dict_inline.o: vbuf.h
+dict_inline.o: vstream.h
+dict_inline.o: vstring.h
dict_lmdb.o: argv.h
dict_lmdb.o: dict.h
dict_lmdb.o: dict_lmdb.c
dict_static.o: msg.h
dict_static.o: myflock.h
dict_static.o: mymalloc.h
+dict_static.o: stringops.h
dict_static.o: sys_defs.h
dict_static.o: vbuf.h
dict_static.o: vstream.h
load_file.o: vstream.h
load_file.o: warn_stat.h
load_lib.o: load_lib.c
+load_lib.o: load_lib.h
+load_lib.o: msg.h
load_lib.o: sys_defs.h
lowercase.o: lowercase.c
lowercase.o: stringops.h
--- /dev/null
+/*++
+/* NAME
+/* dict_inline 3
+/* SUMMARY
+/* dictionary manager interface for inline table
+/* SYNOPSIS
+/* #include <dict_inline.h>
+/*
+/* DICT *dict_inline_open(name, open_flags, dict_flags)
+/* const char *name;
+/* int open_flags;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_inline_open() opens a read-only, in-memory table.
+/* Example: "\fBinline:{\fIkey_1=value_1, ..., key_n=value_n\fR}".
+/* The longer form with { key = value } allows values that
+/* contain whitespace or comma.
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <htable.h>
+#include <stringops.h>
+#include <dict.h>
+#include <dict_inline.h>
+
+/* Application-specific. */
+
+typedef struct {
+ DICT dict; /* generic members */
+ HTABLE *table; /* lookup table */
+} DICT_INLINE;
+
+/* dict_inline_lookup - search inline table */
+
+static const char *dict_inline_lookup(DICT *dict, const char *query)
+{
+ DICT_INLINE *dict_inline = (DICT_INLINE *) dict;
+
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE,
+ htable_find(dict_inline->table, query));
+}
+
+/* dict_inline_close - disassociate from inline table */
+
+static void dict_inline_close(DICT *dict)
+{
+ DICT_INLINE *dict_inline = (DICT_INLINE *) dict;
+
+ htable_free(dict_inline->table, myfree);
+ dict_free(dict);
+}
+
+/* dict_inline_open - open inline table */
+
+DICT *dict_inline_open(const char *name, int open_flags, int dict_flags)
+{
+ DICT_INLINE *dict_inline;
+ char *cp, *saved_name = 0;
+ size_t len;
+ HTABLE *table = 0;
+ char *nameval, *vname, *value;
+ const char *err = 0;
+
+ /*
+ * Clarity first. Let the optimizer worry about redundant code.
+ */
+#define DICT_INLINE_RETURN(x) do { \
+ if (saved_name != 0) \
+ myfree(saved_name); \
+ if (table != 0) \
+ htable_free(table, myfree); \
+ return (x); \
+ } while (0)
+
+ /*
+ * Sanity checks.
+ */
+ if (open_flags != O_RDONLY)
+ DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
+ open_flags, dict_flags,
+ "%s:%s map requires O_RDONLY access mode",
+ DICT_TYPE_INLINE, name));
+
+ /*
+ * Parse the table into its constituent name=value pairs.
+ */
+ if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
+ || *(cp = saved_name = mystrndup(name + 1, len - 2)) == 0)
+ DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
+ open_flags, dict_flags,
+ "bad syntax: \"%s:%s\"; "
+ "need \"%s:{name=value...}\"",
+ DICT_TYPE_INLINE, name,
+ DICT_TYPE_INLINE));
+
+ table = htable_create(5);
+ while ((nameval = mystrtokq(&cp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
+ if ((nameval[0] != CHARS_BRACE[0]
+ || (err = extpar(&nameval, CHARS_BRACE, EXTPAR_FLAG_STRIP)) == 0)
+ && (err = split_nameval(nameval, &vname, &value)) != 0)
+ break;
+ (void) htable_enter(table, vname, mystrdup(value));
+ }
+ if (err != 0 || table->used == 0)
+ DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
+ open_flags, dict_flags,
+ "%s: \"%s:%s\"; "
+ "need \"%s:{name=value...}\"",
+ err != 0 ? err : "empty table",
+ DICT_TYPE_INLINE, name,
+ DICT_TYPE_INLINE));
+
+ /*
+ * Bundle up the result.
+ */
+ dict_inline = (DICT_INLINE *)
+ dict_alloc(DICT_TYPE_INLINE, name, sizeof(*dict_inline));
+ dict_inline->dict.lookup = dict_inline_lookup;
+ dict_inline->dict.close = dict_inline_close;
+ dict_inline->dict.flags = dict_flags | DICT_FLAG_FIXED;
+ dict_inline->dict.owner.status = DICT_OWNER_TRUSTED;
+ dict_inline->table = table;
+ table = 0;
+ DICT_INLINE_RETURN(DICT_DEBUG (&dict_inline->dict));
+}
--- /dev/null
+#ifndef _DICT_INLINE_H_INCLUDED_
+#define _DICT_INLINE_H_INCLUDED_
+
+/*++
+/* NAME
+/* dict_inline 3h
+/* SUMMARY
+/* dictionary manager interface for inline tables
+/* SYNOPSIS
+/* #include <dict_inline.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+
+ /*
+ * External interface.
+ */
+#define DICT_TYPE_INLINE "inline"
+
+extern DICT *dict_inline_open(const char *, int, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
--- /dev/null
+./dict_open: error: empty table: "inline:{ }"; need "inline:{name=value...}"
+owner=trusted (uid=-1)
+./dict_open: error: missing '=' after attribute name: "inline:{ foo = xx }"; need "inline:{name=value...}"
+owner=trusted (uid=-1)
+./dict_open: error: bad syntax: "inline:{ foo=xx }x"; need "inline:{name=value...}"
+owner=trusted (uid=-1)
+./dict_open: error: bad syntax: "inline:{ foo=xx x"; need "inline:{name=value...}"
+owner=trusted (uid=-1)
+./dict_open: error: syntax error after '}' in "{x=y}x": "inline:{ foo=xx {x=y}x}"; need "inline:{name=value...}"
+owner=trusted (uid=-1)
+owner=trusted (uid=-1)
+> get foo
+foo=xx
+> get bar
+bar=lotsa stuff
+> get baz
+baz: not found
#include <dict_pipe.h>
#include <dict_random.h>
#include <dict_union.h>
+#include <dict_inline.h>
#include <stringops.h>
#include <split_at.h>
#include <htable.h>
DICT_TYPE_PIPE, dict_pipe_open,
DICT_TYPE_RANDOM, dict_random_open,
DICT_TYPE_UNION, dict_union_open,
+ DICT_TYPE_INLINE, dict_inline_open,
#ifndef USE_DYNAMIC_MAPS
#ifdef HAS_PCRE
DICT_TYPE_PCRE, dict_pcre_open,
#include "mymalloc.h"
#include "msg.h"
+#include "stringops.h"
#include "dict.h"
#include "dict_static.h"
/* dict_static_open - make association with static variable */
-DICT *dict_static_open(const char *name, int unused_flags, int dict_flags)
+DICT *dict_static_open(const char *name, int open_flags, int dict_flags)
{
DICT *dict;
+ const char *err;
+ char *cp, *saved_name = 0;
+ /*
+ * Let the optimizer worry about eliminating redundant code.
+ */
+#define DICT_STATIC_OPEN_RETURN(d) do { \
+ DICT *__d = (d); \
+ if (saved_name != 0) \
+ myfree(saved_name); \
+ return (__d); \
+ } while (0)
+
+ /*
+ * Optionally strip surrounding braces and whitespace.
+ */
+ if (name[0] == CHARS_BRACE[0]) {
+ saved_name = cp = mystrdup(name);
+ if ((err = extpar(&cp, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0)
+ DICT_STATIC_OPEN_RETURN(dict_surrogate(DICT_TYPE_STATIC, name,
+ open_flags, dict_flags,
+ "bad %s:name syntax: %s",
+ DICT_TYPE_STATIC, err));
+ name = cp;
+ }
+
+ /*
+ * Bundle up the request.
+ */
dict = dict_alloc(DICT_TYPE_STATIC, name, sizeof(*dict));
dict->lookup = dict_static_lookup;
dict->close = dict_static_close;
dict->flags = dict_flags | DICT_FLAG_FIXED;
dict->owner.status = DICT_OWNER_TRUSTED;
- return (DICT_DEBUG (dict));
+ DICT_STATIC_OPEN_RETURN(DICT_DEBUG (dict));
}
--- /dev/null
+owner=trusted (uid=-1)
+> get foo
+foo=fooxx
+> get bar
+bar=fooxx
+./dict_open: error: bad static:name syntax: missing '}' in "{ foo xx "
+owner=trusted (uid=-1)
+./dict_open: error: bad static:name syntax: syntax error after '}' in "{ foo xx }x"
+owner=trusted (uid=-1)
+owner=trusted (uid=-1)
+> get foo
+foo=foo xx
+> get bar
+bar=foo xx