summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.indent.pro3
-rw-r--r--HISTORY777
-rw-r--r--INSTALL44
-rw-r--r--Makefile.in9
-rw-r--r--README_FILES/AAAREADME2
-rw-r--r--README_FILES/ADDRESS_CLASS_README76
-rw-r--r--README_FILES/ADDRESS_REWRITING_README223
-rw-r--r--README_FILES/COMPATIBILITY_README64
-rw-r--r--README_FILES/DATABASE_README5
-rw-r--r--README_FILES/DEPRECATION_README270
-rw-r--r--README_FILES/INSTALL44
-rw-r--r--README_FILES/LOCAL_RECIPIENT_README2
-rw-r--r--README_FILES/MAILLOG_README10
-rw-r--r--README_FILES/MILTER_README6
-rw-r--r--README_FILES/MONGODB_README188
-rw-r--r--README_FILES/POSTSCREEN_README4
-rw-r--r--README_FILES/TLS_README120
-rw-r--r--RELEASE_NOTES334
-rw-r--r--RELEASE_NOTES-3.8128
-rw-r--r--WISHLIST29
-rw-r--r--conf/access4
-rw-r--r--conf/aliases162
-rw-r--r--conf/canonical49
-rw-r--r--conf/dynamicmaps.cf1
-rw-r--r--conf/generic10
-rw-r--r--conf/header_checks66
-rw-r--r--conf/main.cf4
-rw-r--r--conf/post-install28
-rw-r--r--conf/postfix-files7
-rwxr-xr-xconf/postfix-script21
-rw-r--r--conf/relocated10
-rw-r--r--conf/virtual202
-rw-r--r--html/ADDRESS_CLASS_README.html83
-rw-r--r--html/ADDRESS_REWRITING_README.html159
-rw-r--r--html/COMPATIBILITY_README.html96
-rw-r--r--html/DATABASE_README.html9
-rw-r--r--html/DEPRECATION_README.html411
-rw-r--r--html/INSTALL.html3
-rw-r--r--html/LOCAL_RECIPIENT_README.html3
-rw-r--r--html/MAILLOG_README.html10
-rw-r--r--html/MILTER_README.html2
-rw-r--r--html/MONGODB_README.html263
-rw-r--r--html/Makefile.in6
-rw-r--r--html/POSTSCREEN_README.html4
-rw-r--r--html/TLS_README.html164
-rw-r--r--html/access.5.html4
-rw-r--r--html/aliases.5.html14
-rw-r--r--html/canonical.5.html30
-rw-r--r--html/cleanup.8.html98
-rw-r--r--html/dnsblog.8.html4
-rw-r--r--html/generic.5.html17
-rw-r--r--html/header_checks.5.html59
-rw-r--r--html/index.html4
-rw-r--r--html/lmtp.8.html248
-rw-r--r--html/local.8.html234
-rw-r--r--html/mailq.1.html8
-rw-r--r--html/makedefs.1.html6
-rw-r--r--html/master.5.html13
-rw-r--r--html/master.8.html8
-rw-r--r--html/mongodb_table.5.html215
-rw-r--r--html/mysql_table.5.html188
-rw-r--r--html/newaliases.1.html8
-rw-r--r--html/pcre_table.5.html8
-rw-r--r--html/pgsql_table.5.html13
-rw-r--r--html/pipe.8.html106
-rw-r--r--html/postcat.1.html2
-rw-r--r--html/postconf.1.html170
-rw-r--r--html/postconf.5.html771
-rw-r--r--html/postdrop.1.html2
-rw-r--r--html/postfix-manuals.html6
-rw-r--r--html/postfix.1.html5
-rw-r--r--html/postkick.1.html2
-rw-r--r--html/postlock.1.html2
-rw-r--r--html/postlog.1.html7
-rw-r--r--html/postlogd.8.html13
-rw-r--r--html/postscreen.8.html32
-rw-r--r--html/postsuper.1.html2
-rw-r--r--html/posttls-finger.1.html12
-rw-r--r--html/proxymap.8.html2
-rw-r--r--html/qmgr.8.html4
-rw-r--r--html/qmqpd.8.html2
-rw-r--r--html/regexp_table.5.html8
-rw-r--r--html/relocated.5.html9
-rw-r--r--html/sendmail.1.html8
-rw-r--r--html/smtp-source.1.html43
-rw-r--r--html/smtp.8.html248
-rw-r--r--html/smtpd.8.html298
-rw-r--r--html/socketmap_table.5.html2
-rw-r--r--html/tlsproxy.8.html111
-rw-r--r--html/trivial-rewrite.8.html21
-rw-r--r--html/virtual.5.html159
-rw-r--r--makedefs6
-rw-r--r--man/Makefile.in7
-rw-r--r--man/man1/makedefs.11
-rw-r--r--man/man1/postcat.12
-rw-r--r--man/man1/postconf.117
-rw-r--r--man/man1/postdrop.12
-rw-r--r--man/man1/postfix.13
-rw-r--r--man/man1/postkick.12
-rw-r--r--man/man1/postlock.12
-rw-r--r--man/man1/postlog.16
-rw-r--r--man/man1/postsuper.16
-rw-r--r--man/man1/posttls-finger.111
-rw-r--r--man/man1/sendmail.17
-rw-r--r--man/man1/smtp-source.142
-rw-r--r--man/man5/access.54
-rw-r--r--man/man5/aliases.514
-rw-r--r--man/man5/canonical.522
-rw-r--r--man/man5/generic.56
-rw-r--r--man/man5/header_checks.546
-rw-r--r--man/man5/master.512
-rw-r--r--man/man5/mongodb_table.5259
-rw-r--r--man/man5/mysql_table.518
-rw-r--r--man/man5/pcre_table.511
-rw-r--r--man/man5/pgsql_table.511
-rw-r--r--man/man5/postconf.5719
-rw-r--r--man/man5/regexp_table.511
-rw-r--r--man/man5/relocated.56
-rw-r--r--man/man5/socketmap_table.52
-rw-r--r--man/man5/virtual.522
-rw-r--r--man/man8/cleanup.824
-rw-r--r--man/man8/dnsblog.83
-rw-r--r--man/man8/local.831
-rw-r--r--man/man8/master.88
-rw-r--r--man/man8/pipe.85
-rw-r--r--man/man8/postlogd.814
-rw-r--r--man/man8/postscreen.832
-rw-r--r--man/man8/proxymap.82
-rw-r--r--man/man8/qmgr.82
-rw-r--r--man/man8/qmqpd.82
-rw-r--r--man/man8/smtp.899
-rw-r--r--man/man8/smtpd.821
-rw-r--r--man/man8/tlsproxy.86
-rw-r--r--man/man8/trivial-rewrite.817
-rwxr-xr-xmantools/check-see-postconf-d-output6
-rwxr-xr-xmantools/check-snapshot-nonprod13
-rwxr-xr-xmantools/dehtml6
-rwxr-xr-xmantools/postlink12
-rw-r--r--postfix-install9
-rw-r--r--proto/ADDRESS_CLASS_README.html83
-rw-r--r--proto/ADDRESS_REWRITING_README.html157
-rw-r--r--proto/COMPATIBILITY_README.html96
-rw-r--r--proto/DATABASE_README.html7
-rw-r--r--proto/DEPRECATION_README.html411
-rw-r--r--proto/INSTALL.html3
-rw-r--r--proto/LOCAL_RECIPIENT_README.html3
-rw-r--r--proto/MAILLOG_README.html10
-rw-r--r--proto/MILTER_README.html2
-rw-r--r--proto/MONGODB_README.html263
-rw-r--r--proto/Makefile.in16
-rw-r--r--proto/POSTSCREEN_README.html4
-rw-r--r--proto/TLS_README.html164
-rw-r--r--proto/access4
-rw-r--r--proto/aliases14
-rw-r--r--proto/canonical22
-rw-r--r--proto/generic6
-rw-r--r--proto/header_checks46
-rw-r--r--proto/master12
-rw-r--r--proto/mongodb_table240
-rw-r--r--proto/mysql_table18
-rw-r--r--proto/pcre_table11
-rw-r--r--proto/pgsql_table11
-rw-r--r--proto/postconf.proto738
-rw-r--r--proto/regexp_table11
-rw-r--r--proto/relocated6
-rw-r--r--proto/socketmap_table2
-rw-r--r--proto/stop35
-rw-r--r--proto/stop.double-cc2
-rw-r--r--proto/stop.double-history87
-rw-r--r--proto/stop.double-install-proto-text4
-rw-r--r--proto/stop.double-proto-html118
-rw-r--r--proto/stop.spell-cc42
-rw-r--r--proto/stop.spell-history20
-rw-r--r--proto/stop.spell-proto-html17
-rw-r--r--proto/virtual22
-rw-r--r--src/bounce/bounce_notify_util.c13
-rw-r--r--src/bounce/with-msgid-with-filter-no-thread.ref2
-rw-r--r--src/bounce/with-msgid-with-filter-with-thread.ref2
-rw-r--r--src/cleanup/Makefile.in44
-rw-r--r--src/cleanup/cleanup.c24
-rw-r--r--src/cleanup/cleanup_addr.c6
-rw-r--r--src/cleanup/cleanup_init.c2
-rw-r--r--src/cleanup/cleanup_message.c5
-rw-r--r--src/cleanup/cleanup_milter.c9
-rw-r--r--src/cleanup/cleanup_milter.in18a8
-rw-r--r--src/cleanup/cleanup_milter.in18b8
-rw-r--r--src/cleanup/cleanup_milter.in18c9
-rw-r--r--src/cleanup/cleanup_milter.in18d8
-rw-r--r--src/cleanup/cleanup_milter.ref18a11
-rw-r--r--src/cleanup/cleanup_milter.ref18a229
-rw-r--r--src/cleanup/cleanup_milter.ref18b11
-rw-r--r--src/cleanup/cleanup_milter.ref18b227
-rw-r--r--src/cleanup/cleanup_milter.ref18c11
-rw-r--r--src/cleanup/cleanup_milter.ref18c229
-rw-r--r--src/cleanup/cleanup_milter.ref18d11
-rw-r--r--src/cleanup/cleanup_milter.ref18d227
-rw-r--r--src/cleanup/test-queue-file18bin0 -> 653 bytes
-rw-r--r--src/dns/Makefile.in26
-rw-r--r--src/dns/dns_lookup.c8
-rw-r--r--src/dns/dns_rr_test.c433
-rw-r--r--src/dns/mxonly_test.ref2
-rw-r--r--src/dns/no-mx.ref6
-rw-r--r--src/dns/test_dns_lookup.c5
-rw-r--r--src/dnsblog/dnsblog.c3
-rw-r--r--src/global/Makefile.in31
-rw-r--r--src/global/dict_ldap.c4
-rw-r--r--src/global/dict_mongodb.c570
-rwxr-xr-xsrc/global/dict_mongodb.h43
-rw-r--r--src/global/dict_mysql.c87
-rw-r--r--src/global/dict_pgsql.c73
-rw-r--r--src/global/dict_sqlite.c2
-rw-r--r--src/global/mail_addr_find.c4
-rw-r--r--src/global/mail_date.c9
-rw-r--r--src/global/mail_dict.c4
-rw-r--r--src/global/mail_params.c19
-rw-r--r--src/global/mail_params.h32
-rw-r--r--src/global/mail_proto.h7
-rw-r--r--src/global/mail_version.h4
-rw-r--r--src/global/maillog_client.c2
-rw-r--r--src/global/maps.c12
-rw-r--r--src/global/wildcard_inet_addr.c2
-rw-r--r--src/local/command.c5
-rw-r--r--src/local/local.c31
-rw-r--r--src/master/master.c12
-rw-r--r--src/master/master_ent.c8
-rw-r--r--src/oqmgr/qmgr_deliver.c4
-rw-r--r--src/pipe/pipe.c9
-rw-r--r--src/postalias/postalias.c2
-rw-r--r--src/postcat/postcat.c6
-rw-r--r--src/postconf/Makefile.in85
-rw-r--r--src/postconf/postconf.c40
-rw-r--r--src/postconf/postconf.h7
-rw-r--r--src/postconf/postconf_dbms.c49
-rw-r--r--src/postconf/postconf_unused.c112
-rw-r--r--src/postconf/postconf_user.c16
-rw-r--r--src/postconf/test29.ref3
-rw-r--r--src/postconf/test72.ref3
-rw-r--r--src/postconf/test73.ref3
-rw-r--r--src/postconf/test74.ref3
-rw-r--r--src/postconf/test75.ref3
-rw-r--r--src/postconf/test76.ref9
-rw-r--r--src/postdrop/postdrop.c2
-rw-r--r--src/postfix/postfix.c3
-rw-r--r--src/postkick/postkick.c2
-rw-r--r--src/postlock/postlock.c2
-rw-r--r--src/postlog/postlog.c6
-rw-r--r--src/postlogd/postlogd.c14
-rw-r--r--src/postmap/postmap.c2
-rw-r--r--src/postqueue/showq_json.c79
-rw-r--r--src/postscreen/postscreen.c32
-rw-r--r--src/postscreen/postscreen_smtpd.c16
-rw-r--r--src/postsuper/postsuper.c2
-rw-r--r--src/posttls-finger/posttls-finger.c64
-rw-r--r--src/proxymap/proxymap.c38
-rw-r--r--src/qmgr/qmgr.c2
-rw-r--r--src/qmgr/qmgr_deliver.c4
-rw-r--r--src/qmqpd/qmqpd.c2
-rw-r--r--src/sendmail/sendmail.c7
-rw-r--r--src/smtp/lmtp_params.c2
-rw-r--r--src/smtp/smtp.c136
-rw-r--r--src/smtp/smtp.h2
-rw-r--r--src/smtp/smtp_addr.c2
-rw-r--r--src/smtp/smtp_params.c2
-rw-r--r--src/smtp/smtp_proto.c2
-rw-r--r--src/smtp/smtp_sasl_glue.c4
-rw-r--r--src/smtp/smtp_tls_policy.c56
-rw-r--r--src/smtpd/Makefile.in11
-rw-r--r--src/smtpd/smtpd.c117
-rw-r--r--src/smtpd/smtpd.h4
-rw-r--r--src/smtpd/smtpd_check.c177
-rw-r--r--src/smtpd/smtpd_check_backup.ref1
-rw-r--r--src/smtpd/smtpd_deprecated.in20
-rw-r--r--src/smtpd/smtpd_deprecated.ref35
-rw-r--r--src/smtpd/smtpd_exp.ref10
-rw-r--r--src/smtpd/smtpd_sasl_glue.c4
-rw-r--r--src/smtpd/smtpd_state.c1
-rw-r--r--src/smtpstone/smtp-source.c94
-rw-r--r--src/tls/tls.h31
-rw-r--r--src/tls/tls_client.c157
-rw-r--r--src/tls/tls_dane.c77
-rw-r--r--src/tls/tls_fprint.c53
-rw-r--r--src/tls/tls_misc.c129
-rw-r--r--src/tls/tls_proxy.h13
-rw-r--r--src/tls/tls_proxy_client_print.c1
-rw-r--r--src/tls/tls_proxy_client_scan.c3
-rw-r--r--src/tls/tls_proxy_context_print.c4
-rw-r--r--src/tls/tls_proxy_context_scan.c4
-rw-r--r--src/tls/tls_server.c73
-rw-r--r--src/tls/tls_verify.c18
-rw-r--r--src/tlsproxy/tlsproxy.c11
-rw-r--r--src/trivial-rewrite/resolve.c2
-rw-r--r--src/trivial-rewrite/trivial-rewrite.c17
-rw-r--r--src/util/Makefile.in47
-rw-r--r--src/util/argv.c57
-rw-r--r--src/util/argv.h2
-rw-r--r--src/util/casefold.c2
-rw-r--r--src/util/dict_inline.c2
-rw-r--r--src/util/dict_thash.c6
-rw-r--r--src/util/dict_utf8.c4
-rw-r--r--src/util/inet_prefix_top.c1
-rw-r--r--src/util/logwriter.c34
-rw-r--r--src/util/logwriter.h1
-rw-r--r--src/util/midna_domain.c4
-rw-r--r--src/util/parse_utf8_char.h122
-rw-r--r--src/util/printable.c162
-rw-r--r--src/util/quote_for_json.c218
-rw-r--r--src/util/readlline.c231
-rw-r--r--src/util/stringops.h3
-rw-r--r--src/util/sys_defs.h7
-rw-r--r--src/util/valid_hostname.c13
-rw-r--r--src/util/valid_hostname.in6
-rw-r--r--src/util/valid_hostname.ref10
-rw-r--r--src/util/valid_utf8_string.c247
-rw-r--r--src/util/vstream.c34
-rw-r--r--src/xsasl/xsasl_cyrus_server.c4
-rw-r--r--src/xsasl/xsasl_server.c9
316 files changed, 12719 insertions, 3748 deletions
diff --git a/.indent.pro b/.indent.pro
index 4ba45d0..8ee03db 100644
--- a/.indent.pro
+++ b/.indent.pro
@@ -88,6 +88,7 @@
-TDICT_LDAP
-TDICT_LMDB
-TDICT_MC
+-TDICT_MONGODB
-TDICT_MYSQL
-TDICT_NI
-TDICT_NIS
@@ -248,6 +249,7 @@
-TNVTABLE_INFO
-TOPTIONS
-TPCF_DBMS_INFO
+-TPCF_DEPR_PARAM_INFO
-TPCF_EVAL_CTX
-TPCF_MASTER_EDIT_REQ
-TPCF_MASTER_ENT
@@ -411,6 +413,7 @@
-TXSASL_SERVER_IMPL
-TXSASL_SERVER_IMPL_INFO
-Tbind_props
+-Tbson_iter_t
-Tcipher_probe_t
-Td2i_X509_t
-Tdane_digest
diff --git a/HISTORY b/HISTORY
index 3892273..959e0fa 100644
--- a/HISTORY
+++ b/HISTORY
@@ -27056,14 +27056,28 @@ Apologies for any names omitted.
sometimes incomplete) lookup table configuration info with
a reference to the corresponding *_table(5) manpage.
+20230417
+
+ Cleanup: in the MySQL client configuration file, the default
+ characterset is now configurable with the "charset" attribute.
+ Previously, the default was determined by the MySQL
+ implementation (utf8mb4 as of MySQL 8.0, latin1 with older
+ versions). This setting implicitly controls the collation
+ order. Files: proto/mysql_table, global/dict_mysql.c.
+
20230418
- Bugfix defect (introduced: Postfix 3.2): the MySQL client
- could return "not found" instead of "error" (for example,
- resulting in a 5XX SMTP status instead of 4XX) during the
- time that all MySQL server connections were turned down
- after error. Found during code maintenance. File:
- global/dict_mysql.c.
+ Bugfix (introduced: Postfix 3.2): the MySQL client could
+ return "not found" instead of "error" (for example, resulting
+ in a 5XX SMTP status instead of 4XX) during the time that
+ all MySQL server connections were turned down after error.
+ Found during code maintenance. File: global/dict_mysql.c.
+
+20230419
+
+ Cleanup: in the PostgreSQL client, cosmetic changes to make
+ the code easier to maintain (in preparation for adding new
+ functionality). File: global/dict_pgsql.c.
20230428
@@ -27091,6 +27105,74 @@ Apologies for any names omitted.
...' with a single service definition 'name2 type2 ...'.
Problem reported by SATOH Fumiyasu. File: postconf/postconf_edit.c.
+20230503
+
+ Documentation: clarified the relationship between
+ smtp_bind*address, inet_interfaces, and system-chosen source
+ IP addresses for outbound SMTP/LMTP connections. File:
+ proto/postconf.proto.
+
+20230504
+
+ Documentation: clarified the relationships between
+ local_transport, virtual_mailbox_transport, relay_transport,
+ default_transport, relay_host, sender_dependent_relayhost_maps,
+ sender_dependent_default_transport_maps, and their precedences
+ when determining a delivery transport or next-hop destination,
+ in ADDRESS_REWRITING_README and in the text that defines
+ individual configuration features. Files: proto/postconf.proto,
+ proto/ADDRESS_REWRITING_README.html.
+
+20230505
+
+ Documentation: clarified the differences between virtual
+ and local aliasing, in four places. Files: mantools/postlink,
+ proto/postconf.proto, proto/ADDRESS_REWRITING_README.html.
+ cleanup/cleanup.c, local/local.c, smtpd/smtpd.c.
+
+ Usability: improved error message when master.cf specifies
+ a wild-card network listener (like "smtp inet ... smtpd")
+ while inet_interfaces is empty. File: master/master_ent.c.
+
+ More documentation updates for local aliasing versus virtual
+ aliasing. Files: proto/aliases, proto/virtual, postfix/postfix.c.
+
+20230506
+
+ Cleanup: simplified the master code to handle an empty
+ inet_interfaces setting. it is now closer to the original
+ code. Also documented that wildcard_inet_addr_list() will
+ not return an empty list. Files: master/master_ent.c,
+ global/own_inet_addr_list.c.
+
+20230507
+
+ Documentation: fine tuning of text about local aliasing
+ versus virtual aliasing. Files: proto/postconf.proto,
+ proto/aliases, proto/virtual, proto/ADDRESS_REWRITING_README.html.
+
+20230508
+
+ Documentation: more fine tuning of text about local aliasing
+ versus virtual aliasing, and inet_interfaces. Files:
+ proto/postconf.proto, proto/aliases, proto/virtual,
+ proto/ADDRESS_REWRITING_README.html.
+
+20230516
+
+ Bugfix (defect introduced: Postfix 3.4): the postlog(1)
+ command created a logfile with permissions 0644, but the
+ postlogd(8) daemon created it with permissions 0600, for
+ example after "postfix logrotate". The discrepancy is now
+ eliminated, and the permissions when creating a file are
+ now configurable with the "maillog_file_permissions"
+ parameter, default 0600 for backwards compatibility. Files:
+ mantools/postlink, proto/MAILLOG_README.html, proto/postconf.proto,
+ global/mail_params.c, global/mail_params.h, global/Makefile.in,
+ master/master.c, postlog/postlog.c, postlogd/postlogd.c,
+ util/logwriter.c, util/logwriter.h, util/Makefile.in,
+ util/vstream.c.
+
20230517
Bugfix (defect introduced: Postfix 3.8) the posttls-finger
@@ -27101,6 +27183,17 @@ Apologies for any names omitted.
20230519
+ Cleanup: fixed postconf tests for dynamically-linked builds.
+ File: postconf/Makefile.in.
+
+20230521
+
+ Bitrot: library error messages in SMTP server tests. File:
+ smtpd/Makefile.in.
+
+ Cleanup: removed some "the the" instances. Files:
+ proto/MILTER_README.html proto/stop.double-proto-html.
+
Bitrot: preliminary support for OpenSSL configuration files,
primarily OpenSSL 1.1.1b and later. This introduces new
parameters "tls_config_file" and "tls_config_name", which
@@ -27117,13 +27210,13 @@ Apologies for any names omitted.
20230523
- Cleanup: use TLS_CLIENT_PARAMS to pass the OpensSSL 'init'
- configurations. This information is independent from the
- client or server TLS context, and therefore does not belong
- in tls_*_init() or tls_*_start() calls. The tlsproxy(8)
- server uses TLS_CLIENT_PARAMS to report differences between
- its own global TLS settings, and those from its clients.
- Files: posttls-finger/posttls-finger.c, smtp/smtp.c,
+ Cleanup: use TLS_CLIENT_PARAMS to pass the OpenSSL 'init'
+ configuration settings. These are global, i.e. apply to all
+ client TLS contexts, and they do not belong in tls_client_init()
+ or tls_client_start() calls. The tlsproxy(8) server uses
+ TLS_CLIENT_PARAMS information to warn about differences
+ between its own global TLS settings, and those from its
+ clients. Files: posttls-finger/posttls-finger.c, smtp/smtp.c,
smtp/smtp_proto.c, tls/tls.h, tls/tls_proxy_client_misc.c,
tls/tls_proxy_client_print.c, tls/tls_proxy_client_scan.c,
tls/tls_proxy.h, tlsproxy/tlsproxy.c.
@@ -27131,15 +27224,27 @@ Apologies for any names omitted.
20230524
Cleanup: reverted cosmetic-only changes to minimize the
- patch footprint for OpenSSL INI file support; updated daemon
- manpages with the new tls_config_file and tls_config_name
- configuration parameters. Files: smtp/smtp.c, smtpd/smtpd.c,
- tls/tls_client.c, tls/tls.h, tls/tls_server.c, tlsproxy/tlsproxy.c,
+ patch footprint for OpenSSL INI file support for stable
+ releases; updated daemon manpages with the new tls_config_file
+ and tls_config_name configuration parameters. Files:
+ smtp/smtp.c, smtpd/smtpd.c, tls/tls_client.c, tls/tls.h,
+ tls/tls_server.c, tlsproxy/tlsproxy.c,
+
+20230526
+
+ Documentation: clarified address class descriptions; added
+ the availability of back-ported OpenSSL INI file support
+ in stable releases. Files: proto/ADDRESS_CLASS_README.html,
+ proto/postconf.proto smtp/smtp.c, smtpd/smtpd.c,
+ tlsproxy/tlsproxy.c.
+
+ Security: in the Postfix SMTP daemon, improved pipelining
+ detection and reporting; added code to detect illegal command
+ pipelining before the server greeting. File: smtpd/smtpd.c.
20230529
- Cleanup: made OpenSSL 'default' INI file support error
- handling consistent with OpenSSL default behavior. Viktor
+ Cleanup: error handling for OpenSSL INI file support. Viktor
Dukhovni. Files: proto/postconf.proto, tls/tls_misc.c.
20230602
@@ -27150,22 +27255,64 @@ Apologies for any names omitted.
non-default tls_config_xxx settings. File: tls/tls_misc.c.
Cleanup: added a multiple initialization guard in the
- tls_library_init() function, and made an initialization
- error sticky. File: tls/tls_misc.c.
+ tls_library_init() function, and made an initialization error
+ sticky. File: tls/tls_misc.c.
-20230605
+20230603
Security: new parameter smtpd_forbid_unauth_pipelining
- (default: no) to disconnect remote SMTP clients that violate
+ (default: yes) to disconnect remote SMTP clients that violate
RFC 2920 (or 5321) command pipelining constraints. Files:
global/mail_params.h, smtpd/smtpd.c, proto/postconf.proto.
+20230610
+
+ Trouble shooting: when the postfix UID or postdrop GID is
+ also used by a non-Postfix account, log the UID or GID.
+ File: global/mail_params.c.
+
+20240703
+
+ Typo fix by Trent W. Buck. Files: proto/postconf.proto, proto/stop.
+
+20230807
+
+ Feature: optional support to request a raw public key instead
+ of a public-key certificate when a) the Postfix SMTP server
+ requests TLS authentication from a remote SMTP client, or
+ b) when the Postfix SMTP client initiates a TLS handshake
+ with a remote SMTP server. See RELEASE_NOTES for details.
+ Viktor Dukhovni. Files: mantools/postlink, proto/TLS_README.html,
+ proto/postconf.proto, RELEASE_NOTES, global/mail_params.h,
+ posttls-finger/posttls-finger.c, smtp/lmtp_params.c,
+ smtp/smtp.c, smtp/smtp.h, smtp/smtp_params.c, smtp/smtp_proto.c,
+ smtp/smtp_tls_policy.c, smtpd/smtpd.c, smtpd/smtpd_check.c,
+ tls/tls.h, tls/tls_client.c, tls/tls_dane.c, tls/tls_fprint.c,
+ tls/tls_misc.c, tls/tls_proxy.h, tls/tls_proxy_client_print.c,
+ tls/tls_proxy_client_scan.c, tls/tls_proxy_context_print.c,
+ tls/tls_proxy_context_scan.c, tls/tls_server.c, tls/tls_verify.c,
+ tlsproxy/tlsproxy.c.
+
+20230808
+
+ Documentation loose ends. Files: proto/postconf.proto,
+ RELEASE_NOTES.
+
20230815
- Bugfix (bug introduced: 20140218): when opportunistic TLS fails
- during or after the handshake, don't require that a probe
- message spent a minimum time-in-queue before falling back to
- plaintext. Problem reported by Serg. File: smtp/smtp.h.
+ Bugfix (defect introduced: 20140218): when an address
+ verification probe fails during or after an opportunistic
+ TLS handshake, immediately fall back to plaintext, without
+ enforcing a minimum time-in-queue. Problem reported by Serg.
+ File: smtp/smtp.h.
+
+20230820
+
+ Feature: smtp_sasl_password_result_delimiter, for the rare
+ case that the ":" character needs to be part of the username.
+ mantools/postlink, proto/postconf.proto, global/mail_params.h,
+ smtp/lmtp_params.c, smtp/smtp.c, smtp/smtp_params.c,
+ smtp/smtp_sasl_glue.c.
20230819
@@ -27179,12 +27326,81 @@ Apologies for any names omitted.
*.other.example IN A 10.0.0.1
*.other.example IN TLSA ..certificate info...
- Such syntax is blesed in RFC 1034 section 4.3.3.
+ Such syntax is blessed in RFC 1034 section 4.3.3.
This problem was reported first in the context of TLSA
record lookups. Files: util/valid_hostname.[hc],
dns/dns_lookup.c.
+20230831
+
+ Documentation: clarify the scope of local_recipient_maps.
+ Files: proto/LOCAL_RECIPIENT_README.html, proto/postconf.proto.
+
+ Documentation loose ends. Files: HISTORY, dns/dns_lookup.c.
+
+20230901
+
+ Feature: force_mime_input_conversion (default: no) to
+ convert content that claims to be 8-bit into quoted-printable,
+ before header_checks, body_checks, Milters, and before
+ after-queue content filters. The typical use case is an MTA
+ that applies this conversion before signing outbound messages,
+ so that the signatures will remain valid when a message is
+ later delivered to an MTA that does not announce 8BITMIME
+ support, or when a message line exceeds the SMTP length
+ limit. Files: global/mail_params.c, cleanup/cleanup_message.c,
+ cleanup/cleanup.c, cleanup/cleanup_init.c, proto/postconf.proto,
+ mantools/postlink.
+
+20230902
+
+ Cleanup: renamed enforce_mime_input_conversion to
+ force_mime_input_conversion.
+
+20230903
+
+ Cleanup: removed support for MySQL < 4.0 (released 2003),
+ removed the deprecated mysql_escape_string() call, added
+ the preferred mysql_real_escape_string_quote() call, and
+ added error handling for the unlikely case that the legacy
+ mysql_real_escape_string() returns an error. File:
+ global/dict_mysql.c.
+
+20230906
+
+ Documentation: the postconf(5) manpage did not document
+ that the force_mime_input_conversion feature was introduced
+ in Postfix 3.9. Viktor Dukhovni. File: proto/postconf.proto.
+
+20230912
+
+ Cleanup: record the use of a raw public key in Received:
+ headers, when the Postfix SMTP server or the remote SMTP
+ client presents a raw public key. Viktor Dukhovni. File:
+ smtpd/smtpd.c.
+
+20230923
+
+ Documentation: updated descriptions of the postscreen_*_ttl
+ and postscreen_dnsbl_allowlist_threshold parameters. Files:
+ proto/postconf.proto, postscreen/postscreen.c.
+
+20230916
+
+ Documentation: fixed missing and misplaced quotes in "see
+ 'postconf -d' output". Reported by наб. Files: Makefile.in,
+ mantools/check-see-postconf-d-output, proto/postconf.proto,
+ global/maillog_client.c, master/master.c, smtp/smtp.c,
+ smtpd/smtpd.c.
+
+20230917
+
+ Documentation: added a note to smtp_tls_security_level and
+ smtp_tls_policy_maps, that the level "MAY" will fall back
+ to plaintext after TLS failure, when a message has spent
+ minimal_backoff_time in the mail queue. File: proto/postconf.proto.
+
20230929
Bugfix (defect introduced Postfix 2.5, 20080104): the Postfix
@@ -27193,6 +27409,35 @@ Apologies for any names omitted.
error in TLS wrappermode. Reported by Andreas Kinzler. File:
smtpd/smtpd.c.
+20230923
+
+ This changes the smtp-source test program, to avoid the
+ need to configure a large number of "valid" recipient
+ addresses in Postfix, by using a recipient address extension
+ in the form of a sequence number. The change is to append
+ the optional recipient address sequence number to the
+ recipient address localpart, instead of prepending it. To
+ use that sequence number as a recipient address extension,
+ specify an explicit address delimiter in the address
+ localpart, as in "-t localpart+@domain" or "-t localpart+"
+ where "+" is the Postfix recipient address delimiter. File:
+ smtpstone/smtp-source.c.
+
+20230924
+
+ Cleanup: simplified the smtp-source numbered recipient
+ implementation and documentation. File: smtpstone/smtp-source.c.
+
+ Documentation: added smtp_balance_inet_protocols to the
+ text with smtp_address_preference caveats. File:
+ proto/postconf.proto.
+
+20230926
+
+ Documentation: added a section to smtp_balance_inet_protocols
+ to address the problem that servers may flag mail received
+ over IPv6 as more spammy. File: proto/postconf.proto.
+
20231006
Usability: the Postfix SMTP server now attempts to log the
@@ -27204,6 +27449,62 @@ Apologies for any names omitted.
on code by Jozsef Kadlecsik. Files: xsasl/xsasl_server.c,
xsasl/xsasl_cyrus_server.c, smtpd/smtpd_sasl_glue.c.
+20231008
+
+ Cleanup: enforce stricter UTF8 checks in printable(). Factor
+ out the UTF8 parser, so that it can be shared between
+ valid_utf8_string() and printable(). Wietse Venema, with
+ tests by Viktor Dukhovni. Files: util/valid_utf8_string.c,
+ util/printable.c, util/parse_utf8_char.h, util/printable.in,
+ util/printable.ref.
+
+20231010
+
+ Cleanup: printable() uses once again a single-pass algorithm.
+ Converted printable() test files to built-in test cases with
+ proper logging, and removed the printable() test files and
+ git metadata. Added similar tests for the valid_utf8_string()
+ function. Files: util/valid_utf8_string.c, util/printable.c,
+ util/parse_utf8_char.h, util/Makefile.in.
+
+20231011
+
+ Documentation: fixed some instances of "." instead of ",".
+ Files: proto/POSTSCREEN_README.html, proto/socketmap_table.
+
+ Cleanup: finer-grained unit tests for valid_utf8_string().
+ File: util/valid_utf8_string.c.
+
+ Style: converted failed test reports to "got before want"
+ order, and converted tests to "fail before pass" order.
+ Files: util/valid_utf8_string.c, util/printable.c.
+
+ Cleanup: added a valid_utf8_stringz() function to simplify
+ most calls to validate null-terminated strings, eliminating
+ the runtime cost and code maintenance cost of 17 strlen()
+ calls. Files: src/bounce/bounce_notify_util.c,
+ src/cleanup/cleanup_addr.c, src/global/dict_ldap.c,
+ src/global/dict_mysql.c, src/global/dict_pgsql.c,
+ src/global/dict_sqlite.c, src/oqmgr/qmgr_deliver.c,
+ src/postalias/postalias.c, src/postmap/postmap.c,
+ src/postscreen/postscreen_smtpd.c, src/qmgr/qmgr_deliver.c,
+ src/smtpd/smtpd.c, src/smtpd/smtpd_check.c,
+ src/trivial-rewrite/resolve.c, src/util/casefold.c,
+ src/util/dict_inline.c, src/util/dict_thash.c,
+ src/util/dict_utf8.c, src/util/midna_domain.c,
+ src/util/printable.c, src/util/stringops.h,
+ src/util/valid_utf8_string.c.
+
+ Cleanup: added unit tests to the readlline module, with
+ multiline input that contains embedded comments, input that
+ contains a null byte, text not ending in newline. File:
+ readlline.c.
+
+20231024
+
+ Cleanup: emit place holder text when no SASL authentication
+ failure reason is available. File: smtpd/smtpd_sasl_glue.c.
+
20231026
Bugfix (defect introduced: Postfix 2.11): in forward_path,
@@ -27213,39 +27514,15 @@ Apologies for any names omitted.
a configured recipient delimiter value. Reported by Tod
A. Sandman. Files: proto/postconf.proto, local/local_expand.c.
-20240109
-
- Security (outbound SMTP smuggling): with the default setting
- "cleanup_replace_stray_cr_lf = yes" Postfix will replace
- stray <CR> or <LF> characters in message content with a
- space character. This prevents Postfix from enabling
- outbound (remote) SMTP smuggling, and it also makes evaluation
- of Postfix-added DKIM etc. signatures independent from how
- a remote mail server handles stray <CR> or <LF> characters.
- Files: global/mail_params.h, cleanup/cleanup.c,
- cleanup/cleanup_message.c, mantools/postlink, proto/postconf.proto.
+20231027
-20240112
+ Cleanup: missing 'smtpd_tls_enable_rpk' parameter definition
+ in test driver. File: smtpd/smtpd_check.c.
- Security (inbound SMTP smuggling): with "smtpd_forbid_bare_newline
- = normalize" (default "no" for Postfix < 3.9), the Postfix
- SMTP server requires the standard End-of-DATA sequence
- <CR><LF>.<CR><LF>, and otherwise allows command or message
- content lines ending in the non-standard <LF>, processing
- them as if the client sent the standard <CR><LF>.
+20231030
- The alternative setting, "smtpd_forbid_bare_newline = reject"
- will reject any command or message that contains a bare
- <LF>, and is more likely to cause problems with legitimate
- clients.
-
- For backwards compatibility, local clients are excluded by
- default with "smtpd_forbid_bare_newline_exclusions =
- $mynetworks".
-
- Files: mantools/postlink, proto/postconf.proto,
- global/mail_params.h, global/smtp_stream.c, global/smtp_stream.h,
- smtpd/smtpd.c, smtpd/smtpd_check.[hc].
+ Cleanup: explicit %.100s limits for client-controlled strings
+ in SASL error logging. File: smtpd/smtpd_sasl_glue.c.
20231102
@@ -27260,6 +27537,55 @@ Apologies for any names omitted.
Cleanup: Postfix SMTP server response with an empty
authentication failure reason. File: smtpd/smtpd_sasl_glue.c.
+ Cleanup: proxymap error message when the service name is
+ not "proxymap" or "proxywrite". File: proxymap/proxymap.c.
+
+20231109
+
+ Portability: MariaDB emulates MySQL >= 5.7.6, but does not
+ implement mysql_real_escape_string_quote(). Fix by Levente
+ Birta. File: global/dict_mysql.c.
+
+ Portability: more precise MYSQL_VERSION_ID check. File:
+ global/dict_mysql.c.
+
+20231112
+
+ Robustness: don't loop on an 'unfinished' queue file that
+ still has its all-zero SIZE record. File: postcat/postcat.c.
+
+20231126
+
+ Cleanup: implementation and documentation for the selection
+ of SMTP versus LMTP client protocol and parameters, based
+ on process name. Files: smtp/smtp.c, global/mail_proto.h,
+ proto/postconf.proto.
+
+ Cleanup: documented (in proxymap source code) the complexities
+ of determining the optimal proxywrite service process limit,
+ and make the 'invalid' proxymap service name error message
+ more similar to the error message for an invalid SMTP/LMTP
+ client process name. File: proxymap/proxymap.c.
+
+20231127
+
+ Documentation: in the stock main.cf file, mailbox_command
+ uses $default_privs, not $default_user. Vijay Sarvepalli,
+ Cert/CC. File: conf/main.cf.
+
+20231202
+
+ Bugfix: posttls-finger certificate match expectations for
+ opportunistic DANE incorrectly defaulted to ("nexthop",
+ "hostname") instead of ("nexthop", "dot-nexthop"), when no
+ TLSA records were found. Viktor Dukhovni. File: posttls-finger.c.
+
+20231204
+
+ Documentation: updated comments on address validation in
+ smtpd_check.c, making them consistent with the implementation.
+ File: smtpd/smtpd_check.c.
+
20231208
Bugfix (defect introduced: Postfix 3.1, date: 20151128):
@@ -27267,6 +27593,17 @@ Apologies for any names omitted.
character as \uXXXX. Found during code maintenance. File:
postqueue/showq_json.c.
+20231209
+
+ Feature: the local(8) delivery agent exports an ENVID
+ environment variable with the RFC 3461 envelope ID if
+ available. Files: local/command.c, local/local.c,
+ proto/postconf.proto.
+
+ Feature: the pipe(8) delivery agent supports an ${envid}
+ command-line attribute that expands to the RFC 3461 envelope
+ ID if available. File: pipe/pipe.c.
+
20231211
Cleanup: posttls-finger certificate match expectations for
@@ -27289,31 +27626,296 @@ Apologies for any names omitted.
Received: header) when handling requests from a Milter to
delete or update an existing header. Problem report by
Carlos Velasco. This change was verified to have no effect
- on requests from a Milter to add or insert a header. File:
- cleanup/cleanup_milter.c.
+ on requests from a Milter to add or insert a header. Files:
+ cleanup/cleanup_milter.c, cleanup/Makefile.in,
+ cleanup/test-queue-file18, cleanup/cleanup_milter.in18[a-d],
+ cleanup/cleanup_milter.ref18[a-d][12].
+
+20231221
+
+ Security: with "smtpd_forbid_bare_newline = yes" (the default
+ for Postfix 3.9), reply with "Error: bare <LF> received"
+ and disconnect when an SMTP client sends a line ending in
+ <LF>, violating the RFC 5321 requirement that lines must
+ end in <CR><LF>. This prevents SMTP smuggling attacks that
+ target a recipient at a Postfix server. For backwards
+ compatibility, local clients are excluded by default with
+ "smtpd_forbid_bare_newline_exclusions = $mynetworks". Files:
+ mantools/postlink, proto/postconf.proto, global/mail_params.h,
+ global/smtp_stream.c, global/smtp_stream.h, smtpd/smtpd.c.
+
+20240104
+
+ Cleanup: when the Postfix SMTP server rejects bare <LF>,
+ log the helo, mail and rcpt information if available. Files:
+ smtpd/smtpd.c, smtpd/smtpd_check.c.
+
+ Cleanup: when the Postfix SMTP server rejects bare <LF>,
+ keep reading message content after an unexpected <LF>.<LF>
+ or <LF>.<CR><LF>, before responding. This increases the
+ likelihood that the client will actually see the Postfix
+ response and remove the attack from their mail queue. Files:
+ smtpd/smtpd.c, global/smtp_stream.[hc], global/cleanup_user.h.
+
+ Cleanup: added smtpd_forbid_bare_newline settings "reject"
+ and "normalize". The default setting "normalize" (and "yes")
+ will accept bare newlines from local or remote SMTP clients,
+ but if any DATA content line ends in <CR><LF>, require the
+ standard End-of-DATA form <CR><LF>.<CR><LF> and skip
+ non-standard End-of-DATA forms. This may fail to receive
+ email from legitimate clients that send a mix of lines
+ ending in <LF> and <CR><LF>. If such clients exist, they
+ need to be excluded with smtpd_forbid_bare_newline_exclusions.
+ Files: proto/postconf.proto, global/mail_params.h,
+ smtpd/smtpd.c.
+
+ Tooling: mantools/dehtml was breaking words in code examples,
+ causing false spellchecker errors. File: mantools/dehtml,
+ proto/stop.double-proto-html.
+
+20240105
+
+ Cleanup: don't spam the log with unexpected End-of-DATA
+ forms. Files: proto/postconf.proto, smtpd/smtpd.c,
+ RELEASE_NOTES.
+
+20240106
+
+ Inbound smuggling: with smtpd_forbid_bare_newline enabled,
+ do not "strip" extra <CR> characters before <LF>. This avoids
+ ambiguity when a client sends extra <CR> characters as in
+ <CR><LF>.<CR><CR><LF>. There is no smuggling vulnerability
+ because there is no mail system will send the above
+ sequence (mail systems send <CR><LF>..<CR><CR><LF> instead).
+ But this change will silence some testing tools. More at
+ https://www.postfix.org/false-smuggling-claims.html. File:
+ global/smtp_stream.c.
+
+20240109
+
+ Outbound smuggling: with "cleanup_replace_stray_cr_lf =
+ yes" (the default) Postfix will replace stray <CR> or <LF>
+ characters in message content with a space character. This
+ prevents Postfix from enabling outbound (remote) SMTP
+ smuggling, and it also makes evaluation of Postfix-added
+ DKIM etc. signatures independent from how a remote mail
+ server handles stray <CR> or <LF> characters. Files:
+ global/mail_params.h, cleanup/cleanup.c, cleanup/cleanup_message.c,
+ mantools/postlink, proto/postconf.proto.
+
+20240110
+
+ Cleanup: the smtpd_forbid_bare_newline settings "normalize"
+ and "reject" are now more similar. Both now unconditionally
+ require the standard End-of-DATA sequence <CR><LF>.<CR><LF>.
+ Files: smtpd/smtpd.c, proto/postconf.proto, RELEASE_NOTES.
+
+20240112
+
+ Cleanup: updated comments and identifiers because the bare
+ newline handling has evolved. Files: global/smtp_stream.[hc],
+ Files: global/smtp_stream.[hc], smtpd/smtpd.c.
+
+20240116
+
+ Reverted some changes after postfix-3.9-20240112, and updated
+ documentation.
+
+20240121
+
+ Documentation: "smtpd_forbid_bare_newline = reject" will
+ reject email from services that use BDAT to send MIME text
+ containing a bare newline (RFC 3030 Section 3 requires
+ canonical MIME format for text message types, defined in
+ RFC 2045 Sections 2.7 and 2.8) Files: proto/postconf.proto,
+ RELEASE_NOTES.
+
+ Baseline for back porting the SMTP smuggling fixes to Postfix
+ 3.8.5, 3.7.10, 3.6.14, and 3.5.24.
20240124
+ Feature: with "smtpd_forbid_bare_newline = note", the Postfix
+ SMTP server notes in the log if it received any lines with
+ bare LF. Otherwise, "note" is like "normalize". The
+ information is formatted as "disconnect from name[address]
+ ... notes=bare_lf". The new value is expected to become
+ a list of comma-separated names. Files: smtpd/smtpd.[hc].
+
+ Cleanup: require that a stable release disables SNAPSHOT
+ and NONPROD features. File: mantools/check-snapshot-nonprod.
+
+ Bugfix (defect introduced: Postfix 3.4): the SMTP server's
+ BDAT command handler could be tricked to read $message_size_limit
+ bytes into memory. Found during code maintenance. File:
+ smtpd/smtpd.c.
+
+ Feature: never too late, an SMTP server HELP command that
+ lists the implemented commands. Some commands may be
+ implemented but not available due to smtpd_discard_ehlo_keywords
+ or access control limitations. Files: smtpd/smtpd.[hc],
+ util/argv.[hc].
+
Workaround: tlsmgr logfile spam. Some OS lies under load:
it says that a socket is readable, then it says that the
socket has unread data, and then it says that read returns
EOF, causing Postfix to spam the log with a warning message.
File: tlsmgr/tlsmgr.c.
- Bugfix (defect introduced: Postfix 3.4): the SMTP server's
- BDAT command handler could be tricked to read $message_size_limit
- bytes into memory. Found during code maintenance. File:
- smtpd/smtpd.c.
+20240125
+
+ Cleanup: tlsmgr.c fix 20240124. File: tlsmgr/tlsmgr.c.
+
+ Documentation: updated obsolete "CONFIGURATION PARAMETERS"
+ summaries in Postfix manpages, with current text from the
+ postconf(5) manpage. Files: proto/generic, proto/header_checks,
+ proto/aliases, proto/canonical, proto/relocated,
+ postdrop/postdrop.c, postsuper/postsuper.c, sendmail/sendmail.c,
+ dnsblog/dnsblog.c, postkick/postkick.c, postlock/postlock.c,
+ qmgr/qmgr.c, qmqpd/qmqpd.c, trivial-rewrite/trivial-rewrite.c.
+
+20240129
+
+ Documentation: be more precise about server lookups with
+ MX or SRV records. File: smtp/smtp.c.
+
+ Documentation: postlogd is not a short-running process. It
+ wil keep running until it reaches the max_idle limit. File:
+ postlogd/postlogd.c.
+
+ Cleanup (no semantic change): in the mysql: and pgsql:
+ clients, made the hard-coded idle and retry timer settings
+ configurable, and updated the mysql_table(5) and pgsql_table(5)
+ manpages. Files: global/dict_mysql.c, global/dict_pgsql.c,
+ proto/mysql_table, proto/pgsql_table.
+
+20230130
+
+ Reproducible build: added LC_ALL=C to the top of the makedefs
+ script.
+
+20240206
+
+ Documentation: in COMPATIBILITY_README, the descriptions
+ of smtpd_relay_restrictions and smtputf8_enable were grouped
+ under the wrong compatibility level value. Reported by Rune
+ Philosof. File: proto/COMPATIBILITY_README.html.
+
+ Compatibility: the RFC 5322 date and time specification
+ recommends (i.e. should) that a single space be used in
+ each place that FWS appears. To avoid a breaking change,
+ Postfix now formats numerical days as two-digit days, i.e.
+ days 1-9 have a leading zero instead of a leading space.
+ Files: util/sys_defs.h global/mail_date.c.
+
+ Documentation: the post-install(1) manpage now lists
+ $config_directory/makedefs.out as one of the installed
+ files. File: postfix-install.
+
+20240208
+
+ Refactored the JSON string quoting function, so that it can
+ be shared between the postqueue command and the MongoDB
+ client implementation. Files: util.quote_for_json.c,
+ util/stringops.h, postqueue/showq_json.c.
+
+ MongoDB client support, contributed by Hamid Maadani, based
+ on earlier code by Stephan Ferraro. Files: conf/dynamicmaps.cf,
+ conf/postfix-files, makedefs, mantools/postlink,
+ proto/DATABASE_README.html, proto/Makefile.in,
+ proto/MONGODB_README.html, proto/mongodb_table,
+ global/dict_mongodb.c, global/dict_mongodb.h, global/mail_dict.c,
+ global/Makefile.in, postconf/Makefile.in, proto/INSTALL.html,
+ postfix/postfix.c.
20240209
Performance: eliminate worst-case behavior where the queue
- manager defers delivery to all destinations over a specific
+ manager deferred delivery to all destinations over a specific
delivery transport, after only a single delivery agent
failure. The scheduler now throttles one destination, and
allows deliveries to other destinations to keep making
progress. Files: *qmgr/qmgr_deliver.c.
+20240210
+
+ Documentation: introductory text for SMTP and LMTP lookup
+ strategies. File: smtp/smtp.c.
+
+20240211
+
+ Documentation: updated the text for the new "notes=" attribute
+ in SMTP server "disconnect" logging. File: proto/postconf.proto.
+
+20240212
+
+ Documentation: emphasize that email address patterns and
+ host name/address patterns for indexed etc. files are really
+ for indexed etc. files. File: proto/access.
+
+ Documentation: mail_date(3) manpage. File: global/mail_date.c.
+
+20240213
+
+ Tests: updated tests that had suffered from bit rot. Files:
+ bounce/with-msgid-with-filter-no-thread.ref,
+ bounce/with-msgid-with-filter-with-thread.ref,
+ src/dns/mxonly_test.ref, dns/no-mx.ref.
+
+ Logging: indicate which (usually, substring) lookups are
+ skipped. File: global/maps.c.
+
+20240215
+
+ Portability: Clang versions that predate support for the
+ C23 standard do not allow a declaration immediately after
+ a (switch) label. The workaround is to add a null statement
+ between label and declaration. File: global/dict_mongodb.c.
+
+ Documentation: minor edits. Files: proto/mongodb_README.html,
+ proto/mongodb_table.html.
+
+20240216
+
+ Documentation: dropped text about partial matches from the
+ check_{client,helo,sender,recipient,etrn}_access summaries,
+ deferring to the access(5) manpage for details, for consistency
+ with the check_xx_yy_access features. File: proto/postconf.proto.
+
+ Cleanup: missing mongodb checks in the postconf command,
+ missing mongodb under "postconf -m" manpage entry. Files:
+ postconf/postconf.c, postconf/postconf_dbms.c.
+
+20240218
+
+ Deprecation: the Postfix SMTP server logs a warning when
+ "permit_mx_backup" is used (support for restriction
+ "permit_mx_backup" will be removed from Postfix; instead,
+ use "relay_domains"). File: smtpd/smtpd_check.c.
+
+ Deprecation: the postconf command logs a warning when the
+ following parameters are specified in main.cf or master.cf:
+ xxx_use_tls, xxx_enforce_tls (use the corresponding
+ xxx_security_level setting instead); xxx_per_site (use the
+ corresponding xxx_policy_maps setting instead); disable_dns_lookups
+ (use smtp_dns_support_level instead); smtpd_tls_dh1024_param_file,
+ smtpd_tls_eecdh_grade (do not specify, leave at default).
+ Files: postconf/postconf.c, postconf/postconf_unused.c.
+ proto/postconf.proto.
+
+ Cleanup: add "postconf -q" option to avoid redundant warnings
+ about unused or deprecated parameter settings when upgrading
+ or installing Postfix. Such warnings are still logged with
+ the commands postfix start, start-fg, check, reload, or
+ status. Files: postconf/postconf.c, postconf/postconf_dbms.c,
+ postconf/postconf.h, conf/postfix-script, conf/post-install,
+ postfix-install.
+
+20240221
+
+ Documentation: the text for TLS loglevel 2 was incomplete.
+ File: proto/postconf.proto.
+
20240226
Safety: drop and log over-size DNS responses resulting in
@@ -27326,3 +27928,48 @@ Apologies for any names omitted.
restrictions. Files: dns/dns.h, dns/dns_lookup.c, dns/dns_rr.c,
dns/test_dns_lookup.c, posttls-finger/posttls-finger.c,
smtp/smtp_addr.c, smtpd/smtpd_check.c.
+
+20240227
+
+ Documentation: document the need to disable regular expression
+ special characters when using $name inside an inlined
+ pattern. Files: proto/pcre_table, proto/regexp_table.
+
+20240228
+
+ Cleanups. Fixed some dns_rr_create() calls in test code,
+ and reverted a workaround in the DNS record formatter;
+ files: dns/dns_rr_test.c, dns/dns_strrecord.c. Code formatting;
+ file: global/mail_addr_find.c. Added missing test reference;
+ file: postconf/test76.ref.
+
+20240229
+
+ Compatibility: moved the new DNS_RR.flags structure member
+ to the location of a "padding" hole (two bytes for ILP32
+ systems, 6 bytes for LP64). File: dns/dns.h.
+
+ Deprecation: removed permit_naked_ip_address, reject_maps_rbl,
+ and check_relay_domains. These have been logging deprecation
+ warnings since 2005 or earlier, and were removed from Postfix
+ documentation in 2004 (but who reads logs and documentation?).
+ Files: smtpd/smtpd_check.c, smtpd/smtpd_check_backup.ref,
+ smtpd/smtpd_exp.ref, smtpd/smtpd_deprecated.in,
+ smtpd/smtpd_deprecated.ref.
+
+20240302
+
+ Cleanup: fixed inconsistent formatting of deprecation warning
+ messages. Files: postconf/postconf_unused.c, postconf/test76.ref,
+ smtpd/smtpd_check.
+
+ Documentation: DEPRECATION_README suggests replacements for
+ features that will be removed or than have been removed.
+ Files: proto/DEPRECATION_README.html, conf/postfix-files,
+ html/index.html, proto/Makefile.in.
+
+20240305
+
+ Documentation: in the master.cf documentation, added text
+ for "quoting" a command-line argument that starts with "{".
+ File: proto/master.
diff --git a/INSTALL b/INSTALL
index 5939a99..90b1b2d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -376,27 +376,29 @@ whistles. Support for third-party databases etc. must be configured when
Postfix is compiled. The following documents describe how to build Postfix with
support for optional features:
- _____________________________________________________________
- |Optional feature |Document |Availability|
- |__________________________________|_____________|____________|
- |Berkeley DB database |DB_README |Postfix 1.0 |
- |__________________________________|_____________|____________|
- |LMDB database |LMDB_README |Postfix 2.11|
- |__________________________________|_____________|____________|
- |LDAP database |LDAP_README |Postfix 1.0 |
- |__________________________________|_____________|____________|
- |MySQL database |MYSQL_README |Postfix 1.0 |
- |__________________________________|_____________|____________|
- |Perl compatible regular expression|PCRE_README |Postfix 1.0 |
- |__________________________________|_____________|____________|
- |PostgreSQL database |PGSQL_README |Postfix 2.0 |
- |__________________________________|_____________|____________|
- |SASL authentication |SASL_README |Postfix 1.0 |
- |__________________________________|_____________|____________|
- |SQLite database |SQLITE_README|Postfix 2.8 |
- |__________________________________|_____________|____________|
- |STARTTLS session encryption |TLS_README |Postfix 2.2 |
- |__________________________________|_____________|____________|
+ ______________________________________________________________
+ |Optional feature |Document |Availability|
+ |__________________________________|______________|____________|
+ |Berkeley DB database |DB_README |Postfix 1.0 |
+ |__________________________________|______________|____________|
+ |LMDB database |LMDB_README |Postfix 2.11|
+ |__________________________________|______________|____________|
+ |LDAP database |LDAP_README |Postfix 1.0 |
+ |__________________________________|______________|____________|
+ |MongoDB database |MONGODB_README|Postfix 3.9 |
+ |__________________________________|______________|____________|
+ |MySQL database |MYSQL_README |Postfix 1.0 |
+ |__________________________________|______________|____________|
+ |Perl compatible regular expression|PCRE_README |Postfix 1.0 |
+ |__________________________________|______________|____________|
+ |PostgreSQL database |PGSQL_README |Postfix 2.0 |
+ |__________________________________|______________|____________|
+ |SASL authentication |SASL_README |Postfix 1.0 |
+ |__________________________________|______________|____________|
+ |SQLite database |SQLITE_README |Postfix 2.8 |
+ |__________________________________|______________|____________|
+ |STARTTLS session encryption |TLS_README |Postfix 2.2 |
+ |__________________________________|______________|____________|
Note: IP version 6 support is compiled into Postfix on operating systems that
have IPv6 support. See the IPV6_README file for details.
diff --git a/Makefile.in b/Makefile.in
index 474e9b5..4b1fb33 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -117,7 +117,8 @@ manpages:
# Some checks require a bin/postconf executable.
pre-release-checks: typo-check missing-proxy-read-maps-check \
postlink-check postfix-files-check check-spell-history \
- check-double-history check-table-proto
+ check-double-history check-table-proto check-see-postconf-d-output \
+ check-snapshot-nonprod
postfix-files-check:
mantools/check-postfix-files | diff /dev/null -
@@ -158,6 +159,12 @@ check-double-history:
check-table-proto:
mantools/check-table-proto | diff /dev/null -
+check-see-postconf-d-output:
+ mantools/check-see-postconf-d-output | diff /dev/null -
+
+check-snapshot-nonprod:
+ mantools/check-snapshot-nonprod
+
# The build-time shlib_directory setting must take precedence over
# the installed main.cf settings, otherwise we can't update an
# installed system from dynamicmaps=yes<->dynamicmaps=no or from
diff --git a/README_FILES/AAAREADME b/README_FILES/AAAREADME
index 9afa3b7..94d552e 100644
--- a/README_FILES/AAAREADME
+++ b/README_FILES/AAAREADME
@@ -15,6 +15,7 @@ GGeenneerraall ccoonnffiigguurraattiioonn
* SMTPUTF8_README: SMTPUTF8 Support
* MAILLOG_README: Postfix logging to file or stdout
* COMPATIBILITY_README: Backwards-Compatibility Safety Net
+ * DEPRECATION_README: Deprecated features and alternatives
* INSTALL: Installation from source code
PPrroobblleemm ssoollvviinngg
@@ -52,6 +53,7 @@ LLooookkuupp ttaabblleess ((ddaattaabbaasseess))
* LDAP_README: LDAP Howto
* LMDB_README: LMDB Howto
* MEMCACHE_README: Memcache Howto
+ * MONGODB_README: MongoDB Howto
* MYSQL_README: MySQL Howto
* PCRE_README: PCRE Howto
* PGSQL_README: PostgreSQL Howto
diff --git a/README_FILES/ADDRESS_CLASS_README b/README_FILES/ADDRESS_CLASS_README
index 7605aa2..774976e 100644
--- a/README_FILES/ADDRESS_CLASS_README
+++ b/README_FILES/ADDRESS_CLASS_README
@@ -25,18 +25,23 @@ important for the operation of Postfix.
An address class is defined by three items.
- * The list of domains that are a member of that address class: for example,
- all local domains, or all relay domains.
+ * The list of domains that are a member of that address class.
- * The default delivery transport for that address class. For example, the
- local, virtual or relay delivery transport (delivery transports are defined
- in master.cf). This helps to keep Postfix configurations simple, by
- avoiding the need for explicit routing information in transport maps.
+ Examples: all local domains, or all relay domains.
- * The list of valid recipient addresses for that address class. The Postfix
- SMTP server rejects invalid recipients with "User unknown in <name of
- address class here> table". This helps to keep the Postfix queue free of
- undeliverable MAILER-DAEMON messages.
+ * The default delivery transport for domains in that address class.
+
+ Examples: local_transport or relay_transport (these point to services
+ defined in master.cf).
+
+ Benefit: this avoids the need for explicit routing information in transport
+ maps.
+
+ * The list of valid recipient addresses for that address class.
+
+ Benefit: the Postfix SMTP server rejects an invalid recipient with "User
+ unknown in <name of address class> table", and avoids sending a MAILER-
+ DAEMON message with backscatter spam.
WWhhaatt aaddddrreessss ccllaasssseess ddooeess PPoossttffiixx iimmpplleemmeenntt??
@@ -56,11 +61,11 @@ The local domain class.
also includes mail for user@[ipaddress] when the IP address is listed with
the inet_interfaces or proxy_interfaces parameters.
- * Valid recipient addresses are listed with the local_recipient_maps
- parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP server
- rejects invalid recipients with "User unknown in local recipient table". If
- the local_recipient_maps parameter value is empty, then the Postfix SMTP
- server accepts any address in the local domain class.
+ * Valid recipient addresses for those domains are listed with the
+ local_recipient_maps parameter, as described in LOCAL_RECIPIENT_README. The
+ Postfix SMTP server rejects invalid recipients with "User unknown in local
+ recipient table". If the local_recipient_maps parameter value is empty,
+ then the Postfix SMTP server accepts any address in the local domain class.
* The mail delivery transport is specified with the local_transport
parameter. The default value is llooccaall::$$mmyyhhoossttnnaammee for delivery with the
@@ -69,20 +74,23 @@ The local domain class.
The virtual alias domain class.
* Purpose: hosted domains where each recipient address is aliased to an
- address in a different domain, for example, a local UNIX system account or
- a remote address. A virtual alias example is given in the VIRTUAL_README
- file.
+ address in a different domain class, for example, a local UNIX system
+ account or a remote address. A virtual alias example is given in the
+ VIRTUAL_README file.
* Domain names are listed in virtual_alias_domains. The default value is
$virtual_alias_maps for Postfix 1.1 compatibility.
- * Valid recipient addresses are listed with the virtual_alias_maps parameter.
- The Postfix SMTP server rejects invalid recipients with "User unknown in
- virtual alias table". The default value is $virtual_maps for Postfix 1.1
- compatibility.
+ * Valid recipient addresses for those domains are listed with the
+ virtual_alias_maps parameter. The Postfix SMTP server rejects invalid
+ recipients with "User unknown in virtual alias table". The default value is
+ $virtual_maps for Postfix 1.1 compatibility.
+
+ Note: for historical reasons, virtual_alias_maps apply to recipients in
+ all domain classes, not only the virtual alias domain class.
- * There is no mail delivery transport parameter. Every address must be
- aliased to an address in some other domain.
+ * There is no configurable mail delivery transport. Every address must be
+ aliased to an address in some other domain class.
The virtual mailbox domain class.
@@ -93,11 +101,11 @@ The virtual mailbox domain class.
* Domain names are listed with the virtual_mailbox_domains parameter. The
default value is $virtual_mailbox_maps for Postfix 1.1 compatibility.
- * Valid recipient addresses are listed with the virtual_mailbox_maps
- parameter. The Postfix SMTP server rejects invalid recipients with "User
- unknown in virtual mailbox table". If this parameter value is empty, the
- Postfix SMTP server accepts all recipients for domains listed in
- $virtual_mailbox_domains.
+ * Valid recipient addresses for those domains are listed with the
+ virtual_mailbox_maps parameter. The Postfix SMTP server rejects invalid
+ recipients with "User unknown in virtual mailbox table". If this parameter
+ value is empty, the Postfix SMTP server accepts all recipients for domains
+ listed in $virtual_mailbox_domains.
* The mail delivery transport is specified with the virtual_transport
parameter. The default value is vviirrttuuaall for delivery with the virtual(8)
@@ -113,11 +121,11 @@ The relay domain class.
* Domain names are listed with the relay_domains parameter.
- * Valid recipient addresses are listed with the relay_recipient_maps
- parameter. The Postfix SMTP server rejects invalid recipients with "User
- unknown in relay recipient table". If this parameter value is empty, the
- Postfix SMTP server accepts all recipients for domains listed with the
- relay_domains parameter.
+ * Valid recipient addresses for those domains are listed with the
+ relay_recipient_maps parameter. The Postfix SMTP server rejects invalid
+ recipients with "User unknown in relay recipient table". If this parameter
+ value is empty, the Postfix SMTP server accepts all recipients for domains
+ listed with the relay_domains parameter.
* The mail delivery transport is specified with the relay_transport
parameter. The default value is rreellaayy which is a clone of the smtp(8)
diff --git a/README_FILES/ADDRESS_REWRITING_README b/README_FILES/ADDRESS_REWRITING_README
index 78237b9..4c24287 100644
--- a/README_FILES/ADDRESS_REWRITING_README
+++ b/README_FILES/ADDRESS_REWRITING_README
@@ -51,8 +51,7 @@ Topics covered in this document:
* Address rewriting when mail is delivered
- o Resolve address to destination
- o Mail transport switch
+ o Resolve address to (transport, next-hop destination)
o Relocated users table
* Address rewriting with remote delivery
@@ -131,59 +130,57 @@ this document for the first time, skip forward to "Address rewriting when mail
is received". Once you've finished reading the remainder of this document, the
table will help you to quickly find what you need.
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- |AAddddrreessss |SSccooppee |DDaaeemmoonn |GGlloobbaall ttuurrnn--oonn |SSeelleeccttiivvee ttuurrnn--ooffff ccoonnttrrooll |
- |mmaanniippuullaattiioonn| | |ccoonnttrrooll | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Rewrite | |trivial-|append_at_myorigin, | |
- |addresses to|all mail|rewrite |append_dot_mydomain,|local_header_rewrite_clients,|
- |standard | |(8) |swap_bangpath, |remote_header_rewrite_domain |
- |form | | |allow_percent_hack | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Canonical | |cleanup | |receive_override_options, |
- |address |all mail|(8) |canonical_maps |local_header_rewrite_clients,|
- |mapping | | | |remote_header_rewrite_domain |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Address | |cleanup | |receive_override_options, |
- |masquerading|all mail|(8) |masquerade_domains |local_header_rewrite_clients,|
- | | | | |remote_header_rewrite_domain |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Automatic | |cleanup |always_bcc, | |
- |BCC |new mail|(8) |sender_bcc_maps, |receive_override_options |
- |recipients | | |recipient_bcc_maps | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Virtual |all mail|cleanup |virtual_alias_maps |receive_override_options |
- |aliasing | |(8) | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Resolve | |trivial-| | |
- |address to |all mail|rewrite |none |none |
- |destination | |(8) | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Mail | |trivial-| | |
- |transport |all mail|rewrite |transport_maps |none |
- |switch | |(8) | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Relocated | |trivial-| | |
- |users table |all mail|rewrite |relocated_maps |none |
- | | |(8) | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Generic |outgoing| | | |
- |mapping |SMTP |smtp(8) |smtp_generic_maps |none |
- |table |mail | | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Local alias |local | | | |
- |database |mail |local(8)|alias_maps |none |
- | |only | | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Local per- |local | | | |
- |user |mail |local(8)|forward_path |none |
- |.forward |only | | | |
- |files | | | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
- |Local catch-|local | | | |
- |all address |mail |local(8)|luser_relay |none |
- | |only | | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |AAddddrreessss |SSccooppee |DDaaeemmoonn |TTuurrnn--oonn ccoonnttrroollss |TTuurrnn--ooffff ccoonnttrroollss |
+ |mmaanniippuullaattiioonn| | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Rewrite | |trivial-|append_at_myorigin, | |
+ |addresses to|all mail|rewrite |append_dot_mydomain, swap_bangpath, |local_header_rewrite_clients,|
+ |standard | |(8) |allow_percent_hack |remote_header_rewrite_domain |
+ |form | | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Canonical | |cleanup | |receive_override_options, |
+ |address |all mail|(8) |canonical_maps |local_header_rewrite_clients,|
+ |mapping | | | |remote_header_rewrite_domain |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Address | |cleanup | |receive_override_options, |
+ |masquerading|all mail|(8) |masquerade_domains |local_header_rewrite_clients,|
+ | | | | |remote_header_rewrite_domain |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Automatic | |cleanup |always_bcc, sender_bcc_maps, | |
+ |BCC |new mail|(8) |recipient_bcc_maps |receive_override_options |
+ |recipients | | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Virtual |all mail|cleanup |virtual_alias_maps |receive_override_options |
+ |aliasing | |(8) | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Resolve | | |local_transport, virtual_transport, | |
+ |address to | |trivial-|relay_transport, default_transport, | |
+ |(transport, |all mail|rewrite |relayhost, |content_filter |
+ |next-hop | |(8) |sender_dependent_relayhost_maps, | |
+ |destination)| | |sender_dependent_default_transport_maps| |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Relocated | |trivial-| | |
+ |users table |all mail|rewrite |relocated_maps |none |
+ | | |(8) | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Generic |outgoing| | | |
+ |mapping |SMTP |smtp(8) |smtp_generic_maps |none |
+ |table |mail | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Local alias |local | | | |
+ |database |mail |local(8)|alias_maps |none |
+ | |only | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Local per- |local | | | |
+ |user |mail |local(8)|forward_path |none |
+ |.forward |only | | | |
+ |files | | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Local catch-|local | | | |
+ |all address |mail |local(8)|luser_relay |none |
+ | |only | | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
AAddddrreessss rreewwrriittiinngg wwhheenn mmaaiill iiss rreecceeiivveedd
@@ -492,6 +489,10 @@ transform " Firstname.Lastname " back into UNIX login names, although it seems
that local aliases may be a more appropriate vehicle. See the VIRTUAL_README
document for an overview of methods to host virtual domains with Postfix.
+Note: virtual aliasing (virtual_alias_maps) applies to all recipients: local
+(8), virtual, and remote. This is unlike local aliasing (alias_maps) which
+applies only to local(8) recipients.
+
Virtual aliasing is disabled by default. To enable, edit the virtual_alias_maps
parameter in the main.cf file and specify one or more lookup tables, separated
by whitespace or commas.
@@ -537,8 +538,7 @@ manipulations to the trivial-rewrite(8) server.
Address manipulations at this stage are:
- * Resolve address to destination
- * Mail transport switch
+ * Resolve address to (transport, next-hop destination)
* Relocated users table
Each Postfix delivery agent tries to deliver the mail to its destination, while
@@ -560,49 +560,82 @@ Address manipulations when mail is delivered via the local(8) delivery agent:
The remainder of this document presents each address manipulation step in more
detail, with specific examples or with pointers to documentation with examples.
-RReessoollvvee aaddddrreessss ttoo ddeessttiinnaattiioonn
+RReessoollvvee aaddddrreessss ttoo ((ttrraannssppoorrtt,, nneexxtt--hhoopp ddeessttiinnaattiioonn))
The Postfix qmgr(8) queue manager selects new mail from the incoming queue or
-old mail from the deferred queue, and asks the trivial-rewrite(8) address
-rewriting and resolving daemon where it should be delivered.
-
-As of version 2.0, Postfix distinguishes four major address classes. Each class
-has its own list of domain names, and each class has its own default delivery
+old mail from the deferred queue. First it looks for overrides:
+
+ * The REDIRECT action in access(5), header_checks(5) or body_checks(5)
+ overrides all recipients of the message, and overrides a content_filter
+ setting, and FILTER action in access(5), header_checks(5) or body_checks
+ (5). The REDIRECT action was implemented as a short-cut to retaliate for
+ abuse.
+
+ * A content_filter setting and FILTER action in access(5), header_checks(5)
+ or body_checks(5) provide their own (transport, next-hop destination)
+ information. This bypasses all the steps that are described in the
+ remainder of this section.
+
+When there is no content filter override, the qmgr(8) queue manager asks the
+trivial-rewrite(8) address rewriting and resolving daemon for each recipient
+how to deliver it (which message delivery transport) and where to deliver it
+(what next-hop destination).
+
+As of version 2.0, Postfix distinguishes four major domain classes. Each class
+has its own list of recipient domain names, and each class has its own delivery
method, as shown in the table below. See the ADDRESS_CLASS_README document for
the fine details. Postfix versions before 2.0 only distinguish between local
delivery and everything else.
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- |DDeessttiinnaattiioonn ddoommaaiinn lliisstt |DDeeffaauulltt ddeelliivveerryy mmeetthhoodd|AAvvaaiillaabbiilliittyy|
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |$mydestination, $inet_interfaces,|$local_transport |Postfix 1.0 |
- |$proxy_interfaces | | |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |$virtual_mailbox_domains |$virtual_transport |Postfix 2.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |$relay_domains |$relay_transport |Postfix 2.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |none |$default_transport |Postfix 1.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
-
-MMaaiill ttrraannssppoorrtt sswwiittcchh
-
-Once the trivial-rewrite(8) daemon has determined a default delivery method it
-searches the optional transport(5) table for information that overrides the
-message destination and/or delivery method. Typical use of the transport(5)
-table is to send mail to a system that is not connected to the Internet, or to
-use a special SMTP client configuration for destinations that have special
-requirements. See, for example, the STANDARD_CONFIGURATION_README and
-UUCP_README documents, and the examples in the transport(5) manual page.
-
-Transport table lookups are disabled by default. To enable, edit the
-transport_maps parameter in the main.cf file and specify one or more lookup
-tables, separated by whitespace or commas.
+Note that the table does not match recipients against virtual_alias_domains.
+The reason is that all valid recipients in a virtual alias domain must be
+aliased to an address in a different domain. All other recipients in a virtual
+alias domain are by definition undeliverable, and do not need to be considered
+here.
-Example:
-
- /etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |DDoommaaiinn ccllaassss |RReecciippiieenntt ddoommaaiinn mmaattcchh |DDeelliivveerryy mmeetthhoodd |AAvvaaiillaabbiilliittyy|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ | |mydestination, | | |
+ |Local |inet_interfaces, |local_transport |Postfix 1.0 |
+ | |proxy_interfaces | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |Virtual mailbox|virtual_mailbox_domains|virtual_transport|Postfix 2.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |Relay |relay_domains |relay_transport |Postfix 2.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |Default |none |default_transport|Postfix 1.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+
+The delivery methods in the above table may include a next-hop destination in
+addition to a delivery transport. This may override the next-hop destination
+that is by default taken from the recipient domain.
+
+Over time, features have been added to override the above transport and/or
+next-hop destination information. The following table lists where a transport
+or next-hop destination may be taken from, depending on the recipient domain
+class.
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |DDoommaaiinn |TTrraannssppoorrtt ssoouurrcceess ((iinn oorrddeerr ooff |NNeexxtt hhoopp ssoouurrcceess ((iinn oorrddeerr ooff ddeesscceennddiinngg|
+ |ccllaassss |ddeesscceennddiinngg pprreecceeddeennccee)) |pprreecceeddeennccee)) |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Local |transport_maps, local_transport |transport_maps, local_transport, |
+ | | |recipient domain |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |Virtual|transport_maps, virtual_transport |transport_maps, virtual_transport, |
+ |mailbox| |recipient domain |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |transport_maps, relay_transport, |
+ |Relay |transport_maps, relay_transport |sender_dependent_relayhost_maps, |
+ | | |relayhost, recipient domain |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |transport_maps, |
+ | |transport_maps, |sender_dependent_default_transport_maps,|
+ |Default|sender_dependent_default_transport_maps,|default_transport, |
+ | |default_transport |sender_dependent_relayhost_maps, |
+ | | |relayhost, recipient domain |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
RReellooccaatteedd uusseerrss ttaabbllee
@@ -674,6 +707,10 @@ implement distribution lists, or to direct mail for standard aliases such as
postmaster to real people. The table can also be used to map
"Firstname.Lastname" addresses to login names.
+Note: local aliasing (alias_maps) applies only to local(8) recipients. This is
+unlike virtual aliasing (virtual_alias_maps) which applies to all recipients:
+local(8), virtual, and remote.
+
Alias lookups are enabled by default. The default configuration depends on the
operating system environment, but it is typically one of the following:
diff --git a/README_FILES/COMPATIBILITY_README b/README_FILES/COMPATIBILITY_README
index 55182b7..aa9e7f6 100644
--- a/README_FILES/COMPATIBILITY_README
+++ b/README_FILES/COMPATIBILITY_README
@@ -33,17 +33,17 @@ Logged with compatibility_level < 1:
* Using backwards-compatible default setting chroot=y
-Logged with compatibility_level < 2:
-
* Using backwards-compatible default setting "smtpd_relay_restrictions =
(empty)"
+ * Using backwards-compatible default setting smtputf8_enable=no
+
+Logged with compatibility_level < 2:
+
* Using backwards-compatible default setting mynetworks_style=subnet
* Using backwards-compatible default setting relay_domains=$mydestination
- * Using backwards-compatible default setting smtputf8_enable=no
-
Logged with compatibility_level < 3.6:
* Using backwards-compatible default setting smtpd_tls_fingerprint_digest=md5
@@ -152,6 +152,34 @@ permanent in main.cf:
# ppoossttccoonnff ssmmttppdd__rreellaayy__rreessttrriiccttiioonnss==
# ppoossttffiixx rreellooaadd
+UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg ssmmttppuuttff88__eennaabbllee==nnoo
+
+The smtputf8_enable default value has changed from "no" to "yes". With the new
+"yes" setting, the Postfix SMTP server rejects non-ASCII addresses from clients
+that don't request SMTPUTF8 support, after Postfix is updated from an older
+version. The backwards-compatibility safety net is designed to prevent such
+surprises.
+
+As long as the smtputf8_enable parameter is left at its implicit default value,
+and the compatibility_level setting is less than 1, Postfix logs a warning each
+time an SMTP command uses a non-ASCII address localpart without requesting
+SMTPUTF8 support:
+
+ postfix/smtpd[27560]: using backwards-compatible default setting
+ smtputf8_enable=no to accept non-ASCII sender address
+ "??@example.org" from localhost[127.0.0.1]
+
+ postfix/smtpd[27560]: using backwards-compatible default setting
+ smtputf8_enable=no to accept non-ASCII recipient address
+ "??@example.com" from localhost[127.0.0.1]
+
+If the address should not be rejected, and the client cannot be updated to use
+SMTPUTF8, then the system administrator should make the backwards-compatible
+setting "smtputf8_enable = no" permanent in main.cf:
+
+ # ppoossttccoonnff ssmmttppuuttff88__eennaabbllee==nnoo
+ # ppoossttffiixx rreellooaadd
+
UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg mmyynneettwwoorrkkss__ssttyyllee==ssuubbnneett
The mynetworks_style default value has changed from "subnet" to "host". This
@@ -223,34 +251,6 @@ Note: quotes are required as indicated above.
Instead of $mydestination, it may be better to specify an explicit list of
domain names.
-UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg ssmmttppuuttff88__eennaabbllee==nnoo
-
-The smtputf8_enable default value has changed from "no" to "yes". With the new
-"yes" setting, the Postfix SMTP server rejects non-ASCII addresses from clients
-that don't request SMTPUTF8 support, after Postfix is updated from an older
-version. The backwards-compatibility safety net is designed to prevent such
-surprises.
-
-As long as the smtputf8_enable parameter is left at its implicit default value,
-and the compatibility_level setting is less than 1, Postfix logs a warning each
-time an SMTP command uses a non-ASCII address localpart without requesting
-SMTPUTF8 support:
-
- postfix/smtpd[27560]: using backwards-compatible default setting
- smtputf8_enable=no to accept non-ASCII sender address
- "??@example.org" from localhost[127.0.0.1]
-
- postfix/smtpd[27560]: using backwards-compatible default setting
- smtputf8_enable=no to accept non-ASCII recipient address
- "??@example.com" from localhost[127.0.0.1]
-
-If the address should not be rejected, and the client cannot be updated to use
-SMTPUTF8, then the system administrator should make the backwards-compatible
-setting "smtputf8_enable = no" permanent in main.cf:
-
- # ppoossttccoonnff ssmmttppuuttff88__eennaabbllee==nnoo
- # ppoossttffiixx rreellooaadd
-
UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg ssmmttppdd__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt==mmdd55
The smtpd_tls_fingerprint_digest default value has changed from "md5" to
diff --git a/README_FILES/DATABASE_README b/README_FILES/DATABASE_README
index 3fd88c3..f1629e9 100644
--- a/README_FILES/DATABASE_README
+++ b/README_FILES/DATABASE_README
@@ -28,7 +28,7 @@ Examples of lookup tables that appear often in the Postfix documentation:
alias_maps = hash:/etc/postfix/aliases (local aliasing)
header_checks = regexp:/etc/postfix/header_checks (content filtering)
transport_maps = hash:/etc/postfix/transport (routing table)
- virtual_alias_maps = hash:/etc/postfix/virtual (address rewriting)
+ virtual_alias_maps = hash:/etc/postfix/virtual (virtual aliasing)
All Postfix lookup tables store information as (key, value) pairs. This
interface may seem simplistic at first, but it turns out to be very powerful.
@@ -236,6 +236,9 @@ To find out what database types your Postfix system supports, use the "ppooss
mmeemmccaacchhee
Memcache database client. Configuration details are given in
memcache_table(5).
+ mmoonnggooddbb (read-only)
+ MongoDB database client. Configuration details are given in
+ mongodb_table(5), with examples in MONGODB_README.
mmyyssqqll (read-only)
MySQL database client. Configuration details are given in mysql_table
(5).
diff --git a/README_FILES/DEPRECATION_README b/README_FILES/DEPRECATION_README
new file mode 100644
index 0000000..87cf247
--- /dev/null
+++ b/README_FILES/DEPRECATION_README
@@ -0,0 +1,270 @@
+PPoossttffiixx RReeppllaacceemmeennttss ffoorr DDeepprreeccaatteedd FFeeaattuurreess
+
+-------------------------------------------------------------------------------
+
+PPuurrppoossee ooff tthhiiss ddooccuummeenntt
+
+This document describes Postfix features that are deprecated (will be removed)
+or that have already been removed. It also has tips for making an existing
+Postfix configuration more future-proof.
+
+Overview:
+
+ * Why deprecate?
+ * Deprecation process
+ * Deprecated features
+
+WWhhyy ddeepprreeccaattee??
+
+Sometimes, a Postfix feature needs to be replaced with a different one. To give
+an example:
+
+ * The initial Postfix TLS implementation used multiple boolean parameters:
+ one parameter to enable opportunistic TLS (for example, "smtp_enforce_tls =
+ yes") and one parameter to enable mandatory TLS (for example,
+ "smtp_require_tls = yes").
+
+ * As we added support more features such as fingerprint, dane, and so on, we
+ decided not to add more boolean parameters. Instead we introduced one
+ configuration parameter to select from multiple deployment models (for
+ example, smtp_tls_security_level = may | encrypt | dane, etc...).
+
+Having both the "old" and "new" way to configure Postfix is convenient for
+existing Postfix installations, because their configuration does not break
+after an upgrade to a new version. Unfortunately, there are also disadvantages.
+Having multiple ways to do similar things is not only confusing for newcomers,
+it also makes Postfix harder to change.
+
+DDeepprreeccaattiioonn pprroocceessss
+
+The basic process steps are:
+
+ 1. Inform humans that a feature will be removed, and suggest replacements, in
+ logging and documentation.
+
+ 2. Remove the feature, and update logging and documentation.
+
+Disclaimer: it has taken 20 years for some features to be removed. This past is
+not a guarantee for the future.
+
+DDeepprreeccaatteedd ffeeaattuurreess
+
+The table summarizes removed or deprecated features and replacements. Click on
+the "obsolete feature" name for a more detailed description.
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ | |WWaarrnniinngg| | |
+ |OObbssoolleettee ffeeaattuurree nnaammee |aass |RReemmoovveedd |RReeppllaacceemmeenntt |
+ | |ooff |iinn vveerrssiioonn| |
+ | |vveerrssiioonn| | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |disable_dns_lookups | 3.9 | - |smtp_dns_support_level |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |xxx_use_tls | 3.9 | - |xxx_tls_security_level |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |xxx_enforce_tls | 3.9 | - |xxx_tls_security_level |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |xxx_per_site | 3.9 | - |xxx_policy_maps |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |smtpd_tls_dh1024_param_file| 3.9 | - |do not specify (leave at |
+ | | | |default) |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |smtpd_tls_eecdh_grade | 3.9 | - |do not specify (leave at |
+ | | | |default) |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |permit_mx_backup | 3.9 | - |relay_domains |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |check_relay_domains | 2.2 | 3.9 |permit_mynetworks, |
+ | | | |reject_unauth_destination|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |reject_maps_rbl | 2.1 | 3.9 |reject_rbl_client |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |permit_naked_ip_address | 2.0 | 3.9 |permit_mynetworks, |
+ | | | |permit_sasl_authenticated|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+OObbssoolleettee DDNNSS oonn//ooffff ccoonnffiigguurraattiioonn
+
+The postconf(1) command logs the following:
+
+ * support for parameter "disable_dns_lookups" will be removed; instead,
+ specify "smtp_dns_support_level"
+
+Replace obsolete configuration with its replacement:
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |GGooaall |OObbssoolleettee ccoonnffiigguurraattiioonn |RReeppllaacceemmeenntt |
+ | | |ccoonnffiigguurraattiioonn |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |To disable DNS lookups|disable_dns_lookups = |smtp_dns_support_level =|
+ |in the Postfix SMTP/ |yes |disabled |
+ |LMTP client | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Leave |
+ | | |smtp_dns_support_level |
+ |To enable DNS lookups | |at the implicit default |
+ |in the Postfix SMTP/ |disable_dns_lookups = no|which is empty, unless |
+ |LMTP client | |you need a higher |
+ | | |support level such as |
+ | | |DNSSEC. |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+OObbssoolleettee ooppppoorrttuunniissttiicc TTLLSS ccoonnffiigguurraattiioonn
+
+The postconf(1) command logs one of the following:
+
+ * support for parameter "lmtp_use_tls" will be removed; instead, specify
+ "lmtp_tls_security_level"
+ * support for parameter "smtp_use_tls" will be removed; instead, specify
+ "smtp_tls_security_level"
+ * support for parameter "smtpd_use_tls" will be removed; instead, specify
+ "smtpd_tls_security_level"
+
+There are similarly-named parameters and warnings for postscreen(8) and
+tlsproxy(8), but those parameters should rarely be specified by hand.
+
+Replace obsolete configuration with its replacement:
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |GGooaall |OObbssoolleettee ccoonnffiigguurraattiioonn|RReeppllaacceemmeenntt ccoonnffiigguurraattiioonn|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |To turn off TLS |xxx_use_tls = no |xxx_security_level = none|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |To turn on opportunistic|xxx_use_tls = yes |xxx_security_level = may |
+ |TLS | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+OObbssoolleettee mmaannddaattoorryy TTLLSS ccoonnffiigguurraattiioonn
+
+The postconf(1) command logs one of the following:
+
+ * support for parameter "lmtp_enforce_tls" will be removed; instead, specify
+ "lmtp_tls_security_level"
+ * support for parameter "smtp_enforce_tls" will be removed; instead, specify
+ "smtp_tls_security_level"
+ * support for parameter "smtpd_enforce_tls" will be removed; instead, specify
+ "smtpd_tls_security_level"
+
+There are similarly-named parameters and warnings for postscreen(8) and
+tlsproxy(8), but those parameters should rarely be specified by hand.
+
+Replace obsolete configuration with its replacement:
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |GGooaall |OObbssoolleettee ccoonnffiigguurraattiioonn|RReeppllaacceemmeenntt ccoonnffiigguurraattiioonn|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |To turn off mandatory |xxx_enforce_tls = no |xxx_security_level = may |
+ |TLS | | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |To turn on mandatory TLS|xxx_enforce_tls = yes |xxx_security_level = |
+ | | |encrypt |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+OObbssoolleettee TTLLSS ppoolliiccyy ttaabbllee ccoonnffiigguurraattiioonn
+
+The postconf(1) command logs one of the following:
+
+ * support for parameter "lmtp_tls_per_site" will be removed; instead, specify
+ "lmtp_tls_policy_maps"
+ * support for parameter "smtp_tls_per_site" will be removed; instead, specify
+ "smtp_tls_policy_maps"
+
+There is similarly-named parameter and warning for tlsproxy(8), but that
+parameter should rarely be specified by hand.
+
+Unfortunately, this is more than a name change: the table format has changed
+too, as has the table search process. There is no simple conversion of the
+obsolete form to its replacement.
+
+cchheecckk__rreellaayy__ddoommaaiinnss
+
+Depending on the Postfix version, the Postfix SMTP daemon logs following
+warning:
+
+ * support for restriction "check_relay_domains" has been removed in Postfix
+ 3.9"; instead, specify "reject_unauth_destination"
+ * support for restriction "check_relay_domains" will be removed from Postfix;
+ use "reject_unauth_destination" instead
+
+This feature was removed because it would relay based on the client domain
+name, which is not robust.
+
+Recommended configuration to prevent an "open relay" problem with the SMTP
+service on port 25:
+
+ main.cf:
+ smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination
+ ...other restrictions...
+
+Or equivalent in smtpd_relay_restrictions.
+
+ppeerrmmiitt__mmxx__bbaacckkuupp
+
+The Postfix version 3.9 and later SMTP daemon logs the following warning:
+
+ * support for restriction "permit_mx_backup" will be removed from Postfix;
+ instead, specify "relay_domains"
+
+This feature will be removed because it is too difficult to configure recipient
+address validation, making Postfix a source of backscatter bounces.
+
+To specify the domains that Postfix will provide MX backup service for, see
+Configuring Postfix as primary or backup MX host for a remote site.
+
+rreejjeecctt__mmaappss__rrbbll
+
+Depending on the Postfix version, the SMTP daemon logs one of the following
+warnings:
+
+ * support for restriction "reject_maps_rbl" has been removed in Postfix 3.9";
+ instead, specify "reject_rbl_client domain-name"
+ * support for restriction "reject_maps_rbl" will be removed from Postfix; use
+ "reject_rbl_client domain-name" instead
+
+This feature was replaced because "MAPS RBL" is the name of a specific
+reputation service. The reject_rbl_client feature provides a superset of the
+reject_maps_rbl functionality.
+
+Recommended configuration:
+
+ main.cf:
+ smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination
+ reject_rbl_client domain-name
+ ...other restrictions...
+
+Where domain-name is the domain name of a DNS reputation service.
+
+ppeerrmmiitt__nnaakkeedd__iipp__aaddddrreessss
+
+Depending on the Postfix version, the SMTP daemon logs one of the following
+warnings:
+
+ * support for restriction "permit_naked_ip_address" has been removed in
+ Postfix 3.9"; instead, specify "permit_mynetworks" or
+ "permit_sasl_authenticated"
+ * restriction permit_naked_ip_address is deprecated. Use permit_mynetworks or
+ permit_sasl_authenticated instead
+
+This feature was removed because it was easy to get a false match when
+smtpd_recipient_restrictions was intended to match a remote SMTP client IP
+address.
+
+Recommended configuration:
+
+ main.cf:
+ smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination
+ reject_rbl_client domain-name
+ ...other restrictions...
+
+That is, no restriction on HELO or EHLO syntax. Such restrictions ar rarely
+useful nowadays.
+
diff --git a/README_FILES/INSTALL b/README_FILES/INSTALL
index 09d0f80..85ed2cc 100644
--- a/README_FILES/INSTALL
+++ b/README_FILES/INSTALL
@@ -376,27 +376,29 @@ whistles. Support for third-party databases etc. must be configured when
Postfix is compiled. The following documents describe how to build Postfix with
support for optional features:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- |OOppttiioonnaall ffeeaattuurree |DDooccuummeenntt |AAvvaaiillaabbiilliittyy|
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |Berkeley DB database |DB_README |Postfix 1.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |LMDB database |LMDB_README |Postfix 2.11|
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |LDAP database |LDAP_README |Postfix 1.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |MySQL database |MYSQL_README |Postfix 1.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |Perl compatible regular expression|PCRE_README |Postfix 1.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |PostgreSQL database |PGSQL_README |Postfix 2.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |SASL authentication |SASL_README |Postfix 1.0 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |SQLite database |SQLITE_README|Postfix 2.8 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
- |STARTTLS session encryption |TLS_README |Postfix 2.2 |
- |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |OOppttiioonnaall ffeeaattuurree |DDooccuummeenntt |AAvvaaiillaabbiilliittyy|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |Berkeley DB database |DB_README |Postfix 1.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |LMDB database |LMDB_README |Postfix 2.11|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |LDAP database |LDAP_README |Postfix 1.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |MongoDB database |MONGODB_README|Postfix 3.9 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |MySQL database |MYSQL_README |Postfix 1.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |Perl compatible regular expression|PCRE_README |Postfix 1.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |PostgreSQL database |PGSQL_README |Postfix 2.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |SASL authentication |SASL_README |Postfix 1.0 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |SQLite database |SQLITE_README |Postfix 2.8 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
+ |STARTTLS session encryption |TLS_README |Postfix 2.2 |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ |
Note: IP version 6 support is compiled into Postfix on operating systems that
have IPv6 support. See the IPV6_README file for details.
diff --git a/README_FILES/LOCAL_RECIPIENT_README b/README_FILES/LOCAL_RECIPIENT_README
index ea4ce25..c8b97bd 100644
--- a/README_FILES/LOCAL_RECIPIENT_README
+++ b/README_FILES/LOCAL_RECIPIENT_README
@@ -30,7 +30,7 @@ addresses of local recipients. A recipient address is local when its domain
matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local
username or address is not listed in $local_recipient_maps, then the Postfix
SMTP server will reject the address with "User unknown in local recipient
-table".
+table". Other Postfix interfaces may still accept an "unknown" recipient.
The default setting, shown below, assumes that you use the default Postfix
local(8) delivery agent for local delivery, where recipients are either UNIX
diff --git a/README_FILES/MAILLOG_README b/README_FILES/MAILLOG_README
index 6f8fead..75fa4b5 100644
--- a/README_FILES/MAILLOG_README
+++ b/README_FILES/MAILLOG_README
@@ -30,8 +30,14 @@ problems for systemd-based systems.
2. Configure Postfix to write logging, to, for example, /var/log/postfix.log.
See also the "Logfile rotation" section below for logfile management.
+ In the example below, specifying maillog_file_permissions is optional
+ (Postfix 3.9 and later). The default value is 0600, i.e., only the super-
+ user can access the file; the value 0644 also adds 'group' and 'other' read
+ access.
+
# postfix stop
# postconf maillog_file=/var/log/postfix.log
+ # postconf maillog_file_permissions=0644 # (Postfix 3.9 and later)
# postfix start
By default, the logfile name must start with "/var" or "/dev/stdout" (the
@@ -71,6 +77,10 @@ implements the following steps:
* After a brief pause, compress the old logfile. The compression program is
configured with the maillog_file_compressor parameter (default: gzip).
+ * The next time it logs an event, postlogd(8) will create a new logfile, with
+ permissions specified with the maillog_file_permissions parameter (default:
+ 0600).
+
Notes:
* This command will not rotate a logfile with a pathname under the /dev
diff --git a/README_FILES/MILTER_README b/README_FILES/MILTER_README
index 4ace868..7d9e938 100644
--- a/README_FILES/MILTER_README
+++ b/README_FILES/MILTER_README
@@ -392,9 +392,9 @@ ccoommmmaa wwiitthhiinn aa vvaalluuee oorr aarroouunndd
DDiiffffeerreenntt sseettttiinnggss ffoorr ddiiffffeerreenntt SSMMTTPP cclliieennttss
The smtpd_milter_maps feature supports different Milter settings for different
-client IP addresses. Lookup results override the the global smtpd_milters
-setting, and have the same syntax. For example, to disable Milter settings for
-local address ranges:
+client IP addresses. Lookup results override the global smtpd_milters setting,
+and have the same syntax. For example, to disable Milter settings for local
+address ranges:
/etc/postfix/main.cf:
smtpd_milter_maps = cidr:/etc/postfix/smtpd_milter_map
diff --git a/README_FILES/MONGODB_README b/README_FILES/MONGODB_README
new file mode 100644
index 0000000..c8b8fc6
--- /dev/null
+++ b/README_FILES/MONGODB_README
@@ -0,0 +1,188 @@
+PPoossttffiixx MMoonnggooDDBB HHoowwttoo
+
+-------------------------------------------------------------------------------
+
+MMoonnggooDDBB SSuuppppoorrtt iinn PPoossttffiixx
+
+Postfix can use MongoDB as a source for any of its lookups: aliases(5), virtual
+(5), canonical(5), etc. This allows you to keep information for your mail
+service in a replicated noSQL database with fine-grained access controls. By
+not storing it locally on the mail server, the administrators can maintain it
+from anywhere, and the users can control whatever bits of it you think
+appropriate. You can have multiple mail servers using the same information,
+without the hassle and delay of having to copy it to each.
+
+Topics covered in this document:
+
+ * Building Postfix with MongoDB support
+ * Configuring MongoDB lookups
+ * Example: virtual alias maps
+ * Example: Mailing lists
+ * Example: MongoDB projections
+ * Feedback
+ * Credits
+
+BBuuiillddiinngg PPoossttffiixx wwiitthh MMoonnggooDDBB ssuuppppoorrtt
+
+These instructions assume that you build Postfix from source code as described
+in the INSTALL document. Some modification may be required if you build Postfix
+from a vendor-specific source package.
+
+The Postfix MongoDB client requires the mmoonnggoo--cc--ddrriivveerr library. This can be
+built from source code from the mongod-c project, or this can be installed as a
+binary package from your OS distribution, typically named mmoonnggoo--cc--ddrriivveerr,
+mmoonnggoo--cc--ddrriivveerr--ddeevveell or lliibbmmoonnggoocc--ddeevv. Installing the mongo-c-driver library
+may also install lliibbbbssoonn as a dependency.
+
+To build Postfix with mongodb map support, add to the CCARGS environment
+variable the options -DHAS_MONGODB and -I for the directory containing the
+mongodb headers, and specify the AUXLIBS_MONGODB with the libmongoc and libbson
+libraries, for example:
+
+ % make tidy
+ % make -f Makefile.init makefiles \
+ CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
+ -I/usr/include/libbson-1.0" \
+ AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0"
+
+The 'make tidy' command is needed only if you have previously built Postfix
+without MongoDB support.
+
+If your MongoDB shared library is in a directory that the RUN-TIME linker does
+not know about, add a "-Wl,-R,/path/to/directory" option after "-lbson-1.0".
+Then, just run 'make'.
+
+CCoonnffiigguurriinngg MMoonnggooDDBB llooookkuuppss
+
+In order to use MongoDB lookups, define a MongoDB source as a table lookup in
+main.cf, for example:
+
+ alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf
+
+The file /etc/postfix/mongo-aliases.cf can specify a number of parameters. For
+a complete description, see the mongodb_table(5) manual page.
+
+EExxaammppllee:: vviirrttuuaall((55)) aalliiaass mmaappss
+
+Here's a basic example for using MongoDB to look up virtual(5) aliases. Assume
+that in main.cf, you have:
+
+ virtual_alias_maps = hash:/etc/postfix/virtual_aliases,
+ proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf
+
+and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have:
+
+ uri = mongodb+srv://user_name:password@some_server
+ dbname = mail
+ collection = mailbox
+ query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}],
+ "active": 1}
+ result_attribute = username
+
+This example assumes mailbox names are stored in a MongoDB backend, in a format
+like:
+
+ { "username": "user@example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+ }
+
+Upon receiving mail for "admin@example.com" that isn't found in the /etc/
+postfix/virtual_aliases database, Postfix will search the MongoDB server/
+cluster listening at port 27017 on some_server. It will connect using the
+provided credentials, and search for any entries whose username is, or alias
+field has "admin@example.com". It will return the username attribute of those
+found, and build a list of their email addresses.
+
+Notes:
+
+ * As with pprroojjeeccttiioonn (see below), the Postfix mongodb client automatically
+ removes the top-level '_id' field from a result_attribute result.
+
+ * The Postfix mongodb client will only parse result fields with data types
+ UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, with a warning
+ in the logs.
+
+EExxaammppllee:: MMaaiilliinngg lliissttss
+
+When it comes to mailing lists, one way of implementing one would be as below:
+
+ { "name": "dev@example.com", "active": 1, "address":
+ [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
+
+using the filter below, will result in a comma separated string with all email
+addresses in this list.
+
+ query_filter = {"name": "%s", "active": 1}
+ result_attribute = address
+
+Notes:
+
+ * As with pprroojjeeccttiioonn (see below), the Postfix mongodb client automatically
+ removes the top-level '_id' field from a result_attribute result.
+
+ * The Postfix mongodb client will only parse result fields with data types
+ UTF8, INT32, INT64 and ARRAY. Other fields will be ignored, with a warning
+ in the logs.
+
+EExxaammppllee:: aaddvvaanncceedd pprroojjeeccttiioonnss
+
+This module also supports the use of more complex MongoDB projections. There
+may be some use cases where operations such as concatenation are necessary to
+be performed on the data retrieved from the database. Although it is encouraged
+to keep the database design simple enough so this is not necessary, postfix
+supports the use of MongoDB projections to achieve the goal.
+
+Consider the example below:
+
+ { "username": "user@example.com",
+ "local_part": "user",
+ "domain": "example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+ }
+
+virtual_mailbox_maps can be created using below parameters in a mongodb:/etc/
+postfix/mongo-virtual-mailboxes.cf file:
+
+ uri = mongodb+srv://user_name:password@some_server
+ dbname = mail
+ collection = mailbox
+ query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}],
+ "active": 1}
+ projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
+
+This will return 'example.com/user' path built from the database fields.
+
+A couple of considerations when using projections:
+
+ * As with rreessuulltt__aattttrriibbuuttee, the Postfix mongodb client automatically removes
+ the top-level '_id' field from a projection result.
+
+ * The Postfix mongodb client will only parse fields with data types UTF8,
+ INT32, INT64 and ARRAY. Other fields will be ignored, with a warning in the
+ logs. It is suggested to exclude any unnecessary fields when using a
+ projection.
+
+FFeeeeddbbaacckk
+
+If you have questions, send them to postfix-users@postfix.org. Please include
+relevant information about your Postfix setup: MongoDB-related output from
+postconf, which libraries you built with, and such. If your question involves
+your database contents, please include the applicable bits of some database
+entries.
+
+CCrreeddiittss
+
+ * Stephan Ferraro (Aionda GmbH) implemented an early version of the Postfix
+ MongoDB client.
+ * Hamid Maadani (Dextrous Technologies, LLC) added support for projections
+ and %letter interpolation, and added documentation.
+ * Wietse Venema adopted and restructured the code and documentation.
+
diff --git a/README_FILES/POSTSCREEN_README b/README_FILES/POSTSCREEN_README
index 9467e68..5b4d200 100644
--- a/README_FILES/POSTSCREEN_README
+++ b/README_FILES/POSTSCREEN_README
@@ -78,7 +78,7 @@ Zombies have challenges too: they have only a limited amount of time to deliver
spam before their IP address becomes denylisted. To speed up spam deliveries,
zombies make compromises in their SMTP protocol implementation. For example,
they speak before their turn, or they ignore responses from SMTP servers and
-continue sending mail even when the server tells them to go away.
+continue sending commands even when the server tells them to go away.
postscreen(8) uses a variety of measurements to recognize zombies. First,
postscreen(8) determines if the remote SMTP client IP address is denylisted.
@@ -114,7 +114,7 @@ clients.
QQuuiicckk tteessttss bbeeffoorree eevveerryytthhiinngg eellssee
-Before engaging in SMTP-level tests. postscreen(8) queries a number of local
+Before engaging in SMTP-level tests, postscreen(8) queries a number of local
deny and allowlists. These tests speed up the handling of known clients.
* Permanent allow/denylist test
diff --git a/README_FILES/TLS_README b/README_FILES/TLS_README
index e7fd259..5e63554 100644
--- a/README_FILES/TLS_README
+++ b/README_FILES/TLS_README
@@ -1726,73 +1726,109 @@ describe the corresponding table syntax:
nnoonnee
No TLS. No additional attributes are supported at this level.
mmaayy
- Opportunistic TLS. The optional "ciphers", "exclude" and "protocols"
- attributes (available for opportunistic TLS with Postfix >= 2.6) override
- the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols"
- configuration parameters. At this level and higher, the optional
- "servername" attribute (available with Postfix >= 3.4) overrides the global
- "smtp_tls_servername" parameter, enabling per-destination configuration of
- the SNI extension sent to the remote SMTP server.
+ Opportunistic TLS. The optional "ciphers", "exclude", and "protocols"
+ attributes (available for opportunistic TLS with Postfix >= 2.6) and
+ "connection_reuse" attribute (Postfix >= 3.4) override the
+ "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols", and
+ "smtp_tls_connection_reuse" configuration parameters. At this level and
+ higher, the optional "servername" attribute (available with Postfix >= 3.4)
+ overrides the global "smtp_tls_servername" parameter, enabling per-
+ destination configuration of the SNI extension sent to the remote SMTP
+ server. The optional "enable_rpk" attribute (Postfix >= 3.9) overrides the
+ main.cf smtp_tls_enable_rpk parameter. When opportunistic TLS handshakes
+ fail, Postfix retries the connection with TLS disabled. This allows mail
+ delivery to sites with non-interoperable TLS implementations.
eennccrryypptt
Mandatory encryption. Mail is delivered only if the remote SMTP server
offers STARTTLS and the TLS handshake succeeds. At this level and higher,
the optional "protocols" attribute overrides the main.cf
smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute
- overrides the main.cf smtp_tls_mandatory_ciphers parameter, and the
- optional "exclude" attribute (Postfix >= 2.6) overrides the main.cf
- smtp_tls_mandatory_exclude_ciphers parameter.
+ overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional
+ "exclude" attribute (Postfix >= 2.6) overrides the main.cf
+ smtp_tls_mandatory_exclude_ciphers parameter, and the optional
+ "connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf
+ smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute
+ (Postfix >= 3.9) overrides the main.cf smtp_tls_enable_rpk parameter.
ddaannee
Opportunistic DANE TLS. The TLS policy for the destination is obtained via
TLSA records in DNSSEC. If no TLSA records are found, the effective
security level used is may. If TLSA records are found, but none are usable,
the effective security level is encrypt. When usable TLSA records are
- obtained for the remote SMTP server, SSLv2+3 are automatically disabled
- (see smtp_tls_mandatory_protocols), and the server certificate must match
- the TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is
- available with Postfix 2.11 and later.
+ obtained for the remote SMTP server, the server certificate must match the
+ TLSA records (and the SNI name is unconditionally set to the TLSA base
+ domain). RFC 7672 (DANE) TLS authentication and DNSSEC support is available
+ with Postfix 2.11 and later. The optional "connection_reuse" attribute
+ (Postfix >= 3.4) overrides the main.cf smtp_tls_connection_reuse parameter.
+ When the effective security level used is may, the optional "ciphers",
+ "exclude", and "protocols" attributes (Postfix >= 2.6) override the
+ "smtp_tls_ciphers", "smtp_tls_exclude_ciphers", and "smtp_tls_protocols"
+ configuration parameters. When the effective security level used is
+ encrypt, the optional "ciphers", "exclude", and "protocols" attributes
+ (Postfix >= 2.6) override the "smtp_tls_mandatory_ciphers",
+ "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+ configuration parameters.
ddaannee--oonnllyy
Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA
records in DNSSEC. If no TLSA records are found, or none are usable, no
connection is made to the server. When usable TLSA records are obtained for
- the remote SMTP server, SSLv2+3 are automatically disabled (see
- smtp_tls_mandatory_protocols), and the server certificate must match the
- TLSA records. RFC 7672 (DANE) TLS authentication and DNSSEC support is
- available with Postfix 2.11 and later.
+ the remote SMTP server, the server certificate must match the TLSA records.
+ RFC 7672 (DANE) TLS authentication and DNSSEC support is available with
+ Postfix 2.11 and later. The optional "ciphers", "exclude", and "protocols"
+ attributes (Postfix >= 2.6) override the "smtp_tls_mandatory_ciphers",
+ "smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+ configuration parameters. The optional "connection_reuse" attribute
+ (Postfix >= 3.4) overrides the main.cf smtp_tls_connection_reuse parameter.
ffiinnggeerrpprriinntt
Certificate fingerprint verification. Available with Postfix 2.5 and later.
At this security level, there are no trusted Certification Authorities. The
certificate trust chain, expiration date, ... are not checked. Instead, the
- optional mmaattcchh attribute, or else the main.cf
- ssmmttpp__ttllss__ffiinnggeerrpprriinntt__cceerrtt__mmaattcchh parameter, lists the server certificate
- fingerprints or public key fingerprints (Postfix 2.9 and later). The digest
- algorithm used to calculate fingerprints is selected by the
- ssmmttpp__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt parameter. Multiple fingerprints can be
- combined with a "|" delimiter in a single match attribute, or multiple
- match attributes can be employed. The ":" character is not used as a
- delimiter as it occurs between each pair of fingerprint (hexadecimal)
- digits.
+ optional "match" attribute, or else the main.cf
+ ssmmttpp__ttllss__ffiinnggeerrpprriinntt__cceerrtt__mmaattcchh parameter, lists the certificate
+ fingerprints or the public key fingerprints (Postfix 2.9 and later) of
+ acceptable server certificates. The digest algorithm used to calculate the
+ fingerprint is selected by the ssmmttpp__ttllss__ffiinnggeerrpprriinntt__ddiiggeesstt parameter.
+ Multiple fingerprints can be combined with a "|" delimiter in a single
+ match attribute, or multiple match attributes can be employed. The ":
+ " character is not used as a delimiter as it occurs between each pair of
+ fingerprint (hexadecimal) digits. The optional "ciphers", "exclude", and
+ "protocols" attributes (Postfix >= 2.6) override the
+ "smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
+ "smtp_tls_mandatory_protocols" configuration parameters. The optional
+ "connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf
+ smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute
+ (Postfix >= 3.9) overrides the main.cf smtp_tls_enable_rpk parameter.
vveerriiffyy
Mandatory server certificate verification. Mail is delivered only if the
- TLS handshake succeeds, if the remote SMTP server certificate can be
- validated (not expired or revoked, and signed by a trusted Certification
- Authority), and if the server certificate name matches the optional "match"
- attribute (or the main.cf smtp_tls_verify_cert_match parameter value when
- no optional "match" attribute is specified). With Postfix >= 2.11 the
+ TLS handshake succeeds, the remote SMTP server certificate chain can be
+ validated, and a DNS name in the certificate matches the specified match
+ criteria. At this security level, DNS MX lookups are presumed to be secure
+ enough, and the name verified in the server certificate is potentially
+ obtained via unauthenticated DNS MX lookups. The server certificate name
+ must match either the optional "match" attribute, or else the main.cf
+ smtp_tls_verify_cert_match parameter value. With Postfix >= 2.11 the
"tafile" attribute optionally modifies trust chain verification in the same
manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
attribute may be specified multiple times to load multiple trust-anchor
- files.
+ files. The optional "connection_reuse" attribute (Postfix >= 3.4) overrides
+ the main.cf smtp_tls_connection_reuse parameter.
sseeccuurree
Secure certificate verification. Mail is delivered only if the TLS
- handshake succeeds, and DNS forgery resistant remote SMTP certificate
- verification succeeds (not expired or revoked, and signed by a trusted
- Certification Authority), and if the server certificate name matches the
- optional "match" attribute (or the main.cf smtp_tls_secure_cert_match
- parameter value when no optional "match" attribute is specified). With
- Postfix >= 2.11 the "tafile" attribute optionally modifies trust chain
- verification in the same manner as the "smtp_tls_trust_anchor_file"
- parameter. The "tafile" attribute may be specified multiple times to load
- multiple trust-anchor files.
+ handshake succeeds, the remote SMTP server certificate chain can be
+ validated, and a DNS name in the certificate matches the specified match
+ criteria. At this security level, DNS MX lookups, though potentially used
+ to determine the candidate next-hop gateway IP addresses, are nnoott presumed
+ to be secure enough for TLS peername verification. Instead, the default
+ name verified in the server certificate is obtained directly from the next-
+ hop, or is explicitly specified via the optional "match" attribute which
+ overrides the main.cf smtp_tls_secure_cert_match parameter. The optional
+ "ciphers", "exclude", and "protocols" attributes (Postfix >= 2.6) override
+ the "smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
+ "smtp_tls_mandatory_protocols" configuration parameters. With Postfix >=
+ 2.11 the "tafile" attribute optionally modifies trust chain verification in
+ the same manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
+ attribute may be specified multiple times to load multiple trust-anchor
+ files. The optional "connection_reuse" attribute (Postfix >= 3.4) overrides
+ the main.cf smtp_tls_connection_reuse parameter.
Notes:
* The "match" attribute is especially useful to verify TLS certificates for
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 0a23bf8..6d32de2 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,19 +1,19 @@
-This is the Postfix 3.8 stable release.
+This is the Postfix 3.9 stable release.
-The stable Postfix release is called postfix-3.8.x where 3=major
-release number, 8=minor release number, x=patchlevel. The stable
+The stable Postfix release is called postfix-3.9.x where 3=major
+release number, 9=minor release number, x=patchlevel. The stable
release never changes except for patches that address bugs or
emergencies. Patches change the patchlevel and the release date.
New features are developed in snapshot releases. These are called
-postfix-3.9-yyyymmdd where yyyymmdd is the release date (yyyy=year,
+postfix-3.10-yyyymmdd where yyyymmdd is the release date (yyyy=year,
mm=month, dd=day). Patches are never issued for snapshot releases;
instead, a new snapshot is released.
The mail_release_date configuration parameter (format: yyyymmdd)
specifies the release date of a stable release or snapshot release.
-If you upgrade from Postfix 3.6 or earlier, please read RELEASE_NOTES-3.7
+If you upgrade from Postfix 3.7 or earlier, please read RELEASE_NOTES-3.8
before proceeding.
Dual license
@@ -26,32 +26,142 @@ now also distributed with the more recent Eclipse Public License
license of their choice. Those who are more comfortable with the
IPL can continue with that license.
-Incompatibility with Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24
-==============================================================
+Topics in this document
+-----------------------
+- changes that are less visible
+- database support
+- envid support
+- feature deprecation
+- mime conversion
+- protocol compliance
+- security
+- tls support
-Improvements for outbound SMTP smuggling defense:
+Changes that are less visible
+-----------------------------
-- With "cleanup_replace_stray_cr_lf = yes" (the default), the cleanup
- daemon replaces each stray <CR> or <LF> character in message
- content with a space character. The replacement happens before
- any other content management (header/body_checks, Milters, etc).
+The documentation has been updated to address many questions
+that were asked on the postfix-users mailing list.
- This prevents outbound SMTP smuggling, where an attacker uses
- Postfix to send email containing a non-standard End-of-DATA
- sequence, to exploit inbound SMTP smuggling at a vulnerable remote
- SMTP server.
+More unit tests to make Postfix future-proof. Wietse is now looking
+into migrating unit tests to Google test, because other people are
+familiar with that framework, than with a Postfix-specific one.
- This also improves the remote evaluation of Postfix-added DKIM
- and other signatures, as the evaluation result will not depend
- on how a remote email server handles stray <CR> or <LF> characters.
+Major changes - database support
+--------------------------------
+
+[Feature 20240208] MongoDB client support, contributed by Hamid
+Maadani, based on earlier code by Stephan Ferraro. For build and
+usage instructions see MONGODB_README and mongodb_table(5).
+
+[Feature 20240129] In the mysql: and pgsql: clients, the hard-coded
+idle and retry timer settings are now configurable. Details are in
+the updated mysql_table(5) and pgsql_table(5) manpages.
+
+[Incompat 20230903] The MySQL client no longer supports MySQL
+versions < 4.0. MySQL version 4.0 was released in 2003.
+
+[Incompat 20230419] The MySQL client default characterset is now
+configurable with the "charset" configuration file attribute. The
+default is "utf8mb4", consistent with the MySQL 8.0 built-in default,
+but different from earlier MySQL versions where the built-in default
+was "latin1".
+
+Major changes - envid support
+-----------------------------
+
+[Feature 20230901] The local(8) delivery agent exports an ENVID
+environment variable with the RFC 3461 envelope ID if available.
+
+The pipe(8) delivery agent supports an ${envid} command-line attribute
+that expands to the RFC 3461 envelope ID if available.
+
+Major changes - feature deprecation
+-----------------------------------
+
+[Incompat 20240218] The new document DEPRECATION_README covers
+features that have been removed and that will be removed in the
+future, with suggestions how to migrate.
+
+The Postfix SMTP server logs a warning when "permit_mx_backup" is
+used (support for restriction "permit_mx_backup" will be removed
+from Postfix; instead, use "relay_domains"). File: smtpd/smtpd_check.c.
+
+The postconf command logs a warning when the following parameters
+are specified in main.cf or master.cf: xxx_use_tls, xxx_enforce_tls
+(use the corresponding xxx_security_level setting instead);
+xxx_per_site (use the corresponding xxx_policy_maps setting instead);
+disable_dns_lookups (use smtp_dns_support_level instead);
+smtpd_tls_dh1024_param_file, smtpd_tls_eecdh_grade (do not specify,
+leave at default). These warning are silenced with the "postconf
+-q".
+
+[Incompat 20240218] The Postfix SMTP server now logs that
+permit_naked_ip_address, reject_maps_rbl, and check_relay_domains
+have been removed and suggests a replacement. These features have
+been logging deprecation warnings since 2005 or earlier, and were
+removed from Postfix documentation in 2004.
+
+Major changes - mime conversion
+-------------------------------
+
+[Feature 20230901] New parameter force_mime_input_conversion (default:
+no) to convert body content that claims to be 8-bit into quoted-printable,
+before header_checks, body_checks, Milters, and before after-queue
+content filters. This feature does not affect messages that are
+sent into smtpd_proxy_filter.
+
+The typical use case is an MTA that applies this conversion before
+signing outbound messages, so that the signatures will remain valid
+when a message is later handled by an MTA that does not announce
+8BITMIME support, or when a message line exceeds the SMTP length
+limit.
+
+Major changes - protocol compliance
+-----------------------------------
+
+[Incompat 20240206] In message headers, Postfix now formats numerical
+days as two-digit days, i.e. days 1-9 have a leading zero instead
+of a leading space. This change was made because the RFC 5322 date
+and time specification recommends (i.e. SHOULD) that a single space
+be used in each place that FWS appears. This change avoids a breaking
+change in the date string length.
+
+Major changes - security
+------------------------
+
+[Incompat 20240226] The Postfix DNS client now limits the total
+size of DNS lookup results to 100 records; it drops the excess
+records, and logs a warning. This limit is 20x larger than the
+number of server addresses that the Postfix SMTP client is willing
+to consider when delivering mail, and is far below the number of
+records that could cause a tail recursion crash in dns_rr_append()
+as reported by Toshifumi Sakaguchi.
+
+This change introduces a similar limit on the number of DNS requests
+that a check_*_*_access restriction can make.
+
+[Incompat 20240110] With "cleanup_replace_stray_cr_lf = yes" (the
+default), the cleanup daemon replaces each stray <CR> or <LF>
+character in message content with a space character. The replacement
+happens before any other content management (header/body_checks,
+Milters, etc).
+
+This prevents outbound SMTP smuggling, where an attacker uses Postfix
+to send email containing a non-standard End-of-DATA sequence, to
+exploit inbound SMTP smuggling at a vulnerable remote SMTP server.
+
+This also improves the remote evaluation of Postfix-added DKIM and
+other signatures, as the evaluation result will not depend on how
+a remote email server handles stray <CR> or <LF> characters.
This feature applies to all email that Postfix locally or remotely
sends out. It is not allowlisted based on client identity.
-Major changes with Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24
-============================================================
+[Feature 20240118] This updates Postfix fixes for inbound SMTP smuggling
+attacks. For background, see https://www.postfix.org/smtp-smuggling.html
-Improvements for inbound SMTP smuggling defense:
+This will be back ported to Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24.
- Better compatibility: the recommended setting "smtpd_forbid_bare_newline
= normalize" requires the standard End-of-DATA sequence
@@ -124,120 +234,76 @@ Alternative settings:
# 10.0.0.0/24 chunking, silent-discard
# smtpd_discard_ehlo_keywords = chunking, silent-discard
-Major changes with Postfix 3.8.1
-================================
-
-Security: the Postfix SMTP server optionally disconnects remote
-SMTP clients that violate RFC 2920 (or 5321) command pipelining
+[Incompat 20230603] the Postfix SMTP server by default disconnects
+remote SMTP clients that violate RFC 2920 (or 5321) command pipelining
constraints. The server replies with "554 5.5.0 Error: SMTP protocol
synchronization" and logs the unexpected remote SMTP client input.
-Specify "smtpd_forbid_unauth_pipelining = yes" to enable. This
-feature is enabled by default in Postfix 3.9 and later.
-
-Workaround to limit collateral damage from OS distributions that
-crank up security to 11, increasing the number of plaintext email
-deliveries. This introduces basic OpenSSL configuration file support,
-with two new parameters "tls_config_file" and "tls_config_name".
-Details are in the postconf(5) manpage under "tls_config_file" and
-"tls_config_name".
-
-Major changes - documentation and code cleanup
-----------------------------------------------
-
-There are numerous small fixes to Postfix documentation, and small
-code-health changes that should not affect documented behavior but
-may improve Postfix behavior for malformed input, or that make
-Postfix easier to maintain. See the HISTORY file for details.
+Specify "smtpd_reject_unauth_pipelining = no" to disable.
-Major changes - SRV support
+Major changes - tls support
---------------------------
-[Feature 20230214] Support to look up DNS SRV records in the Postfix
-SMTP/LMTP client, Based on code by Tomas Korbar (Red Hat).
-
-For example, with "use_srv_lookup = submission" and "relayhost =
-example.com:submission", the Postfix SMTP client will look up DNS
-SRV records for _submission._tcp.example.com, and will relay email
-through the hosts and ports that are specified with those records.
-
-See https://www.postfix.org/postconf.5.html#use_srv_lookup for more
-details, including how to selectively use SRV in a configuration
-that connects to multiple ISP accounts.
-
-SRV support may also be useful inside a cloud-based infrastructure
-when Postfix needs to deliver mail to services that run on a
-dynamically-allocated port.
-
-Major changes - TLS support
----------------------------
-
-[Incompat 20230304] This introduces the following changes:
-
-- Postfix treats the "export" and "low" cipher grade settings as
- "medium". The "export" and "low" grades are no longer supported
- in OpenSSL 1.1.1, the minimum version that Postfix requires.
-
-- Postfix default settings now exclude the following deprecated or
- unused ciphers (SEED, IDEA, 3DES, RC2, RC4, RC5), digest (MD5),
- key exchange algorithms (DH, ECDH), and public key algorithm
- (DSS).
-
-[Feature 20230108] New configuration parameter tls_ffdhe_auto_groups
-for finite-field Diffie-Hellman ephemeral (FFDHE) support in TLS
-1.3 with OpenSSL 3.0.
-
-Major changes - attack resistance
----------------------------------
-
-[Feature 20240312] the Postfix SMTP server can now aggregate
-smtpd_client_*_rate and smtpd_client_*_count statistics by network
-block, as specified with smtpd_client_ipv4_prefix_length (default
-32, no aggregation) and smtpd_client_ipv6_prefix_length (default
-84, aggregation by /84 network blocks). The latter raises the bar
-for a memory exhaustion attack.
-
-[Feature 20221023] Unconditionally disable a CPU resource attack
-requesting TLS renegotiation. There's no good reason to support
-this in the middle of an SMTP connection.
-
-Major changes - bit rot
------------------------
-
-[Incompat 20221228] Postfix documentation and code have been converted
-to use "grep -E" and "grep -F" instead of the historical forms
-"egrep" and "fgrep". To build Postfix on a system that supports
-only the historical forms, run the script auxiliary/fix-grep/fix-grep.sh
-to revert this change.
-
-Major changes - configuration checks
-------------------------------------
-
-[Feature 20240406] The postconf command now warns for #comment in
-or after a Postfix parameter value. Postfix programs do not support
-#comment after other text, and treat that as input.
-
-Major changes - database support
---------------------------------
-
-[Incompat 20220509] The PostgreSQL client encoding is now configurable
-with the "encoding" Postfix configuration file attribute. The default
-is "UTF8". Previously the encoding was hard-coded as "LATIN1".
-
-Major changes - logging
------------------------
-
-[Incompat 20230308] The postfix(1) and postlog(1) commands now
-produce stderr logging even when stderr is not connected to a
-terminal. This eliminates an inconsistency, and makes these programs
-easier to use in some automated procedures. The canonical example
-is to capture output from "postmulti -p status" to figure out which
-instances are or are not running.
-
-Major changes - source code organization
-----------------------------------------
-
-[Incompat 20220507] Most global/mkmap*.[hc] files are moved to the
-util directory; only global/mkmap_proxy.* remains. The old file
-organization was designed before support for dynamically-loadable
-databases was added, and that code suffered from complexity.
-
+[Feature 20230807] Optional Postfix TLS support to request an RFC7250
+raw public key instead of an X.509 public-key certificate. The
+configuration settings for raw key public support will be ignored
+when there is no raw public key support in the local TLS implementation
+(i.e. Postfix with OpenSSL versions before 3.2).
+
+- With "smtpd_tls_enable_rpk = yes", the Postfix SMTP server will
+ request that a remote SMTP client sends an RFC7250 raw public key
+ instead of an X.509 certificate when asking for or requiring TLS
+ client authentication. The Postfix SMTP server will still accept
+ a client public-key certificate instead of a public key.
+
+- With "smtp_tls_enable_rpk = yes" (or "enable_rpk = yes" in an
+ smtp policy table) at the security levels "may", "encrypt" or
+ "fingerprint", the Postfix SMTP client will request that a remote
+ SMTP server sends an RFC7250 raw public key instead of an X.509
+ certificate. The Postfix SMTP client will still accept a server
+ public key certificate instead of a public key.
+
+- At the "secure" and "verify" security level, the Postfix SMTP
+ client will ignore smtp_tls_enable_rpk or enable_rpk settings,
+ because these levels require a server certificate.
+
+- At the "dane" and "dane-only" security levels, the Postfix SMTP
+ client will ignore smtp_tls_enable_rpk or enable_rpk settings,
+ and will request that a remote SMTP server sends an RFC7250 raw
+ public key instead of an X.509 certificate when all valid TLSA
+ records specify only server public keys (no certificates). The
+ Postfix SMTP client will still accept a server public key
+ certificate.
+
+- The Postfix SMTP client and server always send a raw public key
+ instead of a certificate, if solicited by the remote SMTP peer
+ and the local TLS implementation supports raw public keys.
+
+- If a remote SMTP client sends a server name indication with an
+ SNI TLS extension, and tls_server_sni_maps is configured, the
+ Postfix SMTP server will extract a raw public key from the indicated
+ certificate.
+
+Caution: enabling Postfix raw key support will break authentication
+based on certificate fingerprints in check_ccert_access or
+smtp_tls_policy_maps, when a remote peer's TLS implementation starts
+to send a raw public key instead of a certificate. The solution is
+to always use public key fingerprint patterns; these will match not
+only a "raw" public key, but also the public key in a certificate.
+
+To detect such problems before they happen, the Postfix SMTP server
+will log a warning when it requests an RFC7250 raw public key instead
+of an X.509 certificate, the remote peer sends a certificate instead
+of a public key, and check_ccert_access has a matching fingerprint
+for the certificate but not for the public key in that certificate.
+There is no corresponding warning from the Postfix SMTP client.
+
+For instructions to generate public-key fingerprints, see the
+postconf(5) man pages for smtp_tls_enable_rpk and smtpd_tls_enable_rpk.
+
+[Feature 20230522] Preliminary support for OpenSSL configuration
+files, primarily OpenSSL 1.1.1b and later. This introduces two new
+parameters "tls_config_file" and "tls_config_name", which can be
+used to limit collateral damage from OS distributions that crank
+up security to 11, increasing the number of plaintext email deliveries.
+Details are in the postconf(5) manpage under "tls_config_file" and
+"tls_config_name".
diff --git a/RELEASE_NOTES-3.8 b/RELEASE_NOTES-3.8
new file mode 100644
index 0000000..2944830
--- /dev/null
+++ b/RELEASE_NOTES-3.8
@@ -0,0 +1,128 @@
+This is the Postfix 3.8 stable release.
+
+The stable Postfix release is called postfix-3.8.x where 3=major
+release number, 8=minor release number, x=patchlevel. The stable
+release never changes except for patches that address bugs or
+emergencies. Patches change the patchlevel and the release date.
+
+New features are developed in snapshot releases. These are called
+postfix-3.9-yyyymmdd where yyyymmdd is the release date (yyyy=year,
+mm=month, dd=day). Patches are never issued for snapshot releases;
+instead, a new snapshot is released.
+
+The mail_release_date configuration parameter (format: yyyymmdd)
+specifies the release date of a stable release or snapshot release.
+
+If you upgrade from Postfix 3.6 or earlier, please read RELEASE_NOTES-3.7
+before proceeding.
+
+Dual license
+------------
+
+As of Postfix 3.2.5 this software is distributed with a dual license:
+in addition to the historical IBM Public License (IPL) 1.0, it is
+now also distributed with the more recent Eclipse Public License
+(EPL) 2.0. Recipients can choose to take the software under the
+license of their choice. Those who are more comfortable with the
+IPL can continue with that license.
+
+Major changes - documentation and code cleanup
+----------------------------------------------
+
+There are numerous small fixes to Postfix documentation, and small
+code-health changes that should not affect documented behavior but
+may improve Postfix behavior for malformed input, or that make
+Postfix easier to maintain. See the HISTORY file for details.
+
+Major changes - SRV support
+---------------------------
+
+[Feature 20230214] Support to look up DNS SRV records in the Postfix
+SMTP/LMTP client, Based on code by Tomas Korbar (Red Hat).
+
+For example, with "use_srv_lookup = submission" and "relayhost =
+example.com:submission", the Postfix SMTP client will look up DNS
+SRV records for _submission._tcp.example.com, and will relay email
+through the hosts and ports that are specified with those records.
+
+See https://www.postfix.org/postconf.5.html#use_srv_lookup for more
+details, including how to selectively use SRV in a configuration
+that connects to multiple ISP accounts.
+
+SRV support may also be useful inside a cloud-based infrastructure
+when Postfix needs to deliver mail to services that run on a
+dynamically-allocated port.
+
+Major changes - TLS support
+---------------------------
+
+[Incompat 20230304] This introduces the following changes:
+
+- Postfix treats the "export" and "low" cipher grade settings as
+ "medium". The "export" and "low" grades are no longer supported
+ in OpenSSL 1.1.1, the minimum version that Postfix requires.
+
+- Postfix default settings now exclude the following deprecated or
+ unused ciphers (SEED, IDEA, 3DES, RC2, RC4, RC5), digest (MD5),
+ key exchange algorithms (DH, ECDH), and public key algorithm
+ (DSS).
+
+[Feature 20230108] New configuration parameter tls_ffdhe_auto_groups
+for finite-field Diffie-Hellman ephemeral (FFDHE) support in TLS
+1.3 with OpenSSL 3.0.
+
+Major changes - attack resistance
+---------------------------------
+
+[Feature 20240312] the Postfix SMTP server can now aggregate
+smtpd_client_*_rate and smtpd_client_*_count statistics by network
+block, as specified with smtpd_client_ipv4_prefix_length (default
+32, no aggregation) and smtpd_client_ipv6_prefix_length (default
+84, aggregation by /84 network blocks). The latter raises the bar
+for a memory exhaustion attack.
+
+[Feature 20221023] Unconditionally disable a CPU resource attack
+requesting TLS renegotiation. There's no good reason to support
+this in the middle of an SMTP connection.
+
+Major changes - bit rot
+-----------------------
+
+[Incompat 20221228] Postfix documentation and code have been converted
+to use "grep -E" and "grep -F" instead of the historical forms
+"egrep" and "fgrep". To build Postfix on a system that supports
+only the historical forms, run the script auxiliary/fix-grep/fix-grep.sh
+to revert this change.
+
+Major changes - configuration checks
+------------------------------------
+
+[Feature 20240406] The postconf command now warns for #comment in
+or after a Postfix parameter value. Postfix programs do not support
+#comment after other text, and treat that as input.
+
+Major changes - database support
+--------------------------------
+
+[Incompat 20220509] The PostgreSQL client encoding is now configurable
+with the "encoding" Postfix configuration file attribute. The default
+is "UTF8". Previously the encoding was hard-coded as "LATIN1".
+
+Major changes - logging
+-----------------------
+
+[Incompat 20230308] The postfix(1) and postlog(1) commands now
+produce stderr logging even when stderr is not connected to a
+terminal. This eliminates an inconsistency, and makes these programs
+easier to use in some automated procedures. The canonical example
+is to capture output from "postmulti -p status" to figure out which
+instances are or are not running.
+
+Major changes - source code organization
+----------------------------------------
+
+[Incompat 20220507] Most global/mkmap*.[hc] files are moved to the
+util directory; only global/mkmap_proxy.* remains. The old file
+organization was designed before support for dynamically-loadable
+databases was added, and that code suffered from complexity.
+
diff --git a/WISHLIST b/WISHLIST
index bc52ebc..f3d9860 100644
--- a/WISHLIST
+++ b/WISHLIST
@@ -6,6 +6,25 @@ Wish list:
Disable -DSNAPSHOT and -DNONPROD in makedefs.
+ The postconf command needs more mongodb tests.
+
+ The mongodb client needs tests.
+
+ Remove .printfck directories, and remove printfck targets
+ from Makefiles.
+
+ In documentation and configuration file examples, replace
+ IPv4 address prefixes from Cloud9 with 192.168.* from RFC
+ 1918, and replace IPv6 address prefixes with unique local
+ IPv6 address prefixes fd00:* from RFC 4193.
+
+ Add a pre-release check for '.' instead of ','. Generalize
+ from grep '[a-zA-Z0-9]\. *[a-z]' proto/*|egrep -v
+ 'i\.e\.|etc\.|e\.g\.|\. *[a-zA-Z0-9]*\('
+
+ Update DKIM examples for signing with the benefits of forced
+ MIME converison with "force_mime_input_conversion = yes"
+
Scan Postfix code with github.com/googleprojectzero/weggli
(depends on "rust").
@@ -14,16 +33,16 @@ Wish list:
Check out https://github.com/milter-manager/milter-manager/
- Check out https://cutter.osdn.jp/ (C/C++ unit tests).
+ Check out https://github.com/clear-code/cutter
+ (https://cutter.osdn.jp/) for C/C++ unit tests.
- Follow https://github.com/vdukhovni/postfix/commits/rpk
+ postscreen hints to smtpd to suppress the server greeting
+ after a remote SMTP client has pregreeted. This makes the
+ PIPELINING detection more meaningful.
Multi-recipient support in sender/recipient_bcc_maps and
always_bcc.
- Test for dns_rr_copy() + dns_rr_free().
-
-
mail_conf_xxx supprt for non-negative numbers (i.e.
numbers with a lower bound of zero).
diff --git a/conf/access b/conf/access
index 97892eb..6da2db2 100644
--- a/conf/access
+++ b/conf/access
@@ -59,7 +59,7 @@
# line that starts with whitespace continues a logi-
# cal line.
#
-# EMAIL ADDRESS PATTERNS
+# EMAIL ADDRESS PATTERNS IN INDEXED TABLES
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below:
@@ -97,7 +97,7 @@
# becomes: user+foo@domain, user@domain, domain, user+foo@,
# and user@.
#
-# HOST NAME/ADDRESS PATTERNS
+# HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES
# With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, the following
# lookup patterns are examined in the order as listed:
diff --git a/conf/aliases b/conf/aliases
index 8f1a284..280c3d2 100644
--- a/conf/aliases
+++ b/conf/aliases
@@ -45,25 +45,29 @@ decode: root
# newaliases
#
# DESCRIPTION
-# The aliases(5) table provides a system-wide mechanism to
-# redirect mail for local recipients. The redirections are
-# processed by the Postfix local(8) delivery agent.
+# The optional aliases(5) table (alias_maps) redirects mail
+# for local recipients. The redirections are processed by
+# the Postfix local(8) delivery agent.
+#
+# This is unlike virtual(5) aliasing (virtual_alias_maps)
+# which applies to all recipients: local(8), virtual, and
+# remote, and which is implemented by the cleanup(8) daemon.
#
# Normally, the aliases(5) table is specified as a text file
-# that serves as input to the postalias(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast lookup by the mail system. Execute the command
-# newaliases in order to rebuild the indexed file after
+# that serves as input to the postalias(1) command. The
+# result, an indexed file in dbm or db format, is used for
+# fast lookup by the mail system. Execute the command
+# newaliases in order to rebuild the indexed file after
# changing the Postfix alias database.
#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
-# Alternatively, the table can be provided as a regu-
-# lar-expression map where patterns are given as regular
-# expressions. In this case, the lookups are done in a
-# slightly different way as described below under "REGULAR
+# Alternatively, the table can be provided as a regu-
+# lar-expression map where patterns are given as regular
+# expressions. In this case, the lookups are done in a
+# slightly different way as described below under "REGULAR
# EXPRESSION TABLES".
#
# Users can control delivery of their own mail by setting up
@@ -77,61 +81,61 @@ decode: root
#
# name: value1, value2, ...
#
-# o Empty lines and whitespace-only lines are ignored,
-# as are lines whose first non-whitespace character
+# o Empty lines and whitespace-only lines are ignored,
+# as are lines whose first non-whitespace character
# is a `#'.
#
-# o A logical line starts with non-whitespace text. A
-# line that starts with whitespace continues a logi-
+# o A logical line starts with non-whitespace text. A
+# line that starts with whitespace continues a logi-
# cal line.
#
-# The name is a local address (no domain part). Use double
-# quotes when the name contains any special characters such
-# as whitespace, `#', `:', or `@'. The name is folded to
+# The name is a local address (no domain part). Use double
+# quotes when the name contains any special characters such
+# as whitespace, `#', `:', or `@'. The name is folded to
# lowercase, in order to make database lookups case insensi-
# tive.
#
-# In addition, when an alias exists for owner-name, this
-# will override the envelope sender address, so that deliv-
+# In addition, when an alias exists for owner-name, this
+# will override the envelope sender address, so that deliv-
# ery diagnostics are directed to owner-name, instead of the
-# originator of the message (for details, see
-# owner_request_special, expand_owner_alias and
-# reset_owner_alias). This is typically used to direct
-# delivery errors to the maintainer of a mailing list, who
+# originator of the message (for details, see
+# owner_request_special, expand_owner_alias and
+# reset_owner_alias). This is typically used to direct
+# delivery errors to the maintainer of a mailing list, who
# is in a better position to deal with mailing list delivery
# problems than the originator of the undelivered mail.
#
# The value contains one or more of the following:
#
# address
-# Mail is forwarded to address, which is compatible
+# Mail is forwarded to address, which is compatible
# with the RFC 822 standard.
#
# /file/name
-# Mail is appended to /file/name. For details on how
-# a file is written see the sections "EXTERNAL FILE
-# DELIVERY" and "DELIVERY RIGHTS" in the local(8)
-# documentation. Delivery is not limited to regular
-# files. For example, to dispose of unwanted mail,
+# Mail is appended to /file/name. For details on how
+# a file is written see the sections "EXTERNAL FILE
+# DELIVERY" and "DELIVERY RIGHTS" in the local(8)
+# documentation. Delivery is not limited to regular
+# files. For example, to dispose of unwanted mail,
# deflect it to /dev/null.
#
# |command
-# Mail is piped into command. Commands that contain
-# special characters, such as whitespace, should be
-# enclosed between double quotes. For details on how
-# a command is executed see "EXTERNAL COMMAND DELIV-
+# Mail is piped into command. Commands that contain
+# special characters, such as whitespace, should be
+# enclosed between double quotes. For details on how
+# a command is executed see "EXTERNAL COMMAND DELIV-
# ERY" and "DELIVERY RIGHTS" in the local(8) documen-
# tation.
#
# When the command fails, a limited amount of command
-# output is mailed back to the sender. The file
-# /usr/include/sysexits.h defines the expected exit
-# status codes. For example, use "|exit 67" to simu-
-# late a "user unknown" error, and "|exit 0" to
+# output is mailed back to the sender. The file
+# /usr/include/sysexits.h defines the expected exit
+# status codes. For example, use "|exit 67" to simu-
+# late a "user unknown" error, and "|exit 0" to
# implement an expensive black hole.
#
# :include:/file/name
-# Mail is sent to the destinations listed in the
+# Mail is sent to the destinations listed in the
# named file. Lines in :include: files have the same
# syntax as the right-hand side of alias entries.
#
@@ -143,12 +147,12 @@ decode: root
#
# ADDRESS EXTENSION
# When alias database search fails, and the recipient local-
-# part contains the optional recipient delimiter (e.g.,
-# user+foo), the search is repeated for the unextended
+# part contains the optional recipient delimiter (e.g.,
+# user+foo), the search is repeated for the unextended
# address (e.g., user).
#
-# The propagate_unmatched_extensions parameter controls
-# whether an unmatched address extension (+foo) is propa-
+# The propagate_unmatched_extensions parameter controls
+# whether an unmatched address extension (+foo) is propa-
# gated to the result of table lookup.
#
# CASE FOLDING
@@ -156,83 +160,85 @@ decode: root
# to lowercase before database lookup.
#
# REGULAR EXPRESSION TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
-# a description of regular expression lookup table syntax,
-# see regexp_table(5) or pcre_table(5). NOTE: these formats
+# a description of regular expression lookup table syntax,
+# see regexp_table(5) or pcre_table(5). NOTE: these formats
# do not use ":" at the end of a pattern.
#
-# Each regular expression is applied to the entire search
-# string. Thus, a search string user+foo is not broken up
+# Each regular expression is applied to the entire search
+# string. Thus, a search string user+foo is not broken up
# into user and foo.
#
-# Regular expressions are applied in the order as specified
-# in the table, until a regular expression is found that
+# Regular expressions are applied in the order as specified
+# in the table, until a regular expression is found that
# matches the search string.
#
-# Lookup results are the same as with indexed file lookups.
-# For security reasons there is no support for $1, $2 etc.
+# Lookup results are the same as with indexed file lookups.
+# For security reasons there is no support for $1, $2 etc.
# substring interpolation.
#
# SECURITY
-# The local(8) delivery agent disallows regular expression
-# substitution of $1 etc. in alias_maps, because that would
+# The local(8) delivery agent disallows regular expression
+# substitution of $1 etc. in alias_maps, because that would
# open a security hole.
#
-# The local(8) delivery agent will silently ignore requests
-# to use the proxymap(8) server within alias_maps. Instead
-# it will open the table directly. Before Postfix version
-# 2.2, the local(8) delivery agent will terminate with a
+# The local(8) delivery agent will silently ignore requests
+# to use the proxymap(8) server within alias_maps. Instead
+# it will open the table directly. Before Postfix version
+# 2.2, the local(8) delivery agent will terminate with a
# fatal error.
#
# CONFIGURATION PARAMETERS
-# The following main.cf parameters are especially relevant.
-# The text below provides only a parameter summary. See
+# The following main.cf parameters are especially relevant.
+# The text below provides only a parameter summary. See
# postconf(5) for more details including examples.
#
# alias_database (see 'postconf -d' output)
-# The alias databases for local(8) delivery that are
+# The alias databases for local(8) delivery that are
# updated with "newaliases" or with "sendmail -bi".
#
# alias_maps (see 'postconf -d' output)
-# The alias databases that are used for local(8)
-# delivery.
+# Optional lookup tables with aliases that apply only
+# to local(8) recipients; this is unlike vir-
+# tual_alias_maps that apply to all recipients:
+# local(8), virtual, and remote.
#
# allow_mail_to_commands (alias, forward)
-# Restrict local(8) mail delivery to external com-
+# Restrict local(8) mail delivery to external com-
# mands.
#
# allow_mail_to_files (alias, forward)
-# Restrict local(8) mail delivery to external files.
+# Restrict local(8) mail delivery to external files.
#
# expand_owner_alias (no)
# When delivering to an alias "aliasname" that has an
# "owner-aliasname" companion alias, set the envelope
-# sender address to the expansion of the
+# sender address to the expansion of the
# "owner-aliasname" alias.
#
# propagate_unmatched_extensions (canonical, virtual)
-# What address lookup tables copy an address exten-
+# What address lookup tables copy an address exten-
# sion from the lookup key to the lookup result.
#
# owner_request_special (yes)
# Enable special treatment for owner-listname entries
# in the aliases(5) file, and don't split owner-list-
-# name and listname-request address localparts when
+# name and listname-request address localparts when
# the recipient_delimiter is set to "-".
#
# recipient_delimiter (empty)
-# The set of characters that can separate an email
-# address localpart, user name, or a .forward file
+# The set of characters that can separate an email
+# address localpart, user name, or a .forward file
# name from its extension.
#
# Available in Postfix version 2.3 and later:
#
# frozen_delivered_to (yes)
-# Update the local(8) delivery agent's idea of the
-# Delivered-To: address (see prepend_deliv-
-# ered_header) only once, at the start of a delivery
-# attempt; do not update the Delivered-To: address
+# Update the local(8) delivery agent's idea of the
+# Delivered-To: address (see prepend_deliv-
+# ered_header) only once, at the start of a delivery
+# attempt; do not update the Delivered-To: address
# while expanding aliases or .forward files.
#
# STANDARDS
@@ -245,12 +251,12 @@ decode: root
# postconf(5), configuration parameters
#
# README FILES
-# Use "postconf readme_directory" or "postconf html_direc-
+# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
#
# LICENSE
-# The Secure Mailer license must be distributed with this
+# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
diff --git a/conf/canonical b/conf/canonical
index 4957fcc..894fd5b 100644
--- a/conf/canonical
+++ b/conf/canonical
@@ -225,57 +225,56 @@
# Other parameters of interest:
#
# inet_interfaces (all)
-# The network interface addresses that this mail sys-
-# tem receives mail on.
+# The local network interface addresses that this
+# mail system receives mail on.
#
# local_header_rewrite_clients (permit_inet_interfaces)
-# Rewrite message header addresses in mail from these
-# clients and update incomplete addresses with the
-# domain name in $myorigin or $mydomain; 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
-# remote_header_rewrite_domain parameter.
+# Rewrite or add message headers in mail from these
+# clients, updating incomplete addresses with the
+# domain name in $myorigin or $mydomain, and adding
+# missing headers.
#
# proxy_interfaces (empty)
-# The network interface addresses that this mail sys-
-# tem receives mail on by way of a proxy or network
-# address translation unit.
+# The remote network interface addresses that this
+# mail system receives mail on by way of a proxy or
+# network address translation unit.
#
-# masquerade_classes (envelope_sender, header_sender,
+# masquerade_classes (envelope_sender, header_sender,
# header_recipient)
# What addresses are subject to address masquerading.
#
# masquerade_domains (empty)
-# Optional list of domains whose subdomain structure
+# Optional list of domains whose subdomain structure
# will be stripped off in email addresses.
#
# masquerade_exceptions (empty)
-# Optional list of user names that are not subjected
-# to address masquerading, even when their addresses
+# Optional list of user names that are not subjected
+# to address masquerading, even when their addresses
# match $masquerade_domains.
#
# mydestination ($myhostname, localhost.$mydomain, local-
# host)
-# The list of domains that are delivered via the
+# The list of domains that are delivered via the
# $local_transport mail delivery transport.
#
# myorigin ($myhostname)
# 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.
#
# owner_request_special (yes)
# Enable special treatment for owner-listname entries
# in the aliases(5) file, and don't split owner-list-
-# name and listname-request address localparts when
+# name and listname-request address localparts when
# the recipient_delimiter is set to "-".
#
# remote_header_rewrite_domain (empty)
-# Don't rewrite message headers from remote clients
-# at all when this parameter is empty; otherwise, re-
-# write message headers and append the specified
-# domain name to incomplete addresses.
+# Rewrite or add message headers in mail from remote
+# clients if the remote_header_rewrite_domain parame-
+# ter value is non-empty, updating incomplete
+# addresses with the domain specified in the
+# remote_header_rewrite_domain parameter, and adding
+# missing headers.
#
# SEE ALSO
# cleanup(8), canonicalize and enqueue mail
@@ -284,13 +283,13 @@
# virtual(5), virtual aliasing
#
# README FILES
-# Use "postconf readme_directory" or "postconf html_direc-
+# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
# ADDRESS_REWRITING_README, address rewriting guide
#
# LICENSE
-# The Secure Mailer license must be distributed with this
+# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
diff --git a/conf/dynamicmaps.cf b/conf/dynamicmaps.cf
index 5179f66..feeb6a1 100644
--- a/conf/dynamicmaps.cf
+++ b/conf/dynamicmaps.cf
@@ -2,6 +2,7 @@
cdb ${LIB_PREFIX}cdb${LIB_SUFFIX} dict_cdb_open mkmap_cdb_open
ldap ${LIB_PREFIX}ldap${LIB_SUFFIX} dict_ldap_open
lmdb ${LIB_PREFIX}lmdb${LIB_SUFFIX} dict_lmdb_open mkmap_lmdb_open
+mongodb ${LIB_PREFIX}mongodb${LIB_SUFFIX} dict_mongodb_open
mysql ${LIB_PREFIX}mysql${LIB_SUFFIX} dict_mysql_open
pcre ${LIB_PREFIX}pcre${LIB_SUFFIX} dict_pcre_open
pgsql ${LIB_PREFIX}pgsql${LIB_SUFFIX} dict_pgsql_open
diff --git a/conf/generic b/conf/generic
index f371eb9..508e44a 100644
--- a/conf/generic
+++ b/conf/generic
@@ -193,13 +193,13 @@
# Other parameters of interest:
#
# inet_interfaces (all)
-# The network interface addresses that this mail sys-
-# tem receives mail on.
+# The local network interface addresses that this
+# mail system receives mail on.
#
# proxy_interfaces (empty)
-# The network interface addresses that this mail sys-
-# tem receives mail on by way of a proxy or network
-# address translation unit.
+# The remote network interface addresses that this
+# mail system receives mail on by way of a proxy or
+# network address translation unit.
#
# mydestination ($myhostname, localhost.$mydomain, local-
# host)
diff --git a/conf/header_checks b/conf/header_checks
index bcd96a9..db295d0 100644
--- a/conf/header_checks
+++ b/conf/header_checks
@@ -440,46 +440,32 @@
# tent-Length:, Return-Path:.
#
# CONFIGURATION PARAMETERS
-# body_checks
-# Lookup tables with content filter rules for message
-# body lines. These filters see one physical line at
-# a time, in chunks of at most $line_length_limit
-# bytes.
-#
-# body_checks_size_limit
-# The amount of content per message body segment
-# (attachment) that is subjected to $body_checks fil-
-# tering.
-#
-# header_checks
-#
-# mime_header_checks (default: $header_checks)
-#
-# nested_header_checks (default: $header_checks)
-# Lookup tables with content filter rules for message
-# header lines: respectively, these are applied to
-# the initial message headers (not including MIME
-# headers), to the MIME headers anywhere in the mes-
-# sage, and to the initial headers of attached mes-
-# sages.
-#
-# Note: these filters see one logical message header
-# at a time, even when a message header spans multi-
-# ple lines. Message headers that are longer than
-# $header_size_limit characters are truncated.
-#
-# disable_mime_input_processing
-# While receiving mail, give no special treatment to
-# MIME related message headers; all text after the
-# initial message headers is considered to be part of
-# the message body. This means that header_checks is
-# applied to all the initial message headers, and
-# that body_checks is applied to the remainder of the
-# message.
-#
-# Note: when used in this manner, body_checks will
-# process a multi-line message header one line at a
-# time.
+# body_checks (empty)
+# Optional lookup tables for content inspection as
+# specified in the body_checks(5) manual page.
+#
+# body_checks_size_limit (51200)
+# How much text in a message body segment (or attach-
+# ment, if you prefer to use that term) is subjected
+# to body_checks inspection.
+#
+# header_checks (empty)
+# Optional lookup tables for content inspection of
+# primary non-MIME message headers, as specified in
+# the header_checks(5) manual page.
+#
+# mime_header_checks ($header_checks)
+# Optional lookup tables for content inspection of
+# MIME related message headers, as described in the
+# header_checks(5) manual page.
+#
+# nested_header_checks ($header_checks)
+# Optional lookup tables for content inspection of
+# non-MIME message headers in attached messages, as
+# described in the header_checks(5) manual page.
+#
+# disable_mime_input_processing (no)
+# Turn off MIME processing while receiving mail.
#
# EXAMPLES
# Header pattern to block attachments with bad file name
diff --git a/conf/main.cf b/conf/main.cf
index 2ee7996..2f4eba9 100644
--- a/conf/main.cf
+++ b/conf/main.cf
@@ -31,7 +31,7 @@
#
# The level below is what should be used with new (not upgrade) installs.
#
-compatibility_level = 3.8
+compatibility_level = 3.9
# SOFT BOUNCE
#
@@ -452,7 +452,7 @@ unknown_local_recipient_reject_code = 550
# The mailbox_command parameter specifies the optional external
# command to use instead of mailbox delivery. The command is run as
# the recipient with proper HOME, SHELL and LOGNAME environment settings.
-# Exception: delivery for root is done as $default_user.
+# Exception: delivery for root is done as $default_privs.
#
# Other environment variables of interest: USER (recipient username),
# EXTENSION (address extension), DOMAIN (domain part of address),
diff --git a/conf/post-install b/conf/post-install
index 2a7d99b..ed7c79a 100644
--- a/conf/post-install
+++ b/conf/post-install
@@ -205,6 +205,10 @@
# Google, Inc.
# 111 8th Avenue
# New York, NY 10011, USA
+#
+# Wietse Venema
+# porcupine.org
+# Amawalk, NY 10501, USA
#--
umask 022
@@ -291,7 +295,7 @@ test -d "$config_directory" || {
# XXX Solaris does not have "test -e".
instances=`test ! -f $def_config_directory/main.cf ||
- $POSTCONF -c $def_config_directory -h multi_instance_directories |
+ $POSTCONF -qc $def_config_directory -h multi_instance_directories |
sed 's/,/ /'` || exit 1
update_shared_files=1
@@ -360,7 +364,7 @@ test -f $config_directory/main.cf && {
case "$junk" in
"") eval unset $name;;
esac
- eval : \${$name=\`$POSTCONF -c $config_directory -h $name\`} || exit 1
+ eval : \${$name=\`$POSTCONF -qc $config_directory -h $name\`} || exit 1
done
}
@@ -461,14 +465,14 @@ override=
for name in $MOST_PARAMETERS
do
eval junk=\"\$$name\"
- test "$junk" = "`$POSTCONF -c $config_directory -h $name`" || {
+ test "$junk" = "`$POSTCONF -qc $config_directory -h $name`" || {
override=1
break
}
done
test -n "$override" && {
- $POSTCONF -c $config_directory -e \
+ $POSTCONF -qc $config_directory -e \
"daemon_directory = $daemon_directory" \
"command_directory = $command_directory" \
"queue_directory = $queue_directory" \
@@ -679,13 +683,13 @@ EOF
# require now is that defer and deferred are hashed because those
# can contain lots of files.
- found=`$POSTCONF -c $config_directory -h hash_queue_names`
+ found=`$POSTCONF -qc $config_directory -h hash_queue_names`
missing=
(echo "$found" | grep defer >/dev/null) || missing="$missing defer"
(echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
test -n "$missing" && {
echo fixing main.cf hash_queue_names for missing $missing
- $POSTCONF -c $config_directory -e hash_queue_names="$found$missing" ||
+ $POSTCONF -qc $config_directory -e hash_queue_names="$found$missing" ||
exit 1
}
@@ -857,14 +861,14 @@ EOF
# when IPv6 support is not compiled in. See util/sys_defs.h.
test "`$POSTCONF -dh inet_protocols`" = "ipv4" ||
- test -n "`$POSTCONF -c $config_directory -n inet_protocols`" || {
+ test -n "`$POSTCONF -qc $config_directory -n inet_protocols`" || {
cat <<EOF | ${FMT}
COMPATIBILITY: editing $config_directory/main.cf, setting
inet_protocols=ipv4. Specify inet_protocols explicitly if you
want to enable IPv6.
In a future release IPv6 will be enabled by default.
EOF
- $POSTCONF -c $config_directory inet_protocols=ipv4 || exit 1
+ $POSTCONF -qc $config_directory inet_protocols=ipv4 || exit 1
}
# Disabled because unhelpful down-stream maintainers disable the safety net.
@@ -875,7 +879,7 @@ EOF
# # PLEASE DO NOT REMOVE THIS CODE. ITS PURPOSE IS TO PREVENT
# # INBOUND MAIL FROM UNEXPECTEDLY BOUNCING AFTER UPGRADING FROM
# # POSTFIX BEFORE 2.10.
-# test -n "`$POSTCONF -c $config_directory -n smtpd_relay_restrictions`" || {
+# test -n "`$POSTCONF -qc $config_directory -n smtpd_relay_restrictions`" || {
# cat <<EOF | ${FMT}
# COMPATIBILITY: editing $config_directory/main.cf, overriding
# smtpd_relay_restrictions to prevent inbound mail from
@@ -883,7 +887,7 @@ EOF
# Specify an empty smtpd_relay_restrictions value to keep using
# smtpd_recipient_restrictions as before.
#EOF
-# $POSTCONF -c $config_directory "smtpd_relay_restrictions = \
+# $POSTCONF -qc $config_directory "smtpd_relay_restrictions = \
# permit_mynetworks permit_sasl_authenticated \
# defer_unauth_destination" || exit 1
# }
@@ -903,8 +907,8 @@ EOF
test -n "$first_install_reminder" && {
- ALIASES=`$POSTCONF -c $config_directory -h alias_database | sed 's/^[^:]*://'`
- NEWALIASES_PATH=`$POSTCONF -c $config_directory -h newaliases_path`
+ ALIASES=`$POSTCONF -qc $config_directory -h alias_database | sed 's/^[^:]*://'`
+ NEWALIASES_PATH=`$POSTCONF -qc $config_directory -h newaliases_path`
cat <<EOF | ${FMT}
Warning: you still need to edit myorigin/mydestination/mynetworks
diff --git a/conf/postfix-files b/conf/postfix-files
index 12a7ccb..5a93982 100644
--- a/conf/postfix-files
+++ b/conf/postfix-files
@@ -75,6 +75,7 @@ $shlib_directory/lib${LIB_PREFIX}master${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}cdb${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}ldap${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}lmdb${LIB_SUFFIX}:f:root:-:755
+$shlib_directory/${LIB_PREFIX}mongodb${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}mysql${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}pcre${LIB_SUFFIX}:f:root:-:755
$shlib_directory/${LIB_PREFIX}pgsql${LIB_SUFFIX}:f:root:-:755
@@ -194,6 +195,7 @@ $manpage_directory/man5/ldap_table.5:f:root:-:644
$manpage_directory/man5/lmdb_table.5:f:root:-:644
$manpage_directory/man5/master.5:f:root:-:644
$manpage_directory/man5/memcache_table.5:f:root:-:644
+$manpage_directory/man5/mongodb_table.5:f:root:-:644
$manpage_directory/man5/mysql_table.5:f:root:-:644
$manpage_directory/man5/socketmap_table.5:f:root:-:644
$manpage_directory/man5/sqlite_table.5:f:root:-:644
@@ -285,6 +287,7 @@ $readme_directory/CONTENT_INSPECTION_README:f:root:-:644
$readme_directory/DATABASE_README:f:root:-:644
$readme_directory/DB_README:f:root:-:644
$readme_directory/DEBUG_README:f:root:-:644
+$readme_directory/DEPRECATION_README:f:root:-:644
$readme_directory/DSN_README:f:root:-:644
$readme_directory/ETRN_README:f:root:-:644
$readme_directory/FILTER_README:f:root:-:644
@@ -301,6 +304,7 @@ $readme_directory/MAILDROP_README:f:root:-:644
$readme_directory/MAILLOG_README:f:root:-:644
$readme_directory/MEMCACHE_README:f:root:-:644
$readme_directory/MILTER_README:f:root:-:644
+$readme_directory/MONGODB_README:f:root:-:644
$readme_directory/MULTI_INSTANCE_README:f:root:-:644
$readme_directory/MYSQL_README:f:root:-:644
$readme_directory/SMTPUTF8_README:f:root:-:644
@@ -348,6 +352,7 @@ $html_directory/CYRUS_README.html:f:root:-:644:o
$html_directory/DATABASE_README.html:f:root:-:644
$html_directory/DB_README.html:f:root:-:644
$html_directory/DEBUG_README.html:f:root:-:644
+$html_directory/DEPRECATION_README.html:f:root:-:644
$html_directory/DSN_README.html:f:root:-:644
$html_directory/ETRN_README.html:f:root:-:644
$html_directory/FILTER_README.html:f:root:-:644
@@ -362,6 +367,7 @@ $html_directory/MAILDROP_README.html:f:root:-:644
$html_directory/MAILLOG_README.html:f:root:-:644
$html_directory/MEMCACHE_README.html:f:root:-:644
$html_directory/MILTER_README.html:f:root:-:644
+$html_directory/MONGODB_README.html:f:root:-:644
$html_directory/MULTI_INSTANCE_README.html:f:root:-:644
$html_directory/MYSQL_README.html:f:root:-:644
$html_directory/SMTPUTF8_README.html:f:root:-:644
@@ -418,6 +424,7 @@ $html_directory/mailq.1.html:f:root:-:644
$html_directory/master.5.html:f:root:-:644
$html_directory/master.8.html:f:root:-:644
$html_directory/memcache_table.5.html:f:root:-:644
+$html_directory/mongodb_table.5.html:f:root:-:644
$html_directory/mysql_table.5.html:f:root:-:644
$html_directory/sqlite_table.5.html:f:root:-:644
$html_directory/nisplus_table.5.html:f:root:-:644
diff --git a/conf/postfix-script b/conf/postfix-script
index da98375..c43d764 100755
--- a/conf/postfix-script
+++ b/conf/postfix-script
@@ -28,6 +28,10 @@
# Google, Inc.
# 111 8th Avenue
# New York, NY 10011, USA
+#
+# Wietse Venema
+# porcupine.org
+# Amawalk, NY 10501, USA
#--
# Avoid POSIX death due to SIGHUP when some parent process exits.
@@ -92,7 +96,7 @@ def_config_directory=`$command_directory/postconf -dh config_directory` || {
# If this is a secondary instance, don't touch shared files.
instances=`test ! -f $def_config_directory/main.cf ||
- $command_directory/postconf -c $def_config_directory \
+ $command_directory/postconf -qc $def_config_directory \
-h multi_instance_directories | sed 's/,/ /'` || {
$FATAL cannot execute $command_directory/postconf!
exit 1
@@ -216,6 +220,9 @@ abort)
reload)
+ # Warn once for deprecated parameters.
+ $command_directory/postconf >/dev/null
+
$daemon_directory/master -t 2>/dev/null && {
$FATAL the Postfix mail system is not running
exit 1
@@ -244,6 +251,9 @@ check)
status)
+ # Warn once for deprecated parameters.
+ $command_directory/postconf >/dev/null
+
$daemon_directory/master -t 2>/dev/null && {
$INFO the Postfix mail system is not running
exit 1
@@ -268,12 +278,12 @@ check-fatal)
exit 1
}
- maillog_file=`$command_directory/postconf -h maillog_file` || {
+ maillog_file=`$command_directory/postconf -qh maillog_file` || {
$FATAL cannot execute $command_directory/postconf!
exit 1
}
test -n "$maillog_file" && {
- $command_directory/postconf -M postlog/unix-dgram 2>/dev/null \
+ $command_directory/postconf -qM postlog/unix-dgram 2>/dev/null \
| grep . >/dev/null || {
$FATAL "missing 'postlog' service in master.cf - run 'postfix upgrade-configuration'"
exit 1
@@ -291,6 +301,9 @@ check-fatal)
check-warn)
# This command is NOT part of the public interface.
+ # Warn once for deprecated parameters.
+ $command_directory/postconf >/dev/null
+
# Check Postfix root-owned directory owner/permissions.
find $queue_directory/. $queue_directory/pid \
@@ -413,7 +426,7 @@ logrotate)
for name in maillog_file maillog_file_compressor \
maillog_file_rotate_suffix
do
- value="`$command_directory/postconf -h $name`"
+ value="`$command_directory/postconf -qh $name`"
case "$value" in
"") $FATAL "empty '$name' parameter value - logfile rotation failed"
exit 1;;
diff --git a/conf/relocated b/conf/relocated
index 90f63ec..5c43266 100644
--- a/conf/relocated
+++ b/conf/relocated
@@ -131,8 +131,8 @@
# Other parameters of interest:
#
# inet_interfaces (all)
-# The network interface addresses that this mail sys-
-# tem receives mail on.
+# The local network interface addresses that this
+# mail system receives mail on.
#
# mydestination ($myhostname, localhost.$mydomain, local-
# host)
@@ -145,9 +145,9 @@
# ered to.
#
# proxy_interfaces (empty)
-# The network interface addresses that this mail sys-
-# tem receives mail on by way of a proxy or network
-# address translation unit.
+# The remote network interface addresses that this
+# mail system receives mail on by way of a proxy or
+# network address translation unit.
#
# SEE ALSO
# trivial-rewrite(8), address resolver
diff --git a/conf/virtual b/conf/virtual
index e99eee4..8200ca4 100644
--- a/conf/virtual
+++ b/conf/virtual
@@ -11,98 +11,99 @@
# postmap -q - /etc/postfix/virtual <inputfile
#
# DESCRIPTION
-# The optional virtual(5) alias table rewrites recipient
-# addresses for all local, all virtual, and all remote mail
-# destinations. This is unlike the aliases(5) table which
-# is used only for local(8) delivery. This feature is imple-
-# mented in the Postfix cleanup(8) daemon before mail is
-# queued.
-#
-# Virtual aliasing is recursive; to terminate recursion for
+# The optional virtual(5) alias table (virtual_alias_maps)
+# applies to all recipients: local(8), virtual, and remote.
+# This feature is implemented in the Postfix cleanup(8) dae-
+# mon before mail is queued.
+#
+# This is unlike the aliases(5) table (alias_maps) which
+# applies only to local(8) recipients.
+#
+# Virtual aliasing is recursive; to terminate recursion for
# a specific address, alias that address to itself.
#
# The main applications of virtual aliasing are:
#
-# o To redirect mail for one address to one or more
+# o To redirect mail for one address to one or more
# addresses.
#
-# o To implement virtual alias domains where all
-# addresses are aliased to addresses in other
+# o To implement virtual alias domains where all
+# addresses are aliased to addresses in other
# domains.
#
-# Virtual alias domains are not to be confused with
-# the virtual mailbox domains that are implemented
-# with the Postfix virtual(8) mail delivery agent.
-# With virtual mailbox domains, each recipient
+# Virtual alias domains are not to be confused with
+# the virtual mailbox domains that are implemented
+# with the Postfix virtual(8) mail delivery agent.
+# With virtual mailbox domains, each recipient
# address can have its own mailbox.
#
-# Virtual aliasing is applied only to recipient envelope
-# addresses, and does not affect message headers. Use
-# canonical(5) mapping to rewrite header and envelope
+# Virtual aliasing is applied only to recipient envelope
+# addresses, and does not affect message headers. Use
+# canonical(5) mapping to rewrite header and envelope
# addresses in general.
#
-# Normally, the virtual(5) alias table is specified as a
-# text file that serves as input to the postmap(1) command.
-# The result, an indexed file in dbm or db format, is used
+# Normally, the virtual(5) alias table is specified as a
+# text file that serves as input to the postmap(1) command.
+# The result, an indexed file in dbm or db format, is used
# for fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/virtual" to rebuild an indexed file
+# "postmap /etc/postfix/virtual" to rebuild an indexed file
# after changing the corresponding text file.
#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
# indexed files.
#
-# Alternatively, the table can be provided as a regu-
-# lar-expression map where patterns are given as regular
-# expressions, or lookups can be directed to a TCP-based
-# server. In those case, the lookups are done in a slightly
+# Alternatively, the table can be provided as a regu-
+# lar-expression map where patterns are given as regular
+# expressions, or lookups can be directed to a TCP-based
+# server. In those case, the lookups are done in a slightly
# different way as described below under "REGULAR EXPRESSION
# TABLES" or "TCP-BASED TABLES".
#
# CASE FOLDING
-# The search string is folded to lowercase before database
-# lookup. As of Postfix 2.3, the search string is not case
-# folded with database types such as regexp: or pcre: whose
+# The search string is folded to lowercase before database
+# lookup. As of Postfix 2.3, the search string is not case
+# folded with database types such as regexp: or pcre: whose
# lookup fields can match both upper and lower case.
#
# TABLE FORMAT
# The input format for the postmap(1) command is as follows:
#
# pattern address, address, ...
-# When pattern matches a mail address, replace it by
+# When pattern matches a mail address, replace it by
# the corresponding address.
#
# blank lines and comments
-# Empty lines and whitespace-only lines are ignored,
-# as are lines whose first non-whitespace character
+# Empty lines and whitespace-only lines are ignored,
+# as are lines whose first non-whitespace character
# is a `#'.
#
# multi-line text
-# A logical line starts with non-whitespace text. A
-# line that starts with whitespace continues a logi-
+# A logical line starts with non-whitespace text. A
+# line that starts with whitespace continues a logi-
# cal line.
#
# TABLE SEARCH ORDER
# With lookups from indexed files such as DB or DBM, or from
-# networked tables such as NIS, LDAP or SQL, each
+# networked tables such as NIS, LDAP or SQL, each
# user@domain query produces a sequence of query patterns as
# described below.
#
-# Each query pattern is sent to each specified lookup table
-# before trying the next query pattern, until a match is
+# Each query pattern is sent to each specified lookup table
+# before trying the next query pattern, until a match is
# found.
#
# user@domain address, address, ...
-# Redirect mail for user@domain to address. This
+# Redirect mail for user@domain to address. This
# form has the highest precedence.
#
# user address, address, ...
# Redirect mail for user@site to address when site is
-# equal to $myorigin, when site is listed in $mydes-
-# tination, or when it is listed in $inet_interfaces
+# equal to $myorigin, when site is listed in $mydes-
+# tination, or when it is listed in $inet_interfaces
# or $proxy_interfaces.
#
-# This functionality overlaps with the functionality
+# This functionality overlaps with the functionality
# of the local aliases(5) database. The difference is
# that virtual(5) mapping can be applied to non-local
# addresses.
@@ -111,18 +112,18 @@
# Redirect mail for other users in domain to address.
# This form has the lowest precedence.
#
-# Note: @domain is a wild-card. With this form, the
-# Postfix SMTP server accepts mail for any recipient
-# in domain, regardless of whether that recipient
-# exists. This may turn your mail system into a
-# backscatter source: Postfix first accepts mail for
-# non-existent recipients and then tries to return
-# that mail as "undeliverable" to the often forged
+# Note: @domain is a wild-card. With this form, the
+# Postfix SMTP server accepts mail for any recipient
+# in domain, regardless of whether that recipient
+# exists. This may turn your mail system into a
+# backscatter source: Postfix first accepts mail for
+# non-existent recipients and then tries to return
+# that mail as "undeliverable" to the often forged
# sender address.
#
-# To avoid backscatter with mail for a wild-card
+# To avoid backscatter with mail for a wild-card
# domain, replace the wild-card mapping with explicit
-# 1:1 mappings, or add a reject_unverified_recipient
+# 1:1 mappings, or add a reject_unverified_recipient
# restriction for that domain:
#
# smtpd_recipient_restrictions =
@@ -132,19 +133,19 @@
# inline:{example.com=reject_unverified_recipient}
# unverified_recipient_reject_code = 550
#
-# In the above example, Postfix may contact a remote
-# server if the recipient is aliased to a remote
+# In the above example, Postfix may contact a remote
+# server if the recipient is aliased to a remote
# address.
#
# RESULT ADDRESS REWRITING
# The lookup result is subject to address rewriting:
#
-# o When the result has the form @otherdomain, the
-# result becomes the same user in otherdomain. This
+# o When the result has the form @otherdomain, the
+# result becomes the same user in otherdomain. This
# works only for the first address in a multi-address
# lookup result.
#
-# o When "append_at_myorigin=yes", append "@$myorigin"
+# o When "append_at_myorigin=yes", append "@$myorigin"
# to addresses without "@domain".
#
# o When "append_dot_mydomain=yes", append ".$mydomain"
@@ -152,29 +153,29 @@
#
# ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
-# ient delimiter (e.g., user+foo@domain), the lookup order
+# ient delimiter (e.g., user+foo@domain), the lookup order
# becomes: user+foo@domain, user@domain, user+foo, user, and
# @domain.
#
-# The propagate_unmatched_extensions parameter controls
-# whether an unmatched address extension (+foo) is propa-
+# The propagate_unmatched_extensions parameter controls
+# whether an unmatched address extension (+foo) is propa-
# gated to the result of a table lookup.
#
# VIRTUAL ALIAS DOMAINS
-# Besides virtual aliases, the virtual alias table can also
+# Besides virtual aliases, the virtual alias table can also
# be used to implement virtual alias domains. With a virtual
-# alias domain, all recipient addresses are aliased to
+# alias domain, all recipient addresses are aliased to
# addresses in other domains.
#
# Virtual alias domains are not to be confused with the vir-
# tual mailbox domains that are implemented with the Postfix
# virtual(8) mail delivery agent. With virtual mailbox
-# domains, each recipient address can have its own mailbox.
+# domains, each recipient address can have its own mailbox.
#
-# With a virtual alias domain, the virtual domain has its
-# own user name space. Local (i.e. non-virtual) usernames
-# are not visible in a virtual alias domain. In particular,
-# local aliases(5) and local mailing lists are not visible
+# With a virtual alias domain, the virtual domain has its
+# own user name space. Local (i.e. non-virtual) usernames
+# are not visible in a virtual alias domain. In particular,
+# local aliases(5) and local mailing lists are not visible
# as localname@virtual-alias.domain.
#
# Support for a virtual alias domain looks like:
@@ -183,7 +184,7 @@
# virtual_alias_maps = hash:/etc/postfix/virtual
#
# Note: some systems use dbm databases instead of hash. See
-# the output from "postconf -m" for available database
+# the output from "postconf -m" for available database
# types.
#
# /etc/postfix/virtual:
@@ -192,72 +193,73 @@
# user1@virtual-alias.domain address1
# user2@virtual-alias.domain address2, address3
#
-# The virtual-alias.domain anything entry is required for a
+# The virtual-alias.domain anything entry is required for a
# virtual alias domain. Without this entry, mail is rejected
-# with "relay access denied", or bounces with "mail loops
+# with "relay access denied", or bounces with "mail loops
# back to myself".
#
-# Do not specify virtual alias domain names in the main.cf
+# Do not specify virtual alias domain names in the main.cf
# mydestination or relay_domains configuration parameters.
#
-# With a virtual alias domain, the Postfix SMTP server
-# accepts mail for known-user@virtual-alias.domain, and
-# rejects mail for unknown-user@virtual-alias.domain as
+# With a virtual alias domain, the Postfix SMTP server
+# accepts mail for known-user@virtual-alias.domain, and
+# rejects mail for unknown-user@virtual-alias.domain as
# undeliverable.
#
-# Instead of specifying the virtual alias domain name via
-# the virtual_alias_maps table, you may also specify it via
+# Instead of specifying the virtual alias domain name via
+# the virtual_alias_maps table, you may also specify it via
# the main.cf virtual_alias_domains configuration parameter.
-# This latter parameter uses the same syntax as the main.cf
+# This latter parameter uses the same syntax as the main.cf
# mydestination configuration parameter.
#
# REGULAR EXPRESSION TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
-# a description of regular expression lookup table syntax,
+# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
-# Each pattern is a regular expression that is applied to
+# Each pattern is a regular expression that is applied to
# the entire address being looked up. Thus, user@domain mail
-# addresses are not broken up into their user and @domain
+# addresses are not broken up into their user and @domain
# constituent parts, nor is user+foo broken up into user and
# foo.
#
-# Patterns are applied in the order as specified in the ta-
-# ble, until a pattern is found that matches the search
+# Patterns are applied in the order as specified in the ta-
+# ble, until a pattern is found that matches the search
# string.
#
-# Results are the same as with indexed file lookups, with
-# the additional feature that parenthesized substrings from
+# Results are the same as with indexed file lookups, with
+# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# TCP-BASED TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# lookups are directed to a TCP-based server. For a descrip-
# tion of the TCP client/server lookup protocol, see tcp_ta-
-# ble(5). This feature is available in Postfix 2.5 and
+# ble(5). This feature is available in Postfix 2.5 and
# later.
#
# Each lookup operation uses the entire address once. Thus,
-# user@domain mail addresses are not broken up into their
+# user@domain mail addresses are not broken up into their
# user and @domain constituent parts, nor is user+foo broken
# up into user and foo.
#
# Results are the same as with indexed file lookups.
#
# BUGS
-# The table format does not understand quoting conventions.
+# The table format does not understand quoting conventions.
#
# CONFIGURATION PARAMETERS
-# The following main.cf parameters are especially relevant
-# to this topic. See the Postfix main.cf file for syntax
-# details and for default values. Use the "postfix reload"
+# The following main.cf parameters are especially relevant
+# to this topic. See the Postfix main.cf file for syntax
+# details and for default values. Use the "postfix reload"
# command after a configuration change.
#
# virtual_alias_maps ($virtual_maps)
-# Optional lookup tables that alias specific mail
-# addresses or domains to other local or remote
-# addresses.
+# Optional lookup tables with aliases that apply to
+# all recipients: local(8), virtual, and remote; this
+# is unlike alias_maps that apply only to local(8)
+# recipients.
#
# virtual_alias_domains ($virtual_alias_maps)
# Postfix is the final destination for the specified
@@ -272,8 +274,8 @@
# Other parameters of interest:
#
# inet_interfaces (all)
-# The network interface addresses that this mail sys-
-# tem receives mail on.
+# The local network interface addresses that this
+# mail system receives mail on.
#
# mydestination ($myhostname, localhost.$mydomain, local-
# host)
@@ -292,9 +294,9 @@
# the recipient_delimiter is set to "-".
#
# proxy_interfaces (empty)
-# The network interface addresses that this mail sys-
-# tem receives mail on by way of a proxy or network
-# address translation unit.
+# The remote network interface addresses that this
+# mail system receives mail on by way of a proxy or
+# network address translation unit.
#
# SEE ALSO
# cleanup(8), canonicalize and enqueue mail
diff --git a/html/ADDRESS_CLASS_README.html b/html/ADDRESS_CLASS_README.html
index ec46627..179d13d 100644
--- a/html/ADDRESS_CLASS_README.html
+++ b/html/ADDRESS_CLASS_README.html
@@ -52,20 +52,25 @@ address classes are very important for the operation of Postfix. </p>
<ul>
<li> <p> The list of domains that are a member of that address
-class: for example, all <a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a>, or all <a href="ADDRESS_CLASS_README.html#relay_domain_class">relay domains</a>. </p>
+class. </p>
+
+<p> Examples: all <a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a>, or all <a href="ADDRESS_CLASS_README.html#relay_domain_class">relay domains</a>. </p>
+
+<li> <p> The default delivery transport for domains in that address
+class. </p>
+
+<p> Examples: <a href="postconf.5.html#local_transport">local_transport</a> or <a href="postconf.5.html#relay_transport">relay_transport</a> (these point
+to services defined in <a href="master.5.html">master.cf</a>). </p>
-<li> <p> The default delivery transport for that address class. For
-example, the local,
-virtual or relay delivery transport (delivery transports are defined
-in <a href="master.5.html">master.cf</a>). This helps to keep Postfix configurations simple,
-by avoiding the need for explicit routing information in transport
-maps. </p>
+<p> Benefit: this avoids the need for explicit routing information
+in transport maps. </p>
<li> <p> The list of valid recipient addresses for that address
-class. The Postfix SMTP server rejects invalid recipients with
-"User unknown in &lt;name of address class here&gt; table". This
-helps to keep the Postfix queue free of undeliverable MAILER-DAEMON
-messages. </p>
+class. </p>
+
+<p> Benefit: the Postfix SMTP server rejects an invalid recipient
+with "User unknown in &lt;name of address class&gt; table", and
+avoids sending a MAILER-DAEMON message with backscatter spam. </p>
</ul>
@@ -92,12 +97,12 @@ This domain class also includes mail for <i>user@[ipaddress]</i>
when the IP address is listed with the <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> parameters. </p>
-<li> <p> Valid recipient addresses are listed with the <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>
-parameter, as described in <a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a>. The Postfix SMTP
-server rejects invalid recipients with "User unknown in local
-recipient table". If the <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> parameter value is
-empty, then the Postfix SMTP server accepts any address in the
-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domain</a> class. </p>
+<li> <p> Valid recipient addresses for those domains are
+listed with the <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> parameter, as described in
+<a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a>. The Postfix SMTP server rejects invalid recipients
+with "User unknown in local recipient table". If the <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>
+parameter value is empty, then the Postfix SMTP server accepts any
+address in the <a href="ADDRESS_CLASS_README.html#local_domain_class">local domain</a> class. </p>
<li> <p> The mail delivery transport is specified with the
<a href="postconf.5.html#local_transport">local_transport</a> parameter. The default value is <b><a href="local.8.html">local</a>:$<a href="postconf.5.html#myhostname">myhostname</a></b>
@@ -111,21 +116,25 @@ class. </p>
<ul>
<li> <p> Purpose: <a href="VIRTUAL_README.html#canonical">hosted domains</a> where each recipient address is
-aliased to an address in a different domain, for example, a local
-UNIX system account or a remote address. A
+aliased to an address in a different domain class, for example, a
+local UNIX system account or a remote address. A
<a href="VIRTUAL_README.html#virtual_alias">virtual alias example</a> is given in the <a href="VIRTUAL_README.html">VIRTUAL_README</a> file. </p>
<li> <p> Domain names are listed in <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>. The
default value is $<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> for Postfix 1.1 compatibility.
</p>
-<li> <p> Valid recipient addresses are listed with the <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>
-parameter. The Postfix SMTP server rejects invalid recipients with
-"User unknown in virtual alias table". The default value is
-$<a href="postconf.5.html#virtual_maps">virtual_maps</a> for Postfix 1.1 compatibility. </p>
+<li> <p> Valid recipient addresses for those domains are listed with the
+<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> parameter. The Postfix SMTP server rejects invalid
+recipients with "User unknown in virtual alias table". The default
+value is $<a href="postconf.5.html#virtual_maps">virtual_maps</a> for Postfix 1.1 compatibility. </p>
-<li> <p> There is no mail delivery transport parameter. Every
-address must be aliased to an address in some other domain. </p>
+<blockquote ><p> Note: for historical reasons, <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>
+apply to recipients in all domain classes, not only the virtual
+alias domain class. </p> </blockquote>
+
+<li> <p> There is no configurable mail delivery transport. Every
+address must be aliased to an address in some other domain class. </p>
</ul>
@@ -136,18 +145,19 @@ class. </p>
<li> <p> Purpose: final delivery for <a href="VIRTUAL_README.html#canonical">hosted domains</a> where each
recipient address can have its own mailbox, and where users do not
-need to have a UNIX system account. A <a href="VIRTUAL_README.html#virtual_mailbox">virtual mailbox example</a> is
+need to have a UNIX system account. A <a href="VIRTUAL_README.html#virtual_mailbox">virtual mailbox example</a> is
given in the <a href="VIRTUAL_README.html">VIRTUAL_README</a> file. </p>
<li> <p> Domain names are listed with the <a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>
parameter. The default value is $<a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> for Postfix
1.1 compatibility. </p>
-<li> <p> Valid recipient addresses are listed with the <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a>
-parameter. The Postfix SMTP server rejects invalid recipients with
-"User unknown in virtual mailbox table". If this parameter value
-is empty, the Postfix SMTP server accepts all recipients for domains
-listed in $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>. </p>
+<li> <p> Valid recipient addresses for those domains are listed
+with the <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> parameter. The Postfix SMTP server
+rejects invalid recipients with "User unknown in virtual mailbox
+table". If this parameter value is empty, the Postfix SMTP server
+accepts all recipients for domains listed in $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
+</p>
<li> <p> The mail delivery transport is specified with the
<a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter. The default value is <b>virtual</b>
@@ -169,11 +179,12 @@ file. </p>
<li> <p> Domain names are listed with the <a href="postconf.5.html#relay_domains">relay_domains</a> parameter.
</p>
-<li> <p> Valid recipient addresses are listed with the <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a>
-parameter. The Postfix SMTP server rejects invalid recipients with
-"User unknown in relay recipient table". If this parameter value
-is empty, the Postfix SMTP server accepts all recipients for domains
-listed with the <a href="postconf.5.html#relay_domains">relay_domains</a> parameter. </p>
+<li> <p> Valid recipient addresses for those domains are listed
+with the <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> parameter. The Postfix SMTP server
+rejects invalid recipients with "User unknown in relay recipient
+table". If this parameter value is empty, the Postfix SMTP server
+accepts all recipients for domains listed with the <a href="postconf.5.html#relay_domains">relay_domains</a>
+parameter. </p>
<li> <p> The mail delivery transport is specified with the
<a href="postconf.5.html#relay_transport">relay_transport</a> parameter. The default value is <b>relay</b> which
diff --git a/html/ADDRESS_REWRITING_README.html b/html/ADDRESS_REWRITING_README.html
index 85e296f..c92a314 100644
--- a/html/ADDRESS_REWRITING_README.html
+++ b/html/ADDRESS_REWRITING_README.html
@@ -94,9 +94,7 @@ as invalid </a>
<ul>
-<li> <a href="#resolve"> Resolve address to destination </a>
-
-<li> <a href="#transport"> Mail transport switch </a>
+<li> <a href="#resolve"> Resolve address to (transport, next-hop destination) </a>
<li> <a href="#relocated"> Relocated users table </a>
@@ -312,8 +310,8 @@ find what you need. </p>
<table border="1">
<tr> <th nowrap> Address manipulation </th> <th nowrap> Scope </th>
-<th> Daemon </th> <th nowrap> Global turn-on control </th> <th nowrap> Selective
-turn-off control </th> </tr>
+<th> Daemon </th> <th nowrap> Turn-on controls </th> <th nowrap>
+Turn-off controls </th> </tr>
<tr> <td> <a href="#standard"> Rewrite addresses to standard form</a>
</td> <td nowrap> all mail </td> <td> <a href="trivial-rewrite.8.html">trivial-<br>rewrite(8)</a> </td>
@@ -340,13 +338,12 @@ nowrap> all mail </td> <td> <a href="cleanup.8.html">cleanup(8)</a> </td> <td> <
nowrap> all mail </td> <td> <a href="cleanup.8.html">cleanup(8)</a> </td> <td> <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>
</td> <td> <a href="postconf.5.html#receive_override_options">receive_override_options</a> </td> </tr>
-<tr> <td> <a href="#resolve"> Resolve address to destination </a>
-</td> <td nowrap> all mail </td> <td> <a href="trivial-rewrite.8.html">trivial-<br>rewrite(8)</a> </td>
-<td> none </td> <td> none </td> </tr>
-
-<tr> <td> <a href="#transport"> Mail transport switch</a> </td>
-<td nowrap> all mail </td> <td> <a href="trivial-rewrite.8.html">trivial-<br>rewrite(8)</a> </td> <td>
-<a href="postconf.5.html#transport_maps">transport_maps</a> </td> <td> none </td> </tr>
+<tr> <td> <a href="#resolve"> Resolve address to (transport, next-hop
+destination) </a> </td> <td nowrap> all mail </td> <td>
+<a href="trivial-rewrite.8.html">trivial-<br>rewrite(8)</a> </td> <td> <a href="postconf.5.html#local_transport">local_transport</a>, <a href="postconf.5.html#virtual_transport">virtual_transport</a>,
+<a href="postconf.5.html#relay_transport">relay_transport</a>, <a href="postconf.5.html#default_transport">default_transport</a>, <a href="postconf.5.html#relayhost">relayhost</a>,
+<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>, <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>
+</td> <td> <a href="postconf.5.html#content_filter">content_filter</a> </td> </tr>
<tr> <td> <a href="#relocated"> Relocated users table</a> </td>
<td nowrap> all mail </td> <td> <a href="trivial-rewrite.8.html">trivial-<br>rewrite(8)</a> </td> <td>
@@ -774,6 +771,11 @@ may be a more appropriate vehicle. See the <a href="VIRTUAL_README.html">VIRTUAL
for an overview of methods to host virtual domains with Postfix.
</p>
+<p> Note: <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a> (<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>) applies to all
+recipients: <a href="local.8.html">local(8)</a>, virtual, and remote. <!-- wrap filler -->
+This is unlike <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a> (<a href="postconf.5.html#alias_maps">alias_maps</a>) which applies only to
+<a href="local.8.html">local(8)</a> recipients. </p>
+
<p> Virtual aliasing is disabled by default. To enable, edit the
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> parameter in the <a href="postconf.5.html">main.cf</a> file and
specify one or more lookup tables, separated by whitespace or
@@ -792,7 +794,7 @@ commas. </p>
</blockquote>
<p> Addresses found in virtual alias maps are subjected to another
-iteration of virtual aliasing, but are not subjected to canonical
+iteration of <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a>, but are not subjected to canonical
mapping, in order to avoid loops. </p>
<p> For static mappings as shown above, lookup tables such as <a href="DATABASE_README.html#types">hash</a>:,
@@ -833,9 +835,8 @@ manager delegates the more complex address manipulations to the
<ul>
-<li> <a href="#resolve"> Resolve address to destination </a>
-
-<li> <a href="#transport"> Mail transport switch</a>
+<li> <a href="#resolve"> Resolve address to (transport, next-hop
+destination) </a>
<li> <a href="#relocated"> Relocated users table</a>
@@ -873,67 +874,108 @@ via the <a href="local.8.html">local(8)</a> delivery agent: </p>
step in more detail, with specific examples or with pointers to
documentation with examples. </p>
-<h3> <a name="resolve"> Resolve address to destination </a> </h3>
+<h3> <a name="resolve"> Resolve address to (transport, next-hop
+destination) </a> </h3>
<p> The Postfix <a href="qmgr.8.html">qmgr(8)</a> queue manager selects new mail from the
-<a href="QSHAPE_README.html#incoming_queue">incoming queue</a> or old mail from the <a href="QSHAPE_README.html#deferred_queue">deferred queue</a>, and asks the
-<a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> address rewriting and resolving daemon where it
-should be delivered. </p>
+<a href="QSHAPE_README.html#incoming_queue">incoming queue</a> or old mail from the <a href="QSHAPE_README.html#deferred_queue">deferred queue</a>. First it
+looks for overrides: </p>
+
+<ul>
-<p> As of version 2.0, Postfix distinguishes four major address
-classes. Each class has its own list of domain names, and each
-class has its own default delivery method, as shown in the table
-below. See the <a href="ADDRESS_CLASS_README.html">ADDRESS_CLASS_README</a> document for the fine details.
-Postfix versions before 2.0 only distinguish between local delivery
-and everything else. </p>
+<li> <p> The REDIRECT action in <a href="access.5.html">access(5)</a>, <a href="header_checks.5.html">header_checks(5)</a> or
+<a href="header_checks.5.html">body_checks(5)</a> overrides all recipients of the message, and overrides
+a <a href="postconf.5.html#content_filter">content_filter</a> setting, and FILTER action in <a href="access.5.html">access(5)</a>,
+<a href="header_checks.5.html">header_checks(5)</a> or <a href="header_checks.5.html">body_checks(5)</a>. The REDIRECT action was implemented
+as a short-cut to retaliate for abuse. </p>
+
+<li> <p> A <a href="postconf.5.html#content_filter">content_filter</a> setting and FILTER action in <a href="access.5.html">access(5)</a>,
+<a href="header_checks.5.html">header_checks(5)</a> or <a href="header_checks.5.html">body_checks(5)</a> provide their own (transport,
+next-hop destination) information. This bypasses all the steps that
+are described in the remainder of this section. </p>
+
+</ul>
+
+<p> When there is no content filter override, the <a href="qmgr.8.html">qmgr(8)</a> queue
+manager asks the <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> address rewriting and resolving
+daemon for each recipient how to deliver it (which message delivery
+transport) and where to deliver it (what next-hop destination). </p>
+
+<p> As of version 2.0, Postfix distinguishes four major domain
+classes. Each class has its own list of recipient domain names, and
+each class has its own delivery method, as shown in the table below.
+See the <a href="ADDRESS_CLASS_README.html">ADDRESS_CLASS_README</a> document for the fine details. Postfix
+versions before 2.0 only distinguish between local delivery and
+everything else. </p>
+
+<p> Note that the table does not match recipients against
+<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>. The reason is that all valid recipients in
+a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> must be aliased to an address in a different
+domain. All other recipients in a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> are by
+definition undeliverable, and do not need to be considered here.
+</p>
<blockquote>
<table border="1">
-<tr><th align="left">Destination domain list </th> <th
-align="left">Default delivery method </th> <th>Availability
-</th> </tr>
+<tr> <th align="left">Domain class</th> <th align="left">Recipient
+domain match </th> <th> Delivery method </th> <th>Availability </th>
+</tr>
-<tr><td>$<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>, $<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> </td>
-<td>$<a href="postconf.5.html#local_transport">local_transport</a> </td> <td>Postfix 1.0</td></tr>
+<tr><td>Local</td> <td><a href="postconf.5.html#mydestination">mydestination</a>, <a href="postconf.5.html#inet_interfaces">inet_interfaces</a>, <a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>
+</td> <td><a href="postconf.5.html#local_transport">local_transport</a> </td> <td>Postfix 1.0</td></tr>
-<tr><td>$<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> </td> <td>$<a href="postconf.5.html#virtual_transport">virtual_transport</a> </td>
-<td>Postfix 2.0</td> </tr>
+<tr><td>Virtual mailbox</td> <td><a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> </td>
+<td><a href="postconf.5.html#virtual_transport">virtual_transport</a> </td> <td>Postfix 2.0</td> </tr>
-<tr><td>$<a href="postconf.5.html#relay_domains">relay_domains</a> </td> <td>$<a href="postconf.5.html#relay_transport">relay_transport</a> </td> <td>Postfix
-2.0</td> </tr>
+<tr><td>Relay</td> <td><a href="postconf.5.html#relay_domains">relay_domains</a> </td> <td><a href="postconf.5.html#relay_transport">relay_transport</a>
+</td> <td>Postfix 2.0</td> </tr>
-<tr><td>none </td> <td>$<a href="postconf.5.html#default_transport">default_transport</a> </td> <td>Postfix 1.0</td>
-</tr>
+<tr><td>Default</td><td> none </td> <td><a href="postconf.5.html#default_transport">default_transport</a> </td>
+<td>Postfix 1.0</td> </tr>
</table>
</blockquote>
-<h3> <a name="transport"> Mail transport switch </a> </h3>
+<p> The delivery methods in the above table may include a next-hop
+destination in addition to a delivery transport. This may override
+the next-hop destination that is by default taken from the recipient
+domain. </p>
-<p> Once the <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> daemon has determined a default
-delivery method it searches the optional <a href="transport.5.html">transport(5)</a> table for
-information that overrides the message destination and/or delivery
-method. Typical use of the <a href="transport.5.html">transport(5)</a> table is to send mail to
-a system
-that is not connected to the Internet, or to use a special SMTP
-client configuration for destinations that have special requirements.
-See, for example, the <a href="STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README</a> and <a href="UUCP_README.html">UUCP_README</a>
-documents, and the examples in the <a href="transport.5.html">transport(5)</a> manual page. </p>
+<p> Over time, features have been added to override the above
+transport and/or next-hop destination information. The following
+table lists where a transport or next-hop destination may be taken
+from, depending on the recipient domain class. </p>
-<p> Transport table lookups are disabled by default. To enable,
-edit the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter in the <a href="postconf.5.html">main.cf</a> file and specify
-one or more lookup tables, separated by whitespace or commas. </p>
+<blockquote>
-<p> Example: </p>
+<table border="1">
+
+<tr> <th>Domain class</th> <th>Transport sources (in order of
+descending precedence)</th> <th> Next hop sources (in order of
+descending precedence)</th> </tr>
+
+<tr> <td> Local </td> <td> <a href="postconf.5.html#transport_maps">transport_maps</a>, <a href="postconf.5.html#local_transport">local_transport</a></td>
+<td> <a href="postconf.5.html#transport_maps">transport_maps</a>, <a href="postconf.5.html#local_transport">local_transport</a>, recipient domain</td> </tr>
+
+<tr> <td> Virtual mailbox </td> <td> <a href="postconf.5.html#transport_maps">transport_maps</a>,
+<a href="postconf.5.html#virtual_transport">virtual_transport</a></td> <td> <a href="postconf.5.html#transport_maps">transport_maps</a>, <a href="postconf.5.html#virtual_transport">virtual_transport</a>,
+recipient domain</td> </tr>
+
+<tr> <td> Relay </td> <td> <a href="postconf.5.html#transport_maps">transport_maps</a>, <a href="postconf.5.html#relay_transport">relay_transport</a></td>
+<td> <a href="postconf.5.html#transport_maps">transport_maps</a>, <a href="postconf.5.html#relay_transport">relay_transport</a>, <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>,
+<a href="postconf.5.html#relayhost">relayhost</a>, recipient domain</td> </tr>
+
+<tr> <td> Default </td> <td> <a href="postconf.5.html#transport_maps">transport_maps</a>,
+<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>, <a href="postconf.5.html#default_transport">default_transport</a></td>
+<td> <a href="postconf.5.html#transport_maps">transport_maps</a>, <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>,
+<a href="postconf.5.html#default_transport">default_transport</a>, <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>, <a href="postconf.5.html#relayhost">relayhost</a>,
+recipient domain</td> </tr>
+
+</table>
-<blockquote>
-<pre>
-/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
-</pre>
</blockquote>
<h3> <a name="relocated"> Relocated users table </a> </h3>
@@ -1019,6 +1061,11 @@ direct mail for standard aliases such as postmaster to real people.
The table can also be used to map "Firstname.Lastname" addresses
to login names. </p>
+<p> Note: <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a> (<a href="postconf.5.html#alias_maps">alias_maps</a>) applies only to <a href="local.8.html">local(8)</a>
+recipients. This is unlike <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a> (<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>)
+which applies to all recipients: <a href="local.8.html">local(8)</a>, virtual, and remote.
+</p>
+
<p> Alias lookups are enabled by default. The default configuration
depends on the operating system environment, but it is typically
one of the following: </p>
diff --git a/html/COMPATIBILITY_README.html b/html/COMPATIBILITY_README.html
index 2b6a58b..37c37a5 100644
--- a/html/COMPATIBILITY_README.html
+++ b/html/COMPATIBILITY_README.html
@@ -61,24 +61,24 @@ default setting append_dot_mydomain=yes </a> </p>
<li> <p> <a href="#chroot"> Using backwards-compatible default setting
chroot=y</a> </p>
+<li><p> <a href="#relay_restrictions"> Using backwards-compatible
+default setting "smtpd_relay_restrictions = (empty)"</a> </p>
+
+<li> <p> <a href="#smtputf8_enable"> Using backwards-compatible
+default setting smtputf8_enable=no</a> </p>
+
</ul>
<p> Logged with <a href="postconf.5.html#compatibility_level">compatibility_level</a> &lt; 2: </p>
<ul>
-<li><p> <a href="#relay_restrictions"> Using backwards-compatible
-default setting "smtpd_relay_restrictions = (empty)"</a> </p>
-
<li> <p> <a href="#mynetworks_style"> Using backwards-compatible
default setting mynetworks_style=subnet </a> </p>
<li> <p> <a href="#relay_domains"> Using backwards-compatible default
setting relay_domains=$mydestination </a> </p>
-<li> <p> <a href="#smtputf8_enable"> Using backwards-compatible
-default setting smtputf8_enable=no</a> </p>
-
</ul>
<p> Logged with <a href="postconf.5.html#compatibility_level">compatibility_level</a> &lt; 3.6: </p>
@@ -241,6 +241,48 @@ administrator should make the backwards-compatible setting
</pre>
</blockquote>
+<h2> <a name="smtputf8_enable"> Using backwards-compatible default
+setting smtputf8_enable=no</a> </h2>
+
+<p> The <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> default value has changed from "no" to "yes".
+With the new "yes" setting, the Postfix SMTP server rejects non-ASCII
+addresses from clients that don't request SMTPUTF8 support, after
+Postfix is updated from an older version. The backwards-compatibility
+safety net is designed to prevent such surprises. </p>
+
+<p> As long as the <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> parameter is left at its implicit
+default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting is
+less than 1, Postfix logs a warning each time an SMTP command uses a
+non-ASCII address localpart without requesting SMTPUTF8 support: </p>
+
+<blockquote>
+<pre>
+postfix/smtpd[27560]: using backwards-compatible default setting
+ <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>=no to accept non-ASCII sender address
+ "??@example.org" from localhost[127.0.0.1]
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+postfix/smtpd[27560]: using backwards-compatible default setting
+ <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>=no to accept non-ASCII recipient address
+ "??@example.com" from localhost[127.0.0.1]
+</pre>
+</blockquote>
+
+<p> If the address should not be rejected, and the client cannot
+be updated to use SMTPUTF8, then the system administrator should
+make the backwards-compatible setting "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = no" permanent
+in <a href="postconf.5.html">main.cf</a>:
+
+<blockquote>
+<pre>
+# <b>postconf <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>=no</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
<h2> <a name="mynetworks_style"> Using backwards-compatible default
setting mynetworks_style=subnet</a> </h2>
@@ -352,48 +394,6 @@ administrator should make the backwards-compatible setting
<p> Instead of $<a href="postconf.5.html#mydestination">mydestination</a>, it may be better to specify an
explicit list of domain names. </p>
-<h2> <a name="smtputf8_enable"> Using backwards-compatible default
-setting smtputf8_enable=no</a> </h2>
-
-<p> The <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> default value has changed from "no" to "yes".
-With the new "yes" setting, the Postfix SMTP server rejects non-ASCII
-addresses from clients that don't request SMTPUTF8 support, after
-Postfix is updated from an older version. The backwards-compatibility
-safety net is designed to prevent such surprises. </p>
-
-<p> As long as the <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> parameter is left at its implicit
-default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting is
-less than 1, Postfix logs a warning each time an SMTP command uses a
-non-ASCII address localpart without requesting SMTPUTF8 support: </p>
-
-<blockquote>
-<pre>
-postfix/smtpd[27560]: using backwards-compatible default setting
- <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>=no to accept non-ASCII sender address
- "??@example.org" from localhost[127.0.0.1]
-</pre>
-</blockquote>
-
-<blockquote>
-<pre>
-postfix/smtpd[27560]: using backwards-compatible default setting
- <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>=no to accept non-ASCII recipient address
- "??@example.com" from localhost[127.0.0.1]
-</pre>
-</blockquote>
-
-<p> If the address should not be rejected, and the client cannot
-be updated to use SMTPUTF8, then the system administrator should
-make the backwards-compatible setting "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = no" permanent
-in <a href="postconf.5.html">main.cf</a>:
-
-<blockquote>
-<pre>
-# <b>postconf <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>=no</b>
-# <b>postfix reload</b>
-</pre>
-</blockquote>
-
<h2> <a name="smtpd_digest"> Using backwards-compatible
default setting smtpd_tls_fingerprint_digest=md5</a> </h2>
diff --git a/html/DATABASE_README.html b/html/DATABASE_README.html
index e3b3c05..87941bc 100644
--- a/html/DATABASE_README.html
+++ b/html/DATABASE_README.html
@@ -56,10 +56,10 @@ documentation: </p>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/aliases (local aliasing)
+ <a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/aliases (<a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a>)
<a href="postconf.5.html#header_checks">header_checks</a> = <a href="regexp_table.5.html">regexp</a>:/etc/postfix/header_checks (content filtering)
<a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport (routing table)
- <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual (address rewriting)
+ <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual (<a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a>)
</pre>
</blockquote>
@@ -349,6 +349,11 @@ See <a href="lmdb_table.5.html">lmdb_table(5)</a> for details. </dd>
<dd> Memcache database client. Configuration details are given in
<a href="memcache_table.5.html">memcache_table(5)</a>. </dd>
+<dt> <b>mongodb</b> (read-only) </dt>
+
+<dd> MongoDB database client. Configuration details are given in
+<a href="mongodb_table.5.html">mongodb_table(5)</a>, with examples in <a href="MONGODB_README.html">MONGODB_README</a>. </dd>
+
<dt> <b>mysql</b> (read-only) </dt>
<dd> MySQL database client. Configuration details are given in
diff --git a/html/DEPRECATION_README.html b/html/DEPRECATION_README.html
new file mode 100644
index 0000000..4729568
--- /dev/null
+++ b/html/DEPRECATION_README.html
@@ -0,0 +1,411 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix Replacements for Deprecated Features </title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
+Replacements for Deprecated Features</h1>
+
+<hr>
+
+<h2>Purpose of this document </h2>
+
+<p> This document describes Postfix features that are deprecated
+(will be removed) or that have already been removed. It also has
+tips for making an existing Postfix configuration more future-proof.
+</p>
+
+<p> Overview: </p>
+
+<ul>
+
+<li> <a href="#why"> Why deprecate? </a>
+
+<li> <a href="#process"> Deprecation process </a>
+
+<li> <a href="#features"> Deprecated features </a>
+
+</ul>
+
+<h2> <a name="why"> Why deprecate? </a> </h2>
+
+<p> Sometimes, a Postfix feature needs to be replaced with a different
+one. To give an example: </p>
+
+<ul>
+
+<li> <p> The initial Postfix TLS implementation used multiple boolean
+parameters: one parameter to enable opportunistic TLS (for example,
+"<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes") and one parameter to enable mandatory TLS
+(for example, "smtp_require_tls = yes"). </p>
+
+<li> <p> As we added support more features such as fingerprint,
+dane, and so on, we decided not to add more boolean parameters.
+Instead we introduced one configuration parameter to select from
+multiple deployment models (for example, <a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a> =
+may | encrypt | dane, etc...). </p>
+
+</ul>
+
+<!--
+
+<p> Over time it has become clear that 'level' is too rigid, so this may
+have to change again. Wietse and Viktor have been discussing a way to
+specify a range with minimum properties that are required (e.g., encrypt)
+and nice-to-have properties if they are available (dane or mta-sts). </p>
+
+-->
+
+<p> Having both the "old" and "new" way to configure Postfix is
+convenient for existing Postfix installations, because their
+configuration does not break after an upgrade to a new version.
+Unfortunately, there are also disadvantages. Having multiple ways
+to do similar things is not only confusing for newcomers, it also
+makes Postfix harder to change. </p>
+
+<h2> <a name="process"> Deprecation process </a> </h2>
+
+<p> The basic process steps are: </p>
+
+<ol>
+
+<li> <p> Inform humans that a feature will be removed, and suggest
+replacements, in logging and documentation. </p>
+
+<li> <p> Remove the feature, and update logging and documentation. </p>
+
+</ol>
+
+<p> Disclaimer: it has taken 20 years for some features to be
+removed. This past is not a guarantee for the future. </p>
+
+<h2> <a name="features"> Deprecated features </a> </h2>
+
+<p> The table summarizes removed or deprecated features and
+replacements. Click on the "obsolete feature" name for a more
+detailed description. </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th> Obsolete feature name </th> <th> Warning as <br> of version
+</th> <th> Removed <br> in version </th> <th> Replacement </th>
+</tr>
+
+<tr> <td> <a href="#disable_dns_lookups"> disable_dns_lookups </a>
+</td> <td align="center"> 3.9 </td> <td align="center"> - </td>
+<td> <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a> </td> </tr>
+
+<tr> <td> <a href="#xxx_enforce_tls"> <i>xxx</i>_use_tls </a> </td>
+<td align="center"> 3.9 </td> <td align="center"> - </td> <td>
+<i>xxx</i>_tls_security_level </td> </tr>
+
+<tr> <td> <a href="#xxx_enforce_tls"> <i>xxx</i>_enforce_tls </a>
+</td> <td align="center"> 3.9 </td> <td align="center"> - </td>
+<td> <i>xxx</i>_tls_security_level </td> </tr>
+
+<tr> <td> <a href="#xxx_per_site"> <i>xxx</i>_per_site </a> </td>
+<td align="center"> 3.9 </td> <td align="center"> - </td> <td>
+<i>xxx</i>_policy_maps </td> </tr>
+
+<tr> <td> <a href="#smtpd_tls_dh1024_param_file">
+smtpd_tls_dh1024_param_file </a> </td> <td align="center"> 3.9 </td>
+<td align="center"> - </td> <td> do not specify (leave at default)
+</td> </tr>
+
+<tr> <td> <a href="#smtpd_tls_eecdh_grade"> smtpd_tls_eecdh_grade
+</a> </td> <td align="center"> 3.9 </td> <td align="center"> - </td>
+<td> do not specify (leave at default) </td> </tr>
+
+<tr> <td> <a href="#permit_mx_backup"> permit_mx_backup </a> </td>
+<td align="center"> 3.9 </td> <td align="center"> - </td> <td>
+<a href="postconf.5.html#relay_domains">relay_domains</a> </td> </tr>
+
+<tr> <td> <a href="#check_relay_domains"> check_relay_domains </a>
+</td> <td align="center"> 2.2 </td> <td align="center"> 3.9 </td>
+<td> <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> </td> </tr>
+
+<tr> <td> <a href="#reject_maps_rbl"> reject_maps_rbl </a> </td>
+<td align="center"> 2.1 </td> <td align="center"> 3.9 </td> <td>
+<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> </td> </tr>
+
+<tr> <td> <a href="#permit_naked_ip_address"> permit_naked_ip_address
+</a> </td> <td align="center"> 2.0 </td> <td align="center"> 3.9
+</td> <td> <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a> </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="disable_dns_lookups"> Obsolete DNS on/off configuration
+</a> </h3>
+
+<p> The <a href="postconf.1.html">postconf(1)</a> command logs the following: </p>
+
+<ul>
+
+<li> support for parameter "<a href="postconf.5.html#disable_dns_lookups">disable_dns_lookups</a>" will be removed; instead, specify "<a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a>"
+
+</ul>
+
+<p> Replace obsolete configuration with its replacement: </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th width="33%"> Goal </th> <th width="33%"> Obsolete configuration
+</th> <th> Replacement configuration </th> </tr>
+
+<tr> <td> To disable DNS lookups in the Postfix SMTP/LMTP client
+</td> <td> <a href="postconf.5.html#disable_dns_lookups">disable_dns_lookups</a> = yes </td> <td> <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a>
+= disabled </td> </tr>
+
+<tr> <td> To enable DNS lookups in the Postfix SMTP/LMTP client </td> <td>
+<a href="postconf.5.html#disable_dns_lookups">disable_dns_lookups</a> = no </td> <td>
+Leave <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a> at the implicit default which is empty, unless
+you need a higher support level such as DNSSEC. </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="xxx_use_tls"> Obsolete opportunistic TLS configuration
+</a> </h3>
+
+<p> The <a href="postconf.1.html">postconf(1)</a> command logs one of the following: </p>
+
+<ul>
+
+<li> support for parameter "<a href="postconf.5.html#lmtp_use_tls">lmtp_use_tls</a>" will be removed; instead, specify "<a href="postconf.5.html#lmtp_tls_security_level">lmtp_tls_security_level</a>"
+
+<li> support for parameter "<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>" will be removed; instead, specify "<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>"
+
+<li> support for parameter "<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>" will be removed; instead, specify "<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>"
+
+</ul>
+
+<p> There are similarly-named parameters and warnings for <a href="postscreen.8.html">postscreen(8)</a>
+and <a href="tlsproxy.8.html">tlsproxy(8)</a>, but those parameters should rarely be specified
+by hand. </p>
+
+<p> Replace obsolete configuration with its replacement: </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th width="33%"> Goal </th> <th width="33%"> Obsolete configuration </th> <th> Replacement configuration </th> </tr>
+
+<tr> <td> To turn off TLS </td> <td> <i>xxx</i>_use_tls = no </td>
+<td> <i>xxx</i>_security_level = none </td> </tr>
+
+<tr> <td> To turn on opportunistic TLS </td> <td> <i>xxx</i>_use_tls
+= yes </td> <td> <i>xxx</i>_security_level = may </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="xxx_enforce_tls"> Obsolete mandatory TLS configuration
+</a> </h3>
+
+<p> The <a href="postconf.1.html">postconf(1)</a> command logs one of the following: </p>
+
+<ul>
+
+<li> support for parameter "<a href="postconf.5.html#lmtp_enforce_tls">lmtp_enforce_tls</a>" will be removed; instead, specify "<a href="postconf.5.html#lmtp_tls_security_level">lmtp_tls_security_level</a>"
+
+<li> support for parameter "<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>" will be removed; instead, specify "<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>"
+
+<li> support for parameter "<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>" will be removed; instead, specify "<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>"
+
+</ul>
+
+<p> There are similarly-named parameters and warnings for <a href="postscreen.8.html">postscreen(8)</a>
+and <a href="tlsproxy.8.html">tlsproxy(8)</a>, but those parameters should rarely be specified
+by hand. </p>
+
+<p> Replace obsolete configuration with its replacement: </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th width="33%"> Goal </th> <th width="33%"> Obsolete configuration </th> <th> Replacement configuration </th> </tr>
+
+<tr> <td> To turn off mandatory TLS </td> <td> <i>xxx</i>_enforce_tls
+= no </td> <td> <i>xxx</i>_security_level = may </td> </tr>
+
+<tr> <td> To turn on mandatory TLS </td> <td> <i>xxx</i>_enforce_tls
+= yes </td> <td> <i>xxx</i>_security_level = encrypt </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="xxx_per_site"> Obsolete TLS policy table configuration
+</a> </h3>
+
+<p> The <a href="postconf.1.html">postconf(1)</a> command logs one of the following: </p>
+
+<ul>
+
+<li> support for parameter "<a href="postconf.5.html#lmtp_tls_per_site">lmtp_tls_per_site</a>" will be removed;
+instead, specify "<a href="postconf.5.html#lmtp_tls_policy_maps">lmtp_tls_policy_maps</a>"
+
+<li> support for parameter "<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>" will be removed;
+instead, specify "<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>"
+
+</ul>
+
+<p> There is similarly-named parameter and warning for <a href="tlsproxy.8.html">tlsproxy(8)</a>,
+but that parameter should rarely be specified by hand. </p>
+
+<p> Unfortunately, this is more than a name change: the table format
+has changed too, as has the table search process. There is no simple
+conversion of the obsolete form to its replacement. </p>
+
+<h3> <a name="check_relay_domains"> check_relay_domains </a> </h3>
+
+<p> Depending on the Postfix version, the Postfix SMTP daemon logs
+following warning: </p>
+
+<ul>
+
+<li> support for restriction "check_relay_domains" has been removed
+in Postfix 3.9"; instead, specify "<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>"
+
+<li> support for restriction "check_relay_domains" will be removed
+from Postfix; use "<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>" instead
+
+</ul>
+
+<p> This feature was removed because it would relay based on the
+client domain name, which is not robust. </p>
+
+<p> Recommended configuration to prevent an "open relay" problem
+with the SMTP service on port 25:
+</p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
+ <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
+ <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>,
+ <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
+ ...other restrictions...
+</pre>
+</blockquote>
+
+<p> Or equivalent in <a href="postconf.5.html#smtpd_relay_restrictions">smtpd_relay_restrictions</a>. </p>
+
+<h3> <a name="permit_mx_backup"> permit_mx_backup</a> </h3>
+
+<p> The Postfix version 3.9 and later SMTP daemon logs the following
+warning: </p>
+
+<ul>
+
+<li> support for restriction "<a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a>" will be removed
+from Postfix; instead, specify "<a href="postconf.5.html#relay_domains">relay_domains</a>"
+
+</ul>
+
+<p> This feature will be removed because it is too difficult to
+configure recipient address validation, making Postfix a source of
+backscatter bounces. </p>
+
+<p> To specify the domains that Postfix will provide MX backup
+service for, see <a href="STANDARD_CONFIGURATION_README.html#backup">
+Configuring Postfix as primary or backup MX host for a remote
+site</a>. </p>
+
+<h3> <a name="reject_maps_rbl"> reject_maps_rbl</a> </h3>
+
+<p> Depending on the Postfix version, the SMTP daemon logs one of
+the following warnings: </p>
+
+<ul>
+
+<li> support for restriction "reject_maps_rbl" has been removed in
+Postfix 3.9"; instead, specify "<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> domain-name"
+
+<li> support for restriction "reject_maps_rbl" will be removed from
+Postfix; use "<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> domain-name" instead
+
+</ul>
+
+<p> This feature was replaced because "MAPS RBL" is the name of a
+specific reputation service. The <a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> feature provides
+a superset of the reject_maps_rbl functionality. </p>
+
+<p> Recommended configuration: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
+ <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
+ <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>,
+ <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
+ <a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> <i>domain-name</i>
+ ...other restrictions...
+</pre>
+</blockquote>
+
+<p> Where <i>domain-name</i> is the domain name of a DNS reputation service. </p>
+
+<h3> <a name="permit_naked_ip_address"> permit_naked_ip_address</a> </h3>
+
+<p> Depending on the Postfix version, the SMTP daemon logs one of
+the following warnings: </p>
+
+<ul>
+
+<li> support for restriction "permit_naked_ip_address" has been
+removed in Postfix 3.9"; instead, specify "<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>" or
+"<a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>"
+
+<li> restriction permit_naked_ip_address is deprecated. Use
+<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a> or <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a> instead
+
+</ul>
+
+<p> This feature was removed because it was easy to get a false
+match when <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> was intended to match a
+remote SMTP client IP address. </p>
+
+<p> Recommended configuration: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
+ <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
+ <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>,
+ <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
+ <a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> <i>domain-name</i>
+ ...other restrictions...
+</pre>
+</blockquote>
+
+<p> That is, no restriction on HELO or EHLO syntax. Such restrictions
+ar rarely useful nowadays.
+
+</body>
+
+</html>
diff --git a/html/INSTALL.html b/html/INSTALL.html
index 6cd70d1..94d78ba 100644
--- a/html/INSTALL.html
+++ b/html/INSTALL.html
@@ -605,6 +605,9 @@ describe how to build Postfix with support for optional features:
<tr> <td> LDAP database</td> <td><a href="LDAP_README.html">LDAP_README</a></td> <td> Postfix
1.0 </td> </tr>
+<tr> <td> MongoDB database</td> <td><a href="MONGODB_README.html">MONGODB_README</a></td> <td> Postfix
+3.9 </td> </tr>
+
<tr> <td> MySQL database</td> <td><a href="MYSQL_README.html">MYSQL_README</a></td> <td> Postfix
1.0 </td> </tr>
diff --git a/html/LOCAL_RECIPIENT_README.html b/html/LOCAL_RECIPIENT_README.html
index a3a3636..5a614e0 100644
--- a/html/LOCAL_RECIPIENT_README.html
+++ b/html/LOCAL_RECIPIENT_README.html
@@ -57,7 +57,8 @@ 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>. If a local username or address is not listed in
$<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>, then the Postfix SMTP server will reject
-the address with "User unknown in local recipient table". </p>
+the address with "User unknown in local recipient table". Other
+Postfix interfaces may still accept an "unknown" recipient. </p>
<p> The default setting, shown below, assumes that you use the
default Postfix <a href="local.8.html">local(8)</a> delivery agent for local delivery, where
diff --git a/html/MAILLOG_README.html b/html/MAILLOG_README.html
index be58e33..ab751f4 100644
--- a/html/MAILLOG_README.html
+++ b/html/MAILLOG_README.html
@@ -63,10 +63,16 @@ Postfix version. </p>
/var/log/postfix.log. See also the "<a href="#logrotate">Logfile
rotation</a>" section below for logfile management. </p>
+<p> In the example below, specifying <a href="postconf.5.html#maillog_file_permissions">maillog_file_permissions</a> is
+optional (Postfix 3.9 and later). The default value is 0600, i.e.,
+only the super-user can access the file; the value 0644 also
+adds 'group' and 'other' read access. </p>
+
<blockquote>
<pre>
# postfix stop
# postconf <a href="postconf.5.html#maillog_file">maillog_file</a>=/var/log/postfix.log
+# postconf <a href="postconf.5.html#maillog_file_permissions">maillog_file_permissions</a>=0644 # (Postfix 3.9 and later)
# postfix start
</pre>
</blockquote>
@@ -124,6 +130,10 @@ old logfile. </p>
program is configured with the <a href="postconf.5.html#maillog_file_compressor">maillog_file_compressor</a> parameter
(default: gzip). </p>
+<li> <p> The next time it logs an event, <a href="postlogd.8.html">postlogd(8)</a> will create a
+new logfile, with permissions specified with the <a href="postconf.5.html#maillog_file_permissions">maillog_file_permissions</a>
+parameter (default: 0600). </p>
+
</ul>
<p> Notes: </p>
diff --git a/html/MILTER_README.html b/html/MILTER_README.html
index c69a5bf..b72fdb8 100644
--- a/html/MILTER_README.html
+++ b/html/MILTER_README.html
@@ -630,7 +630,7 @@ and protocol. </p>
clients </a></h3>
<p> The <a href="postconf.5.html#smtpd_milter_maps">smtpd_milter_maps</a> feature supports different Milter settings
-for different client IP addresses. Lookup results override the the
+for different client IP addresses. Lookup results override the
global <a href="postconf.5.html#smtpd_milters">smtpd_milters</a> setting, and have the same syntax. For example,
to disable Milter settings for local address ranges: </p>
diff --git a/html/MONGODB_README.html b/html/MONGODB_README.html
new file mode 100644
index 0000000..a05d1f5
--- /dev/null
+++ b/html/MONGODB_README.html
@@ -0,0 +1,263 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>Postfix MongoDB Howto</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix MongoDB Howto</h1>
+<hr>
+
+<h2>MongoDB Support in Postfix</h2>
+
+<p> Postfix can use MongoDB as a source for any of its lookups:
+<a href="aliases.5.html">aliases(5)</a>, <a href="virtual.5.html">virtual(5)</a>, <a href="canonical.5.html">canonical(5)</a>, etc. This allows you to keep
+information for your mail service in a replicated noSQL database
+with fine-grained access controls. By not storing it locally on the
+mail server, the administrators can maintain it from anywhere, and
+the users can control whatever bits of it you think appropriate.
+You can have multiple mail servers using the same information,
+without the hassle and delay of having to copy it to each. </p>
+
+<p> Topics covered in this document:</p>
+
+<ul>
+<li><a href="#build">Building Postfix with MongoDB support</a>
+<li><a href="#config">Configuring MongoDB lookups</a>
+<li><a href="#example_virtual">Example: virtual alias maps</a>
+<li><a href="#example_mailing_list">Example: Mailing lists</a>
+<li><a href="#example_projections">Example: MongoDB projections</a>
+<li><a href="#feedback">Feedback</a>
+<li><a href="#credits">Credits</a>
+</ul>
+
+<h2><a name="build">Building Postfix with MongoDB support</a></h2>
+
+<p>These instructions assume that you build Postfix from source
+code as described in the <a href="INSTALL.html">INSTALL</a> document. Some modification may
+be required if you build Postfix from a vendor-specific source
+package. </p>
+
+<p>The Postfix MongoDB client requires the <b>mongo-c-driver</b>
+library. This can be built from source code from <a
+href="https://github.com/mongodb/mongo-c-driver/releases">the
+mongod-c project</a>, or this can be installed as a binary package
+from your OS distribution, typically named <b>mongo-c-driver</b>,
+<b>mongo-c-driver-devel</b> or <b>libmongoc-dev</b>.
+Installing the mongo-c-driver library may also install <b>libbson</b>
+as a dependency. </p>
+
+<p> To build Postfix with mongodb map support, add to the CCARGS
+environment variable the options -DHAS_MONGODB and -I for the
+directory containing the mongodb headers, and specify the <a href="MONGODB_README.html">AUXLIBS_MONGODB</a>
+with the libmongoc and libbson libraries, for example:</p>
+
+<blockquote>
+<pre>
+% make tidy
+% make -f Makefile.init makefiles \
+ CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
+ -I/usr/include/libbson-1.0" \
+ <a href="MONGODB_README.html">AUXLIBS_MONGODB</a>="-lmongoc-1.0 -lbson-1.0"
+</pre>
+</blockquote>
+
+<p>The 'make tidy' command is needed only if you have previously
+built Postfix without MongoDB support. </p>
+
+<p>If your MongoDB shared library is in a directory that the RUN-TIME
+linker does not know about, add a "-Wl,-R,/path/to/directory" option
+after "-lbson-1.0". Then, just run 'make'.</p>
+
+<h2><a name="config">Configuring MongoDB lookups</a></h2>
+
+<p> In order to use MongoDB lookups, define a MongoDB source as a
+table lookup in <a href="postconf.5.html">main.cf</a>, for example: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases, <a href="proxymap.8.html">proxy</a>:<a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongo-aliases.cf
+</pre>
+</blockquote>
+
+<p> The file /etc/postfix/mongo-aliases.cf can specify a number of
+parameters. For a complete description, see the <a href="mongodb_table.5.html">mongodb_table(5)</a>
+manual page. </p>
+
+<h2><a name="example_virtual">Example: virtual(5) alias maps</a></h2>
+
+<p> Here's a basic example for using MongoDB to look up <a href="virtual.5.html">virtual(5)</a>
+aliases. Assume that in <a href="postconf.5.html">main.cf</a>, you have: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual_aliases,
+ <a href="proxymap.8.html">proxy</a>:<a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongo-virtual-aliases.cf
+</pre>
+</blockquote>
+
+<p> and in <a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongo-virtual-aliases.cf you have: </p>
+
+<blockquote>
+<pre>
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+result_attribute = username
+</pre>
+</blockquote>
+
+<p>This example assumes mailbox names are stored in a MongoDB backend,
+in a format like:</p>
+
+<blockquote>
+<pre>
+{ "username": "user@example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+</pre>
+</blockquote>
+
+<p>Upon receiving mail for "admin@example.com" that isn't found in the
+/etc/postfix/virtual_aliases database, Postfix will search the
+MongoDB server/cluster listening at port 27017 on some_server. It
+will connect using the provided credentials, and search for any
+entries whose username is, or alias field has "admin@example.com".
+It will return the username attribute of those found, and build a
+list of their email addresses. </p>
+
+<p> Notes: </p>
+
+<ul>
+
+<li><p> As with <b>projection</b> (see below), the Postfix mongodb
+client automatically removes the top-level '_id' field from a
+result_attribute result. </p> </li>
+
+<li><p> The Postfix mongodb client will only parse result fields
+with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
+ignored, with a warning in the logs. </p> </li>
+
+</ul>
+
+<h2><a name="example_mailing_list">Example: Mailing lists</a></h2>
+
+<p>When it comes to mailing lists, one way of implementing one would
+be as below:</p>
+
+<blockquote>
+<pre>
+{ "name": "dev@example.com", "active": 1, "address":
+ [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
+</pre>
+</blockquote>
+
+<p>using the filter below, will result in a comma separated string
+with all email addresses in this list. </p>
+
+<blockquote>
+<pre>
+query_filter = {"name": "%s", "active": 1}
+result_attribute = address
+</pre>
+</blockquote>
+
+<p> Notes: </p>
+
+<ul>
+
+<li><p> As with <b>projection</b> (see below), the Postfix mongodb
+client automatically removes the top-level '_id' field from a
+result_attribute result. </p> </li>
+
+<li><p> The Postfix mongodb client will only parse result fields
+with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
+ignored, with a warning in the logs. </p> </li>
+
+</ul>
+
+<h2><a name="example_projections">Example: advanced projections</a></h2>
+
+<p>This module also supports the use of more complex MongoDB
+projections. There may be some use cases where operations such as
+concatenation are necessary to be performed on the data retrieved
+from the database. Although it is encouraged to keep the database
+design simple enough so this is not necessary, postfix supports the
+use of MongoDB projections to achieve the goal. </p>
+
+<p>Consider the example below:</p>
+
+<blockquote>
+<pre>
+{ "username": "user@example.com",
+ "local_part": "user",
+ "domain": "example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+</pre>
+</blockquote>
+
+<p><a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> can be created using below parameters in a
+<a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongo-virtual-mailboxes.cf file:</p>
+
+<blockquote>
+<pre>
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
+</pre>
+</blockquote>
+
+<p>This will return 'example.com/user' path built from the database fields. </p>
+
+<p>A couple of considerations when using projections:</p>
+
+<ul>
+
+<li><p>As with <b>result_attribute</b>, the Postfix mongodb client
+automatically removes the top-level '_id' field from a projection
+result. </p></li>
+
+<li><p> The Postfix mongodb client will only parse fields with data
+types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored,
+with a warning in the logs. It is suggested to exclude any unnecessary
+fields when using a projection. </p></li>
+
+</ul>
+
+<h2><a name="feedback">Feedback</a></h2>
+
+<p> If you have questions, send them to postfix-users@postfix.org.
+Please include relevant information about your Postfix setup:
+MongoDB-related output from postconf, which libraries you built
+with, and such. If your question involves your database contents,
+please include the applicable bits of some database entries. </p>
+
+<h2><a name="credits">Credits</a></h2>
+
+<ul>
+
+<li> Stephan Ferraro (Aionda GmbH) implemented an early version of the
+Postfix MongoDB client.
+
+<li> Hamid Maadani (Dextrous Technologies, LLC) added support for
+projections and %<i>letter</i> interpolation, and added documentation.
+
+<li> Wietse Venema adopted and restructured the code and documentation.
+
+</ul>
+
+</body>
+
+</html>
diff --git a/html/Makefile.in b/html/Makefile.in
index c5481f8..7f23ed7 100644
--- a/html/Makefile.in
+++ b/html/Makefile.in
@@ -20,7 +20,7 @@ CONFIG = access.5.html aliases.5.html canonical.5.html relocated.5.html \
transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html \
cidr_table.5.html tcp_table.5.html header_checks.5.html \
ldap_table.5.html lmdb_table.5.html mysql_table.5.html \
- pgsql_table.5.html memcache_table.5.html \
+ pgsql_table.5.html memcache_table.5.html mongodb_table.5.html \
master.5.html nisplus_table.5.html generic.5.html bounce.5.html \
postfix-wrapper.5.html sqlite_table.5.html socketmap_table.5.html
OTHER = postfix-manuals.html
@@ -298,6 +298,10 @@ memcache_table.5.html: ../proto/memcache_table
PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+mongodb_table.5.html: ../proto/mongodb_table
+ PATH=../mantools:$$PATH; \
+ srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+
mysql_table.5.html: ../proto/mysql_table
PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
diff --git a/html/POSTSCREEN_README.html b/html/POSTSCREEN_README.html
index bca2ef0..9bef8db 100644
--- a/html/POSTSCREEN_README.html
+++ b/html/POSTSCREEN_README.html
@@ -120,7 +120,7 @@ of time to deliver spam before their IP address becomes denylisted.
To speed up spam deliveries, zombies make compromises in their SMTP
protocol implementation. For example, they speak before their turn,
or they ignore responses from SMTP servers and continue sending
-mail even when the server tells them to go away. </p>
+commands even when the server tells them to go away. </p>
<p> <a href="postscreen.8.html">postscreen(8)</a> uses a variety of measurements to recognize
zombies. First, <a href="postscreen.8.html">postscreen(8)</a> determines if the remote SMTP client
@@ -159,7 +159,7 @@ overhead for legitimate clients. </p>
<h2> <a name="quick">Quick tests before everything else</a> </h2>
-<p> Before engaging in SMTP-level tests. <a href="postscreen.8.html">postscreen(8)</a> queries a
+<p> Before engaging in SMTP-level tests, <a href="postscreen.8.html">postscreen(8)</a> queries a
number of local deny and allowlists. These tests speed up the
handling of known clients. </p>
diff --git a/html/TLS_README.html b/html/TLS_README.html
index eb9965a..a77f69d 100644
--- a/html/TLS_README.html
+++ b/html/TLS_README.html
@@ -2266,82 +2266,124 @@ describe the corresponding table syntax: </p>
additional attributes are supported at this level. </dd>
<dt><b>may</b></dt> <dd><a href="#client_tls_may">Opportunistic TLS</a>.
-The optional "ciphers", "exclude" and "protocols" attributes
-(available for opportunistic TLS with Postfix &ge; 2.6) override the
-"<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>", "<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>" and "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>"
-configuration parameters. At this level and higher, the optional
-"servername" attribute (available with Postfix &ge; 3.4) overrides the
-global "<a href="postconf.5.html#smtp_tls_servername">smtp_tls_servername</a>" parameter, enabling per-destination
-configuration of the SNI extension sent to the remote SMTP server. </dd>
+The optional "ciphers", "exclude", and "protocols" attributes (available
+for opportunistic TLS with Postfix &ge; 2.6) and "connection_reuse"
+attribute (Postfix &ge; 3.4) override the "<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>",
+"<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>", "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>", and
+"<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a>" configuration parameters. At this level and
+higher, the optional "servername" attribute (available with Postfix &ge;
+3.4) overrides the global "<a href="postconf.5.html#smtp_tls_servername">smtp_tls_servername</a>" parameter, enabling
+per-destination configuration of the SNI extension sent to the remote
+SMTP server. The optional "enable_rpk" attribute (Postfix &ge; 3.9)
+overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> parameter. When opportunistic
+TLS handshakes fail, Postfix retries the connection with TLS disabled.
+This allows mail delivery to sites with non-interoperable TLS
+implementations.</dd>
<dt><b>encrypt</b></dt> <dd><a href="#client_tls_encrypt"> Mandatory encryption</a>.
-Mail is delivered only if the remote SMTP server offers STARTTLS
-and the TLS handshake succeeds. At this level and higher, the optional
+Mail is delivered only if the remote SMTP server offers STARTTLS and the
+TLS handshake succeeds. At this level and higher, the optional
"protocols" attribute overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>
-parameter, the optional "ciphers" attribute overrides the
-<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a> parameter, and the optional
-"exclude" attribute (Postfix &ge; 2.6) overrides the <a href="postconf.5.html">main.cf</a>
-<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a> parameter. </dd>
+parameter, the optional "ciphers" attribute overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a> parameter, the optional "exclude" attribute
+(Postfix &ge; 2.6) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a> parameter, and the optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. The optional "enable_rpk" attribute
+(Postfix &ge; 3.9) overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> parameter.
+</dd>
<dt><b>dane</b></dt> <dd><a href="#client_tls_dane">Opportunistic DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
-DNSSEC. If no TLSA records are found, the effective security level
-used is <a href="#client_tls_may">may</a>. If TLSA records are
-found, but none are usable, the effective security level is <a
-href="#client_tls_encrypt">encrypt</a>. When usable TLSA records
-are obtained for the remote SMTP server, SSLv2+3 are automatically
-disabled (see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate
-must match the TLSA records. <a href="https://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication
-and DNSSEC support is available with Postfix 2.11 and later. </dd>
+DNSSEC. If no TLSA records are found, the effective security level used
+is <a href="#client_tls_may">may</a>. If TLSA records are found, but
+none are usable, the effective security level is <a
+href="#client_tls_encrypt">encrypt</a>. When usable TLSA records are
+obtained for the remote SMTP server, the server certificate must match
+the TLSA records (and the SNI name is unconditionally set to the TLSA
+<i>base domain</i>). <a href="https://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and DNSSEC
+support is available with Postfix 2.11 and later. The optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. When the effective security level
+used is <a href="#client_tls_may">may</a>, the optional "ciphers",
+"exclude", and "protocols" attributes (Postfix &ge; 2.6) override the
+"<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>", "<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>", and "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>"
+configuration parameters. When the effective security level used is <a
+href="#client_tls_encrypt">encrypt</a>, the optional "ciphers",
+"exclude", and "protocols" attributes (Postfix &ge; 2.6) override the
+"<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>", "<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and
+"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>" configuration parameters. </dd>
<dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
-DNSSEC. If no TLSA records are found, or none are usable, no
-connection is made to the server. When usable TLSA records are
-obtained for the remote SMTP server, SSLv2+3 are automatically disabled
-(see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate must
-match the TLSA records. <a href="https://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and
-DNSSEC support is available with Postfix 2.11 and later. </dd>
+DNSSEC. If no TLSA records are found, or none are usable, no connection
+is made to the server. When usable TLSA records are obtained for the
+remote SMTP server, the server certificate must match the TLSA records.
+<a href="https://tools.ietf.org/html/rfc7672">RFC 7672</a> (DANE) TLS authentication and DNSSEC support is available with
+Postfix 2.11 and later. The optional "ciphers", "exclude", and
+"protocols" attributes (Postfix &ge; 2.6) override the
+"<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>", "<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and
+"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>" configuration parameters. The optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
<dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
-fingerprint verification.</a> Available with Postfix 2.5 and
-later. At this security level, there are no trusted Certification
-Authorities. The certificate trust chain, expiration date, ... are
-not checked. Instead, the optional <b>match</b> attribute, or else
-the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a></b> parameter, lists
-the server certificate fingerprints or public key fingerprints
-(Postfix 2.9 and later). The
-digest algorithm used to calculate fingerprints is selected by the
-<b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b> parameter. Multiple fingerprints can
-be combined with a "|" delimiter in a single match attribute, or multiple
-match attributes can be employed. The ":" character is not used as a
-delimiter as it occurs between each pair of fingerprint (hexadecimal)
-digits. </dd>
+fingerprint verification.</a> Available with Postfix 2.5 and later. At
+this security level, there are no trusted Certification Authorities. The
+certificate trust chain, expiration date, ... are not checked. Instead,
+the optional "match" attribute, or else the <a href="postconf.5.html">main.cf</a>
+<b><a href="postconf.5.html#smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a></b> parameter, lists the certificate
+fingerprints or the public key fingerprints (Postfix 2.9 and later) of
+acceptable server certificates. The digest algorithm used to calculate
+the fingerprint is selected by the <b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b>
+parameter. Multiple fingerprints can be combined with a "|" delimiter in
+a single match attribute, or multiple match attributes can be employed.
+The ":" character is not used as a delimiter as it occurs between each
+pair of fingerprint (hexadecimal) digits. The optional "ciphers",
+"exclude", and "protocols" attributes (Postfix &ge; 2.6) override the
+"<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>", "<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and
+"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>" configuration parameters. The optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. The optional "enable_rpk"
+attribute (Postfix &ge; 3.9) overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a>
+parameter. </dd>
<dt><b>verify</b></dt> <dd><a href="#client_tls_verify">Mandatory
-server certificate verification</a>. Mail is delivered only if the
-TLS handshake succeeds, if the remote SMTP server certificate can
-be validated (not expired or revoked, and signed by a trusted
-Certification Authority), and if the server certificate name matches
-the optional "match" attribute (or the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_verify_cert_match">smtp_tls_verify_cert_match</a>
-parameter value when no optional "match" attribute is specified).
-With Postfix &ge; 2.11 the "tafile" attribute optionally modifies
-trust chain verification in the same manner as the
-"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute
-may be specified multiple times to load multiple trust-anchor
-files. </dd>
+server certificate verification</a>. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups are presumed to be
+secure enough, and the name verified in the server certificate is
+potentially obtained via unauthenticated DNS MX lookups. The server
+certificate name must match either the optional "match" attribute, or
+else the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_verify_cert_match">smtp_tls_verify_cert_match</a> parameter value. With
+Postfix &ge; 2.11 the "tafile" attribute optionally modifies trust chain
+verification in the same manner as the "<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>"
+parameter. The "tafile" attribute may be specified multiple times to
+load multiple trust-anchor files. The optional "connection_reuse"
+attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
<dt><b>secure</b></dt> <dd><a href="#client_tls_secure">Secure certificate
-verification.</a> Mail is delivered only if the TLS handshake succeeds,
-and DNS forgery resistant remote SMTP certificate verification succeeds
-(not expired or revoked, and signed by a trusted Certification Authority),
-and if the server certificate name matches the optional "match" attribute
-(or the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_secure_cert_match">smtp_tls_secure_cert_match</a> parameter value when no optional
-"match" attribute is specified). With Postfix &ge; 2.11 the "tafile"
-attribute optionally modifies trust chain verification in the same manner
-as the "<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute
-may be specified multiple times to load multiple trust-anchor
-files. </dd>
+verification.</a>
+Mail is delivered only if the TLS handshake succeeds, the remote SMTP
+server certificate chain can be validated, and a DNS name in the
+certificate matches the specified match criteria. At this security
+level, DNS MX lookups, though potentially used to determine the
+candidate next-hop gateway IP addresses, are <b>not</b> presumed to be
+secure enough for TLS peername verification. Instead, the default name
+verified in the server certificate is obtained directly from the
+next-hop, or is explicitly specified via the optional "match" attribute
+which overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_secure_cert_match">smtp_tls_secure_cert_match</a> parameter. The
+optional "ciphers", "exclude", and "protocols" attributes (Postfix &ge;
+2.6) override the "<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>",
+"<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and "<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>"
+configuration parameters. With Postfix &ge; 2.11 the "tafile" attribute
+optionally modifies trust chain verification in the same manner as the
+"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute may be
+specified multiple times to load multiple trust-anchor files. The
+optional "connection_reuse" attribute (Postfix &ge; 3.4) overrides the
+<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
</dl>
diff --git a/html/access.5.html b/html/access.5.html
index 24f844b..427eacf 100644
--- a/html/access.5.html
+++ b/html/access.5.html
@@ -60,7 +60,7 @@ ACCESS(5) ACCESS(5)
A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
-<b>EMAIL ADDRESS PATTERNS</b>
+<b>EMAIL ADDRESS PATTERNS IN INDEXED TABLES</b>
With lookups from indexed files such as DB or DBM, or from networked
tables such as NIS, LDAP or SQL, patterns are tried in the order as
listed below:
@@ -92,7 +92,7 @@ ACCESS(5) ACCESS(5)
(e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>domain</i>, <i>user+foo</i>@, and <i>user</i>@.
-<b>HOST NAME/ADDRESS PATTERNS</b>
+<b>HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES</b>
With lookups from indexed files such as DB or DBM, or from networked
tables such as NIS, LDAP or SQL, the following lookup patterns are
examined in the order as listed:
diff --git a/html/aliases.5.html b/html/aliases.5.html
index 27cfe69..79d01b4 100644
--- a/html/aliases.5.html
+++ b/html/aliases.5.html
@@ -14,9 +14,13 @@ ALIASES(5) ALIASES(5)
<b>newaliases</b>
<b>DESCRIPTION</b>
- The <a href="aliases.5.html"><b>aliases</b>(5)</a> table provides a system-wide mechanism to redirect mail
- for local recipients. The redirections are processed by the Postfix
- <a href="local.8.html"><b>local</b>(8)</a> delivery agent.
+ The optional <a href="aliases.5.html"><b>aliases</b>(5)</a> table (<a href="postconf.5.html#alias_maps">alias_maps</a>) redirects mail for local
+ recipients. The redirections are processed by the Postfix <a href="local.8.html"><b>local</b>(8)</a>
+ delivery agent.
+
+ This is unlike <a href="virtual.5.html"><b>virtual</b>(5)</a> aliasing (<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>) which applies
+ to all recipients: <a href="local.8.html">local(8)</a>, virtual, and remote, and which is imple-
+ mented by the <a href="cleanup.8.html"><b>cleanup</b>(8)</a> daemon.
Normally, the <a href="aliases.5.html"><b>aliases</b>(5)</a> table is specified as a text file that serves
as input to the <a href="postalias.1.html"><b>postalias</b>(1)</a> command. The result, an indexed file in
@@ -144,7 +148,9 @@ ALIASES(5) ALIASES(5)
"<b>newaliases</b>" or with "<b>sendmail -bi</b>".
<b><a href="postconf.5.html#alias_maps">alias_maps</a> (see 'postconf -d' output)</b>
- The alias databases that are used for <a href="local.8.html"><b>local</b>(8)</a> delivery.
+ Optional lookup tables with aliases that apply only to <a href="local.8.html"><b>local</b>(8)</a>
+ recipients; this is unlike <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> that apply to all
+ recipients: <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote.
<b><a href="postconf.5.html#allow_mail_to_commands">allow_mail_to_commands</a> (alias, forward)</b>
Restrict <a href="local.8.html"><b>local</b>(8)</a> mail delivery to external commands.
diff --git a/html/canonical.5.html b/html/canonical.5.html
index 68b6532..d051297 100644
--- a/html/canonical.5.html
+++ b/html/canonical.5.html
@@ -56,7 +56,7 @@ CANONICAL(5) CANONICAL(5)
systems.
The <a href="canonical.5.html"><b>canonical</b>(5)</a> mapping is not to be confused with <i>virtual alias</i> sup-
- port or with local aliasing. To change the destination but not the
+ port or with <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a>. To change the destination but not the
headers, use the <a href="virtual.5.html"><b>virtual</b>(5)</a> or <a href="aliases.5.html"><b>aliases</b>(5)</a> map instead.
<b>CASE FOLDING</b>
@@ -211,20 +211,18 @@ CANONICAL(5) CANONICAL(5)
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The network interface addresses that this mail system receives
- mail on.
+ The local network interface addresses that this mail system
+ receives mail on.
<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 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 <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_re</a>-
- <a href="postconf.5.html#remote_header_rewrite_domain">write_domain</a> parameter.
+ Rewrite or add message headers in mail from these clients,
+ updating incomplete addresses with the domain name in $<a href="postconf.5.html#myorigin">myorigin</a>
+ or $<a href="postconf.5.html#mydomain">mydomain</a>, and adding missing headers.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The network interface addresses that this mail system receives
- mail on by way of a proxy or network address translation unit.
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
+ tion unit.
<b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender, header_recipient)</b>
What addresses are subject to address masquerading.
@@ -253,15 +251,17 @@ CANONICAL(5) CANONICAL(5)
set to "-".
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
- append the specified domain name to incomplete addresses.
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
+ <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
+ ers.
<b>SEE ALSO</b>
<a href="cleanup.8.html">cleanup(8)</a>, canonicalize and enqueue mail
<a href="postmap.1.html">postmap(1)</a>, Postfix lookup table manager
<a href="postconf.5.html">postconf(5)</a>, configuration parameters
- <a href="virtual.5.html">virtual(5)</a>, virtual aliasing
+ <a href="virtual.5.html">virtual(5)</a>, <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a>
<b>README FILES</b>
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
diff --git a/html/cleanup.8.html b/html/cleanup.8.html
index 6e662f6..e4ecd43 100644
--- a/html/cleanup.8.html
+++ b/html/cleanup.8.html
@@ -172,26 +172,26 @@ CLEANUP(8) CLEANUP(8)
<b>BEFORE QUEUE MILTER CONTROLS</b>
As of version 2.3, Postfix supports the Sendmail version 8 Milter (mail
- filter) protocol. When mail is not received via the <a href="smtpd.8.html">smtpd(8)</a> server,
+ filter) protocol. When mail is not received via the <a href="smtpd.8.html">smtpd(8)</a> server,
the <a href="cleanup.8.html">cleanup(8)</a> server will simulate SMTP events to the extent that this
is possible. For details see the <a href="MILTER_README.html">MILTER_README</a> document.
<b><a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a> (empty)</b>
- A list of Milter (mail filter) applications for new mail that
+ A list of Milter (mail filter) applications for new mail that
does not arrive 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 protocol exten-
- sions for communication with a Milter application; prior to
+ The mail filter protocol version and optional protocol exten-
+ sions for communication with a Milter application; prior to
Postfix 2.6 the default protocol 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) response is
- unavailable (for example, bad Postfix configuration or Milter
+ The default action when a Milter (mail filter) response is
+ unavailable (for example, bad Postfix configuration or Milter
failure).
<b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The {daemon_name} macro value for Milter (mail filter) applica-
+ The {daemon_name} macro value for Milter (mail filter) applica-
tions.
<b><a href="postconf.5.html#milter_macro_v">milter_macro_v</a> ($<a href="postconf.5.html#mail_name">mail_name</a> $<a href="postconf.5.html#mail_version">mail_version</a>)</b>
@@ -202,45 +202,45 @@ CLEANUP(8) CLEANUP(8)
tion, 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 Milter (mail
+ 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 Milter (mail
+ 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
+ The macros that are sent to Milter (mail filter) applications
after completion of an SMTP connection.
<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) applications
+ 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) applications
+ 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) applications
+ 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
+ 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
+ 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_data_macros">milter_end_of_data_macros</a> (see 'postconf -d' output)</b>
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
Available in Postfix version 2.5 and later:
<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) applications
+ The macros that are sent to Milter (mail filter) applications
after the end of the message header.
Available in Postfix version 2.7 and later:
@@ -252,8 +252,8 @@ CLEANUP(8) CLEANUP(8)
Available in Postfix version 3.1 and later:
<b><a href="postconf.5.html#milter_macro_defaults">milter_macro_defaults</a> (empty)</b>
- Optional list of <i>name=value</i> pairs that specify default values
- for arbitrary macros that Postfix may send to Milter applica-
+ Optional list of <i>name=value</i> pairs that specify default values
+ for arbitrary macros that Postfix may send to Milter applica-
tions.
<b>MIME PROCESSING CONTROLS</b>
@@ -279,82 +279,83 @@ CLEANUP(8) CLEANUP(8)
ing information.
<b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b>
- Reject mail with invalid Content-Transfer-Encoding: information
+ Reject mail with invalid Content-Transfer-Encoding: information
for the message/* or multipart/* MIME content types.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#detect_8bit_encoding_header">detect_8bit_encoding_header</a> (yes)</b>
- Automatically detect 8BITMIME body content by looking at Con-
- tent-Transfer-Encoding: message headers; historically, this
+ Automatically detect 8BITMIME body content by looking at Con-
+ tent-Transfer-Encoding: message headers; historically, this
behavior was hard-coded to be "always on".
<b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
- Postfix can automatically add BCC (blind carbon copy) when mail enters
+ Postfix can automatically add BCC (blind carbon copy) when mail enters
the mail system:
<b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b>
- Optional address that receives a "blind carbon copy" of each
+ Optional address that receives a "blind carbon copy" of each
message that is received by the Postfix mail system.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b>
- Optional BCC (blind carbon-copy) address lookup tables, indexed
- by sender address.
+ Optional BCC (blind carbon-copy) address lookup tables, indexed
+ by envelope sender address.
<b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
- Optional BCC (blind carbon-copy) address lookup tables, indexed
- by recipient address.
+ Optional BCC (blind carbon-copy) address lookup tables, indexed
+ by envelope recipient address.
<b>ADDRESS TRANSFORMATION CONTROLS</b>
- Address rewriting is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> daemon. The
+ Address rewriting is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> daemon. The
<a href="cleanup.8.html"><b>cleanup</b>(8)</a> server implements table driven address mapping.
<b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
The recipient of mail addressed to the null address.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for message headers and
+ 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>
- Optional address mapping lookup tables for envelope and header
+ Optional address mapping lookup tables for envelope and header
recipient addresses.
<b><a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for envelope and header
+ Optional address mapping lookup tables for envelope and header
sender addresses.
<b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender, header_recipient)</b>
What addresses are subject to address masquerading.
<b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
- Optional list of domains whose subdomain structure will be
+ Optional list of domains whose subdomain structure will be
stripped off in email addresses.
<b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
- Optional list of user names that are not subjected to address
- masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquer</a>-
+ Optional list of user names that are not subjected to address
+ masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquer</a>-
<a href="postconf.5.html#masquerade_domains">ade_domains</a>.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
Available before Postfix version 2.0:
<b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
- Optional lookup tables with a) names of domains for which all
- addresses are aliased to addresses in other local or remote
+ Optional lookup tables with a) names of domains for which all
+ addresses are aliased to addresses in other local or remote
domains, and b) addresses that are aliased to addresses in other
local or remote domains.
Available in Postfix version 2.0 and later:
<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 address.
+ Optional lookup tables with aliases that apply to all recipi-
+ ents: <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote; this is unlike <a href="postconf.5.html#alias_maps">alias_maps</a>
+ that apply only to <a href="local.8.html"><b>local</b>(8)</a> recipients.
Available in Postfix version 2.2 and later:
@@ -371,9 +372,11 @@ CLEANUP(8) CLEANUP(8)
ping.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
- append the specified domain name to incomplete addresses.
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
+ <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
+ ers.
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
@@ -433,7 +436,7 @@ CLEANUP(8) CLEANUP(8)
<b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b>
Enable preliminary SMTPUTF8 support for the protocols described
- in <a href="https://tools.ietf.org/html/rfc6531">RFC 6531</a>..6533.
+ in <a href="https://tools.ietf.org/html/rfc6531">RFC 6531</a>, <a href="https://tools.ietf.org/html/rfc6532">RFC 6532</a>, and <a href="https://tools.ietf.org/html/rfc6533">RFC 6533</a>.
<b><a href="postconf.5.html#smtputf8_autodetect_classes">smtputf8_autodetect_classes</a> (sendmail, verify)</b>
Detect that a message requires SMTPUTF8 support for the speci-
@@ -520,6 +523,13 @@ CLEANUP(8) CLEANUP(8)
The email address form that will be used in non-debug logging
(info, warning, etc.).
+ Available in Postfix 3.9 and later:
+
+ <b><a href="postconf.5.html#force_mime_input_conversion">force_mime_input_conversion</a> (no)</b>
+ Convert body content that claims to be 8-bit into quoted-print-
+ able, before <a href="postconf.5.html#header_checks">header_checks</a>, <a href="postconf.5.html#body_checks">body_checks</a>, Milters, and before
+ after-queue content filters.
+
<b>FILES</b>
/etc/postfix/canonical*, canonical mapping table
/etc/postfix/virtual*, virtual mapping table
diff --git a/html/dnsblog.8.html b/html/dnsblog.8.html
index 250b046..2028fa1 100644
--- a/html/dnsblog.8.html
+++ b/html/dnsblog.8.html
@@ -49,8 +49,8 @@ DNSBLOG(8) DNSBLOG(8)
request before it is terminated by a built-in watchdog timer.
<b><a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> (empty)</b>
- Optional list of DNS allow/denylist domains, filters and weight
- factors.
+ Optional list of patterns with DNS allow/denylist domains, fil-
+ ters and weight factors.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
The time limit for sending or receiving information over an
diff --git a/html/generic.5.html b/html/generic.5.html
index 813d47e..c1a8a30 100644
--- a/html/generic.5.html
+++ b/html/generic.5.html
@@ -182,25 +182,26 @@ GENERIC(5) GENERIC(5)
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The network interface addresses that this mail system receives
- mail on.
+ The local network interface addresses that this mail system
+ receives mail on.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The network interface addresses that this mail system receives
- mail on by way of a proxy or network address translation unit.
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
+ tion unit.
<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>, localhost)</b>
- The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
+ 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#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The domain name that locally-posted mail appears to come from,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#owner_request_special">owner_request_special</a> (yes)</b>
- Enable special treatment for owner-<i>listname</i> entries in the
+ Enable special treatment for owner-<i>listname</i> entries in the
<a href="aliases.5.html"><b>aliases</b>(5)</a> file, and don't split owner-<i>listname</i> and <i>list-</i>
- <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
+ <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
set to "-".
<b>SEE ALSO</b>
diff --git a/html/header_checks.5.html b/html/header_checks.5.html
index 6bb114a..c1c8b17 100644
--- a/html/header_checks.5.html
+++ b/html/header_checks.5.html
@@ -392,40 +392,31 @@ HEADER_CHECKS(5) HEADER_CHECKS(5)
<b>Return-Path:</b>.
<b>CONFIGURATION PARAMETERS</b>
- <b><a href="postconf.5.html#body_checks">body_checks</a></b>
- Lookup tables with content filter rules for message body lines.
- These filters see one physical line at a time, in chunks of at
- most <b>$<a href="postconf.5.html#line_length_limit">line_length_limit</a></b> bytes.
-
- <b><a href="postconf.5.html#body_checks_size_limit">body_checks_size_limit</a></b>
- The amount of content per message body segment (attachment) that
- is subjected to <b>$<a href="postconf.5.html#body_checks">body_checks</a></b> filtering.
-
- <b><a href="postconf.5.html#header_checks">header_checks</a></b>
-
- <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a></b> (default: <b>$<a href="postconf.5.html#header_checks">header_checks</a></b>)
-
- <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a></b> (default: <b>$<a href="postconf.5.html#header_checks">header_checks</a></b>)
- Lookup tables with content filter rules for message header
- lines: respectively, these are applied to the initial message
- headers (not including MIME headers), to the MIME headers any-
- where in the message, and to the initial headers of attached
- messages.
-
- Note: these filters see one logical message header at a time,
- even when a message header spans multiple lines. Message headers
- that are longer than <b>$<a href="postconf.5.html#header_size_limit">header_size_limit</a></b> characters are trun-
- cated.
-
- <b><a href="postconf.5.html#disable_mime_input_processing">disable_mime_input_processing</a></b>
- While receiving mail, give no special treatment to MIME related
- message headers; all text after the initial message headers is
- considered to be part of the message body. This means that
- <b><a href="postconf.5.html#header_checks">header_checks</a></b> is applied to all the initial message headers, and
- that <b><a href="postconf.5.html#body_checks">body_checks</a></b> is applied to the remainder of the message.
-
- Note: when used in this manner, <b><a href="postconf.5.html#body_checks">body_checks</a></b> will process a
- multi-line message header one line at a time.
+ <b><a href="postconf.5.html#body_checks">body_checks</a> (empty)</b>
+ Optional lookup tables for content inspection as specified in
+ the <a href="header_checks.5.html"><b>body_checks</b>(5)</a> manual page.
+
+ <b><a href="postconf.5.html#body_checks_size_limit">body_checks_size_limit</a> (51200)</b>
+ How much text in a message body segment (or attachment, if you
+ prefer to use that term) is subjected to <a href="postconf.5.html#body_checks">body_checks</a> inspection.
+
+ <b><a href="postconf.5.html#header_checks">header_checks</a> (empty)</b>
+ Optional lookup tables for content inspection of primary
+ non-MIME message headers, as specified in the <a href="header_checks.5.html"><b>header_checks</b>(5)</a>
+ manual page.
+
+ <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
+ Optional lookup tables for content inspection of MIME related
+ message headers, as described in the <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual
+ page.
+
+ <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
+ Optional lookup tables for content inspection of non-MIME mes-
+ sage headers in attached messages, as described in the
+ <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
+
+ <b><a href="postconf.5.html#disable_mime_input_processing">disable_mime_input_processing</a> (no)</b>
+ Turn off MIME processing while receiving mail.
<b>EXAMPLES</b>
Header pattern to block attachments with bad file name extensions. For
diff --git a/html/index.html b/html/index.html
index 68edc59..a7da6cb 100644
--- a/html/index.html
+++ b/html/index.html
@@ -53,6 +53,8 @@ configuration examples </a>
<li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Safety Net</a>
+<li> <a href="DEPRECATION_README.html"> Deprecated features and alternatives </a>
+
<li> <a href="INSTALL.html"> Installation from source code </a>
</ul>
@@ -141,6 +143,8 @@ Per-client/user/etc. access </a>
<li> <a href="MEMCACHE_README.html"> Memcache Howto </a>
+<li> <a href="MONGODB_README.html"> MongoDB Howto </a>
+
<li> <a href="MYSQL_README.html"> MySQL Howto </a>
<li> <a href="PCRE_README.html"> PCRE Howto </a>
diff --git a/html/lmtp.8.html b/html/lmtp.8.html
index 1144ee8..4cc187c 100644
--- a/html/lmtp.8.html
+++ b/html/lmtp.8.html
@@ -5,88 +5,100 @@
<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
<title> Postfix manual - smtp(8) </title>
</head> <body> <pre>
-SMTP(8) SMTP(8)
+SMTP,(LMTP) SMTP,(LMTP)
<b>NAME</b>
- smtp - Postfix SMTP+LMTP client
+ smtp, lmtp - Postfix SMTP+LMTP client
<b>SYNOPSIS</b>
<b>smtp</b> [generic Postfix daemon options] [flags=DORX]
+ <b>lmtp</b> [generic Postfix daemon options] [flags=DORX]
+
<b>DESCRIPTION</b>
The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery
protocols. It processes message delivery requests from the queue man-
ager. Each request specifies a queue file, a sender address, a domain
or host to deliver to, and recipient information. This program expects
- to be run from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
+ to be run from the <a href="master.8.html"><b>master</b>(8)</a> process manager. The process name, <b>smtp</b> or
+ <b>lmtp</b>, controls the protocol, and the names of the configuration parame-
+ ters that will be used.
The SMTP+LMTP client updates the queue file and marks recipients as
finished, or it informs the queue manager that delivery should be tried
again at a later time. Delivery status reports are sent to the
<a href="bounce.8.html"><b>bounce</b>(8)</a>, <a href="defer.8.html"><b>defer</b>(8)</a> or <a href="trace.8.html"><b>trace</b>(8)</a> daemon as appropriate.
- The SMTP+LMTP client looks up a list of mail exchanger addresses for
- the destination host, sorts the list by preference, and connects to
- each listed address until it finds a server that responds.
-
- When a server is not reachable, or when mail delivery fails due to a
- recoverable error condition, the SMTP+LMTP client will try to deliver
- the mail to an alternate host.
+ The server lookup strategy is different for SMTP and LMTP, as described
+ in the sections "SMTP SERVER LOOKUP" and "LMTP SERVER LOOKUP".
- After a successful mail transaction, a connection may be saved to the
- <a href="scache.8.html"><b>scache</b>(8)</a> connection cache server, so that it may be used by any
+ After a successful mail transaction, a connection may be saved to the
+ <a href="scache.8.html"><b>scache</b>(8)</a> connection cache server, so that it may be used by any
SMTP+LMTP client for a subsequent transaction.
- By default, connection caching is enabled temporarily for destinations
+ By default, connection caching is enabled temporarily for destinations
that have a high volume of mail in the <a href="QSHAPE_README.html#active_queue">active queue</a>. Connection caching
can be enabled permanently for specific destinations.
-<b>SMTP DESTINATION SYNTAX</b>
- The Postfix SMTP+LMTP client supports multiple destinations separated
- by comma or whitespace (Postfix 3.5 and later). SMTP destinations have
- the following form:
+<b>SMTP SERVER LOOKUP</b>
+ The Postfix SMTP client supports multiple destinations separated by
+ comma or whitespace (Postfix 3.5 and later). Each destination is tried
+ in the specified order.
+
+ SMTP destinations have the following form:
<i>domainname</i>
- <i>domainname</i>:<i>port</i>
- Look up the mail exchangers for the specified domain, and con-
- nect to the specified port (default: <b>smtp</b>).
+ <i>domainname</i>:<i>service</i>
+ Look up the mail exchangers for the specified domain, and con-
+ nect to the specified service (default: <b>smtp</b>). Optionally, mail
+ exchangers may be looked up with SRV queries instead of MX; this
+ requires that <i>service</i> is given in symbolic form.
[<i>hostname</i>]
- [<i>hostname</i>]:<i>port</i>
- Look up the address(es) of the specified host, and connect to
- the specified port (default: <b>smtp</b>).
+ [<i>hostname</i>]:<i>service</i>
+ Look up the address(es) for the specified host, and connect to
+ the specified service (default: <b>smtp</b>).
[<i>address</i>]
- [<i>address</i>]:<i>port</i>
+ [<i>address</i>]:<i>service</i>
Connect to the host at the specified address, and connect to the
- specified port (default: <b>smtp</b>). An IPv6 address must be format-
- ted as [<b>ipv6</b>:<i>address</i>].
+ specified service (default: <b>smtp</b>). An IPv6 address must be for-
+ matted as [<b>ipv6</b>:<i>address</i>].
-<b>LMTP DESTINATION SYNTAX</b>
- The Postfix SMTP+LMTP client supports multiple destinations separated
- by comma or whitespace (Postfix 3.5 and later). LMTP destinations have
- the following form:
+<b>LMTP SERVER LOOKUP</b>
+ The Postfix LMTP client supports multiple destinations separated by
+ comma or whitespace (Postfix 3.5 and later). Each destination is tried
+ in the specified order.
+
+ LMTP destinations have the following form:
<b>unix</b>:<i>pathname</i>
- Connect to the local UNIX-domain server that is bound to the
- specified <i>pathname</i>. If the process runs chrooted, an absolute
+ Connect to the local UNIX-domain server that is bound to the
+ specified <i>pathname</i>. If the process runs chrooted, an absolute
pathname is interpreted relative to the Postfix queue directory.
+ <b>inet</b>:<i>domainname</i>
+
+ <b>inet</b>:<i>domainname</i>:<i>service</i>
+ Look up the LMTP servers for the specified domain and service
+ (default: <b>lmtp</b>). This form is supported when SRV lookups are
+ enabled, and requires that <i>service</i> is in symbolic form.
+
<b>inet</b>:<i>hostname</i>
- <b>inet</b>:<i>hostname</i>:<i>port</i>
+ <b>inet</b>:<i>hostname</i>:<i>service</i>
+ Look up the address(es) for the specified host, and connect to
+ the specified service (default: <b>lmtp</b>). When SRV lookups are
+ enabled, use the form <b>[</b><i>hostname</i><b>]</b> to force address lookups.
<b>inet</b>:[<i>address</i>]
- <b>inet</b>:[<i>address</i>]:<i>port</i>
- Connect to the specified TCP port on the specified local or
- remote host. If no port is specified, connect to the port
- defined as <b>lmtp</b> in <b>services</b>(4). If no such service is found,
- the <b><a href="postconf.5.html#lmtp_tcp_port">lmtp_tcp_port</a></b> configuration parameter (default value of 24)
- will be used. An IPv6 address must be formatted as
+ <b>inet</b>:[<i>address</i>]:<i>service</i>
+ Connect to the specified local or remote host and service
+ (default: <b>lmtp</b>). An IPv6 address must be formatted as
[<b>ipv6</b>:<i>address</i>].
<b>SINGLE-RECIPIENT DELIVERY</b>
@@ -136,10 +148,9 @@ SMTP(8) SMTP(8)
This feature is available as of Postfix 3.5.
<b>SECURITY</b>
- The SMTP+LMTP client is moderately security-sensitive. It
- talks to SMTP or LMTP servers and to DNS servers on the
- network. The SMTP+LMTP client can be run chrooted at fixed
- low privilege.
+ The SMTP+LMTP client is moderately security-sensitive. It talks to SMTP
+ or LMTP servers and to DNS servers on the network. The SMTP+LMTP client
+ can be run chrooted at fixed low privilege.
<b>STANDARDS</b>
<a href="https://tools.ietf.org/html/rfc821">RFC 821</a> (SMTP protocol)
@@ -180,20 +191,19 @@ SMTP(8) SMTP(8)
for all destinations that map onto the same IP address and TCP port.
<b>CONFIGURATION PARAMETERS</b>
- Before Postfix version 2.3, the LMTP client is a separate program that
- implements only a subset of the functionality available with SMTP:
- there is no support for TLS, and connections are cached in-process,
- making it ineffective when the client is used for multiple domains.
+ Postfix versions 2.3 and later implement the SMTP and LMTP client with
+ the same program, and choose the protocol and configuration parameters
+ based on the process name, <b>smtp</b> or <b>lmtp</b>.
Most smtp_<i>xxx</i> configuration parameters have an lmtp_<i>xxx</i> "mirror" param-
- eter for the equivalent LMTP feature. This document describes only
+ eter for the equivalent LMTP feature. This document describes only
those LMTP-related parameters that aren't simply "mirror" parameters.
- Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="smtp.8.html"><b>smtp</b>(8)</a> processes
+ Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="smtp.8.html"><b>smtp</b>(8)</a> processes
run for only a limited amount of time. Use the command "<b>postfix reload</b>"
to speed up a change.
- 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>COMPATIBILITY CONTROLS</b>
@@ -214,8 +224,8 @@ SMTP(8) SMTP(8)
will send via SMTP.
<b><a href="postconf.5.html#smtp_pix_workaround_delay_time">smtp_pix_workaround_delay_time</a> (10s)</b>
- How long the Postfix SMTP client pauses before sending
- ".&lt;CR&gt;&lt;LF&gt;" in order to work around the PIX firewall
+ How long the Postfix SMTP client pauses before sending
+ ".&lt;CR&gt;&lt;LF&gt;" in order to work around the PIX firewall
"&lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;" bug.
<b><a href="postconf.5.html#smtp_pix_workaround_threshold_time">smtp_pix_workaround_threshold_time</a> (500s)</b>
@@ -224,19 +234,19 @@ SMTP(8) SMTP(8)
delivery through firewalls with "smtp fixup" mode turned on.
<b><a href="postconf.5.html#smtp_pix_workarounds">smtp_pix_workarounds</a> (disable_esmtp, delay_dotcrlf)</b>
- A list that specifies zero or more workarounds for CISCO PIX
+ A list that specifies zero or more workarounds for CISCO PIX
firewall bugs.
<b><a href="postconf.5.html#smtp_pix_workaround_maps">smtp_pix_workaround_maps</a> (empty)</b>
- Lookup tables, indexed by the remote SMTP server address, with
+ Lookup tables, indexed by the remote SMTP server address, with
per-destination workarounds for CISCO PIX firewall bugs.
<b><a href="postconf.5.html#smtp_quote_rfc821_envelope">smtp_quote_rfc821_envelope</a> (yes)</b>
- Quote addresses in Postfix SMTP client MAIL FROM and RCPT TO
+ Quote addresses in Postfix SMTP client MAIL FROM and RCPT TO
commands as required by <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a>.
<b><a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> (empty)</b>
- A mechanism to transform replies from remote SMTP servers one
+ A mechanism to transform replies from remote SMTP servers one
line at a time.
<b><a href="postconf.5.html#smtp_skip_5xx_greeting">smtp_skip_5xx_greeting</a> (yes)</b>
@@ -248,68 +258,68 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.0 and earlier:
<b><a href="postconf.5.html#smtp_skip_4xx_greeting">smtp_skip_4xx_greeting</a> (yes)</b>
- Skip SMTP servers that greet with a 4XX status code (go away,
+ Skip SMTP servers that greet with a 4XX status code (go away,
try again later).
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtp_discard_ehlo_keyword_address_maps">smtp_discard_ehlo_keyword_address_maps</a> (empty)</b>
- Lookup tables, indexed by the remote SMTP server address, with
- case insensitive lists of EHLO keywords (pipelining, starttls,
+ Lookup tables, indexed by the remote SMTP server address, with
+ case insensitive lists of EHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix SMTP client will ignore in the EHLO
response from a remote SMTP server.
<b><a href="postconf.5.html#smtp_discard_ehlo_keywords">smtp_discard_ehlo_keywords</a> (empty)</b>
- A case insensitive list of EHLO keywords (pipelining, starttls,
+ A case insensitive list of EHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix SMTP client will ignore in the EHLO
response from a remote SMTP server.
<b><a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> (empty)</b>
- Optional lookup tables that perform address rewriting in the
- Postfix SMTP client, typically to transform a locally valid
- address into a globally valid address when sending mail across
+ Optional lookup tables that perform address rewriting in the
+ Postfix SMTP client, typically to transform a locally valid
+ address into a globally valid address when sending mail across
the Internet.
Available in Postfix version 2.2.9 and later:
<b><a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> (version dependent)</b>
- When the remote SMTP servername is a DNS CNAME, replace the
- servername with the result from CNAME expansion for the purpose
- of logging, SASL password lookup, TLS policy decisions, or TLS
+ When the remote SMTP servername is a DNS CNAME, replace the
+ servername with the result from CNAME expansion for the purpose
+ of logging, SASL password lookup, TLS policy decisions, or TLS
certificate verification.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#lmtp_discard_lhlo_keyword_address_maps">lmtp_discard_lhlo_keyword_address_maps</a> (empty)</b>
- Lookup tables, indexed by the remote LMTP server address, with
- case insensitive lists of LHLO keywords (pipelining, starttls,
+ Lookup tables, indexed by the remote LMTP server address, with
+ case insensitive lists of LHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix LMTP client will ignore in the LHLO
response from a remote LMTP server.
<b><a href="postconf.5.html#lmtp_discard_lhlo_keywords">lmtp_discard_lhlo_keywords</a> (empty)</b>
- A case insensitive list of LHLO keywords (pipelining, starttls,
+ A case insensitive list of LHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix LMTP client will ignore in the LHLO
response from a remote LMTP server.
Available in Postfix version 2.4.4 and later:
<b><a href="postconf.5.html#send_cyrus_sasl_authzid">send_cyrus_sasl_authzid</a> (no)</b>
- When authenticating to a remote SMTP or LMTP server with the
- default setting "no", send no SASL authoriZation ID (authzid);
- send only the SASL authentiCation ID (authcid) plus the auth-
+ When authenticating to a remote SMTP or LMTP server with the
+ default setting "no", send no SASL authoriZation ID (authzid);
+ send only the SASL authentiCation ID (authcid) plus the auth-
cid's password.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtp_header_checks">smtp_header_checks</a> (empty)</b>
- Restricted <a href="header_checks.5.html"><b>header_checks</b>(5)</a> tables for the Postfix SMTP client.
+ Restricted <a href="header_checks.5.html"><b>header_checks</b>(5)</a> tables for the Postfix SMTP client.
<b><a href="postconf.5.html#smtp_mime_header_checks">smtp_mime_header_checks</a> (empty)</b>
- Restricted <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a></b>(5) tables for the Postfix SMTP
+ Restricted <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a></b>(5) tables for the Postfix SMTP
client.
<b><a href="postconf.5.html#smtp_nested_header_checks">smtp_nested_header_checks</a> (empty)</b>
- Restricted <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a></b>(5) tables for the Postfix SMTP
+ Restricted <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a></b>(5) tables for the Postfix SMTP
client.
<b><a href="postconf.5.html#smtp_body_checks">smtp_body_checks</a> (empty)</b>
@@ -318,7 +328,7 @@ SMTP(8) SMTP(8)
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 window scal-
+ An optional workaround for routers that break TCP window scal-
ing.
Available in Postfix version 2.8 and later:
@@ -329,16 +339,16 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.9 - 3.6:
<b><a href="postconf.5.html#smtp_per_record_deadline">smtp_per_record_deadline</a> (no)</b>
- Change the behavior of the smtp_*_timeout time limits, from a
- time limit per read or write system call, to a time limit to
- send or receive a complete record (an SMTP command line, SMTP
- response line, SMTP message content line, or TLS protocol mes-
+ Change the behavior of the smtp_*_timeout time limits, from a
+ time limit per read or write system call, to a time limit to
+ send or receive a complete record (an SMTP command line, SMTP
+ response line, SMTP message content line, or TLS protocol mes-
sage).
Available in Postfix version 2.9 and later:
<b><a href="postconf.5.html#smtp_send_dummy_mail_auth">smtp_send_dummy_mail_auth</a> (no)</b>
- Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
+ Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
command in SASL-authenticated SMTP sessions.
Available in Postfix version 2.11 and later:
@@ -349,7 +359,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 3.0 and later:
<b><a href="postconf.5.html#smtp_delivery_status_filter">smtp_delivery_status_filter</a> ($<a href="postconf.5.html#default_delivery_status_filter">default_delivery_status_filter</a>)</b>
- Optional filter for the <a href="smtp.8.html"><b>smtp</b>(8)</a> delivery agent to change the
+ Optional filter for the <a href="smtp.8.html"><b>smtp</b>(8)</a> delivery agent to change the
delivery status code or explanatory text of successful or unsuc-
cessful deliveries.
@@ -359,38 +369,38 @@ SMTP(8) SMTP(8)
Available in Postfix version 3.3 and later:
<b><a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> (yes)</b>
- When a remote destination resolves to a combination of IPv4 and
+ When a remote destination resolves to a combination of IPv4 and
IPv6 addresses, ensure that the Postfix SMTP client can try both
address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>.
Available in Postfix 3.5 and later:
<b><a href="postconf.5.html#info_log_address_format">info_log_address_format</a> (external)</b>
- The email address form that will be used in non-debug logging
+ The email address form that will be used in non-debug logging
(info, warning, etc.).
Available in Postfix 3.6 and later:
<b><a href="postconf.5.html#dnssec_probe">dnssec_probe</a> (ns:.)</b>
- The DNS query type (default: "ns") and DNS query name (default:
+ The DNS query type (default: "ns") and DNS query name (default:
".") that Postfix may use to determine whether DNSSEC validation
is available.
- <b><a href="postconf.5.html#known_tcp_ports">known_tcp_ports</a> (lmtp=24, smtp=25, smtps=submissions=465, submis-</b>
+ <b><a href="postconf.5.html#known_tcp_ports">known_tcp_ports</a> (lmtp=24, smtp=25, smtps=submissions=465, submis-</b>
<b>sion=587)</b>
- Optional setting that avoids lookups in the <b>services</b>(5) data-
+ Optional setting that avoids lookups in the <b>services</b>(5) data-
base.
Available in Postfix version 3.7 and later:
<b><a href="postconf.5.html#smtp_per_request_deadline">smtp_per_request_deadline</a> (no)</b>
- Change the behavior of the smtp_*_timeout time limits, from a
- time limit per plaintext or TLS read or write call, to a com-
- bined time limit for sending a complete SMTP request and for
+ Change the behavior of the smtp_*_timeout time limits, from a
+ time limit per plaintext or TLS read or write call, to a com-
+ bined time limit for sending a complete SMTP request and for
receiving a complete SMTP response.
<b><a href="postconf.5.html#smtp_min_data_rate">smtp_min_data_rate</a> (500)</b>
- The minimum plaintext data transfer rate in bytes/second for
+ The minimum plaintext data transfer rate in bytes/second for
DATA requests, when deadlines are enabled with
<a href="postconf.5.html#smtp_per_request_deadline">smtp_per_request_deadline</a>.
@@ -400,16 +410,16 @@ SMTP(8) SMTP(8)
Available in Postfix version 3.8 and later:
<b><a href="postconf.5.html#use_srv_lookup">use_srv_lookup</a> (empty)</b>
- Enables discovery for the specified service(s) using DNS SRV
+ Enables discovery for the specified service(s) using DNS SRV
records.
<b><a href="postconf.5.html#ignore_srv_lookup_error">ignore_srv_lookup_error</a> (no)</b>
- When SRV record lookup fails, fall back to MX or IP address
+ When SRV record lookup fails, fall back to MX or IP address
lookup as if SRV record lookup was not enabled.
<b><a href="postconf.5.html#allow_srv_lookup_fallback">allow_srv_lookup_fallback</a> (no)</b>
- When SRV record lookup fails or no SRV record exists, fall back
- to MX or IP address lookup as if SRV record lookup was not
+ When SRV record lookup fails or no SRV record exists, fall back
+ to MX or IP address lookup as if SRV record lookup was not
enabled.
<b>MIME PROCESSING CONTROLS</b>
@@ -428,7 +438,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtp_send_xforward_command">smtp_send_xforward_command</a> (no)</b>
- Send the non-standard XFORWARD command when the Postfix SMTP
+ Send the non-standard XFORWARD command when the Postfix SMTP
server EHLO response announces XFORWARD support.
<b>SASL AUTHENTICATION CONTROLS</b>
@@ -436,60 +446,66 @@ SMTP(8) SMTP(8)
Enable SASL authentication in the Postfix SMTP client.
<b><a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> (empty)</b>
- Optional Postfix SMTP client lookup tables with one user-
- name:password entry per sender, remote hostname or next-hop
+ Optional Postfix SMTP client lookup tables with one user-
+ name:password entry per sender, remote hostname or next-hop
domain.
<b><a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_security_options</a> (noplaintext, noanonymous)</b>
Postfix SMTP client SASL security options; as of Postfix 2.3 the
- list of available features depends on the SASL client implemen-
+ list of available features depends on the SASL client implemen-
tation that is selected with <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b>.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtp_sasl_mechanism_filter">smtp_sasl_mechanism_filter</a> (empty)</b>
- If non-empty, a Postfix SMTP client filter for the remote SMTP
+ If non-empty, a Postfix SMTP client filter for the remote SMTP
server's list of offered SASL mechanisms.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtp_sender_dependent_authentication">smtp_sender_dependent_authentication</a> (no)</b>
Enable sender-dependent authentication in the Postfix SMTP
- client; this is available only with SASL authentication, and
- disables SMTP connection caching to ensure that mail from dif-
+ client; this is available only with SASL authentication, and
+ disables SMTP connection caching to ensure that mail from dif-
ferent senders will use the appropriate credentials.
<b><a href="postconf.5.html#smtp_sasl_path">smtp_sasl_path</a> (empty)</b>
Implementation-specific information that the Postfix SMTP client
- passes through to the SASL plug-in implementation that is
+ passes through to the SASL plug-in implementation that is
selected with <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b>.
<b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a> (cyrus)</b>
- The SASL plug-in type that the Postfix SMTP client should use
+ The SASL plug-in type that the Postfix SMTP client should use
for authentication.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> (empty)</b>
- An optional table to prevent repeated SASL authentication fail-
- ures with the same remote SMTP server hostname, username and
+ An optional table to prevent repeated SASL authentication fail-
+ ures with the same remote SMTP server hostname, username and
password.
<b><a href="postconf.5.html#smtp_sasl_auth_cache_time">smtp_sasl_auth_cache_time</a> (90d)</b>
- The maximal age of an <a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> entry before it
+ The maximal age of an <a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> entry before it
is removed.
<b><a href="postconf.5.html#smtp_sasl_auth_soft_bounce">smtp_sasl_auth_soft_bounce</a> (yes)</b>
- When a remote SMTP server rejects a SASL authentication request
- with a 535 reply code, defer mail delivery instead of returning
+ When a remote SMTP server rejects a SASL authentication request
+ with a 535 reply code, defer mail delivery instead of returning
mail as undeliverable.
Available in Postfix version 2.9 and later:
<b><a href="postconf.5.html#smtp_send_dummy_mail_auth">smtp_send_dummy_mail_auth</a> (no)</b>
- Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
+ Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
command in SASL-authenticated SMTP sessions.
+ Available in Postfix version 3.9 and later:
+
+ <b><a href="postconf.5.html#smtp_sasl_password_result_delimiter">smtp_sasl_password_result_delimiter</a> (:)</b>
+ The delimiter between username and password in sasl_passwd_maps
+ lookup results.
+
<b>STARTTLS SUPPORT CONTROLS</b>
Detailed information about STARTTLS configuration may be found in the
<a href="TLS_README.html">TLS_README</a> document.
@@ -619,7 +635,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.6 and later:
- <b><a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> (see postconf -d output)</b>
+ <b><a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> (see 'postconf -d' output)</b>
TLS protocols that the Postfix SMTP client will use with oppor-
tunistic TLS encryption.
@@ -724,6 +740,12 @@ SMTP(8) SMTP(8)
The application name passed by Postfix to OpenSSL library ini-
tialization functions.
+ Available in Postfix version 3.9 and later:
+
+ <b><a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> (no)</b>
+ Request that remote SMTP servers send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+ instead of an X.509 certificate.
+
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compatibility with
Postfix versions before 2.3. Support for these will be removed in a
@@ -954,7 +976,7 @@ SMTP(8) SMTP(8)
The local network interface addresses that this mail system
receives mail on.
- <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d output')</b>
+ <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d' output)</b>
The Internet protocols Postfix will attempt to use when making
or accepting connections.
@@ -1119,5 +1141,5 @@ SMTP(8) SMTP(8)
Victor Duchovni
Morgan Stanley
- SMTP(8)
+ 8 SMTP,(LMTP)
</pre> </body> </html>
diff --git a/html/local.8.html b/html/local.8.html
index fce3d04..a923ce2 100644
--- a/html/local.8.html
+++ b/html/local.8.html
@@ -178,40 +178,42 @@ LOCAL(8) LOCAL(8)
replaced with underscores. The list of acceptable characters is speci-
fied with the <b><a href="postconf.5.html#command_expansion_filter">command_expansion_filter</a></b> configuration parameter.
- <b>SHELL</b> The recipient user's login shell.
+ <b>SHELL</b> The envelope recipient user's login shell.
- <b>HOME</b> The recipient user's home directory.
+ <b>HOME</b> The envelope recipient user's home directory.
- <b>USER</b> The bare recipient name.
+ <b>USER</b> The bare envelope recipient name.
<b>EXTENSION</b>
- The optional recipient address extension.
+ The optional envelope recipient address extension.
- <b>DOMAIN</b> The recipient address domain part.
+ <b>DOMAIN</b> The envelope recipient address domain part.
<b>LOGNAME</b>
- The bare recipient name.
+ The bare envelope recipient name.
- <b>LOCAL</b> The entire recipient address localpart (text to the left of the
- rightmost @ character).
+ <b>LOCAL</b> The entire envelope recipient address localpart (text to the
+ left of the rightmost @ character).
<b>ORIGINAL_RECIPIENT</b>
- The entire recipient address, before any address rewriting or
- aliasing (Postfix 2.5 and later).
+ The entire envelope recipient address, before any address
+ rewriting or aliasing (Postfix 2.5 and later).
<b>RECIPIENT</b>
- The entire recipient address.
+ The entire envelope recipient address.
- <b>SENDER</b> The entire sender address.
+ <b>SENDER</b> The entire envelope sender address.
- Additional remote client information is made available via the follow-
+ <b>ENVID</b> The optional <a href="https://tools.ietf.org/html/rfc3461">RFC 3461</a> envelope ID. Available as of Postfix 3.9.
+
+ Additional remote client information is made available via the follow-
ing environment variables:
<b>CLIENT_ADDRESS</b>
Remote client network address. Available as of Postfix 2.2.
<b>CLIENT_HELO</b>
- Remote client EHLO command parameter. Available as of Postfix
+ Remote client EHLO command parameter. Available as of Postfix
2.2.
<b>CLIENT_HOSTNAME</b>
@@ -221,69 +223,69 @@ LOCAL(8) LOCAL(8)
Remote client protocol. Available as of Postfix 2.2.
<b>SASL_METHOD</b>
- SASL authentication method specified in the remote client AUTH
+ SASL authentication method specified in the remote client AUTH
command. Available as of Postfix 2.2.
<b>SASL_SENDER</b>
- SASL sender address specified in the remote client MAIL FROM
+ SASL sender address specified in the remote client MAIL FROM
command. Available as of Postfix 2.2.
<b>SASL_USERNAME</b>
- SASL username specified in the remote client AUTH command.
+ SASL username specified in the remote client AUTH command.
Available as of Postfix 2.2.
- The <b>PATH</b> environment variable is always reset to a system-dependent
- default path, and environment variables whose names are blessed by the
+ The <b>PATH</b> environment variable is always reset to a system-dependent
+ default path, and environment variables whose names are blessed by the
<b><a href="postconf.5.html#export_environment">export_environment</a></b> configuration parameter are exported unchanged.
The current working directory is the mail queue directory.
The <a href="local.8.html"><b>local</b>(8)</a> daemon prepends a "<b>From</b> <i>sender time</i><b>_</b><i>stamp</i>" envelope header
- to each message, prepends an <b>X-Original-To:</b> header with the recipient
- address as given to Postfix, prepends an optional <b>Delivered-To:</b> header
- with the final recipient envelope address, prepends a <b>Return-Path:</b>
+ to each message, prepends an <b>X-Original-To:</b> header with the recipient
+ address as given to Postfix, prepends an optional <b>Delivered-To:</b> header
+ with the final recipient envelope address, prepends a <b>Return-Path:</b>
header with the sender envelope address, and appends no empty line.
<b>EXTERNAL FILE DELIVERY</b>
- The delivery format depends on the destination filename syntax. The
- default is to use UNIX-style mailbox format. Specify a name ending in
+ The delivery format depends on the destination filename syntax. The
+ default is to use UNIX-style mailbox format. Specify a name ending in
<b>/</b> for <b>qmail</b>-compatible <b>maildir</b> delivery.
- The <b><a href="postconf.5.html#allow_mail_to_files">allow_mail_to_files</a></b> configuration parameter restricts delivery to
- external files. The default setting (<b>alias, forward</b>) forbids file des-
+ The <b><a href="postconf.5.html#allow_mail_to_files">allow_mail_to_files</a></b> configuration parameter restricts delivery to
+ external files. The default setting (<b>alias, forward</b>) forbids file des-
tinations in <b>:include:</b> files.
- In the case of UNIX-style mailbox delivery, the <a href="local.8.html"><b>local</b>(8)</a> daemon
- prepends a "<b>From</b> <i>sender time</i><b>_</b><i>stamp</i>" envelope header to each message,
- prepends an <b>X-Original-To:</b> header with the recipient address as given
- to Postfix, prepends an optional <b>Delivered-To:</b> header with the final
- recipient envelope address, prepends a &gt; character to lines beginning
- with "<b>From</b> ", and appends an empty line. The envelope sender address
- is available in the <b>Return-Path:</b> header. When the destination is a
- regular file, it is locked for exclusive access while delivery is in
+ In the case of UNIX-style mailbox delivery, the <a href="local.8.html"><b>local</b>(8)</a> daemon
+ prepends a "<b>From</b> <i>sender time</i><b>_</b><i>stamp</i>" envelope header to each message,
+ prepends an <b>X-Original-To:</b> header with the recipient address as given
+ to Postfix, prepends an optional <b>Delivered-To:</b> header with the final
+ recipient envelope address, prepends a &gt; character to lines beginning
+ with "<b>From</b> ", and appends an empty line. The envelope sender address
+ is available in the <b>Return-Path:</b> header. When the destination is a
+ regular file, it is locked for exclusive access while delivery is in
progress. In case of problems, an attempt is made to truncate a regular
file to its original length.
- In the case of <b>maildir</b> delivery, the local daemon prepends an optional
- <b>Delivered-To:</b> header with the final envelope recipient address, and
- prepends an <b>X-Original-To:</b> header with the recipient address as given
- to Postfix. The envelope sender address is available in the
+ In the case of <b>maildir</b> delivery, the local daemon prepends an optional
+ <b>Delivered-To:</b> header with the final envelope recipient address, and
+ prepends an <b>X-Original-To:</b> header with the recipient address as given
+ to Postfix. The envelope sender address is available in the
<b>Return-Path:</b> header.
<b>ADDRESS EXTENSION</b>
- The optional <b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a></b> configuration parameter specifies how
+ The optional <b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a></b> configuration parameter specifies how
to separate address extensions from local recipient names.
- For example, with "<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> = +</b>", mail for <i>name</i>+<i>foo</i> is
- delivered to the alias <i>name</i>+<i>foo</i> or to the alias <i>name</i>, to the destina-
+ For example, with "<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> = +</b>", mail for <i>name</i>+<i>foo</i> is
+ delivered to the alias <i>name</i>+<i>foo</i> or to the alias <i>name</i>, to the destina-
tions listed in ~<i>name</i>/.<b>forward</b>+<i>foo</i> or in ~<i>name</i>/.<b>forward</b>, to the mailbox
owned by the user <i>name</i>, or it is sent back as undeliverable.
<b>DELIVERY RIGHTS</b>
- Deliveries to external files and external commands are made with the
- rights of the receiving user on whose behalf the delivery is made. In
- the absence of a user context, the <a href="local.8.html"><b>local</b>(8)</a> daemon uses the owner
- rights of the <b>:include:</b> file or alias database. When those files are
+ Deliveries to external files and external commands are made with the
+ rights of the receiving user on whose behalf the delivery is made. In
+ the absence of a user context, the <a href="local.8.html"><b>local</b>(8)</a> daemon uses the owner
+ rights of the <b>:include:</b> file or alias database. When those files are
owned by the superuser, delivery is made with the rights specified with
the <b><a href="postconf.5.html#default_privs">default_privs</a></b> configuration parameter.
@@ -292,43 +294,43 @@ LOCAL(8) LOCAL(8)
<a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced status codes)
<b>DIAGNOSTICS</b>
- Problems and transactions are logged to <b>syslogd</b>(8) or <a href="postlogd.8.html"><b>postlogd</b>(8)</a>.
- Corrupted message files are marked so that the queue manager can move
+ Problems and transactions are logged to <b>syslogd</b>(8) or <a href="postlogd.8.html"><b>postlogd</b>(8)</a>.
+ Corrupted message files are marked so that the queue manager can move
them to the <b>corrupt</b> queue afterwards.
- Depending on the setting of the <b><a href="postconf.5.html#notify_classes">notify_classes</a></b> parameter, the postmas-
+ Depending on the setting of the <b><a href="postconf.5.html#notify_classes">notify_classes</a></b> parameter, the postmas-
ter is notified of bounces and of other trouble.
<b>SECURITY</b>
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent needs a dual personality 1) to access the
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent needs a dual personality 1) to access the
private Postfix queue and IPC mechanisms, 2) to impersonate the recipi-
- ent and deliver to recipient-specified files or commands. It is there-
+ ent and deliver to recipient-specified files or commands. It is there-
fore security sensitive.
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent disallows regular expression substitution
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent disallows regular expression substitution
of $1 etc. in <b><a href="postconf.5.html#alias_maps">alias_maps</a></b>, because that would open a security hole.
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent will silently ignore requests to use the
- <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server within <b><a href="postconf.5.html#alias_maps">alias_maps</a></b>. Instead it will open the table
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent will silently ignore requests to use the
+ <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server within <b><a href="postconf.5.html#alias_maps">alias_maps</a></b>. Instead it will open the table
directly. Before Postfix version 2.2, the <a href="local.8.html"><b>local</b>(8)</a> delivery agent will
terminate with a fatal error.
<b>BUGS</b>
- For security reasons, the message delivery status of external commands
- or of external files is never checkpointed to file. As a result, the
- program may occasionally deliver more than once to a command or exter-
+ For security reasons, the message delivery status of external commands
+ or of external files is never checkpointed to file. As a result, the
+ program may occasionally deliver more than once to a command or exter-
nal file. Better safe than sorry.
- Mutually-recursive aliases or ~/.<b>forward</b> files are not detected early.
- The resulting mail forwarding loop is broken by the use of the <b>Deliv-</b>
+ Mutually-recursive aliases or ~/.<b>forward</b> files are not detected early.
+ The resulting mail forwarding loop is broken by the use of the <b>Deliv-</b>
<b>ered-To:</b> message header.
<b>CONFIGURATION PARAMETERS</b>
- Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="local.8.html"><b>local</b>(8)</a> processes
+ Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="local.8.html"><b>local</b>(8)</a> processes
run for only a limited amount of time. Use the command "<b>postfix reload</b>"
to speed up a change.
- 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>COMPATIBILITY CONTROLS</b>
@@ -336,14 +338,14 @@ LOCAL(8) LOCAL(8)
Whether or not to use the local <a href="postconf.5.html#biff">biff</a> service.
<b><a href="postconf.5.html#expand_owner_alias">expand_owner_alias</a> (no)</b>
- When delivering to an alias "<i>aliasname</i>" that has an
+ When delivering to an alias "<i>aliasname</i>" that has an
"owner-<i>aliasname</i>" companion alias, set the envelope sender
address to the expansion of the "owner-<i>aliasname</i>" alias.
<b><a href="postconf.5.html#owner_request_special">owner_request_special</a> (yes)</b>
- Enable special treatment for owner-<i>listname</i> entries in the
+ Enable special treatment for owner-<i>listname</i> entries in the
<a href="aliases.5.html"><b>aliases</b>(5)</a> file, and don't split owner-<i>listname</i> and <i>list-</i>
- <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
+ <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
set to "-".
<b><a href="postconf.5.html#sun_mailtool_compatibility">sun_mailtool_compatibility</a> (no)</b>
@@ -352,62 +354,64 @@ LOCAL(8) LOCAL(8)
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#frozen_delivered_to">frozen_delivered_to</a> (yes)</b>
- Update the <a href="local.8.html"><b>local</b>(8)</a> delivery agent's idea of the Delivered-To:
- address (see <a href="postconf.5.html#prepend_delivered_header">prepend_delivered_header</a>) only once, at the start
- of a delivery attempt; do not update the Delivered-To: address
+ Update the <a href="local.8.html"><b>local</b>(8)</a> delivery agent's idea of the Delivered-To:
+ address (see <a href="postconf.5.html#prepend_delivered_header">prepend_delivered_header</a>) only once, at the start
+ of a delivery attempt; do not update the Delivered-To: address
while expanding aliases or .forward files.
Available in Postfix version 2.5.3 and later:
<b><a href="postconf.5.html#strict_mailbox_ownership">strict_mailbox_ownership</a> (yes)</b>
- Defer delivery when a mailbox file is not owned by its recipi-
+ Defer delivery when a mailbox file is not owned by its recipi-
ent.
<b><a href="postconf.5.html#reset_owner_alias">reset_owner_alias</a> (no)</b>
- Reset the <a href="local.8.html"><b>local</b>(8)</a> delivery agent's idea of the owner-alias
- attribute, when delivering mail to a child alias that does not
+ Reset the <a href="local.8.html"><b>local</b>(8)</a> delivery agent's idea of the owner-alias
+ attribute, when delivering mail to a child alias that does not
have its own owner alias.
Available in Postfix version 3.0 and later:
<b><a href="postconf.5.html#local_delivery_status_filter">local_delivery_status_filter</a> ($<a href="postconf.5.html#default_delivery_status_filter">default_delivery_status_filter</a>)</b>
- Optional filter for the <a href="local.8.html"><b>local</b>(8)</a> delivery agent to change the
- status code or explanatory text of successful or unsuccessful
+ Optional filter for the <a href="local.8.html"><b>local</b>(8)</a> delivery agent to change the
+ status code or explanatory text of successful or unsuccessful
deliveries.
<b>DELIVERY METHOD CONTROLS</b>
- The precedence of <a href="local.8.html"><b>local</b>(8)</a> delivery methods from high to low is:
+ The precedence of <a href="local.8.html"><b>local</b>(8)</a> delivery methods from high to low is:
aliases, .forward files, <a href="postconf.5.html#mailbox_transport_maps">mailbox_transport_maps</a>, <a href="postconf.5.html#mailbox_transport">mailbox_transport</a>,
- <a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a>, <a href="postconf.5.html#mailbox_command">mailbox_command</a>, <a href="postconf.5.html#home_mailbox">home_mailbox</a>, <a href="postconf.5.html#mail_spool_directory">mail_spool_direc</a>-
+ <a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a>, <a href="postconf.5.html#mailbox_command">mailbox_command</a>, <a href="postconf.5.html#home_mailbox">home_mailbox</a>, <a href="postconf.5.html#mail_spool_directory">mail_spool_direc</a>-
<a href="postconf.5.html#mail_spool_directory">tory</a>, <a href="postconf.5.html#fallback_transport_maps">fallback_transport_maps</a>, <a href="postconf.5.html#fallback_transport">fallback_transport</a>, and <a href="postconf.5.html#luser_relay">luser_relay</a>.
<b><a href="postconf.5.html#alias_maps">alias_maps</a> (see 'postconf -d' output)</b>
- The alias databases that are used for <a href="local.8.html"><b>local</b>(8)</a> delivery.
+ Optional lookup tables with aliases that apply only to <a href="local.8.html"><b>local</b>(8)</a>
+ recipients; this is unlike <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> that apply to all
+ recipients: <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote.
<b><a href="postconf.5.html#forward_path">forward_path</a> (see 'postconf -d' output)</b>
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent search list for finding a .forward
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent search list for finding a .forward
file with user-specified delivery methods.
<b><a href="postconf.5.html#mailbox_transport_maps">mailbox_transport_maps</a> (empty)</b>
Optional lookup tables with per-recipient message delivery
- transports to use for <a href="local.8.html"><b>local</b>(8)</a> mailbox delivery, whether or not
+ transports to use for <a href="local.8.html"><b>local</b>(8)</a> mailbox delivery, whether or not
the recipients are found in the UNIX passwd database.
<b><a href="postconf.5.html#mailbox_transport">mailbox_transport</a> (empty)</b>
- Optional message delivery transport that the <a href="local.8.html"><b>local</b>(8)</a> delivery
- agent should use for mailbox delivery to all local recipients,
+ Optional message delivery transport that the <a href="local.8.html"><b>local</b>(8)</a> delivery
+ agent should use for mailbox delivery to all local recipients,
whether or not they are found in the UNIX passwd database.
<b><a href="postconf.5.html#mailbox_command_maps">mailbox_command_maps</a> (empty)</b>
- Optional lookup tables with per-recipient external commands to
+ Optional lookup tables with per-recipient external commands to
use for <a href="local.8.html"><b>local</b>(8)</a> mailbox delivery.
<b><a href="postconf.5.html#mailbox_command">mailbox_command</a> (empty)</b>
- Optional external command that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent
+ Optional external command that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent
should use for mailbox delivery.
<b><a href="postconf.5.html#home_mailbox">home_mailbox</a> (empty)</b>
- Optional pathname of a mailbox file relative to a <a href="local.8.html"><b>local</b>(8)</a>
+ Optional pathname of a mailbox file relative to a <a href="local.8.html"><b>local</b>(8)</a>
user's home directory.
<b><a href="postconf.5.html#mail_spool_directory">mail_spool_directory</a> (see 'postconf -d' output)</b>
@@ -419,17 +423,17 @@ LOCAL(8) LOCAL(8)
not find in the <a href="aliases.5.html"><b>aliases</b>(5)</a> or UNIX password database.
<b><a href="postconf.5.html#fallback_transport">fallback_transport</a> (empty)</b>
- Optional message delivery transport that the <a href="local.8.html"><b>local</b>(8)</a> delivery
- agent should use for names that are not found in the <a href="aliases.5.html"><b>aliases</b>(5)</a>
+ Optional message delivery transport that the <a href="local.8.html"><b>local</b>(8)</a> delivery
+ agent should use for names that are not found in the <a href="aliases.5.html"><b>aliases</b>(5)</a>
or UNIX password database.
<b><a href="postconf.5.html#luser_relay">luser_relay</a> (empty)</b>
- Optional catch-all destination for unknown <a href="local.8.html"><b>local</b>(8)</a> recipients.
+ Optional catch-all destination for unknown <a href="local.8.html"><b>local</b>(8)</a> recipients.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#command_execution_directory">command_execution_directory</a> (empty)</b>
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent working directory for delivery to
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent working directory for delivery to
external commands.
<b>MAILBOX LOCKING CONTROLS</b>
@@ -438,15 +442,15 @@ LOCAL(8) LOCAL(8)
mailbox file or <a href="bounce.8.html"><b>bounce</b>(8)</a> logfile.
<b><a href="postconf.5.html#deliver_lock_delay">deliver_lock_delay</a> (1s)</b>
- The time between attempts to acquire an exclusive lock on a
+ The time between attempts to acquire an exclusive lock on a
mailbox file or <a href="bounce.8.html"><b>bounce</b>(8)</a> logfile.
<b><a href="postconf.5.html#stale_lock_time">stale_lock_time</a> (500s)</b>
- The time after which a stale exclusive mailbox lockfile is
+ The time after which a stale exclusive mailbox lockfile is
removed.
<b><a href="postconf.5.html#mailbox_delivery_lock">mailbox_delivery_lock</a> (see 'postconf -d' output)</b>
- How to lock a UNIX-style <a href="local.8.html"><b>local</b>(8)</a> mailbox before attempting
+ How to lock a UNIX-style <a href="local.8.html"><b>local</b>(8)</a> mailbox before attempting
delivery.
<b>RESOURCE AND RATE CONTROLS</b>
@@ -459,20 +463,20 @@ LOCAL(8) LOCAL(8)
<a href="showq.8.html"><b>showq</b>(8)</a> queue displays.
<b><a href="postconf.5.html#mailbox_size_limit">mailbox_size_limit</a> (51200000)</b>
- The maximal size of any <a href="local.8.html"><b>local</b>(8)</a> individual mailbox or maildir
+ The maximal size of any <a href="local.8.html"><b>local</b>(8)</a> individual mailbox or maildir
file, or zero (no limit).
Implemented in the <a href="qmgr.8.html">qmgr(8)</a> daemon:
<b><a href="postconf.5.html#local_destination_concurrency_limit">local_destination_concurrency_limit</a> (2)</b>
- The maximal number of parallel deliveries via the local mail
- delivery transport to the same recipient (when "<a href="postconf.5.html#local_destination_recipient_limit">local_destina</a>-
- <a href="postconf.5.html#local_destination_recipient_limit">tion_recipient_limit</a> = 1") or the maximal number of parallel
+ The maximal number of parallel deliveries via the local mail
+ delivery transport to the same recipient (when "<a href="postconf.5.html#local_destination_recipient_limit">local_destina</a>-
+ <a href="postconf.5.html#local_destination_recipient_limit">tion_recipient_limit</a> = 1") or the maximal number of parallel
deliveries to the same local domain (when "<a href="postconf.5.html#local_destination_recipient_limit">local_destina</a>-
<a href="postconf.5.html#local_destination_recipient_limit">tion_recipient_limit</a> &gt; 1").
<b><a href="postconf.5.html#local_destination_recipient_limit">local_destination_recipient_limit</a> (1)</b>
- The maximal number of recipients per message delivery via the
+ The maximal number of recipients per message delivery via the
local mail delivery transport.
<b>SECURITY CONTROLS</b>
@@ -483,49 +487,49 @@ LOCAL(8) LOCAL(8)
Restrict <a href="local.8.html"><b>local</b>(8)</a> mail delivery to external files.
<b><a href="postconf.5.html#command_expansion_filter">command_expansion_filter</a> (see 'postconf -d' output)</b>
- Restrict the characters that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent allows
- in $name expansions of $<a href="postconf.5.html#mailbox_command">mailbox_command</a> and $<a href="postconf.5.html#command_execution_directory">command_execu</a>-
+ Restrict the characters that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent allows
+ in $name expansions of $<a href="postconf.5.html#mailbox_command">mailbox_command</a> and $<a href="postconf.5.html#command_execution_directory">command_execu</a>-
<a href="postconf.5.html#command_execution_directory">tion_directory</a>.
<b><a href="postconf.5.html#default_privs">default_privs</a> (nobody)</b>
- The default rights used by the <a href="local.8.html"><b>local</b>(8)</a> delivery agent for
+ The default rights used by the <a href="local.8.html"><b>local</b>(8)</a> delivery agent for
delivery to an external file or command.
<b><a href="postconf.5.html#forward_expansion_filter">forward_expansion_filter</a> (see 'postconf -d' output)</b>
- Restrict the characters that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent allows
+ Restrict the characters that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent allows
in $name expansions of $<a href="postconf.5.html#forward_path">forward_path</a>.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#execution_directory_expansion_filter">execution_directory_expansion_filter</a> (see 'postconf -d' output)</b>
- Restrict the characters that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent allows
+ Restrict the characters that the <a href="local.8.html"><b>local</b>(8)</a> delivery agent allows
in $name expansions of $<a href="postconf.5.html#command_execution_directory">command_execution_directory</a>.
Available in Postfix version 2.5.3 and later:
<b><a href="postconf.5.html#strict_mailbox_ownership">strict_mailbox_ownership</a> (yes)</b>
- Defer delivery when a mailbox file is not owned by its recipi-
+ Defer delivery when a mailbox file is not owned by its recipi-
ent.
<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-
+ 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#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to handle 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#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal point when log-
+ The maximal number of digits after the decimal point when log-
ging sub-second delay values.
<b><a href="postconf.5.html#export_environment">export_environment</a> (see 'postconf -d' output)</b>
- The list of environment variables that a Postfix process will
+ The list of environment variables that a Postfix process will
export to non-Postfix processes.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
- The time limit for sending or receiving information over an
+ The time limit for sending or receiving information over an
internal communication channel.
<b><a href="postconf.5.html#local_command_shell">local_command_shell</a> (empty)</b>
@@ -533,7 +537,7 @@ LOCAL(8) LOCAL(8)
mands.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix daemon process
+ 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>
@@ -541,8 +545,8 @@ LOCAL(8) LOCAL(8)
process will service before terminating voluntarily.
<b><a href="postconf.5.html#prepend_delivered_header">prepend_delivered_header</a> (command, file, forward)</b>
- The message delivery contexts where the Postfix <a href="local.8.html"><b>local</b>(8)</a> deliv-
- ery agent prepends a Delivered-To: message header with the
+ The message delivery contexts where the Postfix <a href="local.8.html"><b>local</b>(8)</a> deliv-
+ ery agent prepends a Delivered-To: message header with the
address that the mail was delivered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
@@ -552,14 +556,14 @@ LOCAL(8) LOCAL(8)
The process name of a Postfix command or daemon process.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
- The set of characters that can separate an email address local-
+ The set of characters that can separate an email address local-
part, user name, or a .forward file name from its extension.
<b><a href="postconf.5.html#require_home_directory">require_home_directory</a> (no)</b>
@@ -570,14 +574,14 @@ LOCAL(8) LOCAL(8)
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix version 3.3 and later:
<b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
- Enable support for the original recipient address after an
- address is rewritten to a different address (for example with
+ Enable support for the original recipient address after an
+ address is rewritten to a different address (for example with
aliasing or with canonical mapping).
<b><a href="postconf.5.html#service_name">service_name</a> (read-only)</b>
@@ -586,7 +590,7 @@ LOCAL(8) LOCAL(8)
Available in Postfix 3.5 and later:
<b><a href="postconf.5.html#info_log_address_format">info_log_address_format</a> (external)</b>
- The email address form that will be used in non-debug logging
+ The email address form that will be used in non-debug logging
(info, warning, etc.).
<b>FILES</b>
@@ -610,10 +614,10 @@ LOCAL(8) LOCAL(8)
The Secure Mailer license must be distributed with this software.
<b>HISTORY</b>
- The <b>Delivered-To:</b> message header appears in the <b>qmail</b> system by Daniel
+ The <b>Delivered-To:</b> message header appears in the <b>qmail</b> system by Daniel
Bernstein.
- The <i>maildir</i> structure appears in the <b>qmail</b> system by Daniel Bernstein.
+ The <i>maildir</i> structure appears in the <b>qmail</b> system by Daniel Bernstein.
<b>AUTHOR(S)</b>
Wietse Venema
diff --git a/html/mailq.1.html b/html/mailq.1.html
index bebc17b..bf6051d 100644
--- a/html/mailq.1.html
+++ b/html/mailq.1.html
@@ -455,9 +455,11 @@ SENDMAIL(1) SENDMAIL(1)
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
- append the specified domain name to incomplete addresses.
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
+ <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
+ ers.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
diff --git a/html/makedefs.1.html b/html/makedefs.1.html
index 7202a8d..ce67257 100644
--- a/html/makedefs.1.html
+++ b/html/makedefs.1.html
@@ -34,9 +34,9 @@ MAKEDEFS(1) MAKEDEFS(1)
<b>AUXLIBS=</b><i>object</i><b>_</b><i>library...</i>
Specifies one or more non-default object libraries. Postfix 3.0
and later specify some of their database library dependencies
- with <a href="CDB_README.html">AUXLIBS_CDB</a>, <a href="LDAP_README.html">AUXLIBS_LDAP</a>, <a href="LMDB_README.html">AUXLIBS_LMDB</a>, <a href="MYSQL_README.html">AUXLIBS_MYSQL</a>,
- <a href="PCRE_README.html">AUXLIBS_PCRE</a>, <a href="PGSQL_README.html">AUXLIBS_PGSQL</a>, AUXLIBS_SDBM, and <a href="SQLITE_README.html">AUXLIBS_SQLITE</a>,
- respectively.
+ with <a href="CDB_README.html">AUXLIBS_CDB</a>, <a href="LDAP_README.html">AUXLIBS_LDAP</a>, <a href="LMDB_README.html">AUXLIBS_LMDB</a>, <a href="MONGODB_README.html">AUXLIBS_MONGODB</a>,
+ <a href="MYSQL_README.html">AUXLIBS_MYSQL</a>, <a href="PCRE_README.html">AUXLIBS_PCRE</a>, <a href="PGSQL_README.html">AUXLIBS_PGSQL</a>, AUXLIBS_SDBM, and
+ <a href="SQLITE_README.html">AUXLIBS_SQLITE</a>, respectively.
<b>CC=</b><i>compiler</i><b>_</b><i>command</i>
Specifies a non-default compiler. On many systems, the default
diff --git a/html/master.5.html b/html/master.5.html
index 04a0c42..21f2b43 100644
--- a/html/master.5.html
+++ b/html/master.5.html
@@ -226,10 +226,17 @@ MASTER(5) MASTER(5)
options to make a Postfix daemon process increasingly
verbose.
- Other command-line arguments
+ <b>Command-line arguments that start with {</b>
+ With Postfix 3.0 and later specify "{" and "}" around
+ command arguments that start with "{". The outer "{" and
+ "}" are removed from the input, together with any leading
+ or trailing whitespace.
+
+ <b>Other command-line arguments</b>
Specify "{" and "}" around command arguments that contain
- whitespace (Postfix 3.0 and later). Whitespace after "{"
- and before "}" is ignored.
+ whitespace (Postfix 3.0 and later). The outer "{" and "}"
+ are removed from the input, together with any leading or
+ trailing whitespace.
<b>SEE ALSO</b>
<a href="master.8.html">master(8)</a>, process manager
diff --git a/html/master.8.html b/html/master.8.html
index cacc801..de0f9a5 100644
--- a/html/master.8.html
+++ b/html/master.8.html
@@ -148,15 +148,15 @@ MASTER(8) MASTER(8)
invoked with the -D option.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The network interface addresses that this mail system receives
- mail on.
+ The local network interface addresses that this mail system
+ receives mail on.
- <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d output')</b>
+ <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d' output)</b>
The Internet protocols Postfix will attempt to use when making
or accepting connections.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
+ The list of environment variables that a privileged Postfix
process will import from a non-Postfix parent process, or
name=value environment overrides.
diff --git a/html/mongodb_table.5.html b/html/mongodb_table.5.html
new file mode 100644
index 0000000..b7434f2
--- /dev/null
+++ b/html/mongodb_table.5.html
@@ -0,0 +1,215 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+<title> Postfix manual - mongodb_table(5) </title>
+</head> <body> <pre>
+MONGODB_TABLE(5) MONGODB_TABLE(5)
+
+<b>NAME</b>
+ mongodb_table - Postfix MongoDB client configuration
+
+<b>SYNOPSIS</b>
+ <b>postmap -q "</b><i>string</i><b>" <a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/</b><i>filename</i>
+
+ <b>postmap -q - <a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/</b><i>filename</i> &lt;<i>inputfile</i>
+
+<b>DESCRIPTION</b>
+ The Postfix mail system uses optional tables for address rewriting or
+ mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+
+ Alternatively, lookup tables can be specified as MongoDB databases. In
+ order to use MongoDB lookups, define a MongoDB source as a lookup table
+ in <a href="postconf.5.html">main.cf</a>, for example:
+ <a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongodb-aliases.cf
+
+ In this example, the file /etc/postfix/mongodb-aliases.cf has the same
+ format as the Postfix <a href="postconf.5.html">main.cf</a> file, and can specify the parameters
+ described below. It is also possible to have the configuration in
+ <a href="postconf.5.html">main.cf</a>; see "OBSOLETE MAIN.CF PARAMETERS" below.
+
+ It is strongly recommended to use <a href="proxymap.8.html">proxy</a>:mongodb, in order to reduce the
+ number of database connections. For example:
+ <a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="proxymap.8.html">proxy</a>:<a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongodb-aliases.cf
+
+ Note: when using <a href="proxymap.8.html">proxy</a>:<a href="mongodb_table.5.html">mongodb</a>:/<i>file</i>, the file must be readable by the
+ unprivileged postfix user (specified with the Postfix <a href="postconf.5.html#mail_owner">mail_owner</a> con-
+ figuration parameter).
+
+<b>MONGODB PARAMETERS</b>
+ <b>uri</b> The URI of mongo server/cluster that Postfix will try to connect
+ to and query from. Please see
+ <a href="https://www.mongodb.com/docs/manual/reference/connection-string/">https://www.mongodb.com/docs/manual/reference/connection-string/</a>
+
+ Example:
+ uri = mongodb+srv://user:pass@loclhost:27017/mail
+
+ <b>dbname</b> Name of the database to read the information from. Example:
+ dbname = mail
+
+ <b>collection</b>
+ Name of the collection (table) to read the information from.
+ Example:
+ collection = mailbox
+
+ <b>query_filter</b>
+ The MongoDB query template used to search the database, where <b>%s</b>
+ is a substitute for the email address that Postfix is trying to
+ resolve. Please see:
+ <a href="https://www.mongodb.com/docs/manual/tutorial/query-documents/">https://www.mongodb.com/docs/manual/tutorial/query-documents/</a>
+
+ Example:
+ query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1}
+
+ This parameter supports the following '%' expansions:
+
+ <b>%%</b> This is replaced by a literal '%' character.
+
+ <b>%s</b> This is replaced by the input key. The %s must appear in
+ quotes, because all Postfix queries are strings contain-
+ ing (parts from) a domain or email address. Postfix makes
+ no numerical queries.
+
+ <b>%u</b> When the input key is an address of the form user@domain,
+ <b>%u</b> is replaced by the local part of the address. Other-
+ wise, <b>%u</b> is replaced by the entire search string.
+
+ <b>%d</b> When the input key is an address of the form user@domain,
+ <b>%d</b> is replaced by the domain part of the address.
+
+ <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is <i>user@mail.example.com</i>, then
+ %1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>.
+
+ In the above substitutions, characters will be quoted as
+ required by <a href="https://tools.ietf.org/html/rfc4627">RFC 4627</a>. For example, each double quote or back-
+ slash character will be escaped with a backslash characacter.
+
+ <b>projection</b>
+ Advanced MongoDB query projections. Please see:
+ <a href="https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/">https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/</a>
+
+ <b>o</b> If <b>projection</b> is non-empty, then <b>result_attribute</b> must be
+ empty.
+
+ <b>o</b> This implementation can extract information only from
+ result fields that have type <b>string</b> (UTF8), <b>integer</b>
+ (int32, int64) and <b>array</b>. Other result fields will be
+ ignored with a warning. Please see:
+ <a href="https://mongoc.org/libbson/current/bson_type_t.html">https://mongoc.org/libbson/current/bson_type_t.html</a>
+
+ <b>o</b> As with <b>result_attribute</b>, the top-level _id field (type
+ OID) is automatically removed from projection results.
+
+ <b>result_attribute</b>
+ Comma or whitespace separated list with the names of fields to
+ be returned in a lookup result.
+
+ <b>o</b> If <b>result_attribute</b> is non-empty, then <b>projection</b> must be
+ empty.
+
+ <b>o</b> As with <b>projection</b>, the top-level _id field (type OID) is
+ automatically removed from lookup results.
+
+ <b>result_format (default: %s</b>)
+ Format template applied to the result from <b>projection</b> or
+ <b>result_attribute</b>. Most commonly used to append (or prepend) text
+ to the result. This parameter supports the following '%' expan-
+ sions:
+
+ <b>%%</b> This is replaced by a literal '%' character.
+
+ <b>%s</b> This is replaced by the value of the result attribute.
+ When result is empty it is skipped.
+
+ <b>%u</b> When the result attribute value is an address of the form
+ user@domain, <b>%u</b> is replaced by the local part of the
+ address. When the result has an empty localpart it is
+ skipped.
+
+ <b>%d</b> When a result attribute value is an address of the form
+ user@domain, <b>%d</b> is replaced by the domain part of the
+ attribute value. When the result is unqualified it is
+ skipped.
+
+ <b>%[SUD1-9]</b>
+ The upper-case and decimal digit expansions interpolate
+ the parts of the input key rather than the result. Their
+ behavior is identical to that described with <b>query_fil-</b>
+ <b>ter</b>, and in fact because the input key is known in
+ advance, lookups whose key does not contain all the
+ information specified in the result template are sup-
+ pressed and return no results.
+
+ For example, using "result_format = <a href="smtp.8.html">smtp</a>:[%s]" allows one to use
+ a mailHost attribute as the basis of a <a href="transport.5.html">transport(5)</a> table. After
+ applying the result format, multiple values are concatenated as
+ comma separated strings. The expansion_limit parameter explained
+ below allows one to restrict the number of values in the result,
+ which is especially useful for maps that should return a single
+ value.
+
+ The default value <b>%s</b> specifies that each attribute value should
+ be used as is.
+
+ NOTE: DO NOT put quotes around the result format! The result is
+ not a JSON string.
+
+ <b>domain (default: no domain list)</b>
+ This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
+ databases. When specified, only fully qualified search keys with
+ a *non-empty* localpart and a matching domain are eligible for
+ lookup: 'user' lookups, bare domain lookups and "@domain"
+ lookups are not performed. This can significantly reduce the
+ query load on the backend database. Example:
+ domain = postfix.org, <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/searchdomains
+
+ <b>expansion_limit (default: 0)</b>
+ A limit on the total number of result elements returned (as a
+ comma separated list) by a lookup against the map. A setting of
+ zero disables the limit. Lookups fail with a temporary error if
+ the limit is exceeded. Setting the limit to 1 ensures that
+ lookups do not return multiple values.
+
+<b>OBSOLETE MAIN.CF PARAMETERS</b>
+ MongoDB parameters can also be defined in <a href="postconf.5.html">main.cf</a>. Specify as MongoDB
+ source a name that doesn't begin with a slash or a dot. The MongoDB
+ parameters will then be accessible as the name you've given the source
+ in its definition, an underscore, and the name of the parameter. For
+ example, if a map is specified as "<a href="mongodb_table.5.html">mongodb</a>:<i>mongodb</i><b>_</b><i>source</i>", the "uri"
+ parameter would be defined in <a href="postconf.5.html">main.cf</a> as "<i>mongodb</i><b>_</b><i>source</i>_uri".
+
+ Note: with this form, passwords are written in <a href="postconf.5.html">main.cf</a>, which is nor-
+ mally world-readable, and '$' in a mongodb parameter setting needs to
+ be written as '$$'.
+
+<b>SEE ALSO</b>
+ <a href="postmap.1.html">postmap(1)</a>, Postfix lookup table maintenance
+ <a href="postconf.5.html">postconf(5)</a>, configuration parameters
+
+<b>README FILES</b>
+ <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
+ <a href="MONGODB_README.html">MONGODB_README</a>, Postfix MONGODB client guide
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this software.
+
+<b>HISTORY</b>
+ MongoDB support was introduced with Postfix version 3.9.
+
+<b>AUTHOR(S)</b>
+ Hamid Maadani (hamid@dexo.tech)
+ Dextrous Technologies, LLC
+
+ Edited by:
+ Wietse Venema
+ porcupine.org
+
+ Based on prior work by:
+ Stephan Ferraro
+ Aionda GmbH
+
+ MONGODB_TABLE(5)
+</pre> </body> </html>
diff --git a/html/mysql_table.5.html b/html/mysql_table.5.html
index 4971e57..5063e65 100644
--- a/html/mysql_table.5.html
+++ b/html/mysql_table.5.html
@@ -72,56 +72,76 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
<b>dbname</b> The database name on the servers. Example:
dbname = customer_database
- <b>query</b> The SQL query template used to search the database, where <b>%s</b> is
- a substitute for the address Postfix is trying to resolve, e.g.
+ <b>charset (default: utf8mb4)</b>
+ The default MySQL client character set; this also implies the
+ collation order.
+
+ This parameter is available with Postfix 3.9 and later. With
+ earlier Postfix versions, the default was chosen by the MySQL
+ implementation (<b>utf8mb4</b> as of MySQL 8.0, <b>latin1</b> historically).
+
+ <b>idle_interval (default: 60)</b>
+ The number of seconds after which an idle database connection
+ will be closed.
+
+ This feature is available in Postfix 3.9 and later.
+
+ <b>retry_interval (default: 60)</b>
+ The number of seconds that a database connection will be skipped
+ after an error.
+
+ This feature is available in Postfix 3.9 and later.
+
+ <b>query</b> The SQL query template used to search the database, where <b>%s</b> is
+ a substitute for the address Postfix is trying to resolve, e.g.
query = SELECT replacement FROM aliases WHERE mailbox = '%s'
- By default, every query must return a result set (instead of
- storing its results in a table); with "<b>require_result_set = no</b>"
- (Postfix 3.2 and later), the absence of a result set is treated
+ By default, every query must return a result set (instead of
+ storing its results in a table); with "<b>require_result_set = no</b>"
+ (Postfix 3.2 and later), the absence of a result set is treated
as "not found".
This parameter supports the following '%' expansions:
<b>%%</b> This is replaced by a literal '%' character.
- <b>%s</b> This is replaced by the input key. SQL quoting is used
- to make sure that the input key does not add unexpected
+ <b>%s</b> This is replaced by the input key. SQL quoting is used
+ to make sure that the input key does not add unexpected
metacharacters.
<b>%u</b> When the input key is an address of the form user@domain,
- <b>%u</b> is replaced by the SQL quoted local part of the
- address. Otherwise, <b>%u</b> is replaced by the entire search
- string. If the localpart is empty, the query is sup-
+ <b>%u</b> is replaced by the SQL quoted local part of the
+ address. Otherwise, <b>%u</b> is replaced by the entire search
+ string. If the localpart is empty, the query is sup-
pressed and returns no results.
<b>%d</b> When the input key is an address of the form user@domain,
- <b>%d</b> is replaced by the SQL quoted domain part of the
- address. Otherwise, the query is suppressed and returns
+ <b>%d</b> is replaced by the SQL quoted domain part of the
+ address. Otherwise, the query is suppressed and returns
no results.
<b>%[SUD]</b> The upper-case equivalents of the above expansions behave
- in the <b>query</b> parameter identically to their lower-case
- counter-parts. With the <b>result_format</b> parameter (see
- below), they expand the input key rather than the result
+ in the <b>query</b> parameter identically to their lower-case
+ counter-parts. With the <b>result_format</b> parameter (see
+ below), they expand the input key rather than the result
value.
- <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
- sponding most significant component of the input key's
- domain. If the input key is <i>user@mail.example.com</i>, then
+ <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is <i>user@mail.example.com</i>, then
%1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. If the input key
- is unqualified or does not have enough domain components
- to satisfy all the specified patterns, the query is sup-
+ is unqualified or does not have enough domain components
+ to satisfy all the specified patterns, the query is sup-
pressed and returns no results.
- The <b>domain</b> parameter described below limits the input keys to
- addresses in matching domains. When the <b>domain</b> parameter is
+ The <b>domain</b> parameter described below limits the input keys to
+ addresses in matching domains. When the <b>domain</b> parameter is
non-empty, SQL queries for unqualified addresses or addresses in
non-matching domains are suppressed and return no results.
- This parameter is available with Postfix 2.2. In prior releases
- the SQL query was built from the separate parameters:
- <b>select_field</b>, <b>table</b>, <b>where_field</b> and <b>additional_conditions</b>. The
+ This parameter is available with Postfix 2.2. In prior releases
+ the SQL query was built from the separate parameters:
+ <b>select_field</b>, <b>table</b>, <b>where_field</b> and <b>additional_conditions</b>. The
mapping from the old parameters to the equivalent query is:
SELECT [<b>select_field</b>]
@@ -129,50 +149,50 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
WHERE [<b>where_field</b>] = '%s'
[<b>additional_conditions</b>]
- The '%s' in the <b>WHERE</b> clause expands to the escaped search
- string. With Postfix 2.2 these legacy parameters are used if
+ The '%s' in the <b>WHERE</b> clause expands to the escaped search
+ string. With Postfix 2.2 these legacy parameters are used if
the <b>query</b> parameter is not specified.
NOTE: DO NOT put quotes around the query parameter.
<b>result_format (default: %s</b>)
Format template applied to result attributes. Most commonly used
- to append (or prepend) text to the result. This parameter sup-
+ to append (or prepend) text to the result. This parameter sup-
ports the following '%' expansions:
<b>%%</b> This is replaced by a literal '%' character.
- <b>%s</b> This is replaced by the value of the result attribute.
+ <b>%s</b> This is replaced by the value of the result attribute.
When result is empty it is skipped.
<b>%u</b> When the result attribute value is an address of the form
- user@domain, <b>%u</b> is replaced by the local part of the
- address. When the result has an empty localpart it is
+ user@domain, <b>%u</b> is replaced by the local part of the
+ address. When the result has an empty localpart it is
skipped.
- <b>%d</b> When a result attribute value is an address of the form
- user@domain, <b>%d</b> is replaced by the domain part of the
- attribute value. When the result is unqualified it is
+ <b>%d</b> When a result attribute value is an address of the form
+ user@domain, <b>%d</b> is replaced by the domain part of the
+ attribute value. When the result is unqualified it is
skipped.
<b>%[SUD1-9]</b>
- The upper-case and decimal digit expansions interpolate
- the parts of the input key rather than the result. Their
- behavior is identical to that described with <b>query</b>, and
- in fact because the input key is known in advance,
- queries whose key does not contain all the information
- specified in the result template are suppressed and
+ The upper-case and decimal digit expansions interpolate
+ the parts of the input key rather than the result. Their
+ behavior is identical to that described with <b>query</b>, and
+ in fact because the input key is known in advance,
+ queries whose key does not contain all the information
+ specified in the result template are suppressed and
return no results.
For example, using "result_format = <a href="smtp.8.html">smtp</a>:[%s]" allows one to use
a mailHost attribute as the basis of a <a href="transport.5.html">transport(5)</a> table. After
- applying the result format, multiple values are concatenated as
+ applying the result format, multiple values are concatenated as
comma separated strings. The expansion_limit and parameter
- explained below allows one to restrict the number of values in
+ explained below allows one to restrict the number of values in
the result, which is especially useful for maps that must return
at most one value.
- The default value <b>%s</b> specifies that each result value should be
+ The default value <b>%s</b> specifies that each result value should be
used as is.
This parameter is available with Postfix 2.2 and later.
@@ -180,15 +200,15 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
NOTE: DO NOT put quotes around the result format!
<b>domain (default: no domain list)</b>
- This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
+ This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
databases. When specified, only fully qualified search keys with
- a *non-empty* localpart and a matching domain are eligible for
+ a *non-empty* localpart and a matching domain are eligible for
lookup: 'user' lookups, bare domain lookups and "@domain"
- lookups are not performed. This can significantly reduce the
+ lookups are not performed. This can significantly reduce the
query load on the MySQL server.
domain = postfix.org, <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/searchdomains
- It is best not to use SQL to store the domains eligible for SQL
+ It is best not to use SQL to store the domains eligible for SQL
lookups.
This parameter is available with Postfix 2.2 and later.
@@ -197,37 +217,37 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
the input keys are always unqualified.
<b>expansion_limit (default: 0)</b>
- A limit on the total number of result elements returned (as a
+ A limit on the total number of result elements returned (as a
comma separated list) by a lookup against the map. A setting of
- zero disables the limit. Lookups fail with a temporary error if
- the limit is exceeded. Setting the limit to 1 ensures that
+ zero disables the limit. Lookups fail with a temporary error if
+ the limit is exceeded. Setting the limit to 1 ensures that
lookups do not return multiple values.
<b>option_file</b>
- Read options from the given file instead of the default my.cnf
- location. This reads options from the <b>[client]</b> option group,
+ Read options from the given file instead of the default my.cnf
+ location. This reads options from the <b>[client]</b> option group,
optionally followed by options from the group given with
<b>option_group</b>.
This parameter is available with Postfix 2.11 and later.
<b>option_group (default: Postfix</b> &gt;<b>=3.2: client,</b> &lt;<b>= 3.1: empty)</b>
- Read options from the given group of the mysql options file,
+ Read options from the given group of the mysql options file,
after reading options from the <b>[client]</b> group.
- Postfix 3.2 and later read <b>[client]</b> option group settings by
- default. To disable this specify no <b>option_file</b> and specify
+ Postfix 3.2 and later read <b>[client]</b> option group settings by
+ default. To disable this specify no <b>option_file</b> and specify
"<b>option_group =</b>" (i.e. an empty value).
- Postfix 3.1 and earlier don't read <b>[client]</b> option group set-
- tings unless a non-empty <b>option_file</b> or <b>option_group</b> value are
+ Postfix 3.1 and earlier don't read <b>[client]</b> option group set-
+ tings unless a non-empty <b>option_file</b> or <b>option_group</b> value are
specified. To enable this, specify, for example, "<b>option_group =</b>
<b>client</b>".
This parameter is available with Postfix 2.11 and later.
<b>require_result_set (default: yes)</b>
- If "<b>yes</b>", require that every query returns a result set. If
+ If "<b>yes</b>", require that every query returns a result set. If
"<b>no</b>", treat the absence of a result set as "not found".
This parameter is available with Postfix 3.2 and later.
@@ -238,19 +258,19 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
This parameter is available with Postfix 2.11 and later.
<b>tls_key_file</b>
- File containing the private key corresponding to <b>tls_cert_file</b>.
+ File containing the private key corresponding to <b>tls_cert_file</b>.
This parameter is available with Postfix 2.11 and later.
<b>tls_CAfile</b>
- File containing certificates for all of the X509 Certification
- Authorities the client will recognize. Takes precedence over
+ File containing certificates for all of the X509 Certification
+ Authorities the client will recognize. Takes precedence over
<b>tls_CApath</b>.
This parameter is available with Postfix 2.11 and later.
<b>tls_CApath</b>
- Directory containing X509 Certification Authority certificates
+ Directory containing X509 Certification Authority certificates
in separate individual files.
This parameter is available with Postfix 2.11 and later.
@@ -261,13 +281,13 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
This parameter is available with Postfix 2.11 and later.
<b>tls_verify_cert (default: no)</b>
- Verify that the server's name matches the common name in the
+ Verify that the server's name matches the common name in the
certificate.
This parameter is available with Postfix 2.11 and later.
<b>USING MYSQL STORED PROCEDURES</b>
- Postfix 3.2 and later support calling a stored procedure instead of
+ Postfix 3.2 and later support calling a stored procedure instead of
using a SELECT statement in the query, e.g.
<b>query</b> = CALL lookup('%s')
@@ -275,17 +295,17 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
The previously described '%' expansions can be used in the parameter(s)
to the stored procedure.
- By default, every stored procedure call must return a result set, i.e.
- every code path must execute a SELECT statement that returns a result
+ By default, every stored procedure call must return a result set, i.e.
+ every code path must execute a SELECT statement that returns a result
set (instead of storing its results in a table). With
- "<b>require_result_set = no</b>", the absence of a result set is treated as
+ "<b>require_result_set = no</b>", the absence of a result set is treated as
"not found".
- A stored procedure must not return multiple result sets. That is,
- there must be no code path that executes multiple SELECT statements
+ A stored procedure must not return multiple result sets. That is,
+ there must be no code path that executes multiple SELECT statements
that return a result (instead of storing their results in a table).
- The following is an example of a stored procedure returning a single
+ The following is an example of a stored procedure returning a single
result set:
CREATE [DEFINER=`user`@`host`] PROCEDURE
@@ -297,26 +317,26 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
END
<b>OBSOLETE MAIN.CF PARAMETERS</b>
- For compatibility with other Postfix lookup tables, MySQL parameters
- can also be defined in <a href="postconf.5.html">main.cf</a>. In order to do that, specify as MySQL
- source a name that doesn't begin with a slash or a dot. The MySQL
- parameters will then be accessible as the name you've given the source
- in its definition, an underscore, and the name of the parameter. For
- example, if the map is specified as "<a href="mysql_table.5.html">mysql</a>:<i>mysqlname</i>", the parameter
+ For compatibility with other Postfix lookup tables, MySQL parameters
+ can also be defined in <a href="postconf.5.html">main.cf</a>. In order to do that, specify as MySQL
+ source a name that doesn't begin with a slash or a dot. The MySQL
+ parameters will then be accessible as the name you've given the source
+ in its definition, an underscore, and the name of the parameter. For
+ example, if the map is specified as "<a href="mysql_table.5.html">mysql</a>:<i>mysqlname</i>", the parameter
"hosts" would be defined in <a href="postconf.5.html">main.cf</a> as "<i>mysqlname</i>_hosts".
- Note: with this form, the passwords for the MySQL sources are written
- in <a href="postconf.5.html">main.cf</a>, which is normally world-readable. Support for this form
+ Note: with this form, the passwords for the MySQL sources are written
+ in <a href="postconf.5.html">main.cf</a>, which is normally world-readable. Support for this form
will be removed in a future Postfix version.
<b>OBSOLETE QUERY INTERFACE</b>
- This section describes an interface that is deprecated as of Postfix
- 2.2. It is replaced by the more general <b>query</b> interface described
- above. If the <b>query</b> parameter is defined, the legacy parameters
- described here ignored. Please migrate to the new interface as the
+ This section describes an interface that is deprecated as of Postfix
+ 2.2. It is replaced by the more general <b>query</b> interface described
+ above. If the <b>query</b> parameter is defined, the legacy parameters
+ described here ignored. Please migrate to the new interface as the
legacy interface may be removed in a future release.
- The following parameters can be used to fill in a SELECT template
+ The following parameters can be used to fill in a SELECT template
statement of the form:
SELECT [<b>select_field</b>]
@@ -325,7 +345,7 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
[<b>additional_conditions</b>]
The specifier %s is replaced by the search string, and is escaped so if
- it contains single quotes or other odd characters, it will not cause a
+ it contains single quotes or other odd characters, it will not cause a
parse error, or worse, a security problem.
<b>select_field</b>
diff --git a/html/newaliases.1.html b/html/newaliases.1.html
index bebc17b..bf6051d 100644
--- a/html/newaliases.1.html
+++ b/html/newaliases.1.html
@@ -455,9 +455,11 @@ SENDMAIL(1) SENDMAIL(1)
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
- append the specified domain name to incomplete addresses.
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
+ <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
+ ers.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
diff --git a/html/pcre_table.5.html b/html/pcre_table.5.html
index 0216e3e..1e03644 100644
--- a/html/pcre_table.5.html
+++ b/html/pcre_table.5.html
@@ -191,8 +191,12 @@ PCRE_TABLE(5) PCRE_TABLE(5)
Postfix parses the result as if it is a file in /etc/postfix.
- Note: if a rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from trying to
- do <i>$name</i> expansion as it evaluates a parameter value.
+ Note: if an inlined rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from
+ trying to do <i>$name</i> expansion as it evaluates a parameter value.
+
+ Note: when using <i>$name</i> inside an inlined pattern, use \Q<i>$name</i>\E to dis-
+ able metacharacters such as '.' in the <i>$name</i> expansion. Otherwise, the
+ pattern may have unexpected matches.
<b>EXAMPLE SMTPD ACCESS MAP</b>
# Protect your outgoing majordomo exploders
diff --git a/html/pgsql_table.5.html b/html/pgsql_table.5.html
index 964bd6d..0b50fd1 100644
--- a/html/pgsql_table.5.html
+++ b/html/pgsql_table.5.html
@@ -72,11 +72,24 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
The encoding used by the database client. The default setting
is:
encoding = UTF8
+
Historically, the database client was hard coded to use LATIN1
in an attempt to disable multibyte character support.
This feature is available in Postfix 3.8 and later.
+ <b>idle_interval (default: 60)</b>
+ The number of seconds after which an idle database connection
+ will be closed.
+
+ This feature is available in Postfix 3.9 and later.
+
+ <b>retry_interval (default: 60)</b>
+ The number of seconds that a database connection will be skipped
+ after an error.
+
+ This feature is available in Postfix 3.9 and later.
+
<b>query</b> The SQL query template used to search the database, where <b>%s</b> is
a substitute for the address Postfix is trying to resolve, e.g.
query = SELECT replacement FROM aliases WHERE mailbox = '%s'
diff --git a/html/pipe.8.html b/html/pipe.8.html
index a0e4678..d813954 100644
--- a/html/pipe.8.html
+++ b/html/pipe.8.html
@@ -242,13 +242,19 @@ PIPE(8) PIPE(8)
This feature is available as of Postfix 2.5.
+ <b>${envid}</b>
+ This macro expands to the <a href="https://tools.ietf.org/html/rfc3461">RFC 3461</a> envelope ID if avail-
+ able, otherwise the empty string.
+
+ This feature is available as of Postfix 3.9.
+
<b>${extension}</b>
- This macro expands to the extension part of a recipient
- address. For example, with an address <i>user+foo@domain</i>
+ This macro expands to the extension part of a recipient
+ address. For example, with an address <i>user+foo@domain</i>
the extension is <i>foo</i>.
- A command-line argument that contains <b>${extension}</b>
- expands into as many command-line arguments as there are
+ A command-line argument that contains <b>${extension}</b>
+ expands into as many command-line arguments as there are
recipients.
This information is modified by the <b>u</b> flag for case fold-
@@ -256,11 +262,11 @@ PIPE(8) PIPE(8)
<b>${mailbox}</b>
This macro expands to the complete local part of a recip-
- ient address. For example, with an address
+ ient address. For example, with an address
<i>user+foo@domain</i> the mailbox is <i>user+foo</i>.
- A command-line argument that contains <b>${mailbox}</b> expands
- to as many command-line arguments as there are recipi-
+ A command-line argument that contains <b>${mailbox}</b> expands
+ to as many command-line arguments as there are recipi-
ents.
This information is modified by the <b>u</b> flag for case fold-
@@ -273,11 +279,11 @@ PIPE(8) PIPE(8)
ing.
<b>${original_recipient}</b>
- This macro expands to the complete recipient address
+ This macro expands to the complete recipient address
before any address rewriting or aliasing.
- A command-line argument that contains <b>${original_recipi-</b>
- <b>ent}</b> expands to as many command-line arguments as there
+ A command-line argument that contains <b>${original_recipi-</b>
+ <b>ent}</b> expands to as many command-line arguments as there
are recipients.
This information is modified by the <b>hqu</b> flags for quoting
@@ -293,8 +299,8 @@ PIPE(8) PIPE(8)
<b>${recipient}</b>
This macro expands to the complete recipient address.
- A command-line argument that contains <b>${recipient}</b>
- expands to as many command-line arguments as there are
+ A command-line argument that contains <b>${recipient}</b>
+ expands to as many command-line arguments as there are
recipients.
This information is modified by the <b>hqu</b> flags for quoting
@@ -302,13 +308,13 @@ PIPE(8) PIPE(8)
<b>${sasl_method}</b>
This macro expands to the name of the SASL authentication
- mechanism in the AUTH command when the Postfix SMTP
+ mechanism in the AUTH command when the Postfix SMTP
server received the message.
This feature is available as of Postfix 2.2.
<b>${sasl_sender}</b>
- This macro expands to the SASL sender name (i.e. the
+ This macro expands to the SASL sender name (i.e. the
original submitter as per <a href="https://tools.ietf.org/html/rfc4954">RFC 4954</a>) in the MAIL FROM com-
mand when the Postfix SMTP server received the message.
@@ -321,25 +327,25 @@ PIPE(8) PIPE(8)
This feature is available as of Postfix 2.2.
<b>${sender}</b>
- This macro expands to the envelope sender address. By
- default, the null sender address expands to MAILER-DAE-
- MON; this can be changed with the <b>null_sender</b> attribute,
+ This macro expands to the envelope sender address. By
+ default, the null sender address expands to MAILER-DAE-
+ MON; this can be changed with the <b>null_sender</b> attribute,
as described above.
This information is modified by the <b>q</b> flag for quoting.
<b>${size}</b>
This macro expands to Postfix's idea of the message size,
- which is an approximation of the size of the message as
+ which is an approximation of the size of the message as
delivered.
<b>${user}</b>
- This macro expands to the username part of a recipient
- address. For example, with an address <i>user+foo@domain</i>
+ This macro expands to the username part of a recipient
+ address. For example, with an address <i>user+foo@domain</i>
the username part is <i>user</i>.
- A command-line argument that contains <b>${user}</b> expands
- into as many command-line arguments as there are recipi-
+ A command-line argument that contains <b>${user}</b> expands
+ into as many command-line arguments as there are recipi-
ents.
This information is modified by the <b>u</b> flag for case fold-
@@ -349,36 +355,36 @@ PIPE(8) PIPE(8)
<a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced status codes)
<b>DIAGNOSTICS</b>
- Command exit status codes are expected to follow the conventions
+ Command exit status codes are expected to follow the conventions
defined in &lt;<b>sysexits.h</b>&gt;. Exit status 0 means normal successful comple-
tion.
In the case of a non-zero exit status, a limited amount of command out-
- put is logged, and reported in a delivery status notification. When
- the output begins with a 4.X.X or 5.X.X enhanced status code, the sta-
- tus code takes precedence over the non-zero exit status (Postfix ver-
+ put is logged, and reported in a delivery status notification. When
+ the output begins with a 4.X.X or 5.X.X enhanced status code, the sta-
+ tus code takes precedence over the non-zero exit status (Postfix ver-
sion 2.3 and later).
- After successful delivery (zero exit status) a limited amount of com-
- mand output is logged, and reported in "success" delivery status noti-
+ After successful delivery (zero exit status) a limited amount of com-
+ mand output is logged, and reported in "success" delivery status noti-
fications (Postfix 3.0 and later). This command output is not examined
for the presence of an enhanced status code.
- Problems and transactions are logged to <b>syslogd</b>(8) or <a href="postlogd.8.html"><b>postlogd</b>(8)</a>.
- Corrupted message files are marked so that the queue manager can move
+ Problems and transactions are logged to <b>syslogd</b>(8) or <a href="postlogd.8.html"><b>postlogd</b>(8)</a>.
+ Corrupted message files are marked so that the queue manager can move
them to the <b>corrupt</b> queue for further inspection.
<b>SECURITY</b>
- This program needs a dual personality 1) to access the private Postfix
- queue and IPC mechanisms, and 2) to execute external commands as the
+ This program needs a dual personality 1) to access the private Postfix
+ queue and IPC mechanisms, and 2) to execute external commands as the
specified user. It is therefore security sensitive.
<b>CONFIGURATION PARAMETERS</b>
Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="pipe.8.html"><b>pipe</b>(8)</a> processes run
- for only a limited amount of time. Use the command "<b>postfix reload</b>" to
+ for only a limited amount of time. Use the command "<b>postfix reload</b>" to
speed up a change.
- 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>RESOURCE AND RATE CONTROLS</b>
@@ -386,50 +392,50 @@ PIPE(8) PIPE(8)
<b><a href="postconf.5.html#transport_time_limit">transport_time_limit</a> ($<a href="postconf.5.html#command_time_limit">command_time_limit</a>)</b>
A transport-specific override for the <a href="postconf.5.html#command_time_limit">command_time_limit</a> parame-
- ter value, where <i>transport</i> is the <a href="master.5.html">master.cf</a> name of the message
+ ter value, where <i>transport</i> is the <a href="master.5.html">master.cf</a> name of the message
delivery transport.
Implemented in the <a href="qmgr.8.html">qmgr(8)</a> daemon:
<b><a href="postconf.5.html#transport_destination_concurrency_limit">transport_destination_concurrency_limit</a> ($<a href="postconf.5.html#default_destination_concurrency_limit">default_destination_concur</a>-</b>
<b><a href="postconf.5.html#default_destination_concurrency_limit">rency_limit</a>)</b>
- A transport-specific override for the <a href="postconf.5.html#default_destination_concurrency_limit">default_destination_con</a>-
+ A transport-specific override for the <a href="postconf.5.html#default_destination_concurrency_limit">default_destination_con</a>-
<a href="postconf.5.html#default_destination_concurrency_limit">currency_limit</a> parameter value, where <i>transport</i> is the <a href="master.5.html">master.cf</a>
name of the message delivery transport.
<b><a href="postconf.5.html#transport_destination_recipient_limit">transport_destination_recipient_limit</a> ($<a href="postconf.5.html#default_destination_recipient_limit">default_destination_recipi</a>-</b>
<b><a href="postconf.5.html#default_destination_recipient_limit">ent_limit</a>)</b>
A transport-specific override for the <a href="postconf.5.html#default_destination_recipient_limit">default_destination_recip</a>-
- <a href="postconf.5.html#default_destination_recipient_limit">ient_limit</a> parameter value, where <i>transport</i> is the <a href="master.5.html">master.cf</a>
+ <a href="postconf.5.html#default_destination_recipient_limit">ient_limit</a> parameter value, where <i>transport</i> is the <a href="master.5.html">master.cf</a>
name of the message delivery transport.
<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-
+ 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#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to handle 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#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal point when log-
+ The maximal number of digits after the decimal point when log-
ging sub-second delay values.
<b><a href="postconf.5.html#export_environment">export_environment</a> (see 'postconf -d' output)</b>
- The list of environment variables that a Postfix process will
+ The list of environment variables that a Postfix process will
export to non-Postfix processes.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
- The time limit for sending or receiving information over an
+ The time limit for sending or receiving information over an
internal communication channel.
<b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
- The UNIX system account that owns the Postfix queue and most
+ The UNIX system account that owns the Postfix queue 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
+ 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>
@@ -446,28 +452,28 @@ PIPE(8) PIPE(8)
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
- The set of characters that can separate an email address local-
+ The set of characters that can separate an email address local-
part, user name, or a .forward file name from its extension.
<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>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix version 3.0 and later:
<b><a href="postconf.5.html#pipe_delivery_status_filter">pipe_delivery_status_filter</a> ($<a href="postconf.5.html#default_delivery_status_filter">default_delivery_status_filter</a>)</b>
- Optional filter for the <a href="pipe.8.html"><b>pipe</b>(8)</a> delivery agent to change the
+ Optional filter for the <a href="pipe.8.html"><b>pipe</b>(8)</a> delivery agent to change the
delivery status code or explanatory text of successful or unsuc-
cessful deliveries.
Available in Postfix version 3.3 and later:
<b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
- Enable support for the original recipient address after an
- address is rewritten to a different address (for example with
+ Enable support for the original recipient address after an
+ address is rewritten to a different address (for example with
aliasing or with canonical mapping).
<b><a href="postconf.5.html#service_name">service_name</a> (read-only)</b>
@@ -476,7 +482,7 @@ PIPE(8) PIPE(8)
Available in Postfix 3.5 and later:
<b><a href="postconf.5.html#info_log_address_format">info_log_address_format</a> (external)</b>
- The email address form that will be used in non-debug logging
+ The email address form that will be used in non-debug logging
(info, warning, etc.).
<b>SEE ALSO</b>
diff --git a/html/postcat.1.html b/html/postcat.1.html
index 4c61c52..71b763e 100644
--- a/html/postcat.1.html
+++ b/html/postcat.1.html
@@ -85,7 +85,7 @@ POSTCAT(1) POSTCAT(1)
figuration files.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
+ The list of environment variables that a privileged Postfix
process will import from a non-Postfix parent process, or
name=value environment overrides.
diff --git a/html/postconf.1.html b/html/postconf.1.html
index 4269a5e..a8444a2 100644
--- a/html/postconf.1.html
+++ b/html/postconf.1.html
@@ -13,7 +13,7 @@ POSTCONF(1) POSTCONF(1)
<b>SYNOPSIS</b>
<b>Managing <a href="postconf.5.html">main.cf</a>:</b>
- <b>postconf</b> [<b>-dfhHnopvx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-C</b> <i>class,...</i>] [<i>parameter ...</i>]
+ <b>postconf</b> [<b>-dfhHnopqvx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-C</b> <i>class,...</i>] [<i>parameter ...</i>]
<b>postconf</b> [<b>-epv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>parameter</i><b>=</b><i>value ...</i>
@@ -23,7 +23,7 @@ POSTCONF(1) POSTCONF(1)
<b>Managing <a href="master.5.html">master.cf</a> service entries:</b>
- <b>postconf -M</b> [<b>-fovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>] <i>...</i>]
+ <b>postconf -M</b> [<b>-foqvx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>] <i>...</i>]
<b>postconf -M</b> [<b>-ev</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type</i><b>=</b><i>value ...</i>
@@ -33,13 +33,13 @@ POSTCONF(1) POSTCONF(1)
<b>Managing <a href="master.5.html">master.cf</a> service fields:</b>
- <b>postconf -F</b> [<b>-fhHovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>[<b>/</b><i>field</i>]] <i>...</i>]
+ <b>postconf -F</b> [<b>-fhHoqvx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>[<b>/</b><i>field</i>]] <i>...</i>]
<b>postconf -F</b> [<b>-ev</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type</i><b>/</b><i>field</i><b>=</b><i>value ...</i>
<b>Managing <a href="master.5.html">master.cf</a> service parameters:</b>
- <b>postconf -P</b> [<b>-fhHovx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>[<b>/</b><i>parameter</i>]] <i>...</i>]
+ <b>postconf -P</b> [<b>-fhHoqvx</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>service</i>[<b>/</b><i>type</i>[<b>/</b><i>parameter</i>]] <i>...</i>]
<b>postconf -P</b> [<b>-ev</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <i>service</i><b>/</b><i>type</i><b>/</b><i>parameter</i><b>=</b><i>value ...</i>
@@ -272,52 +272,58 @@ POSTCONF(1) POSTCONF(1)
This feature is available with Postfix 2.9 and later.
+ <b>mongodb</b>
+ MongoDB database client. This is described in <a href="mongodb_table.5.html"><b>mongodb_ta-</b></a>
+ <a href="mongodb_table.5.html"><b>ble</b>(5)</a>.
+
+ This feature is available with Postfix 3.9 and later.
+
<b>mysql</b> (read-only)
MySQL database client. Available on systems with support
- for MySQL databases. This is described in <a href="mysql_table.5.html"><b>mysql_ta-</b></a>
+ for MySQL databases. This is described in <a href="mysql_table.5.html"><b>mysql_ta-</b></a>
<a href="mysql_table.5.html"><b>ble</b>(5)</a>.
<b>pcre</b> (read-only)
- A lookup table based on Perl Compatible Regular Expres-
+ A lookup table based on Perl Compatible Regular Expres-
sions. The file format is described in <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
<b>pgsql</b> (read-only)
- PostgreSQL database client. This is described in
+ PostgreSQL database client. This is described in
<a href="pgsql_table.5.html"><b>pgsql_table</b>(5)</a>.
This feature is available with Postfix 2.1 and later.
<b>pipemap</b> (read-only)
- A lookup table that constructs a pipeline of tables.
- Example: "<b><a href="DATABASE_README.html#types">pipemap</a>:{</b><i>type</i><b>_</b><i>1:name</i><b>_</b><i>1, ..., type</i><b>_</b><i>n:name</i><b>_</b><i>n</i><b>}</b>".
- Each "<a href="DATABASE_README.html#types">pipemap</a>:" query is given to the first table. Each
+ A lookup table that constructs a pipeline of tables.
+ Example: "<b><a href="DATABASE_README.html#types">pipemap</a>:{</b><i>type</i><b>_</b><i>1:name</i><b>_</b><i>1, ..., type</i><b>_</b><i>n:name</i><b>_</b><i>n</i><b>}</b>".
+ Each "<a href="DATABASE_README.html#types">pipemap</a>:" query is given to the first table. Each
lookup result becomes the query for the next table in the
- pipeline, and the last table produces the final result.
- When any table lookup produces no result, the pipeline
- produces no result. The first and last characters of the
+ pipeline, and the last table produces the final result.
+ When any table lookup produces no result, the pipeline
+ produces no result. The first and last characters of the
"<a href="DATABASE_README.html#types">pipemap</a>:" table name must be "<b>{</b>" and "<b>}</b>". Within these,
individual maps are separated with comma or whitespace.
This feature is available with Postfix 3.0 and later.
- <b>proxy</b> Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> client for shared access to Postfix
+ <b>proxy</b> Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> client for shared access to Postfix
databases. The table name syntax is <i>type</i><b>:</b><i>name</i>.
This feature is available with Postfix 2.0 and later.
<b>randmap</b> (read-only)
- An in-memory table that performs random selection. Exam-
+ An in-memory table that performs random selection. Exam-
ple: "<b><a href="DATABASE_README.html#types">randmap</a>:{</b><i>result</i><b>_</b><i>1, ..., result</i><b>_</b><i>n</i><b>}</b>". Each table
query returns a random choice from the specified results.
- The first and last characters of the "<a href="DATABASE_README.html#types">randmap</a>:" table
- name must be "<b>{</b>" and "<b>}</b>". Within these, individual
+ The first and last characters of the "<a href="DATABASE_README.html#types">randmap</a>:" table
+ name must be "<b>{</b>" and "<b>}</b>". Within these, individual
results are separated with comma or whitespace. To give a
specific result more weight, specify it multiple times.
This feature is available with Postfix 3.0 and later.
<b>regexp</b> (read-only)
- A lookup table based on regular expressions. The file
+ A lookup table based on regular expressions. The file
format is described in <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a>.
<b>sdbm</b> An indexed file type based on hashing. Available on sys-
@@ -326,9 +332,9 @@ POSTCONF(1) POSTCONF(1)
This feature is available with Postfix 2.2 and later.
<b>socketmap</b> (read-only)
- Sendmail-style socketmap client. The table name is
- <b>inet</b>:<i>host</i>:<i>port</i>:<i>name</i> for a TCP/IP server, or <b>unix</b>:<i>path-</i>
- <i>name</i>:<i>name</i> for a UNIX-domain server. This is described in
+ Sendmail-style socketmap client. The table name is
+ <b>inet</b>:<i>host</i>:<i>port</i>:<i>name</i> for a TCP/IP server, or <b>unix</b>:<i>path-</i>
+ <i>name</i>:<i>name</i> for a UNIX-domain server. This is described in
<a href="socketmap_table.5.html"><b>socketmap_table</b>(5)</a>.
This feature is available with Postfix 2.10 and later.
@@ -339,11 +345,11 @@ POSTCONF(1) POSTCONF(1)
This feature is available with Postfix 2.8 and later.
<b>static</b> (read-only)
- A table that always returns its name as lookup result.
+ 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. 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 the opening "<b>{</b>" and before the
+ <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 the opening "<b>{</b>" and before the
closing "<b>}</b>". See also the <i><a href="DATABASE_README.html#types">inline</a>:</i> map.
The form "<b><a href="DATABASE_README.html#types">static</a>:{</b><i>text</i><b>}</b> is available with Postfix 3.0 and
@@ -353,66 +359,66 @@ POSTCONF(1) POSTCONF(1)
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.
This feature is available with Postfix 2.8 and later.
<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>.
This feature is available with Postfix 3.0 and later.
<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
- readability (Postfix 2.9 and later). To show settings that dif-
+ 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). To show settings that dif-
fer from built-in defaults only, use the following bash syntax:
LANG=C comm -23 &lt;(postconf -n) &lt;(postconf -d)
Replace "-23" with "-12" to show settings that duplicate
built-in defaults.
<b>-o</b> <i>name=value</i>
- Override <a href="postconf.5.html"><b>main.cf</b></a> parameter settings. This lets you see the
- effect changing a parameter would have when it is used in other
+ Override <a href="postconf.5.html"><b>main.cf</b></a> parameter settings. This lets you see the
+ effect changing a parameter would have when it is used in other
configuration parameters, e.g.:
postconf -x -o stress=yes
@@ -422,38 +428,42 @@ POSTCONF(1) POSTCONF(1)
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-
- vices and all parameters), formatted as "<i>service/type/parame-</i>
+ <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 "<i>service/type/parame-</i>
<i>ter=value</i>", one 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>-q</b> Do not log warnings for deprecated or unused parameters.
+
+ This feature is available with Postfix 3.9 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 <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter setting, specify
- a template file name at the end of the "<b>postconf -t</b>" command
- line. Specify an empty file name to display built-in templates
+ To override the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter setting, specify
+ a template file name at the end of the "<b>postconf -t</b>" command
+ line. Specify an empty file name to display built-in templates
(in shell language: "").
This feature is available with Postfix 2.3 and later.
<b>-T</b> <i>mode</i>
- If Postfix is compiled without TLS support, the <b>-T</b> option pro-
- duces no output. Otherwise, if an invalid <i>mode</i> is specified,
- the <b>-T</b> option reports an error and exits with a non-zero status
+ If Postfix is compiled without TLS support, the <b>-T</b> option pro-
+ duces no output. Otherwise, if an invalid <i>mode</i> is specified,
+ the <b>-T</b> option reports an error and exits with a non-zero status
code. The valid modes are:
<b>compile-version</b>
Output the OpenSSL version that Postfix was compiled with
- (i.e. the OpenSSL version in a header file). The output
+ (i.e. the OpenSSL version in a header file). The output
format is the same as with the command "<b>openssl version</b>".
<b>run-version</b>
@@ -461,40 +471,40 @@ POSTCONF(1) POSTCONF(1)
runtime (i.e. the OpenSSL version in a shared library).
<b>public-key-algorithms</b>
- Output the lower-case names of the supported public-key
+ Output the lower-case names of the supported public-key
algorithms, one per-line.
This feature is available with Postfix 3.1 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 specified with "<i>service/type/parameter</i>" on the <a href="postconf.1.html"><b>postconf</b>(1)</a>
+ as specified with "<i>service/type/parameter</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.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-
@@ -502,18 +512,18 @@ POSTCONF(1) POSTCONF(1)
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>
@@ -524,18 +534,18 @@ POSTCONF(1) POSTCONF(1)
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
diff --git a/html/postconf.5.html b/html/postconf.5.html
index dbb8cc8..0ac9b68 100644
--- a/html/postconf.5.html
+++ b/html/postconf.5.html
@@ -612,8 +612,14 @@ Examples:
(default: see "postconf -d" output)</b></DT><DD>
<p>
-The alias databases that are used for <a href="local.8.html">local(8)</a> delivery. See
-<a href="aliases.5.html">aliases(5)</a> for syntax details.
+Optional lookup tables with aliases that apply only to <a href="local.8.html">local(8)</a>
+recipients; this is unlike <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> that apply to all
+recipients: <a href="local.8.html">local(8)</a>, virtual, and remote.
+The table format and lookups are documented in <a href="aliases.5.html">aliases(5)</a>. For an
+overview of Postfix address manipulations see the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a>
+document. </p>
+
+<p>
Specify zero or more "type:name" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
until a match is found.
@@ -2732,19 +2738,30 @@ name of the message delivery transport.
<p>
The default mail delivery transport and next-hop destination for
-destinations that do not match $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>,
+the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> class: recipient domains that do not match
+$<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>,
$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>, $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>,
-or $<a href="postconf.5.html#relay_domains">relay_domains</a>. This information can be overruled with the
-<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> parameter and with the
-<a href="transport.5.html">transport(5)</a> table. </p>
+or $<a href="postconf.5.html#relay_domains">relay_domains</a>. This information will not be used when
+<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> returns a result, and may
+be overridden with the <a href="transport.5.html">transport(5)</a> table. </p>
-<p>
-In order of decreasing precedence, the nexthop destination is taken
-from $<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>, $<a href="postconf.5.html#default_transport">default_transport</a>,
-$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>, $<a href="postconf.5.html#relayhost">relayhost</a>, or from the recipient
-domain.
+<p> For recipient domains in the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> class: <p>
+
+<ul>
+
+<li> <p> In order of decreasing precedence, the delivery transport
+is taken from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2)
+$<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> or $<a href="postconf.5.html#default_transport">default_transport</a>.
</p>
+<li> <p> In order of decreasing precedence, the nexthop destination
+is taken from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2)
+$<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> or $<a href="postconf.5.html#default_transport">default_transport</a>, 3)
+$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a> or the recipient
+domain. </p>
+
+</ul>
+
<p>
Specify a string of the form <i>transport:nexthop</i>, where <i>transport</i>
is the name of a mail delivery transport defined in <a href="master.5.html">master.cf</a>.
@@ -3715,6 +3732,25 @@ This feature is available in Postfix 2.0 and later.
</DD>
+<DT><b><a name="force_mime_input_conversion">force_mime_input_conversion</a>
+(default: no)</b></DT><DD>
+
+<p> Convert body content that claims to be 8-bit into quoted-printable,
+before <a href="postconf.5.html#header_checks">header_checks</a>, <a href="postconf.5.html#body_checks">body_checks</a>, Milters, and before after-queue
+content filters. This feature does not affect messages that are
+sent into <a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a>. </p>
+
+<p> The typical use case is an MTA that applies this conversion
+before signing outbound messages, so that the signatures will remain
+valid when a message is later delivered to an MTA that does not
+announce 8BITMIME support, or when a message line exceeds the SMTP
+length limit. </p>
+
+<p> This feature is available in Postfix &ge; 3.9. </p>
+
+
+</DD>
+
<DT><b><a name="fork_attempts">fork_attempts</a>
(default: 5)</b></DT><DD>
@@ -3797,7 +3833,7 @@ filtered with the character set that is specified with the
<dd>The address extension delimiter that was found in the recipient
address (Postfix 2.11 and later), or the 'first' delimiter specified
with the system-wide recipient address extension delimiter (Postfix
-3.5.22, 3.5.12, 3.7.8, 3.8.3 and later). Historically, this was
+3.5.22, 3.6.12, 3.7.8, 3.8.3 and later). Historically, this was
always the system-wide recipient
address extension delimiter (Postfix 2.10 and earlier). </dd>
@@ -4154,12 +4190,17 @@ Specify 0 to disable the feature. Valid delays are 0..10.
<DT><b><a name="inet_interfaces">inet_interfaces</a>
(default: all)</b></DT><DD>
-<p> The local network interface addresses that this mail system receives
-mail on. Specify "all" to receive mail on all network
-interfaces (default), and "loopback-only" to receive mail
-on loopback network interfaces only (Postfix version 2.2 and later). The
-parameter also controls delivery of mail to <tt>user@[ip.address]</tt>.
-</p>
+<p> The local network interface addresses that this mail system
+receives mail on. Specify "all" to receive mail on all network
+interfaces (default), "loopback-only" to receive mail on loopback
+network interfaces only (Postfix version 2.2 and later), or zero
+or more IPv4 or IPv6 addresses (IPv6 is supported in Postfix version
+2.2 and later). The parameter also controls whether Postfix will
+accept mail for <tt>user@[ip.address]</tt>, and prevents Postfix
+from delivering mail to a host that has equal or larger MX preference.
+Specify an empty value if Postfix does not receive mail over the
+network, or if all network listeners have an explicit IP address
+in <a href="master.5.html">master.cf</a>. </p>
<p>
Note 1: you need to stop and start Postfix when this parameter changes.
@@ -4168,22 +4209,44 @@ Note 1: you need to stop and start Postfix when this parameter changes.
<p> Note 2: address information may be enclosed inside <tt>[]</tt>,
but this form is not required here. </p>
-<p> When <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies just one IPv4 and/or IPv6 address
-that is not a loopback address, the Postfix SMTP client will use
-this address as the IP source address for outbound mail. Support
-for IPv6 is available in Postfix version 2.2 and later. </p>
+<p> When <a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> and/or <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> are not
+specified, the <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> setting may constrain the source IP
+address for an outbound SMTP or LMTP connection as described below.
+</p>
+
+<p> The following text is specific to SMTP and IPv4. The same
+reasoning applies to the IPv6 protocol, and to the Postfix LMTP
+client. To disable IPv4 or IPv6 support in the Postfix SMTP and
+LMTP client, use <a href="postconf.5.html#inet_protocols">inet_protocols</a>. </p>
-<p>
-On a multi-homed firewall with separate Postfix instances listening on the
-"inside" and "outside" interfaces, this can prevent each instance from
-being able to reach remote SMTP servers on the "other side" of the
-firewall. Setting
-<a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> to 0.0.0.0 avoids the potential problem for
-IPv4, and setting <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> to :: solves the problem
-for IPv6. </p>
+<ul>
+
+<li> <p> When <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies one IPv4 address, and that
+is not a loopback address, the Postfix SMTP client uses that as the
+source address for outbound IPv4 connections. </p>
+
+<li> <p> Otherwise, the Postfix SMTP client does not constrain the
+source IPv4 address, and connects using a system-chosen source IPv4
+address. This includes the cases where <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> is empty,
+where it specifies <b>all</b>, or where it contains no IPv4 address,
+one IPv4 address that is a loopback address, or multiple IPv4
+addresses. </p>
+
+</ul>
+
+<p> A Postfix SMTP client may fail to reach some remote SMTP servers
+when the client source IP address is constrained explicitly with
+<a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> or <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a>, or implicitly with
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>. This can happen when Postfix runs on a multi-homed
+system such as a firewall, the Postfix SMTP source client IP address
+is constrained to one specific network interface, and the remote
+SMTP server must be reached through a different interface. Setting
+<a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> to 0.0.0.0 avoids the potential problem for IPv4,
+and setting <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> to :: solves the problem for IPv6.
+</p>
<p>
-A better solution for multi-homed firewalls is to leave <a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
+A better solution for multi-homed systems is to leave <a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
at the default value and instead use explicit IP addresses in
the <a href="master.5.html">master.cf</a> SMTP server definitions. This preserves the Postfix
SMTP client's
@@ -4215,7 +4278,7 @@ Examples:
</DD>
<DT><b><a name="inet_protocols">inet_protocols</a>
-(default: see 'postconf -d output')</b></DT><DD>
+(default: see 'postconf -d' output)</b></DT><DD>
<p> The Internet protocols Postfix will attempt to use when making
or accepting connections. Specify one or more of "ipv4"
@@ -4893,6 +4956,9 @@ configuration parameter. See there for details. </p>
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> configuration
parameter. See there for details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#lmtp_tls_security_level">lmtp_tls_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
@@ -5295,6 +5361,15 @@ to the remote host.
</DD>
+<DT><b><a name="lmtp_sasl_password_result_delimiter">lmtp_sasl_password_result_delimiter</a>
+(default: :)</b></DT><DD>
+
+<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_sasl_password_result_delimiter">smtp_sasl_password_result_delimiter</a>
+configuration parameter. See there for details. </p>
+
+
+</DD>
+
<DT><b><a name="lmtp_sasl_path">lmtp_sasl_path</a>
(default: empty)</b></DT><DD>
@@ -5594,6 +5669,17 @@ compiled and linked with OpenSSL 1.0.0 or later. </p>
</DD>
+<DT><b><a name="lmtp_tls_enable_rpk">lmtp_tls_enable_rpk</a>
+(default: yes)</b></DT><DD>
+
+<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a>
+configuration parameter. See there for details. </p>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+
+</DD>
+
<DT><b><a name="lmtp_tls_enforce_peername">lmtp_tls_enforce_peername</a>
(default: yes)</b></DT><DD>
@@ -5694,7 +5780,7 @@ configuration parameter. See there for details. </p>
</DD>
<DT><b><a name="lmtp_tls_mandatory_protocols">lmtp_tls_mandatory_protocols</a>
-(default: see postconf -d output)</b></DT><DD>
+(default: see 'postconf -d' output)</b></DT><DD>
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>
configuration parameter. See there for details. </p>
@@ -5721,6 +5807,9 @@ configuration parameter. See there for details. </p>
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> configuration
parameter. See there for details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#lmtp_tls_policy_maps">lmtp_tls_policy_maps</a> instead. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
@@ -5738,7 +5827,7 @@ configuration parameter. See there for details. </p>
</DD>
<DT><b><a name="lmtp_tls_protocols">lmtp_tls_protocols</a>
-(default: see postconf -d output)</b></DT><DD>
+(default: see 'postconf -d' output)</b></DT><DD>
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> configuration
parameter. See there for details. </p>
@@ -5853,6 +5942,9 @@ parameter. See there for details. </p>
<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> configuration
parameter. See there for details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#lmtp_tls_security_level">lmtp_tls_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
@@ -6149,8 +6241,8 @@ until a match is found.
<p>
If this parameter is non-empty (the default), then the Postfix SMTP
-server will reject mail for unknown local users.
-</p>
+server will reject mail for unknown local users. Other Postfix
+interfaces may still accept an "unknown" recipient. </p>
<p>
To turn off local recipient checking in the Postfix SMTP server,
@@ -6449,6 +6541,11 @@ and later.</dd>
<dd>The domain part of the recipient address. </dd>
+<dt><b>ENVID</b></dt>
+
+<dd>The optional <a href="https://tools.ietf.org/html/rfc3461">RFC 3461</a> envelope ID. Available in Postfix version
+3.9 and later</dd>
+
<dt><b>EXTENSION</b></dt>
<dd>The optional address extension. </dd>
@@ -6683,6 +6780,21 @@ first argument. </p>
</DD>
+<DT><b><a name="maillog_file_permissions">maillog_file_permissions</a>
+(default: 0600)</b></DT><DD>
+
+<p> The file access permissions that will be set when the file
+$<a href="postconf.5.html#maillog_file">maillog_file</a> is created for the first time, or when the file is
+created after an existing file is rotated. Specify one of: <b>0600</b>
+(only super-user read/write access), <b>0640</b> (adds 'group' read
+access), or <b>0644</b> (also adds 'other' read access). The leading
+'0' is optional. </p>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+
+</DD>
+
<DT><b><a name="maillog_file_prefixes">maillog_file_prefixes</a>
(default: /var, /dev/stdout)</b></DT><DD>
@@ -8326,9 +8438,9 @@ it passes the test, before it can talk to a real Postfix SMTP server.
<DT><b><a name="postscreen_bare_newline_ttl">postscreen_bare_newline_ttl</a>
(default: 30d)</b></DT><DD>
-<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the result from
-a successful "bare newline" SMTP protocol test. During this
-time, the client IP address is excluded from this test. The default
+<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a client
+IP address passed a "bare newline" SMTP protocol test, before it
+address is required to pass that test again. The default
is long because a remote SMTP client must disconnect after it passes
the test,
before it can talk to a real Postfix SMTP server. </p>
@@ -8584,9 +8696,10 @@ defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dns
<p> Specify a negative value to enable this feature. When a client
passes the <a href="postconf.5.html#postscreen_dnsbl_allowlist_threshold">postscreen_dnsbl_allowlist_threshold</a> without having
failed other tests, all pending or disabled tests are flagged as
-completed with a time-to-live value equal to <a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>.
-When a test was already completed, its time-to-live value is updated
-if it was less than <a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>. </p>
+completed with an expiration time based on the DNS reply TTL.
+When a test was already completed, its expiration time is updated
+if it was less than the value based on the DNS reply TTL. See
+also <a href="postconf.5.html#postscreen_dnsbl_max_ttl">postscreen_dnsbl_max_ttl</a> and <a href="postconf.5.html#postscreen_dnsbl_min_ttl">postscreen_dnsbl_min_ttl</a>. </p>
<p> This feature is available in Postfix 3.6 and later. </p>
@@ -8599,9 +8712,9 @@ if it was less than <a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dn
<DT><b><a name="postscreen_dnsbl_max_ttl">postscreen_dnsbl_max_ttl</a>
(default: ${<a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>?{$<a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>}:{1}}h)</b></DT><DD>
-<p> The maximum amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the
-result from a successful DNS-based reputation test before a
-client IP address is required to pass that test again. If the DNS
+<p> The maximum amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a
+client IP address passed a DNS-based reputation test, before it is
+required to pass that test again. If the DNS
reply specifies a shorter TTL value, that value will be used unless
it would be smaller than <a href="postconf.5.html#postscreen_dnsbl_min_ttl">postscreen_dnsbl_min_ttl</a>. </p>
@@ -8619,9 +8732,9 @@ is backwards-compatible with older Postfix versions. </p>
<DT><b><a name="postscreen_dnsbl_min_ttl">postscreen_dnsbl_min_ttl</a>
(default: 60s)</b></DT><DD>
-<p> The minimum amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the
-result from a successful DNS-based reputation test before a
-client IP address is required to pass that test again. If the DNS
+<p> The minimum amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a
+client IP address passed a DNS-based reputation test, before it
+is required to pass that test again. If the DNS
reply specifies a larger TTL value, that value will be used unless
it would be larger than <a href="postconf.5.html#postscreen_dnsbl_max_ttl">postscreen_dnsbl_max_ttl</a>. </p>
@@ -8762,9 +8875,9 @@ The default time unit is s (seconds). </p>
<DT><b><a name="postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>
(default: 1h)</b></DT><DD>
-<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the result from
-a successful DNS-based reputation test before a client
-IP address is required to pass that test again. </p>
+<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a client
+IP address passed a DNS-based reputation test, before it is required
+to pass that test again. </p>
<p> Specify a non-zero time value (an integral value plus an optional
one-letter suffix that specifies the time unit). Time units: s
@@ -8880,9 +8993,9 @@ value to disable this feature. </p>
<DT><b><a name="postscreen_greet_ttl">postscreen_greet_ttl</a>
(default: 1d)</b></DT><DD>
-<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the result from
-a successful PREGREET test. During this time, the client IP address
-is excluded from this test. The default is relatively short, because
+<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a client
+IP address passed a PREGREET test, before it is required to pass
+that test again. The default is relatively short, because
a good client can immediately talk to a real Postfix SMTP server. </p>
<p> Specify a non-zero time value (an integral value plus an optional
@@ -8976,9 +9089,9 @@ test, before it can talk to a real Postfix SMTP server. </p>
<DT><b><a name="postscreen_non_smtp_command_ttl">postscreen_non_smtp_command_ttl</a>
(default: 30d)</b></DT><DD>
-<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the result from
-a successful "non_smtp_command" SMTP protocol test. During this
-time, the client IP address is excluded from this test. The default
+<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a client
+IP address passed a "non_smtp_command" SMTP protocol test, before
+it is required to pass that test again. The default
is long because a client must disconnect after it passes the test,
before it can talk to a real Postfix SMTP server. </p>
@@ -9044,9 +9157,9 @@ server. </p>
<DT><b><a name="postscreen_pipelining_ttl">postscreen_pipelining_ttl</a>
(default: 30d)</b></DT><DD>
-<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> will use the result from
-a successful "pipelining" SMTP protocol test. During this time, the
-client IP address is excluded from this test. The default is
+<p> The amount of time that <a href="postscreen.8.html">postscreen(8)</a> remembers that a client
+IP address passed a "pipelining" SMTP protocol test, before it is
+required to pass that test again. The default is
long because a good client must disconnect after it passes the test,
before it can talk to a real Postfix SMTP server. </p>
@@ -10136,13 +10249,24 @@ This feature is available in Postfix 2.0 and later.
<p>
The default mail delivery transport and next-hop destination for
-remote delivery to domains listed with $<a href="postconf.5.html#relay_domains">relay_domains</a>. In order of
-decreasing precedence, the nexthop destination is taken from
-$<a href="postconf.5.html#relay_transport">relay_transport</a>, $<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>, $<a href="postconf.5.html#relayhost">relayhost</a>, or
-from the recipient domain. This information can be overruled with
-the <a href="transport.5.html">transport(5)</a> table.
+the <a href="ADDRESS_CLASS_README.html#relay_domain_class">relay domain</a> address class: recipient domains that match
+$<a href="postconf.5.html#relay_domains">relay_domains</a>. </p>
+
+<p> For recipient domains in the <a href="ADDRESS_CLASS_README.html#relay_domain_class">relay domain</a> address class: </p>
+
+<ul>
+
+<li> <p> In order of decreasing precedence, the message delivery
+transport is taken from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2) $<a href="postconf.5.html#relay_transport">relay_transport</a>.
</p>
+<li> <p> In order of decreasing precedence, the nexthop destination
+is taken from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2) $<a href="postconf.5.html#relay_transport">relay_transport</a>, 3)
+$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a> or the recipient
+domain. </p>
+
+</ul>
+
<p>
Specify a string of the form <i>transport:nexthop</i>, where <i>transport</i>
is the name of a mail delivery transport defined in <a href="master.5.html">master.cf</a>.
@@ -10166,13 +10290,31 @@ This feature is available in Postfix 2.0 and later.
(default: empty)</b></DT><DD>
<p>
-The next-hop destination(s) for non-local mail; overrides non-local
-domains in recipient addresses. This information is overruled with
-<a href="postconf.5.html#relay_transport">relay_transport</a>, <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>,
-<a href="postconf.5.html#default_transport">default_transport</a>, <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>
-and with the <a href="transport.5.html">transport(5)</a> table.
+The next-hop destination(s) for non-local mail; takes precedence
+over non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses. This information
+will not be used when the sender matches $<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>.
</p>
+<p> In order of decreasing precedence: </p>
+
+<ul>
+
+<li> <p> For recipient domains in the <a href="ADDRESS_CLASS_README.html#relay_domain_class">relay domain</a> address class
+(domains matching $<a href="postconf.5.html#relay_domains">relay_domains</a>), the nexthop destination is taken
+from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2) $<a href="postconf.5.html#relay_transport">relay_transport</a>, 3)
+$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a> or the recipient
+domain. <p>
+
+<li> <p> For recipient domains in the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> address class
+(domains that do not match $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>,
+$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>, $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>,
+or $<a href="postconf.5.html#relay_domains">relay_domains</a>), the nexthop destination is taken from 1)
+$<a href="postconf.5.html#transport_maps">transport_maps</a>, 2) $<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> or
+$<a href="postconf.5.html#default_transport">default_transport</a>, 3) $<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a>
+or the recipient domain. </p>
+
+</ul>
+
<p>
On an intranet, specify the organizational domain name. If your
internal DNS uses no MX records, specify the name of the intranet
@@ -10180,11 +10322,12 @@ gateway host instead.
</p>
<p>
-In the case of SMTP or LMTP delivery, specify one or more destinations
-in the form of a domain name, hostname, hostname:port, [hostname]:port,
-[hostaddress] or [hostaddress]:port, separated by comma or whitespace.
-The form [hostname] turns off MX lookups. Multiple destinations are
-supported in Postfix 3.5 and later.
+In the case of SMTP delivery, specify one or more destinations in
+the form of a domain name, hostname, hostname:service, [hostname]:service,
+[hostaddress] or [hostaddress]:service, separated by comma or whitespace.
+The form [hostname] turns off MX or SRV lookups. Multiple destinations
+are supported in Postfix 3.5 and later. Each destination is tried
+in the specified order.
</p>
<p>
@@ -10589,18 +10732,38 @@ address and @domain. A lookup result of DUNNO terminates the search
without overriding the global <a href="postconf.5.html#default_transport">default_transport</a> parameter setting.
This information is overruled with the <a href="transport.5.html">transport(5)</a> table. </p>
-<p>
-Specify zero or more "type:name" lookup tables, separated by
-whitespace or comma. Tables will be searched in the specified order
-until a match is found.
+<p> This setting affects only the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> address class
+(recipient domains that do not match $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>,
+$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>, $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>,
+or $<a href="postconf.5.html#relay_domains">relay_domains</a>): </p>
+
+<ul>
+
+<li> <p> In order of decreasing precedence, the delivery transport
+is taken from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2)
+$<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> or $<a href="postconf.5.html#default_transport">default_transport</a>.
</p>
+<li> <p> In order of decreasing precedence, the nexthop destination
+is taken from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2)
+$<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> or $<a href="postconf.5.html#default_transport">default_transport</a>, 3)
+$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a> or the recipient
+domain. </p>
+
+</ul>
+
<p> Note: this overrides <a href="postconf.5.html#default_transport">default_transport</a>, not <a href="postconf.5.html#transport_maps">transport_maps</a>, and
therefore the expected syntax is that of <a href="postconf.5.html#default_transport">default_transport</a>, not the
syntax of <a href="postconf.5.html#transport_maps">transport_maps</a>. Specifically, this does not support the
<a href="postconf.5.html#transport_maps">transport_maps</a> syntax for null transport, null nexthop, or null
email addresses. </p>
+<p>
+Specify zero or more "type:name" lookup tables, separated by
+whitespace or comma. Tables will be searched in the specified order
+until a match is found.
+</p>
+
<p> For safety reasons, this feature does not allow $number
substitutions in regular expression maps. </p>
@@ -10616,9 +10779,27 @@ substitutions in regular expression maps. </p>
setting. The tables are searched by the envelope sender address and
@domain. A lookup result of DUNNO terminates the search without
overriding the global <a href="postconf.5.html#relayhost">relayhost</a> parameter setting (Postfix 2.6 and
-later). This information is overruled with <a href="postconf.5.html#relay_transport">relay_transport</a>,
-<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>, <a href="postconf.5.html#default_transport">default_transport</a> and with
-the <a href="transport.5.html">transport(5)</a> table. </p>
+later). </p>
+
+<p> In order of decreasing precedence: </p>
+
+<ul>
+
+<li> <p> For recipient domains in the <a href="ADDRESS_CLASS_README.html#relay_domain_class">relay domain</a> address class
+(domains matching $<a href="postconf.5.html#relay_domains">relay_domains</a>), the nexthop destination is taken
+from 1) $<a href="postconf.5.html#transport_maps">transport_maps</a>, 2) $<a href="postconf.5.html#relay_transport">relay_transport</a>, 3)
+$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a> or the recipient
+domain. </p>
+
+<li> <p> For recipient domains in the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> address class
+(domains that do not match <a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>,
+$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>, $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>,
+$<a href="postconf.5.html#relay_domains">relay_domains</a>), the nexthop destination is taken from 1)
+$<a href="postconf.5.html#transport_maps">transport_maps</a>, 2) $<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> or
+$<a href="postconf.5.html#default_transport">default_transport</a>, 3) $<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> or $<a href="postconf.5.html#relayhost">relayhost</a>
+or the recipient domain. </p>
+
+</ul>
<p>
Specify zero or more "type:name" lookup tables, separated by
@@ -10820,13 +11001,38 @@ IPv6 connectivity: </p>
<ul>
<li> <p> The setting "<a href="postconf.5.html#smtp_address_preference">smtp_address_preference</a> = ipv6" is unsafe.
-It can fail to deliver mail when there is an outage that affects
-IPv6, while the destination is still reachable over IPv4. </p>
+All deliveries will suffer delays during an IPv6 outage, even
+while the destination is still reachable over IPv4. Mail may be
+stuck in the queue with Postfix versions &lt; 3.3 that do not
+implement "<a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a>". For similar reasons, the
+setting "<a href="postconf.5.html#smtp_address_preference">smtp_address_preference</a> = ipv4" is also unsafe. </p>
<li> <p> The setting "<a href="postconf.5.html#smtp_address_preference">smtp_address_preference</a> = any" is safe. With
-this, mail will eventually be delivered even if there is an outage
+this, and "<a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> = yes" (the default), only
+half of deliveries will suffer delays if there is an outage
that affects IPv6 or IPv4, as long as it does not affect both. </p>
+<li> <p> The setting "<a href="postconf.5.html#smtp_address_preference">smtp_address_preference</a> = ipv4" is not a
+solution for remote servers that flag email received over IPv6 as
+more 'spammy' (the client IPv6 address has a bad or missing PTR or
+AAAA record, bad network neighbors, etc.). Instead, configure Postfix
+to receive mail over both IPv4 and IPv6, and to deliver mail over
+only IPv4. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#inet_protocols">inet_protocols</a> = all
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="master.5.html">master.cf</a>
+ smtp ...other fields... smtp -o <a href="postconf.5.html#inet_protocols">inet_protocols</a>=ipv4
+</pre>
+</blockquote>
+
</ul>
<p> This feature is available in Postfix 2.8 and later. </p>
@@ -12295,6 +12501,9 @@ If no username:password entry is found, then the Postfix SMTP client
will not attempt to authenticate to the remote host.
</p>
+<p> Use <a href="postconf.5.html#smtp_sasl_password_result_delimiter">smtp_sasl_password_result_delimiter</a> to specify an
+alternative separator between username and password. </p>
+
<p>
The Postfix SMTP client opens the lookup table before going to
chroot jail, so you can leave the password file in /etc/postfix.
@@ -12309,6 +12518,18 @@ until a match is found.
</DD>
+<DT><b><a name="smtp_sasl_password_result_delimiter">smtp_sasl_password_result_delimiter</a>
+(default: :)</b></DT><DD>
+
+<p> The delimiter between username and password in sasl_passwd_maps lookup
+results. Specify one non-whitespace character that does not appear in
+the username. </p>
+
+<p> This feature is available in Postfix &ge; 3.9. </p>
+
+
+</DD>
+
<DT><b><a name="smtp_sasl_path">smtp_sasl_path</a>
(default: empty)</b></DT><DD>
@@ -13035,6 +13256,86 @@ compiled and linked with OpenSSL 1.0.0 or later. </p>
</DD>
+<DT><b><a name="smtp_tls_enable_rpk">smtp_tls_enable_rpk</a>
+(default: no)</b></DT><DD>
+
+<p> Request that remote SMTP servers send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+instead of an X.509 certificate. This feature and the enable_rpk
+policy attribute are ignored when there is no raw public key support
+in the local TLS implementation. </p>
+
+<ul>
+
+<li> <p> At the "may", "encrypt" and "fingerprint" security levels,
+with parameter setting "<a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> = yes" or with "enable_rpk
+= yes" in a policy entry, the Postfix SMTP client will indicate in
+the TLS handshake that it prefers to receive a raw server public
+key, but it will still accept a server public key certificate. </p>
+
+<li> <p> At the "fingerprint" security level, with parameter setting
+"<a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> = yes" or with "enable_rpk = yes" in a policy
+entry, server authentication based on certificate fingerprints
+becomes more fragile. Even if the server private key and certificate
+remain unchanged, the remote SMTP server will fail fingerprint
+authentication (won't match the configured list of fingerprints)
+when it starts sending a raw public key instead of a certificate,
+after its TLS implementation is updated with raw public key support.
+Therefore, <b>DO NOT</b> enable raw public keys to remote destinations
+authenticated by server <b>certificate</b> fingerprints. You should
+enable raw public keys only for servers matched via their public
+key fingerprint. </p>
+
+<li> <p> At the "verify" and "secure" security levels, the Postfix
+SMTP client always ignores the parameter setting <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a>
+or the enable_rpk policy attribute. </p>
+
+<li> <p> At the opportunistic "dane" security level, the Postfix
+SMTP client ignores the parameter setting <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> or
+the enable_rpk policy attribute (but it will respect them when it
+falls back to the "may" or "encrypt" level). When all valid TLSA
+records specify only server public keys (no certificates) and the
+local TLS implementation supports raw public keys, the client will
+indicate in the TLS handshake that it prefers to receive a raw
+public key, but it will still accept a public key certificate. </p>
+
+<li> <p> At the mandatory "dane-only" security level, the Postfix
+SMTP client always ignores the parameter setting <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a>
+or the enable_rpk policy attribute. When all valid TLSA records
+specify only server public keys (no certificates) and the local TLS
+implementation supports raw public keys, the client will indicate
+in the TLS handshake that it prefers to receive a raw public key,
+but it will still accept a public key certificate. </p>
+
+</ul>
+
+<p>The Postfix SMTP client is always willing to send raw public keys
+to servers that solicit them when a client certificate is configured
+and the local TLS implementation supports raw public keys. </p>
+
+<p> Sample commands to compute certificate and public key SHA256 digests: </p>
+
+<pre>
+# SHA256 digest of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -pubkey -noout |
+ openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first private key in "pkey.pem"
+$ openssl pkey -in pkey.pem -pubout -outform DER |
+ openssl dgst -sha256 -c
+</pre>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+
+</DD>
+
<DT><b><a name="smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
(default: yes)</b></DT><DD>
@@ -13296,7 +13597,9 @@ verification errors if server certificate verification is not required.
With Postfix 2.8 and earlier, log the summary message and unconditionally
log trust-chain verification errors. </dd>
-<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
+<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
+library, log session cache operations, and enable OpenSSL logging
+of the progress of the SSL handshake. </dd>
<dt> </dt> <dd> 3 Also log the hexadecimal and ASCII dump of the
TLS negotiation process. </dd>
@@ -13546,11 +13849,13 @@ lookup key, and overrides the global <a href="postconf.5.html#smtp_use_tls">smtp
and <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> settings. </dd>
<dt> MAY </dt> <dd> Try to use TLS if the server announces support,
-otherwise use an unencrypted connection. This has less precedence
+otherwise use an unencrypted connection; after a failed TLS handshake
+or TLS session, fall back to plaintext if the message has spent
+<a href="postconf.5.html#minimal_backoff_time">minimal_backoff_time</a> in the mail queue. This level has less precedence
than a more specific result (including <b>NONE</b>) from the alternate
host or next-hop lookup key, and has less precedence than the more
specific global "<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes" or "<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
-= yes". </dd>
+= yes". </dd>
<dt> MUST_NOPEERMATCH </dt> <dd> Require TLS encryption, but do not
require that the remote SMTP server hostname matches the information
@@ -13643,28 +13948,35 @@ security are: </p>
<dd>Opportunistic TLS. Since sending in the clear is acceptable,
demanding stronger than default TLS security merely reduces
interoperability. The optional "ciphers", "exclude", and "protocols"
-attributes (available for opportunistic TLS with Postfix &ge; 2.6)
-and "connection_reuse" attribute (Postfix &ge; 3.4) override the
+attributes (available for opportunistic TLS with Postfix &ge; 2.6) and
+"connection_reuse" attribute (Postfix &ge; 3.4) override the
"<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>", "<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a>", "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>",
-and
-"<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a>" configuration parameters. In the policy table,
-multiple ciphers, protocols or excluded ciphers must be separated by colons,
-as attribute values may not contain whitespace or commas. When opportunistic
-TLS handshakes fail, Postfix retries the connection with TLS disabled.
-This allows mail delivery to sites with non-interoperable TLS
-implementations.</dd>
+and "<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a>" configuration parameters. In the policy
+table, multiple ciphers, protocols or excluded ciphers must be separated
+by colons, as attribute values may not contain whitespace or commas. At
+this level and higher, the optional "servername" attribute (available
+with Postfix &ge; 3.4) overrides the global "<a href="postconf.5.html#smtp_tls_servername">smtp_tls_servername</a>"
+parameter, enabling per-destination configuration of the SNI extension
+sent to the remote SMTP server. The optional "enable_rpk" attribute
+(Postfix &ge; 3.9) overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> parameter.
+When opportunistic TLS handshakes fail, Postfix retries the connection
+with TLS disabled. This allows mail delivery to sites with
+non-interoperable TLS implementations.</dd>
<dt><b><a href="TLS_README.html#client_tls_encrypt">encrypt</a></b></dt>
-<dd>Mandatory TLS encryption. At this level
-and higher, the optional "protocols" attribute overrides the <a href="postconf.5.html">main.cf</a>
+<dd>Mandatory TLS encryption. Mail is delivered only if the remote SMTP
+server offers STARTTLS and the TLS handshake succeeds. At this level and
+higher, the optional "protocols" attribute overrides the <a href="postconf.5.html">main.cf</a>
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> parameter, the optional "ciphers" attribute
-overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a> parameter, the
-optional "exclude" attribute (Postfix &ge; 2.6) overrides the <a href="postconf.5.html">main.cf</a>
+overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a> parameter, the optional
+"exclude" attribute (Postfix &ge; 2.6) overrides the <a href="postconf.5.html">main.cf</a>
<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a> parameter, and the optional
-"connection_reuse" attribute (Postfix &ge; 3.4) overrides the
-<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. In the policy table,
-multiple ciphers, protocols or excluded ciphers must be separated by colons,
-as attribute values may not contain whitespace or commas. </dd>
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. In the policy table, multiple
+ciphers, protocols or excluded ciphers must be separated by colons, as
+attribute values may not contain whitespace or commas. The optional
+"enable_rpk" attribute (Postfix &ge; 3.9) overrides the <a href="postconf.5.html">main.cf</a>
+<a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> parameter. </dd>
<dt><b><a href="TLS_README.html#client_tls_dane">dane</a></b></dt>
<dd>Opportunistic DANE TLS. The TLS policy for the destination is
@@ -13709,10 +14021,10 @@ configuration parameters. The optional "connection_reuse" attribute
verification. Available with Postfix 2.5 and later. At this security
level, there are no trusted Certification Authorities. The certificate
trust chain, expiration date, ... are not checked. Instead,
-the optional "match" attribute, or else the <a href="postconf.5.html">main.cf</a>
+the optional policy table "match" attribute, or else the <a href="postconf.5.html">main.cf</a>
<b><a href="postconf.5.html#smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a></b> parameter, lists the certificate
-fingerprints or the public key fingerprint (Postfix 2.9 and later)
-of the valid server certificate. The digest
+fingerprints or the public key fingerprints (Postfix 2.9 and later)
+of acceptable server certificates. The digest
algorithm used to calculate the fingerprint is selected by the
<b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b> parameter. Multiple fingerprints can
be combined with a "|" delimiter in a single match attribute, or multiple
@@ -13723,45 +14035,58 @@ digits. The optional "ciphers", "exclude", and "protocols" attributes
"<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and "<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>"
configuration parameters. The optional "connection_reuse" attribute
(Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a>
-parameter. </dd>
+parameter. The optional "enable_rpk" attribute (Postfix &ge; 3.9)
+overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> parameter. </dd>
<dt><b><a href="TLS_README.html#client_tls_verify">verify</a></b></dt>
-<dd>Mandatory TLS verification. At this security
-level, DNS MX lookups are trusted to be secure enough, and the name
-verified in the server certificate is usually obtained indirectly via
-unauthenticated DNS MX lookups. The optional "match" attribute overrides
-the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_verify_cert_match">smtp_tls_verify_cert_match</a> parameter. In the policy table,
-multiple match patterns and strategies must be separated by colons.
-In practice explicit control over matching is more common with the
-"secure" policy, described below. The optional "ciphers", "exclude",
-and "protocols" attributes (Postfix &ge; 2.6) override the
-"<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>", "<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and
-"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>" configuration parameters. The optional
-"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
-<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
+<dd>Mandatory TLS verification. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups are presumed to be
+secure enough, and the name verified in the server certificate is
+potentially obtained via unauthenticated DNS MX lookups. The optional
+"match" attribute overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_verify_cert_match">smtp_tls_verify_cert_match</a>
+parameter. In the policy table, multiple match patterns and strategies
+must be separated by colons. In practice explicit control over matching
+is more common with the "secure" policy, described below. The optional
+"ciphers", "exclude", and "protocols" attributes (Postfix &ge; 2.6)
+override the "<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>",
+"<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and "<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>"
+configuration parameters. With Postfix &ge; 2.11 the optional "tafile"
+policy table attribute modifies trust chain verification in the same
+manner as the "<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile"
+attribute may be specified multiple times to load multiple trust-anchor
+files. The optional "connection_reuse" attribute (Postfix &ge; 3.4)
+overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
<dt><b><a href="TLS_README.html#client_tls_secure">secure</a></b></dt>
-<dd>Secure-channel TLS. At this security level, DNS
-MX lookups, though potentially used to determine the candidate next-hop
-gateway IP addresses, are <b>not</b> trusted to be secure enough for TLS
-peername verification. Instead, the default name verified in the server
-certificate is obtained directly from the next-hop, or is explicitly
-specified via the optional "match" attribute which overrides the
-<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_secure_cert_match">smtp_tls_secure_cert_match</a> parameter. In the policy table,
-multiple match patterns and strategies must be separated by colons.
-The match attribute is most useful when multiple domains are supported by
-a common server: the policy entries for additional domains specify matching
-rules for the primary domain certificate. While transport table overrides
-that route the secondary domains to the primary nexthop also allow secure
-verification, they risk delivery to the wrong destination when domains
-change hands or are re-assigned to new gateways. With the "match"
-attribute approach, routing is not perturbed, and mail is deferred if
-verification of a new MX host fails. The optional "ciphers", "exclude",
-and "protocols" attributes (Postfix &ge; 2.6) override the
-"<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>", "<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and
-"<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>" configuration parameters. The optional
-"connection_reuse" attribute (Postfix &ge; 3.4) overrides the <a href="postconf.5.html">main.cf</a>
-<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
+<dd>Secure certificate verification. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups, though potentially
+used to determine the candidate next-hop gateway IP addresses, are
+<b>not</b> presumed to be secure enough for TLS peername verification.
+Instead, the default name verified in the server certificate is obtained
+directly from the next-hop, or is explicitly specified via the optional
+"match" attribute which overrides the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_secure_cert_match">smtp_tls_secure_cert_match</a>
+parameter. In the policy table, multiple match patterns and strategies
+must be separated by colons. The match attribute is most useful when
+multiple domains are supported by a common server: the policy entries
+for additional domains specify matching rules for the primary domain
+certificate. While transport table overrides that route the secondary
+domains to the primary nexthop also allow secure verification, they risk
+delivery to the wrong destination when domains change hands or are
+re-assigned to new gateways. With the "match" attribute approach,
+routing is not perturbed, and mail is deferred if verification of a new
+MX host fails. The optional "ciphers", "exclude", and "protocols"
+attributes (Postfix &ge; 2.6) override the "<a href="postconf.5.html#smtp_tls_mandatory_ciphers">smtp_tls_mandatory_ciphers</a>",
+"<a href="postconf.5.html#smtp_tls_mandatory_exclude_ciphers">smtp_tls_mandatory_exclude_ciphers</a>", and "<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>"
+configuration parameters. With Postfix &ge; 2.11 the "tafile" attribute
+optionally modifies trust chain verification in the same manner as the
+"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter. The "tafile" attribute may be
+specified multiple times to load multiple trust-anchor files. The
+optional "connection_reuse" attribute (Postfix &ge; 3.4) overrides the
+<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> parameter. </dd>
</dl>
@@ -13807,7 +14132,7 @@ configurations in environments where DNS security is not assured. </p>
</DD>
<DT><b><a name="smtp_tls_protocols">smtp_tls_protocols</a>
-(default: see postconf -d output)</b></DT><DD>
+(default: see 'postconf -d' output)</b></DT><DD>
<p> TLS protocols that the Postfix SMTP client will use with
opportunistic TLS encryption. In <a href="postconf.5.html">main.cf</a> the values are separated by
@@ -13975,7 +14300,9 @@ destinations via <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_
<dt><b><a href="TLS_README.html#client_tls_may">may</a></b></dt>
<dd> Opportunistic TLS. Use TLS if this is supported by the remote
-SMTP server, otherwise use plaintext. Since
+SMTP server, otherwise use plaintext; after a failed TLS handshake
+or TLS session, fall back to plaintext if the message has spent
+<a href="postconf.5.html#minimal_backoff_time">minimal_backoff_time</a> in the mail queue. Since
sending in the clear is acceptable, demanding stronger than default TLS
security merely reduces interoperability.
The "<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a>" and "<a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a>" (Postfix &ge; 2.6)
@@ -14896,9 +15223,8 @@ pubkey_fingerprint } } </dd>
<dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
-<dd>Search the specified access database for the client hostname,
-parent domains, client IP address, or networks obtained by stripping
-least significant octets. See the <a href="access.5.html">access(5)</a> manual page for details. </dd>
+<dd>Search the specified access database for the client hostname
+or IP address. See the <a href="access.5.html">access(5)</a> manual page for details. </dd>
<dt><b><a name="check_client_a_access">check_client_a_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
@@ -14929,8 +15255,7 @@ available in Postfix 2.7 and later. </dd>
<dt><b><a name="check_reverse_client_hostname_access">check_reverse_client_hostname_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified access database for the unverified reverse
-client hostname, parent domains, client IP address, or networks
-obtained by stripping least significant octets. See the <a href="access.5.html">access(5)</a>
+client hostname or IP address. See the <a href="access.5.html">access(5)</a>
manual page for details. Note: a result of "OK" is not allowed for
safety reasons. Instead, use DUNNO in order to exclude specific
hosts from denylists. This feature is available in Postfix 2.6
@@ -15527,6 +15852,9 @@ server. This option is therefore off by default. </p>
STARTTLS due to insufficient privileges to access the server private
key. This is intended behavior. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use <a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> instead. </p>
@@ -15588,8 +15916,8 @@ received with the ETRN command.
<dt><b><a name="check_etrn_access">check_etrn_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
-<dd>Search the specified access database for the ETRN domain name
-or its parent domains. See the <a href="access.5.html">access(5)</a> manual page for details.
+<dd>Search the specified access database for the ETRN domain name.
+See the <a href="access.5.html">access(5)</a> manual page for details.
</dd>
</dl>
@@ -15641,7 +15969,7 @@ This feature is available in Postfix 2.0 and later.
</DD>
<DT><b><a name="smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a>
-(default: Postfix &lt; 3.9: no)</b></DT><DD>
+(default: Postfix &ge; 3.9: normalize)</b></DT><DD>
<p> Reject or restrict input lines from an SMTP client that end in
&lt;LF&gt; instead of the standard &lt;CR&gt;&lt;LF&gt;. Such line
@@ -15654,7 +15982,8 @@ SMTP smuggling</a>. </p>
<dl compact>
-<dt> <b>normalize</b></dt> <dd> Require the standard
+<dt> <b>normalize</b> (default for Postfix &ge; 3.9) </dt>
+<dd> Require the standard
End-of-DATA sequence &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;.
Otherwise, allow command or message content lines ending in the
non-standard &lt;LF&gt;, and process them as if the client sent the
@@ -15666,6 +15995,13 @@ with the standard End-of-DATA sequence
&lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;. <br> <br> Such clients
can be excluded with <a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a>. </dd>
+<dt> <b>note</b> </dt> <dd> Same as "normalize", but also notes in
+the log whether the Postfix SMTP server received any lines with
+"bare &lt;LF&gt;". The information is formatted as "<tt>disconnect
+from name[address] ... notes=bare_lf</tt>". The notes value is
+expected to become a list of comma-separated names. <br> <br> This
+feature is available in Postfix 3.9 and later. </dd>
+
<dt> <b>yes</b> </dt> <dd> Compatibility alias for <b>normalize</b>. </dd>
<dt> <b>reject</b> </dt> <dd> Require the standard End-of-DATA
@@ -15684,8 +16020,8 @@ of BDAT violations, BDAT can be selectively disabled with
<a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">smtpd_discard_ehlo_keyword_address_maps</a>, or globally disabled with
<a href="postconf.5.html#smtpd_discard_ehlo_keywords">smtpd_discard_ehlo_keywords</a>). </dd>
-<dt> <b>no</b> (default)</dt> <dd> Do not require the standard
-End-of-DATA
+<dt> <b>no</b> (default for Postfix &lt; 3.9) </dt>
+<dd> Do not require the standard End-of-DATA
sequence &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;. Always process
a bare &lt;LF&gt; as if the client sent &lt;CR&gt;&lt;LF&gt;. This
option is fully backwards compatible, but is not recommended for
@@ -15793,9 +16129,9 @@ Specify a 5XX status code (521 to disconnect).
<p> Disconnect remote SMTP clients that violate <a href="https://tools.ietf.org/html/rfc2920">RFC 2920</a> (or 5321)
command pipelining constraints. The server replies with "554 5.5.0
Error: SMTP protocol synchronization" and logs the unexpected remote
-SMTP client input. Specify "<a href="postconf.5.html#smtpd_forbid_unauth_pipelining">smtpd_forbid_unauth_pipelining</a> = yes"
-to enable. This feature is enabled by default with Postfix &ge;
-3.9. </p>
+SMTP client input. This feature is enabled by default with Postfix
+&ge; 3.9. Specify "<a href="postconf.5.html#smtpd_forbid_unauth_pipelining">smtpd_forbid_unauth_pipelining</a> = no" to disable.
+</p>
<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20. </p>
@@ -15899,7 +16235,7 @@ received with the HELO or EHLO command.
<dt><b><a name="check_helo_access">check_helo_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified <a href="access.5.html">access(5)</a> database for the HELO or EHLO
-hostname or parent domains, and execute the corresponding action.
+hostname, and execute the corresponding action.
Note: specify "<a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> = yes" to fully enforce this
restriction (without "<a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> = yes", a client can
simply skip <a href="postconf.5.html#check_helo_access">check_helo_access</a> by not sending HELO or EHLO). </dd>
@@ -16563,8 +16899,7 @@ that is received with the RCPT TO command.
<dt><b><a name="check_recipient_access">check_recipient_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified <a href="access.5.html">access(5)</a> database for the resolved RCPT
-TO address, domain, parent domains, or localpart@, and execute the
-corresponding action. </dd>
+TO address, and execute the corresponding action. </dd>
<dt><b><a name="check_recipient_a_access">check_recipient_a_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
@@ -16993,7 +17328,7 @@ The same restrictions are available as documented under
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a>.
</p>
-<p> This feature is available in Postix 2.10 and later. </p>
+<p> This feature is available in Postfix 2.10 and later. </p>
</DD>
@@ -17411,8 +17746,7 @@ received with the MAIL FROM command.
<dt><b><a name="check_sender_access">check_sender_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified <a href="access.5.html">access(5)</a> database for the MAIL FROM
-address, domain, parent domains, or localpart@, and execute the
-corresponding action. </dd>
+address, and execute the corresponding action. </dd>
<dt><b><a name="check_sender_a_access">check_sender_a_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
@@ -18316,6 +18650,53 @@ where EC algorithms have not been disabled by the vendor. </p>
</DD>
+<DT><b><a name="smtpd_tls_enable_rpk">smtpd_tls_enable_rpk</a>
+(default: no)</b></DT><DD>
+
+<p> Request that remote SMTP clients send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+instead of an X.509 certificate, when asking for or requiring client
+authentication. This feature is ignored when there is no raw public
+key support in the local TLS implementation. </p>
+
+<p> The Postfix SMTP server will log a warning when "<a href="postconf.5.html#smtpd_tls_enable_rpk">smtpd_tls_enable_rpk</a>
+= yes", but the remote SMTP client sends a certificate, the
+certificate's public key fingerprint does not match a <a href="postconf.5.html#check_ccert_access">check_ccert_access</a>
+table, while the certificate fingerprint does match a <a href="postconf.5.html#check_ccert_access">check_ccert_access</a>
+table. The remote SMTP client would lose access when it starts
+sending a raw public key instead of a certificate, after its TLS
+implementation is updated with raw public key support. </p>
+
+<p> The Postfix SMTP server always sends a raw public key instead
+of a certificate, if solicited by the remote SMTP client and the
+local TLS implementation supports raw public keys. If the client
+sends a server name indication with an SNI TLS extension, and
+<a href="postconf.5.html#tls_server_sni_maps">tls_server_sni_maps</a> is configured, the server will extract a raw
+public key from the indicated certificate. </p>
+
+<p> Sample commands to compute certificate and public key SHA256 digests: </p>
+
+<pre>
+# SHA256 digest of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -pubkey -noout |
+ openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first private key in "pkey.pem"
+$ openssl pkey -in pkey.pem -pubout -outform DER |
+ openssl dgst -sha256 -c
+</pre>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+
+</DD>
+
<DT><b><a name="smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a>
(default: empty)</b></DT><DD>
@@ -18472,7 +18853,9 @@ if client certificate verification is not required. With Postfix 2.8 and
earlier, log the summary message, peer certificate summary information
and unconditionally log trust-chain verification errors. </dd>
-<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
+<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
+library, log session cache operations, and enable OpenSSL logging
+of the progress of the SSL handshake. </dd>
<dt> </dt> <dd> 3 Also log hexadecimal and ASCII dump of TLS negotiation
process. </dd>
@@ -18655,7 +19038,7 @@ releases &ge; 3.0.14, 3.1.10, 3.2.7 and 3.3.2). </p>
</DD>
<DT><b><a name="smtpd_tls_protocols">smtpd_tls_protocols</a>
-(default: see postconf -d output)</b></DT><DD>
+(default: see 'postconf -d' output)</b></DT><DD>
<p> TLS protocols accepted by the Postfix SMTP server with opportunistic
TLS encryption. If the list is empty, the server supports all available
@@ -18931,6 +19314,9 @@ but do not require that clients use TLS encryption. </p>
STARTTLS due to insufficient privileges to access the server private
key. This is intended behavior. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use <a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> instead. </p>
@@ -19438,8 +19824,7 @@ via the <a href="postconf.5.html#tls_config_file">tls_config_file</a> parameter.
selected name is not present in the configuration file, the default
application name ("openssl_conf") is used as a fallback. </p>
-<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
-3.6.10, and 3.5.20. </p>
+<p> This feature is available in Postfix &ge; 3.9. </p>
</DD>
@@ -20356,6 +20741,9 @@ to configure tlsproxy client keys and certificates is via the
See <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> for further details. Use
<a href="postconf.5.html#tlsproxy_client_security_level">tlsproxy_client_security_level</a> instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#tlsproxy_client_security_level">tlsproxy_client_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 3.4 and later. </p>
@@ -20427,6 +20815,9 @@ value. </p>
usage policy by next-hop destination and by remote TLS server
hostname. See <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> for further details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#tlsproxy_client_policy_maps">tlsproxy_client_policy_maps</a> instead. </p>
+
<p> This feature is available in Postfix 3.4 and later. </p>
@@ -20488,6 +20879,9 @@ was previously called <a href="postconf.5.html#tlsproxy_client_level">tlsproxy_c
support. See <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> for further details. Use
<a href="postconf.5.html#tlsproxy_client_security_level">tlsproxy_client_security_level</a> instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#tlsproxy_client_security_level">tlsproxy_client_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 3.4 and later. </p>
@@ -20500,6 +20894,9 @@ support. See <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> for further
require that clients use TLS encryption. See <a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> for
further details. Use <a href="postconf.5.html#tlsproxy_tls_security_level">tlsproxy_tls_security_level</a> instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#tlsproxy_tls_security_level">tlsproxy_tls_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
@@ -20632,6 +21029,8 @@ private DSA key. DSA is obsolete and should not be used. See
should use with non-export EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>
for further details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Do not specify. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
@@ -20704,11 +21103,25 @@ the "<a href="postconf.5.html#tlsproxy_tls_chain_files">tlsproxy_tls_chain_files
elliptic-curve Diffie-Hellman (EECDH) key exchange. See
<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> for further details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Do not specify. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
</DD>
+<DT><b><a name="tlsproxy_tls_enable_rpk">tlsproxy_tls_enable_rpk</a>
+(default: $<a href="postconf.5.html#smtpd_tls_enable_rpk">smtpd_tls_enable_rpk</a>)</b></DT><DD>
+
+<p> Request that remote SMTP clients send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+instead of an X.509 certificate, when asking or requiring client
+authentication. See $<a href="postconf.5.html#smtpd_tls_enable_rpk">smtpd_tls_enable_rpk</a> for details. </p>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+
+</DD>
+
<DT><b><a name="tlsproxy_tls_exclude_ciphers">tlsproxy_tls_exclude_ciphers</a>
(default: $<a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a>)</b></DT><DD>
@@ -20856,6 +21269,9 @@ shared by all three services, namely <a href="postconf.5.html#smtpd_tls_session_
but do not require that clients use TLS encryption. See <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>
for further details. Use <a href="postconf.5.html#tlsproxy_tls_security_level">tlsproxy_tls_security_level</a> instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+<a href="postconf.5.html#tlsproxy_tls_security_level">tlsproxy_tls_security_level</a> instead. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
@@ -21100,7 +21516,14 @@ built-in suffix (in this case: "_initial_destination_concurrency").
<p>
Optional lookup tables with mappings from recipient address to
(message delivery transport, next-hop destination). See <a href="transport.5.html">transport(5)</a>
-for details.
+for syntax details.
+</p>
+
+<p> This information may override the message delivery transport
+and/or next-hop destination that are specified with $<a href="postconf.5.html#local_transport">local_transport</a>,
+$<a href="postconf.5.html#virtual_transport">virtual_transport</a>, $<a href="postconf.5.html#relay_transport">relay_transport</a>, $<a href="postconf.5.html#default_transport">default_transport</a>,
+$<a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>, $<a href="postconf.5.html#relayhost">relayhost</a>,
+$<a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a>, or the recipient domain.
</p>
<p>
@@ -21735,7 +22158,7 @@ This feature is available in Postfix 1.1 and later.
<p>
The maximal length of an email address after virtual alias expansion.
-This stops virtual aliasing loops that increase the address length
+This stops <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a> loops that increase the address length
exponentially.
</p>
@@ -21814,8 +22237,10 @@ This feature is available in Postfix 2.1 and later.
(default: $<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b></DT><DD>
<p>
-Optional lookup tables that alias specific mail addresses or domains
-to other local or remote addresses. The table format and lookups
+Optional lookup tables with aliases that apply to all recipients:
+<a href="local.8.html">local(8)</a>, virtual, and remote; this is unlike <a href="postconf.5.html#alias_maps">alias_maps</a> that apply
+only to <a href="local.8.html">local(8)</a> recipients.
+The table format and lookups
are documented in <a href="virtual.5.html">virtual(5)</a>. For an overview of Postfix address
manipulations see the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document.
</p>
diff --git a/html/postdrop.1.html b/html/postdrop.1.html
index 72a4abf..bc4293a 100644
--- a/html/postdrop.1.html
+++ b/html/postdrop.1.html
@@ -70,7 +70,7 @@ POSTDROP(1) POSTDROP(1)
figuration files.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
+ The list of environment variables that a privileged Postfix
process will import from a non-Postfix parent process, or
name=value environment overrides.
diff --git a/html/postfix-manuals.html b/html/postfix-manuals.html
index 7ddfa73..84774a5 100644
--- a/html/postfix-manuals.html
+++ b/html/postfix-manuals.html
@@ -135,7 +135,7 @@ the following convention: </p>
<li> <a href="access.5.html">access(5)</a>, Postfix SMTP access control table
-<li> <a href="aliases.5.html">aliases(5)</a>, Postfix alias database
+<li> <a href="aliases.5.html">aliases(5)</a>, Postfix <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a>
<li> <a href="canonical.5.html">canonical(5)</a>, Postfix input address rewriting
@@ -147,7 +147,7 @@ the following convention: </p>
<li> <a href="transport.5.html">transport(5)</a>, Postfix routing table
-<li> <a href="virtual.5.html">virtual(5)</a>, Postfix virtual aliasing
+<li> <a href="virtual.5.html">virtual(5)</a>, Postfix <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a>
</ul>
@@ -164,6 +164,8 @@ the following convention: </p>
<li> <a href="memcache_table.5.html">memcache_table(5)</a>, Postfix memcache client
+<li> <a href="mongodb_table.5.html">mongodb_table(5)</a>, Postfix MongoDB client
+
<li> <a href="mysql_table.5.html">mysql_table(5)</a>, Postfix MYSQL client
<li> <a href="nisplus_table.5.html">nisplus_table(5)</a>, Postfix NIS+ client
diff --git a/html/postfix.1.html b/html/postfix.1.html
index 4654071..a6ede78 100644
--- a/html/postfix.1.html
+++ b/html/postfix.1.html
@@ -346,19 +346,20 @@ POSTFIX(1) POSTFIX(1)
Table-driven mechanisms:
<a href="access.5.html">access(5)</a>, Postfix SMTP access control table
- <a href="aliases.5.html">aliases(5)</a>, Postfix alias database
+ <a href="aliases.5.html">aliases(5)</a>, Postfix <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a>
<a href="canonical.5.html">canonical(5)</a>, Postfix input address rewriting
<a href="generic.5.html">generic(5)</a>, Postfix output address rewriting
<a href="header_checks.5.html">header_checks(5)</a>, <a href="header_checks.5.html">body_checks(5)</a>, Postfix content inspection
<a href="relocated.5.html">relocated(5)</a>, Users that have moved
<a href="transport.5.html">transport(5)</a>, Postfix routing table
- <a href="virtual.5.html">virtual(5)</a>, Postfix virtual aliasing
+ <a href="virtual.5.html">virtual(5)</a>, Postfix <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a>
Table lookup mechanisms:
<a href="cidr_table.5.html">cidr_table(5)</a>, Associate CIDR pattern with value
<a href="ldap_table.5.html">ldap_table(5)</a>, Postfix LDAP client
<a href="lmdb_table.5.html">lmdb_table(5)</a>, Postfix LMDB database driver
<a href="memcache_table.5.html">memcache_table(5)</a>, Postfix memcache client
+ <a href="mongodb_table.5.html">mongodb_table(5)</a>, Postfix MongoDB client
<a href="mysql_table.5.html">mysql_table(5)</a>, Postfix MYSQL client
<a href="nisplus_table.5.html">nisplus_table(5)</a>, Postfix NIS+ client
<a href="pcre_table.5.html">pcre_table(5)</a>, Associate PCRE pattern with value
diff --git a/html/postkick.1.html b/html/postkick.1.html
index 3156fc4..9ca7c59 100644
--- a/html/postkick.1.html
+++ b/html/postkick.1.html
@@ -63,7 +63,7 @@ POSTKICK(1) POSTKICK(1)
the Postfix daemon process input buffer before giving up.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
+ The list of environment variables that a privileged Postfix
process will import from a non-Postfix parent process, or
name=value environment overrides.
diff --git a/html/postlock.1.html b/html/postlock.1.html
index 0ca0b57..9750f9b 100644
--- a/html/postlock.1.html
+++ b/html/postlock.1.html
@@ -93,7 +93,7 @@ POSTLOCK(1) POSTLOCK(1)
figuration files.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
+ The list of environment variables that a privileged Postfix
process will import from a non-Postfix parent process, or
name=value environment overrides.
diff --git a/html/postlog.1.html b/html/postlog.1.html
index 587edbc..617b78b 100644
--- a/html/postlog.1.html
+++ b/html/postlog.1.html
@@ -90,6 +90,13 @@ POSTLOG(1) POSTLOG(1)
<b><a href="postconf.5.html#postlog_service_name">postlog_service_name</a> (postlog)</b>
The name of the <a href="postlogd.8.html"><b>postlogd</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
+ Available in Postfix 3.9 and later:
+
+ <b><a href="postconf.5.html#maillog_file_permissions">maillog_file_permissions</a> (0600)</b>
+ The file access permissions that will be set when the file
+ $<a href="postconf.5.html#maillog_file">maillog_file</a> is created for the first time, or when the file is
+ created after an existing file is rotated.
+
<b>SEE ALSO</b>
<a href="postconf.5.html">postconf(5)</a>, configuration parameters
<a href="postlogd.8.html">postlogd(8)</a>, Postfix logging
diff --git a/html/postlogd.8.html b/html/postlogd.8.html
index 58cdf01..e0a72af 100644
--- a/html/postlogd.8.html
+++ b/html/postlogd.8.html
@@ -36,9 +36,9 @@ POSTLOGD(8) POSTLOGD(8)
<a href="postqueue.1.html"><b>postqueue</b>(1)</a> and (Postfix &gt;= 3.7) <a href="postlog.1.html"><b>postlog</b>(1)</a>.
<b>CONFIGURATION PARAMETERS</b>
- Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="postlogd.8.html"><b>postlogd</b>(8)</a> pro-
- cesses run for only a limited amount of time. Use the command "<b>postfix</b>
- <b>reload</b>" to speed up a change.
+ Changes to <a href="postconf.5.html"><b>main.cf</b></a> are not picked up automatically, because <a href="postlogd.8.html"><b>postlogd</b>(8)</a>
+ terminates only after reaching the <b><a href="postconf.5.html#max_idle">max_idle</a></b> time limit. Use the com-
+ mand "<b>postfix reload</b>" to speed up a change.
The text below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for
more details including examples.
@@ -68,6 +68,13 @@ POSTLOGD(8) POSTLOGD(8)
How much time a <a href="postlogd.8.html"><b>postlogd</b>(8)</a> process may take to process a
request before it is terminated by a built-in watchdog timer.
+ Available in Postfix 3.9 and later:
+
+ <b><a href="postconf.5.html#maillog_file_permissions">maillog_file_permissions</a> (0600)</b>
+ The file access permissions that will be set when the file
+ $<a href="postconf.5.html#maillog_file">maillog_file</a> is created for the first time, or when the file is
+ created after an existing file is rotated.
+
<b>SEE ALSO</b>
<a href="postconf.5.html">postconf(5)</a>, configuration parameters
syslogd(8), system logging
diff --git a/html/postscreen.8.html b/html/postscreen.8.html
index 3511a9c..9ab10b7 100644
--- a/html/postscreen.8.html
+++ b/html/postscreen.8.html
@@ -315,31 +315,35 @@ POSTSCREEN(8) POSTSCREEN(8)
porary allowlist entry before it is removed.
<b><a href="postconf.5.html#postscreen_bare_newline_ttl">postscreen_bare_newline_ttl</a> (30d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the result from a
- successful "bare newline" SMTP protocol test.
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> remembers that a client IP
+ address passed a "bare newline" SMTP protocol test, before it
+ address is required to pass that test again.
<b><a href="postconf.5.html#postscreen_dnsbl_max_ttl">postscreen_dnsbl_max_ttl</a></b>
<b>(${<a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>?{$<a href="postconf.5.html#postscreen_dnsbl_ttl">postscreen_dnsbl_ttl</a>}:{1}}h)</b>
- The maximum amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
- result from a successful DNS-based reputation test before a
- client IP address is required to pass that test again.
+ The maximum amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> remembers that a
+ client IP address passed a DNS-based reputation test, before it
+ is required to pass that test again.
<b><a href="postconf.5.html#postscreen_dnsbl_min_ttl">postscreen_dnsbl_min_ttl</a> (60s)</b>
- The minimum amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the
- result from a successful DNS-based reputation test before a
- client IP address is required to pass that test again.
+ The minimum amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> remembers that a
+ client IP address passed a DNS-based reputation test, before it
+ is required to pass that test again.
<b><a href="postconf.5.html#postscreen_greet_ttl">postscreen_greet_ttl</a> (1d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the result from a
- successful PREGREET test.
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> remembers that a client IP
+ address passed a PREGREET test, before it is required to pass
+ that test again.
<b><a href="postconf.5.html#postscreen_non_smtp_command_ttl">postscreen_non_smtp_command_ttl</a> (30d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the result from a
- successful "non_smtp_command" SMTP protocol test.
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> remembers that a client IP
+ address passed a "non_smtp_command" SMTP protocol test, before
+ it is required to pass that test again.
<b><a href="postconf.5.html#postscreen_pipelining_ttl">postscreen_pipelining_ttl</a> (30d)</b>
- The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will use the result from a
- successful "pipelining" SMTP protocol test.
+ The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> remembers that a client IP
+ address passed a "pipelining" SMTP protocol test, before it is
+ required to pass that test again.
<b>RESOURCE CONTROLS</b>
<b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
diff --git a/html/postsuper.1.html b/html/postsuper.1.html
index 30a524a..cf0681a 100644
--- a/html/postsuper.1.html
+++ b/html/postsuper.1.html
@@ -275,7 +275,7 @@ POSTSUPER(1) POSTSUPER(1)
subdirectory levels.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment parameters that a privileged Postfix
+ The list of environment variables that a privileged Postfix
process will import from a non-Postfix parent process, or
name=value environment overrides.
diff --git a/html/posttls-finger.1.html b/html/posttls-finger.1.html
index 2ed629a..a1475ca 100644
--- a/html/posttls-finger.1.html
+++ b/html/posttls-finger.1.html
@@ -112,7 +112,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1)
ified in the DNS). In Postfix versions prior to 3.6, the
default value was "md5".
- <b>-f</b> Lookup the associated DANE TLSA RRset even when a hostname is
+ <b>-f</b> Look up the associated DANE TLSA RRset even when a hostname is
not an alias and its address records lie in an unsigned zone.
See <a href="postconf.5.html#smtp_tls_force_insecure_host_tlsa_lookup">smtp_tls_force_insecure_host_tlsa_lookup</a> for details.
@@ -302,6 +302,16 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1)
protocol. The destination <i>domain</i>:<i>port</i> must of course provide
such a service.
+ <b>-x</b> Prefer <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> non-X.509 raw public key (RPK) server creden-
+ tials. By default only X.509 certificates are accepted. This
+ is analogous to setting <b><a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> = yes</b> in the <a href="smtp.8.html">smtp(8)</a>
+ client. At the fingerprint security level, when raw public keys
+ are enabled, only public key (and not certificate) fingerprints
+ will be compared against the specified list of <i>match</i> arguments.
+ Certificate fingerprints are fragile when raw public keys are
+ solicited, the server may at some point in time start returning
+ only the public key.
+
<b>-X</b> Enable <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> mode. This is an unsupported mode, for pro-
gram development only.
diff --git a/html/proxymap.8.html b/html/proxymap.8.html
index 7c98c47..a1f2f18 100644
--- a/html/proxymap.8.html
+++ b/html/proxymap.8.html
@@ -41,7 +41,7 @@ PROXYMAP(8) PROXYMAP(8)
<b>o</b> To provide single-updater functionality for lookup tables that
do not reliably support multiple writers (i.e. all file-based
- tables).
+ tables that are not based on <b>lmdb</b>).
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server implements the following requests:
diff --git a/html/qmgr.8.html b/html/qmgr.8.html
index bfaa05f..068b256 100644
--- a/html/qmgr.8.html
+++ b/html/qmgr.8.html
@@ -232,8 +232,8 @@ QMGR(8) QMGR(8)
ter.cf</a> name of the message delivery transport.
<b><a href="postconf.5.html#default_recipient_refill_delay">default_recipient_refill_delay</a> (5s)</b>
- The default per-transport maximum delay between recipients
- refills.
+ The default per-transport maximum delay between refilling recip-
+ ients.
<b><a href="postconf.5.html#transport_recipient_refill_delay">transport_recipient_refill_delay</a> ($<a href="postconf.5.html#default_recipient_refill_delay">default_recipient_refill_delay</a>)</b>
A transport-specific override for the <a href="postconf.5.html#default_recipient_refill_delay">default_recipi</a>-
diff --git a/html/qmqpd.8.html b/html/qmqpd.8.html
index 9506cfa..55cbcdc 100644
--- a/html/qmqpd.8.html
+++ b/html/qmqpd.8.html
@@ -61,7 +61,7 @@ QMQPD(8) QMQPD(8)
<b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b>
Enable preliminary SMTPUTF8 support for the protocols described
- in <a href="https://tools.ietf.org/html/rfc6531">RFC 6531</a>..6533.
+ in <a href="https://tools.ietf.org/html/rfc6531">RFC 6531</a>, <a href="https://tools.ietf.org/html/rfc6532">RFC 6532</a>, and <a href="https://tools.ietf.org/html/rfc6533">RFC 6533</a>.
<b><a href="postconf.5.html#smtputf8_autodetect_classes">smtputf8_autodetect_classes</a> (sendmail, verify)</b>
Detect that a message requires SMTPUTF8 support for the speci-
diff --git a/html/regexp_table.5.html b/html/regexp_table.5.html
index 05cda13..96e4b38 100644
--- a/html/regexp_table.5.html
+++ b/html/regexp_table.5.html
@@ -148,8 +148,12 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
Postfix parses the result as if it is a file in /etc/postfix.
- Note: if a rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from trying to
- do <i>$name</i> expansion as it evaluates a parameter value.
+ Note: if an inlined rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from
+ trying to do <i>$name</i> expansion as it evaluates a parameter value.
+
+ Note: when using <i>$name</i> inside an inlined pattern, this will not disable
+ metacharacters such as '.' in the <i>$name</i> expansion. To prevent unex-
+ pected matches, use a <a href="pcre_table.5.html">pcre</a>: table, and specify \Q<i>$name</i>\E.
<b>EXAMPLE SMTPD ACCESS MAP</b>
# Disallow sender-specified routing. This is a must if you relay mail
diff --git a/html/relocated.5.html b/html/relocated.5.html
index efd2f53..62a580a 100644
--- a/html/relocated.5.html
+++ b/html/relocated.5.html
@@ -125,8 +125,8 @@ RELOCATED(5) RELOCATED(5)
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The network interface addresses that this mail system receives
- mail on.
+ The local network interface addresses that this mail system
+ receives mail on.
<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>, localhost)</b>
The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
@@ -137,8 +137,9 @@ RELOCATED(5) RELOCATED(5)
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The network interface addresses that this mail system receives
- mail on by way of a proxy or network address translation unit.
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
+ tion unit.
<b>SEE ALSO</b>
<a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, address resolver
diff --git a/html/sendmail.1.html b/html/sendmail.1.html
index bebc17b..bf6051d 100644
--- a/html/sendmail.1.html
+++ b/html/sendmail.1.html
@@ -455,9 +455,11 @@ SENDMAIL(1) SENDMAIL(1)
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
- append the specified domain name to incomplete addresses.
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
+ <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
+ ers.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
diff --git a/html/smtp-source.1.html b/html/smtp-source.1.html
index db9a17b..6311971 100644
--- a/html/smtp-source.1.html
+++ b/html/smtp-source.1.html
@@ -49,7 +49,7 @@ SMTP-SOURCE(1) SMTP-SOURCE(1)
over the same connection.
<b>-f</b> <i>from</i>
- Use the specified sender address (default: &lt;foo@<a href="postconf.5.html#myhostname">myhostname</a>&gt;).
+ Use the specified sender address (default: &lt;foo@my-hostname&gt;).
<b>-F</b> <i>file</i>
Send the pre-formatted message header and body in the specified
@@ -65,28 +65,42 @@ SMTP-SOURCE(1) SMTP-SOURCE(1)
<b>-m</b> <i>message</i><b>_</b><i>count</i>
Send the specified number of messages (default: 1).
- <b>-M</b> <i><a href="postconf.5.html#myhostname">myhostname</a></i>
+ <b>-M</b> <i>my-hostname</i>
Use the specified hostname or [address] in the HELO command and
in the default sender and recipient addresses, instead of the
machine hostname.
- <b>-N</b> Prepend a non-repeating sequence number to each recipient
- address. This avoids the artificial 100% hit rate in the resolve
- and rewrite client caches and exercises the trivial-rewrite dae-
- mon, better approximating Postfix performance under real-life
- work-loads.
+ <b>-N</b> Generate each recipient address by appending a number (a
+ per-process recipient counter) to the recipient address local-
+ part specified with the <b>-t</b> option.
+
+ Note: to use the number as an address extension, specify an
+ explicit address delimiter at the end of the recipient local-
+ part, as in "<b>-t localpart+@domain</b>" or "<b>-t localpart+</b>", where "<b>+</b>"
+ is a Postfix recipient address delimiter.
+
+ Benefits:
+
+ <b>o</b> A non-constant recipient address avoids an unrealistic
+ 100% cache hit rate in clients of the Postfix trivial-re-
+ write service, better approximating performance under
+ real-life work-loads.
+
+ <b>o</b> A fixed recipient address local-part with a non-constant
+ address extension avoids the need to configure a large
+ number of valid recipient addresses in the receiving
+ Postfix server.
<b>-o</b> Old mode: don't send HELO, and don't send message headers.
<b>-r</b> <i>recipient</i><b>_</b><i>count</i>
- Send the specified number of recipients per transaction
- (default: 1). Recipient names are generated by prepending a
- number to the recipient address.
+ Send the specified number of recipients per transaction
+ (default: 1), and generate recipient addresses as described
+ under the <b>-N</b> option.
<b>-R</b> <i>interval</i>
- Wait for a random period of time 0 &lt;= n &lt;= interval between mes-
- sages. Suspending one thread does not affect other delivery
- threads.
+ Wait a random time (0 &lt;= n &lt;= <i>interval</i>) between messages. Sus-
+ pending one thread does not affect other delivery threads.
<b>-s</b> <i>session</i><b>_</b><i>count</i>
Run the specified number of SMTP sessions in parallel (default:
@@ -95,7 +109,8 @@ SMTP-SOURCE(1) SMTP-SOURCE(1)
<b>-S</b> <i>subject</i>
Send mail with the named subject line (default: none).
- <b>-t</b> <i>to</i> Use the specified recipient address (default: &lt;foo@<a href="postconf.5.html#myhostname">myhostname</a>&gt;).
+ <b>-t</b> <i>to</i> Use the specified recipient address (default: &lt;foo@my-host-
+ name&gt;).
<b>-T</b> <i>windowsize</i>
Override the default TCP window size. To work around broken TCP
diff --git a/html/smtp.8.html b/html/smtp.8.html
index 1144ee8..4cc187c 100644
--- a/html/smtp.8.html
+++ b/html/smtp.8.html
@@ -5,88 +5,100 @@
<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
<title> Postfix manual - smtp(8) </title>
</head> <body> <pre>
-SMTP(8) SMTP(8)
+SMTP,(LMTP) SMTP,(LMTP)
<b>NAME</b>
- smtp - Postfix SMTP+LMTP client
+ smtp, lmtp - Postfix SMTP+LMTP client
<b>SYNOPSIS</b>
<b>smtp</b> [generic Postfix daemon options] [flags=DORX]
+ <b>lmtp</b> [generic Postfix daemon options] [flags=DORX]
+
<b>DESCRIPTION</b>
The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery
protocols. It processes message delivery requests from the queue man-
ager. Each request specifies a queue file, a sender address, a domain
or host to deliver to, and recipient information. This program expects
- to be run from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
+ to be run from the <a href="master.8.html"><b>master</b>(8)</a> process manager. The process name, <b>smtp</b> or
+ <b>lmtp</b>, controls the protocol, and the names of the configuration parame-
+ ters that will be used.
The SMTP+LMTP client updates the queue file and marks recipients as
finished, or it informs the queue manager that delivery should be tried
again at a later time. Delivery status reports are sent to the
<a href="bounce.8.html"><b>bounce</b>(8)</a>, <a href="defer.8.html"><b>defer</b>(8)</a> or <a href="trace.8.html"><b>trace</b>(8)</a> daemon as appropriate.
- The SMTP+LMTP client looks up a list of mail exchanger addresses for
- the destination host, sorts the list by preference, and connects to
- each listed address until it finds a server that responds.
-
- When a server is not reachable, or when mail delivery fails due to a
- recoverable error condition, the SMTP+LMTP client will try to deliver
- the mail to an alternate host.
+ The server lookup strategy is different for SMTP and LMTP, as described
+ in the sections "SMTP SERVER LOOKUP" and "LMTP SERVER LOOKUP".
- After a successful mail transaction, a connection may be saved to the
- <a href="scache.8.html"><b>scache</b>(8)</a> connection cache server, so that it may be used by any
+ After a successful mail transaction, a connection may be saved to the
+ <a href="scache.8.html"><b>scache</b>(8)</a> connection cache server, so that it may be used by any
SMTP+LMTP client for a subsequent transaction.
- By default, connection caching is enabled temporarily for destinations
+ By default, connection caching is enabled temporarily for destinations
that have a high volume of mail in the <a href="QSHAPE_README.html#active_queue">active queue</a>. Connection caching
can be enabled permanently for specific destinations.
-<b>SMTP DESTINATION SYNTAX</b>
- The Postfix SMTP+LMTP client supports multiple destinations separated
- by comma or whitespace (Postfix 3.5 and later). SMTP destinations have
- the following form:
+<b>SMTP SERVER LOOKUP</b>
+ The Postfix SMTP client supports multiple destinations separated by
+ comma or whitespace (Postfix 3.5 and later). Each destination is tried
+ in the specified order.
+
+ SMTP destinations have the following form:
<i>domainname</i>
- <i>domainname</i>:<i>port</i>
- Look up the mail exchangers for the specified domain, and con-
- nect to the specified port (default: <b>smtp</b>).
+ <i>domainname</i>:<i>service</i>
+ Look up the mail exchangers for the specified domain, and con-
+ nect to the specified service (default: <b>smtp</b>). Optionally, mail
+ exchangers may be looked up with SRV queries instead of MX; this
+ requires that <i>service</i> is given in symbolic form.
[<i>hostname</i>]
- [<i>hostname</i>]:<i>port</i>
- Look up the address(es) of the specified host, and connect to
- the specified port (default: <b>smtp</b>).
+ [<i>hostname</i>]:<i>service</i>
+ Look up the address(es) for the specified host, and connect to
+ the specified service (default: <b>smtp</b>).
[<i>address</i>]
- [<i>address</i>]:<i>port</i>
+ [<i>address</i>]:<i>service</i>
Connect to the host at the specified address, and connect to the
- specified port (default: <b>smtp</b>). An IPv6 address must be format-
- ted as [<b>ipv6</b>:<i>address</i>].
+ specified service (default: <b>smtp</b>). An IPv6 address must be for-
+ matted as [<b>ipv6</b>:<i>address</i>].
-<b>LMTP DESTINATION SYNTAX</b>
- The Postfix SMTP+LMTP client supports multiple destinations separated
- by comma or whitespace (Postfix 3.5 and later). LMTP destinations have
- the following form:
+<b>LMTP SERVER LOOKUP</b>
+ The Postfix LMTP client supports multiple destinations separated by
+ comma or whitespace (Postfix 3.5 and later). Each destination is tried
+ in the specified order.
+
+ LMTP destinations have the following form:
<b>unix</b>:<i>pathname</i>
- Connect to the local UNIX-domain server that is bound to the
- specified <i>pathname</i>. If the process runs chrooted, an absolute
+ Connect to the local UNIX-domain server that is bound to the
+ specified <i>pathname</i>. If the process runs chrooted, an absolute
pathname is interpreted relative to the Postfix queue directory.
+ <b>inet</b>:<i>domainname</i>
+
+ <b>inet</b>:<i>domainname</i>:<i>service</i>
+ Look up the LMTP servers for the specified domain and service
+ (default: <b>lmtp</b>). This form is supported when SRV lookups are
+ enabled, and requires that <i>service</i> is in symbolic form.
+
<b>inet</b>:<i>hostname</i>
- <b>inet</b>:<i>hostname</i>:<i>port</i>
+ <b>inet</b>:<i>hostname</i>:<i>service</i>
+ Look up the address(es) for the specified host, and connect to
+ the specified service (default: <b>lmtp</b>). When SRV lookups are
+ enabled, use the form <b>[</b><i>hostname</i><b>]</b> to force address lookups.
<b>inet</b>:[<i>address</i>]
- <b>inet</b>:[<i>address</i>]:<i>port</i>
- Connect to the specified TCP port on the specified local or
- remote host. If no port is specified, connect to the port
- defined as <b>lmtp</b> in <b>services</b>(4). If no such service is found,
- the <b><a href="postconf.5.html#lmtp_tcp_port">lmtp_tcp_port</a></b> configuration parameter (default value of 24)
- will be used. An IPv6 address must be formatted as
+ <b>inet</b>:[<i>address</i>]:<i>service</i>
+ Connect to the specified local or remote host and service
+ (default: <b>lmtp</b>). An IPv6 address must be formatted as
[<b>ipv6</b>:<i>address</i>].
<b>SINGLE-RECIPIENT DELIVERY</b>
@@ -136,10 +148,9 @@ SMTP(8) SMTP(8)
This feature is available as of Postfix 3.5.
<b>SECURITY</b>
- The SMTP+LMTP client is moderately security-sensitive. It
- talks to SMTP or LMTP servers and to DNS servers on the
- network. The SMTP+LMTP client can be run chrooted at fixed
- low privilege.
+ The SMTP+LMTP client is moderately security-sensitive. It talks to SMTP
+ or LMTP servers and to DNS servers on the network. The SMTP+LMTP client
+ can be run chrooted at fixed low privilege.
<b>STANDARDS</b>
<a href="https://tools.ietf.org/html/rfc821">RFC 821</a> (SMTP protocol)
@@ -180,20 +191,19 @@ SMTP(8) SMTP(8)
for all destinations that map onto the same IP address and TCP port.
<b>CONFIGURATION PARAMETERS</b>
- Before Postfix version 2.3, the LMTP client is a separate program that
- implements only a subset of the functionality available with SMTP:
- there is no support for TLS, and connections are cached in-process,
- making it ineffective when the client is used for multiple domains.
+ Postfix versions 2.3 and later implement the SMTP and LMTP client with
+ the same program, and choose the protocol and configuration parameters
+ based on the process name, <b>smtp</b> or <b>lmtp</b>.
Most smtp_<i>xxx</i> configuration parameters have an lmtp_<i>xxx</i> "mirror" param-
- eter for the equivalent LMTP feature. This document describes only
+ eter for the equivalent LMTP feature. This document describes only
those LMTP-related parameters that aren't simply "mirror" parameters.
- Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="smtp.8.html"><b>smtp</b>(8)</a> processes
+ Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically, as <a href="smtp.8.html"><b>smtp</b>(8)</a> processes
run for only a limited amount of time. Use the command "<b>postfix reload</b>"
to speed up a change.
- 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>COMPATIBILITY CONTROLS</b>
@@ -214,8 +224,8 @@ SMTP(8) SMTP(8)
will send via SMTP.
<b><a href="postconf.5.html#smtp_pix_workaround_delay_time">smtp_pix_workaround_delay_time</a> (10s)</b>
- How long the Postfix SMTP client pauses before sending
- ".&lt;CR&gt;&lt;LF&gt;" in order to work around the PIX firewall
+ How long the Postfix SMTP client pauses before sending
+ ".&lt;CR&gt;&lt;LF&gt;" in order to work around the PIX firewall
"&lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;" bug.
<b><a href="postconf.5.html#smtp_pix_workaround_threshold_time">smtp_pix_workaround_threshold_time</a> (500s)</b>
@@ -224,19 +234,19 @@ SMTP(8) SMTP(8)
delivery through firewalls with "smtp fixup" mode turned on.
<b><a href="postconf.5.html#smtp_pix_workarounds">smtp_pix_workarounds</a> (disable_esmtp, delay_dotcrlf)</b>
- A list that specifies zero or more workarounds for CISCO PIX
+ A list that specifies zero or more workarounds for CISCO PIX
firewall bugs.
<b><a href="postconf.5.html#smtp_pix_workaround_maps">smtp_pix_workaround_maps</a> (empty)</b>
- Lookup tables, indexed by the remote SMTP server address, with
+ Lookup tables, indexed by the remote SMTP server address, with
per-destination workarounds for CISCO PIX firewall bugs.
<b><a href="postconf.5.html#smtp_quote_rfc821_envelope">smtp_quote_rfc821_envelope</a> (yes)</b>
- Quote addresses in Postfix SMTP client MAIL FROM and RCPT TO
+ Quote addresses in Postfix SMTP client MAIL FROM and RCPT TO
commands as required by <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a>.
<b><a href="postconf.5.html#smtp_reply_filter">smtp_reply_filter</a> (empty)</b>
- A mechanism to transform replies from remote SMTP servers one
+ A mechanism to transform replies from remote SMTP servers one
line at a time.
<b><a href="postconf.5.html#smtp_skip_5xx_greeting">smtp_skip_5xx_greeting</a> (yes)</b>
@@ -248,68 +258,68 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.0 and earlier:
<b><a href="postconf.5.html#smtp_skip_4xx_greeting">smtp_skip_4xx_greeting</a> (yes)</b>
- Skip SMTP servers that greet with a 4XX status code (go away,
+ Skip SMTP servers that greet with a 4XX status code (go away,
try again later).
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtp_discard_ehlo_keyword_address_maps">smtp_discard_ehlo_keyword_address_maps</a> (empty)</b>
- Lookup tables, indexed by the remote SMTP server address, with
- case insensitive lists of EHLO keywords (pipelining, starttls,
+ Lookup tables, indexed by the remote SMTP server address, with
+ case insensitive lists of EHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix SMTP client will ignore in the EHLO
response from a remote SMTP server.
<b><a href="postconf.5.html#smtp_discard_ehlo_keywords">smtp_discard_ehlo_keywords</a> (empty)</b>
- A case insensitive list of EHLO keywords (pipelining, starttls,
+ A case insensitive list of EHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix SMTP client will ignore in the EHLO
response from a remote SMTP server.
<b><a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> (empty)</b>
- Optional lookup tables that perform address rewriting in the
- Postfix SMTP client, typically to transform a locally valid
- address into a globally valid address when sending mail across
+ Optional lookup tables that perform address rewriting in the
+ Postfix SMTP client, typically to transform a locally valid
+ address into a globally valid address when sending mail across
the Internet.
Available in Postfix version 2.2.9 and later:
<b><a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> (version dependent)</b>
- When the remote SMTP servername is a DNS CNAME, replace the
- servername with the result from CNAME expansion for the purpose
- of logging, SASL password lookup, TLS policy decisions, or TLS
+ When the remote SMTP servername is a DNS CNAME, replace the
+ servername with the result from CNAME expansion for the purpose
+ of logging, SASL password lookup, TLS policy decisions, or TLS
certificate verification.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#lmtp_discard_lhlo_keyword_address_maps">lmtp_discard_lhlo_keyword_address_maps</a> (empty)</b>
- Lookup tables, indexed by the remote LMTP server address, with
- case insensitive lists of LHLO keywords (pipelining, starttls,
+ Lookup tables, indexed by the remote LMTP server address, with
+ case insensitive lists of LHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix LMTP client will ignore in the LHLO
response from a remote LMTP server.
<b><a href="postconf.5.html#lmtp_discard_lhlo_keywords">lmtp_discard_lhlo_keywords</a> (empty)</b>
- A case insensitive list of LHLO keywords (pipelining, starttls,
+ A case insensitive list of LHLO keywords (pipelining, starttls,
auth, etc.) that the Postfix LMTP client will ignore in the LHLO
response from a remote LMTP server.
Available in Postfix version 2.4.4 and later:
<b><a href="postconf.5.html#send_cyrus_sasl_authzid">send_cyrus_sasl_authzid</a> (no)</b>
- When authenticating to a remote SMTP or LMTP server with the
- default setting "no", send no SASL authoriZation ID (authzid);
- send only the SASL authentiCation ID (authcid) plus the auth-
+ When authenticating to a remote SMTP or LMTP server with the
+ default setting "no", send no SASL authoriZation ID (authzid);
+ send only the SASL authentiCation ID (authcid) plus the auth-
cid's password.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtp_header_checks">smtp_header_checks</a> (empty)</b>
- Restricted <a href="header_checks.5.html"><b>header_checks</b>(5)</a> tables for the Postfix SMTP client.
+ Restricted <a href="header_checks.5.html"><b>header_checks</b>(5)</a> tables for the Postfix SMTP client.
<b><a href="postconf.5.html#smtp_mime_header_checks">smtp_mime_header_checks</a> (empty)</b>
- Restricted <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a></b>(5) tables for the Postfix SMTP
+ Restricted <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a></b>(5) tables for the Postfix SMTP
client.
<b><a href="postconf.5.html#smtp_nested_header_checks">smtp_nested_header_checks</a> (empty)</b>
- Restricted <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a></b>(5) tables for the Postfix SMTP
+ Restricted <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a></b>(5) tables for the Postfix SMTP
client.
<b><a href="postconf.5.html#smtp_body_checks">smtp_body_checks</a> (empty)</b>
@@ -318,7 +328,7 @@ SMTP(8) SMTP(8)
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 window scal-
+ An optional workaround for routers that break TCP window scal-
ing.
Available in Postfix version 2.8 and later:
@@ -329,16 +339,16 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.9 - 3.6:
<b><a href="postconf.5.html#smtp_per_record_deadline">smtp_per_record_deadline</a> (no)</b>
- Change the behavior of the smtp_*_timeout time limits, from a
- time limit per read or write system call, to a time limit to
- send or receive a complete record (an SMTP command line, SMTP
- response line, SMTP message content line, or TLS protocol mes-
+ Change the behavior of the smtp_*_timeout time limits, from a
+ time limit per read or write system call, to a time limit to
+ send or receive a complete record (an SMTP command line, SMTP
+ response line, SMTP message content line, or TLS protocol mes-
sage).
Available in Postfix version 2.9 and later:
<b><a href="postconf.5.html#smtp_send_dummy_mail_auth">smtp_send_dummy_mail_auth</a> (no)</b>
- Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
+ Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
command in SASL-authenticated SMTP sessions.
Available in Postfix version 2.11 and later:
@@ -349,7 +359,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 3.0 and later:
<b><a href="postconf.5.html#smtp_delivery_status_filter">smtp_delivery_status_filter</a> ($<a href="postconf.5.html#default_delivery_status_filter">default_delivery_status_filter</a>)</b>
- Optional filter for the <a href="smtp.8.html"><b>smtp</b>(8)</a> delivery agent to change the
+ Optional filter for the <a href="smtp.8.html"><b>smtp</b>(8)</a> delivery agent to change the
delivery status code or explanatory text of successful or unsuc-
cessful deliveries.
@@ -359,38 +369,38 @@ SMTP(8) SMTP(8)
Available in Postfix version 3.3 and later:
<b><a href="postconf.5.html#smtp_balance_inet_protocols">smtp_balance_inet_protocols</a> (yes)</b>
- When a remote destination resolves to a combination of IPv4 and
+ When a remote destination resolves to a combination of IPv4 and
IPv6 addresses, ensure that the Postfix SMTP client can try both
address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>.
Available in Postfix 3.5 and later:
<b><a href="postconf.5.html#info_log_address_format">info_log_address_format</a> (external)</b>
- The email address form that will be used in non-debug logging
+ The email address form that will be used in non-debug logging
(info, warning, etc.).
Available in Postfix 3.6 and later:
<b><a href="postconf.5.html#dnssec_probe">dnssec_probe</a> (ns:.)</b>
- The DNS query type (default: "ns") and DNS query name (default:
+ The DNS query type (default: "ns") and DNS query name (default:
".") that Postfix may use to determine whether DNSSEC validation
is available.
- <b><a href="postconf.5.html#known_tcp_ports">known_tcp_ports</a> (lmtp=24, smtp=25, smtps=submissions=465, submis-</b>
+ <b><a href="postconf.5.html#known_tcp_ports">known_tcp_ports</a> (lmtp=24, smtp=25, smtps=submissions=465, submis-</b>
<b>sion=587)</b>
- Optional setting that avoids lookups in the <b>services</b>(5) data-
+ Optional setting that avoids lookups in the <b>services</b>(5) data-
base.
Available in Postfix version 3.7 and later:
<b><a href="postconf.5.html#smtp_per_request_deadline">smtp_per_request_deadline</a> (no)</b>
- Change the behavior of the smtp_*_timeout time limits, from a
- time limit per plaintext or TLS read or write call, to a com-
- bined time limit for sending a complete SMTP request and for
+ Change the behavior of the smtp_*_timeout time limits, from a
+ time limit per plaintext or TLS read or write call, to a com-
+ bined time limit for sending a complete SMTP request and for
receiving a complete SMTP response.
<b><a href="postconf.5.html#smtp_min_data_rate">smtp_min_data_rate</a> (500)</b>
- The minimum plaintext data transfer rate in bytes/second for
+ The minimum plaintext data transfer rate in bytes/second for
DATA requests, when deadlines are enabled with
<a href="postconf.5.html#smtp_per_request_deadline">smtp_per_request_deadline</a>.
@@ -400,16 +410,16 @@ SMTP(8) SMTP(8)
Available in Postfix version 3.8 and later:
<b><a href="postconf.5.html#use_srv_lookup">use_srv_lookup</a> (empty)</b>
- Enables discovery for the specified service(s) using DNS SRV
+ Enables discovery for the specified service(s) using DNS SRV
records.
<b><a href="postconf.5.html#ignore_srv_lookup_error">ignore_srv_lookup_error</a> (no)</b>
- When SRV record lookup fails, fall back to MX or IP address
+ When SRV record lookup fails, fall back to MX or IP address
lookup as if SRV record lookup was not enabled.
<b><a href="postconf.5.html#allow_srv_lookup_fallback">allow_srv_lookup_fallback</a> (no)</b>
- When SRV record lookup fails or no SRV record exists, fall back
- to MX or IP address lookup as if SRV record lookup was not
+ When SRV record lookup fails or no SRV record exists, fall back
+ to MX or IP address lookup as if SRV record lookup was not
enabled.
<b>MIME PROCESSING CONTROLS</b>
@@ -428,7 +438,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtp_send_xforward_command">smtp_send_xforward_command</a> (no)</b>
- Send the non-standard XFORWARD command when the Postfix SMTP
+ Send the non-standard XFORWARD command when the Postfix SMTP
server EHLO response announces XFORWARD support.
<b>SASL AUTHENTICATION CONTROLS</b>
@@ -436,60 +446,66 @@ SMTP(8) SMTP(8)
Enable SASL authentication in the Postfix SMTP client.
<b><a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> (empty)</b>
- Optional Postfix SMTP client lookup tables with one user-
- name:password entry per sender, remote hostname or next-hop
+ Optional Postfix SMTP client lookup tables with one user-
+ name:password entry per sender, remote hostname or next-hop
domain.
<b><a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_security_options</a> (noplaintext, noanonymous)</b>
Postfix SMTP client SASL security options; as of Postfix 2.3 the
- list of available features depends on the SASL client implemen-
+ list of available features depends on the SASL client implemen-
tation that is selected with <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b>.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtp_sasl_mechanism_filter">smtp_sasl_mechanism_filter</a> (empty)</b>
- If non-empty, a Postfix SMTP client filter for the remote SMTP
+ If non-empty, a Postfix SMTP client filter for the remote SMTP
server's list of offered SASL mechanisms.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtp_sender_dependent_authentication">smtp_sender_dependent_authentication</a> (no)</b>
Enable sender-dependent authentication in the Postfix SMTP
- client; this is available only with SASL authentication, and
- disables SMTP connection caching to ensure that mail from dif-
+ client; this is available only with SASL authentication, and
+ disables SMTP connection caching to ensure that mail from dif-
ferent senders will use the appropriate credentials.
<b><a href="postconf.5.html#smtp_sasl_path">smtp_sasl_path</a> (empty)</b>
Implementation-specific information that the Postfix SMTP client
- passes through to the SASL plug-in implementation that is
+ passes through to the SASL plug-in implementation that is
selected with <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b>.
<b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a> (cyrus)</b>
- The SASL plug-in type that the Postfix SMTP client should use
+ The SASL plug-in type that the Postfix SMTP client should use
for authentication.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> (empty)</b>
- An optional table to prevent repeated SASL authentication fail-
- ures with the same remote SMTP server hostname, username and
+ An optional table to prevent repeated SASL authentication fail-
+ ures with the same remote SMTP server hostname, username and
password.
<b><a href="postconf.5.html#smtp_sasl_auth_cache_time">smtp_sasl_auth_cache_time</a> (90d)</b>
- The maximal age of an <a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> entry before it
+ The maximal age of an <a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> entry before it
is removed.
<b><a href="postconf.5.html#smtp_sasl_auth_soft_bounce">smtp_sasl_auth_soft_bounce</a> (yes)</b>
- When a remote SMTP server rejects a SASL authentication request
- with a 535 reply code, defer mail delivery instead of returning
+ When a remote SMTP server rejects a SASL authentication request
+ with a 535 reply code, defer mail delivery instead of returning
mail as undeliverable.
Available in Postfix version 2.9 and later:
<b><a href="postconf.5.html#smtp_send_dummy_mail_auth">smtp_send_dummy_mail_auth</a> (no)</b>
- Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
+ Whether or not to append the "AUTH=&lt;&gt;" option to the MAIL FROM
command in SASL-authenticated SMTP sessions.
+ Available in Postfix version 3.9 and later:
+
+ <b><a href="postconf.5.html#smtp_sasl_password_result_delimiter">smtp_sasl_password_result_delimiter</a> (:)</b>
+ The delimiter between username and password in sasl_passwd_maps
+ lookup results.
+
<b>STARTTLS SUPPORT CONTROLS</b>
Detailed information about STARTTLS configuration may be found in the
<a href="TLS_README.html">TLS_README</a> document.
@@ -619,7 +635,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.6 and later:
- <b><a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> (see postconf -d output)</b>
+ <b><a href="postconf.5.html#smtp_tls_protocols">smtp_tls_protocols</a> (see 'postconf -d' output)</b>
TLS protocols that the Postfix SMTP client will use with oppor-
tunistic TLS encryption.
@@ -724,6 +740,12 @@ SMTP(8) SMTP(8)
The application name passed by Postfix to OpenSSL library ini-
tialization functions.
+ Available in Postfix version 3.9 and later:
+
+ <b><a href="postconf.5.html#smtp_tls_enable_rpk">smtp_tls_enable_rpk</a> (no)</b>
+ Request that remote SMTP servers send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+ instead of an X.509 certificate.
+
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compatibility with
Postfix versions before 2.3. Support for these will be removed in a
@@ -954,7 +976,7 @@ SMTP(8) SMTP(8)
The local network interface addresses that this mail system
receives mail on.
- <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d output')</b>
+ <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d' output)</b>
The Internet protocols Postfix will attempt to use when making
or accepting connections.
@@ -1119,5 +1141,5 @@ SMTP(8) SMTP(8)
Victor Duchovni
Morgan Stanley
- SMTP(8)
+ 8 SMTP,(LMTP)
</pre> </body> </html>
diff --git a/html/smtpd.8.html b/html/smtpd.8.html
index 672302a..85a8aee 100644
--- a/html/smtpd.8.html
+++ b/html/smtpd.8.html
@@ -560,7 +560,7 @@ SMTPD(8) SMTPD(8)
Available in Postfix version 2.6 and later:
- <b><a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> (see postconf -d output)</b>
+ <b><a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a> (see 'postconf -d' output)</b>
TLS protocols accepted by the Postfix SMTP server with oppor-
tunistic TLS encryption.
@@ -648,6 +648,13 @@ SMTPD(8) SMTPD(8)
The application name passed by Postfix to OpenSSL library ini-
tialization functions.
+ Available in Postfix version 3.9 and later:
+
+ <b><a href="postconf.5.html#smtpd_tls_enable_rpk">smtpd_tls_enable_rpk</a> (no)</b>
+ Request that remote SMTP clients send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+ instead of an X.509 certificate, when asking for or requiring
+ client authentication.
+
<b>OBSOLETE STARTTLS CONTROLS</b>
The following configuration parameters exist for compatibility with
Postfix versions before 2.3. Support for these will be removed in a
@@ -801,7 +808,7 @@ SMTPD(8) SMTPD(8)
receives mail on by way of a proxy or network address transla-
tion unit.
- <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d output')</b>
+ <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (see 'postconf -d' output)</b>
The Internet protocols Postfix will attempt to use when making
or accepting connections.
@@ -840,30 +847,31 @@ SMTPD(8) SMTPD(8)
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 addresses.
+ Optional lookup tables with aliases that apply to all recipi-
+ ents: <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote; this is unlike <a href="postconf.5.html#alias_maps">alias_maps</a>
+ that apply only to <a href="local.8.html"><b>local</b>(8)</a> recipients.
<b><a href="postconf.5.html#unknown_virtual_alias_reject_code">unknown_virtual_alias_reject_code</a> (550)</b>
- The Postfix 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">virtual_alias_maps</a> speci-
- fies a list of lookup tables that does not match the recipient
+ The Postfix 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">virtual_alias_maps</a> speci-
+ fies a list of lookup tables that does not match the recipient
address.
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 the final destination for the specified list of
- domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">virtual_transport</a> mail
+ Postfix is the final destination for the specified list of
+ domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">virtual_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 the domains
+ 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 Postfix 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">virtual_mailbox_maps</a>
+ The Postfix 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">virtual_mailbox_maps</a>
specifies a list of lookup tables that does not match the recip-
ient address.
@@ -872,7 +880,7 @@ SMTPD(8) SMTPD(8)
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
+ 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>
@@ -880,62 +888,62 @@ SMTPD(8) SMTPD(8)
tem 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 envelope
+ 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 SMTP server
+ 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, overload: 10s)</b>
- When the Postfix SMTP server wants to send an SMTP server
- response, how long the Postfix SMTP server will wait for an
- underlying network write operation to complete; and when the
- Postfix SMTP server Postfix wants to receive an SMTP client
- request, how long the Postfix SMTP server will wait for an
+ When the Postfix SMTP server wants to send an SMTP server
+ response, how long the Postfix SMTP server will wait for an
+ underlying network write operation to complete; and when the
+ Postfix SMTP server Postfix wants to receive an SMTP client
+ request, how long the Postfix SMTP server will wait for an
underlying network read operation to complete.
<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 receipt of EHLO, RSET, or end
+ 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
+ Attempt to look up the remote SMTP client hostname, and verify
that the name matches the client IP address.
The per SMTP client connection count and request rate limits are imple-
- mented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> service, and are available in
+ mented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> service, 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 allowed to make
+ 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
+ The maximal number of connection attempts any 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 per time unit, regardless of
+ 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 unit, regardless of
+ 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 smtpd_client_*_count/rate_limit
+ Clients that are excluded from smtpd_client_*_count/rate_limit
restrictions.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a> (0)</b>
- The maximal number of new (i.e., uncached) TLS sessions that a
+ The maximal number of new (i.e., uncached) TLS sessions that a
remote SMTP client is allowed to negotiate with this service per
time unit.
@@ -943,29 +951,29 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#smtpd_per_record_deadline">smtpd_per_record_deadline</a> (normal: no, overload: yes)</b>
Change the behavior of the <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> and <a href="postconf.5.html#smtpd_starttls_timeout">smtpd_start</a>-
- <a href="postconf.5.html#smtpd_starttls_timeout">tls_timeout</a> time limits, from a time limit per read or write
- system call, to a time limit to send or receive a complete
- record (an SMTP command line, SMTP response line, SMTP message
+ <a href="postconf.5.html#smtpd_starttls_timeout">tls_timeout</a> time limits, from a time limit per read or write
+ system call, to a time limit to send or receive a complete
+ record (an SMTP command line, SMTP response line, SMTP message
content line, or TLS protocol message).
Available in Postfix version 3.1 and later:
<b><a href="postconf.5.html#smtpd_client_auth_rate_limit">smtpd_client_auth_rate_limit</a> (0)</b>
- The maximal number of AUTH commands that any client is allowed
- to send to this service per time unit, regardless of whether or
+ The maximal number of AUTH commands that any client is allowed
+ to send to this service per time unit, regardless of whether or
not Postfix actually accepts those commands.
Available in Postfix version 3.7 and later:
<b><a href="postconf.5.html#smtpd_per_request_deadline">smtpd_per_request_deadline</a> (normal: no, overload: yes)</b>
Change the behavior of the <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> and <a href="postconf.5.html#smtpd_starttls_timeout">smtpd_start</a>-
- <a href="postconf.5.html#smtpd_starttls_timeout">tls_timeout</a> time limits, from a time limit per plaintext or TLS
- read or write call, to a combined time limit for receiving a
- complete SMTP request and for sending a complete SMTP response.
+ <a href="postconf.5.html#smtpd_starttls_timeout">tls_timeout</a> time limits, from a time limit per plaintext or TLS
+ read or write call, to a combined time limit for receiving a
+ complete SMTP request and for sending a complete SMTP response.
<b><a href="postconf.5.html#smtpd_min_data_rate">smtpd_min_data_rate</a> (500)</b>
- The minimum plaintext data transfer rate in bytes/second for
- DATA and BDAT requests, when deadlines are enabled with
+ The minimum plaintext data transfer rate in bytes/second for
+ DATA and BDAT requests, when deadlines are enabled with
<a href="postconf.5.html#smtpd_per_request_deadline">smtpd_per_request_deadline</a>.
<b><a href="postconf.5.html#header_from_format">header_from_format</a> (standard)</b>
@@ -974,27 +982,27 @@ SMTPD(8) SMTPD(8)
Available in Postfix version 3.8 and later:
<b><a href="postconf.5.html#smtpd_client_ipv4_prefix_length">smtpd_client_ipv4_prefix_length</a> (32)</b>
- Aggregate smtpd_client_*_count and smtpd_client_*_rate statis-
+ Aggregate smtpd_client_*_count and smtpd_client_*_rate statis-
tics by IPv4 network blocks with the specified network prefix.
<b><a href="postconf.5.html#smtpd_client_ipv6_prefix_length">smtpd_client_ipv6_prefix_length</a> (84)</b>
- Aggregate smtpd_client_*_count and smtpd_client_*_rate statis-
+ Aggregate smtpd_client_*_count and smtpd_client_*_rate statis-
tics by IPv6 network blocks with the specified network prefix.
Available in Postfix 3.9, 3.8.1, 3.7.6, 3.6.10, 3.5.20 and later:
<b><a href="postconf.5.html#smtpd_forbid_unauth_pipelining">smtpd_forbid_unauth_pipelining</a> (Postfix</b> &gt;<b>= 3.9: yes)</b>
- Disconnect remote SMTP clients that violate <a href="https://tools.ietf.org/html/rfc2920">RFC 2920</a> (or 5321)
+ Disconnect remote SMTP clients that violate <a href="https://tools.ietf.org/html/rfc2920">RFC 2920</a> (or 5321)
command pipelining constraints.
Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later:
- <b><a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> (Postfix</b> &lt; <b>3.9: no)</b>
- Reject or restrict input lines from an SMTP client that end in
+ <b><a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> (Postfix</b> &gt;<b>= 3.9: normalize)</b>
+ Reject or restrict input lines from an SMTP client that end in
&lt;LF&gt; instead of the standard &lt;CR&gt;&lt;LF&gt;.
<b><a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- Exclude the specified clients from <a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a>
+ Exclude the specified clients from <a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a>
enforcement.
Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and later:
@@ -1004,55 +1012,55 @@ SMTPD(8) SMTPD(8)
request with "<a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> = reject".
<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 controlled by an error counter that counts
+ 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 controlled 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
+ 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 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 Postfix SMTP server slows
+ 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, overload: 1)</b>
- The maximal number of errors a remote SMTP client is allowed to
+ 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, overload: 1)</b>
- The number of junk commands (NOOP, VRFY, ETRN or RSET) that a
- remote SMTP client can send before the Postfix SMTP server
+ 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 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
+ 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
+ before the Postfix SMTP 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
+ 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 connection is
+ 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>
- The time after which an active SMTPD policy service connection
+ The time after which an active SMTPD policy service 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 receiving from
+ The time limit for connecting to, writing to, or receiving from
a delegated SMTPD policy server.
Available in Postfix version 3.0 and later:
@@ -1062,81 +1070,81 @@ SMTPD(8) SMTPD(8)
The default action when an SMTPD policy service request fails.
<b><a href="postconf.5.html#smtpd_policy_service_request_limit">smtpd_policy_service_request_limit</a> (0)</b>
- The maximal number of requests per SMTPD policy service connec-
+ The maximal number of requests per SMTPD policy service connec-
tion, or zero (no limit).
<b><a href="postconf.5.html#smtpd_policy_service_try_limit">smtpd_policy_service_try_limit</a> (2)</b>
- The maximal number of attempts to send an SMTPD policy service
+ The maximal number of attempts to send an SMTPD policy service
request before giving up.
<b><a href="postconf.5.html#smtpd_policy_service_retry_delay">smtpd_policy_service_retry_delay</a> (1s)</b>
- The delay between attempts to resend a failed SMTPD policy ser-
+ The delay between attempts to resend a failed SMTPD policy ser-
vice request.
Available in Postfix version 3.1 and later:
<b><a href="postconf.5.html#smtpd_policy_service_policy_context">smtpd_policy_service_policy_context</a> (empty)</b>
- Optional information that the Postfix SMTP server specifies in
- the "policy_context" attribute of a policy service request
- (originally, to share the same service endpoint among multiple
+ Optional information that the Postfix SMTP server specifies in
+ the "policy_context" attribute of a policy service request
+ (originally, to share the same service endpoint among multiple
<a href="postconf.5.html#check_policy_service">check_policy_service</a> clients).
<b>ACCESS CONTROLS</b>
- The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to all the SMTP
+ 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>, $<a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> and
$<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a>, or wait until the ETRN command
- before evaluating $<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> and
+ before evaluating $<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> and
$<a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a>.
<b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' output)</b>
- A list of Postfix features where the pattern "example.com" also
- matches subdomains of example.com, instead of requiring an
+ A list of Postfix features where the pattern "example.com" also
+ matches subdomains of example.com, instead of requiring an
explicit ".example.com" pattern.
<b><a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server applies in
+ Optional restrictions that the Postfix SMTP server applies in
the context of a client 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 with the
- HELO or EHLO command before sending the MAIL command or other
+ Require that a remote SMTP client introduces itself with the
+ HELO or EHLO command before sending the MAIL command or other
commands that require EHLO negotiation.
<b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server applies in
+ Optional restrictions that the Postfix SMTP server applies in
the context of a client HELO command.
<b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server applies in
+ Optional restrictions that the Postfix SMTP server applies in
the context of a client MAIL FROM command.
<b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (see 'postconf -d' output)</b>
- Optional restrictions that the Postfix SMTP server applies in
- the context of a client RCPT TO command, after
+ Optional restrictions that the Postfix SMTP server applies in
+ the context of a client RCPT TO command, after
<a href="postconf.5.html#smtpd_relay_restrictions">smtpd_relay_restrictions</a>.
<b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server applies in
+ Optional restrictions that the Postfix SMTP server applies in
the context of a client ETRN command.
<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 to destina-
+ Forward mail with sender-specified routing
+ (user[@%!]remote[@%!]site) from untrusted clients to destina-
tions 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 restrictions.
<b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b>&lt;&gt;<b>)</b>
- The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables instead of
+ 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
+ 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 hosts match the listed networks.
Available in Postfix version 2.0 and later:
@@ -1146,19 +1154,19 @@ SMTPD(8) SMTPD(8)
applies in the context of the SMTP DATA command.
<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 RBL reply
+ 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>
+ 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 for unknown
- recipient addresses, even when no explicit
+ 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 restriction is specified.
Available in Postfix version 2.2 and later:
@@ -1172,17 +1180,17 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#smtpd_relay_restrictions">smtpd_relay_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>,</b>
<b><a href="postconf.5.html#defer_unauth_destination">defer_unauth_destination</a>)</b>
Access restrictions for mail relay control that the Postfix SMTP
- server applies in the context of the RCPT TO command, before
+ server applies in the context of the RCPT TO command, before
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a>.
<b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
- Postfix version 2.1 introduces sender and recipient address verifica-
+ Postfix version 2.1 introduces sender and recipient address verifica-
tion. This feature is implemented by sending probe email messages that
are not actually delivered. This feature is requested via the
- <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
- restrictions. The status of verification probes is maintained by the
- <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VERIFICATION_README</a> for infor-
- mation about how to configure and operate the Postfix sender/recipient
+ <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
+ restrictions. The status of verification probes is maintained by the
+ <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VERIFICATION_README</a> for infor-
+ mation about how to configure and operate the Postfix sender/recipient
address verification service.
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (normal: 3, overload: 1)</b>
@@ -1194,7 +1202,7 @@ SMTPD(8) SMTPD(8)
fication 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 probes; prior
+ The sender address to use in address verification probes; prior
to Postfix 2.5 the default was "postmaster".
<b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
@@ -1202,18 +1210,18 @@ SMTPD(8) SMTPD(8)
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 recipient
- address is rejected by the <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> restric-
+ The numerical Postfix SMTP server response when a recipient
+ address is rejected by the <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> restric-
tion.
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
+ The numerical Postfix SMTP server response code when a sender
address probe fails due to a temporary 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
+ 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>
@@ -1225,17 +1233,17 @@ SMTPD(8) SMTPD(8)
<a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a>.
<b><a href="postconf.5.html#unverified_sender_tempfail_action">unverified_sender_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b>
- The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a>
+ The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a>
fails due to a temporary error condition.
<b><a href="postconf.5.html#unverified_recipient_tempfail_action">unverified_recipient_tempfail_action</a> ($<a href="postconf.5.html#reject_tempfail_action">reject_tempfail_action</a>)</b>
- The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipi</a>-
+ The Postfix SMTP server's action when <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipi</a>-
<a href="postconf.5.html#reject_unverified_recipient">ent</a> fails due to a temporary error condition.
Available with Postfix 2.9 and later:
<b><a href="postconf.5.html#address_verify_sender_ttl">address_verify_sender_ttl</a> (0s)</b>
- The time between changes in the time-dependent portion of
+ The time between changes in the time-dependent portion of
address verification probe sender addresses.
<b>ACCESS CONTROL RESPONSES</b>
@@ -1247,36 +1255,36 @@ SMTPD(8) SMTPD(8)
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
+ 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
+ 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 when a remote
- SMTP client request is blocked by the <a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>,
+ 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_reverse_client">reject_rhsbl_reverse_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> restriction.
<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 <a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
+ The numerical Postfix SMTP server reply code when a 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
+ The numerical Postfix SMTP server response code when a request
is rejected by the <b><a href="postconf.5.html#reject_plaintext_session">reject_plaintext_session</a></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
+ 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 <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient
+ 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>
@@ -1284,24 +1292,24 @@ SMTPD(8) SMTPD(8)
a sender or recipient address because its domain is unknown.
<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 &lt;=&gt; name mapping is rejected by the
+ The numerical Postfix SMTP server response code when a client
+ without valid address &lt;=&gt; name mapping is rejected by the
<a href="postconf.5.html#reject_unknown_client_hostname">reject_unknown_client_hostname</a> 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 host-
- name specified with the HELO or EHLO command is rejected by the
+ The numerical Postfix SMTP server response code when the host-
+ name 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 Postfix SMTP server response template for a request
+ The default Postfix SMTP server response template for a request
that is rejected by an RBL-based restriction.
<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 when a remote
- SMTP client request is blocked by the <a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipi</a>-
+ 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_recipi</a>-
<a href="postconf.5.html#reject_multi_recipient_bounce">ent_bounce</a> restriction.
<b><a href="postconf.5.html#rbl_reply_maps">rbl_reply_maps</a> (empty)</b>
@@ -1311,52 +1319,52 @@ SMTPD(8) SMTPD(8)
<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 "<a href="postconf.5.html#defer_if_permit">defer_if_permit</a>" or
+ 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
+ The Postfix SMTP server's action when a reject-type restriction
fails due to a temporary error condition.
<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_tempfail_action</a>)</b>
- The Postfix SMTP server's action when <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_host</a>-
+ The Postfix SMTP server's action when <a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_host</a>-
<a href="postconf.5.html#reject_unknown_helo_hostname">name</a> fails due to a temporary 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
- <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>
+ 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 temporary 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 <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#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to handle 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 commands.
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
- The sender address of postmaster notifications that are gener-
+ The sender address of postmaster notifications that are gener-
ated by the mail system.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
- The time limit for sending or receiving information over an
+ The time limit for sending or receiving information over an
internal communication channel.
<b><a href="postconf.5.html#mail_name">mail_name</a> (Postfix)</b>
- The mail system name that is displayed in Received: headers, in
+ The mail system name that is displayed in Received: headers, in
the SMTP greeting banner, and in bounced mail.
<b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
- The UNIX system account that owns the Postfix queue and most
+ The UNIX system account that owns the Postfix queue 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
+ 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>
@@ -1367,11 +1375,11 @@ SMTPD(8) SMTPD(8)
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" remote SMTP clients that have more privi-
+ The list of "trusted" remote SMTP clients that have more privi-
leges 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,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
@@ -1384,24 +1392,24 @@ SMTPD(8) SMTPD(8)
The location of the Postfix top-level queue directory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
- The set of characters that can separate an email address local-
+ The set of characters that can separate an email address local-
part, user name, or a .forward file name from its extension.
<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 SMTP greeting
+ 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>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/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 <a href="regexp_table.5.html">regexp</a>:{{/^[^A-Z]/ Bogus}})</b>
- List of commands that cause the Postfix SMTP server to immedi-
+ List of commands that cause the Postfix SMTP server to immedi-
ately terminate the session with a 221 code.
Available in Postfix version 2.5 and later:
@@ -1418,7 +1426,7 @@ SMTPD(8) SMTPD(8)
Available in Postfix 3.4 and later:
<b><a href="postconf.5.html#smtpd_reject_footer_maps">smtpd_reject_footer_maps</a> (empty)</b>
- Lookup tables, indexed by the complete Postfix SMTP server 4xx
+ Lookup tables, indexed by the complete Postfix SMTP server 4xx
or 5xx response, with reject footer templates.
<b>SEE ALSO</b>
diff --git a/html/socketmap_table.5.html b/html/socketmap_table.5.html
index a8bbd07..4c9e96c 100644
--- a/html/socketmap_table.5.html
+++ b/html/socketmap_table.5.html
@@ -18,7 +18,7 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5)
<b>postmap -q - <a href="socketmap_table.html">socketmap</a>:unix:</b><i>pathname</i><b>:</b><i>name</i> &lt;<i>inputfile</i>
<b>DESCRIPTION</b>
- The Postfix mail system uses optional tables for address rewriting.
+ The Postfix mail system uses optional tables for address rewriting,
mail routing or policy lookup.
The Postfix socketmap client expects TCP endpoint names of the form
diff --git a/html/tlsproxy.8.html b/html/tlsproxy.8.html
index 0c36743..615a222 100644
--- a/html/tlsproxy.8.html
+++ b/html/tlsproxy.8.html
@@ -170,26 +170,26 @@ TLSPROXY(8) TLSPROXY(8)
tialization functions.
<b>STARTTLS SERVER CONTROLS</b>
- These settings are clones of Postfix SMTP server settings. They allow
+ These settings are clones of Postfix SMTP server settings. They allow
<a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> to load the same certificate and private key information as
- the Postfix SMTP server, before dropping privileges, so that the key
- files can be kept read-only for root. These settings can currently not
- be overruled by information in a <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client request, but that
+ the Postfix SMTP server, before dropping privileges, so that the key
+ files can be kept read-only for root. These settings can currently not
+ be overruled by information in a <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client request, but that
limitation may be removed in a future version.
<b><a href="postconf.5.html#tlsproxy_tls_CAfile">tlsproxy_tls_CAfile</a> ($<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>)</b>
- A file containing (PEM format) CA certificates of root CAs
+ A file containing (PEM format) CA certificates of root CAs
trusted to sign either remote SMTP client certificates or inter-
mediate CA certificates.
<b><a href="postconf.5.html#tlsproxy_tls_CApath">tlsproxy_tls_CApath</a> ($<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>)</b>
- A directory containing (PEM format) CA certificates of root CAs
+ A directory containing (PEM format) CA certificates of root CAs
trusted to sign either remote SMTP client certificates or inter-
mediate CA certificates.
<b><a href="postconf.5.html#tlsproxy_tls_always_issue_session_ids">tlsproxy_tls_always_issue_session_ids</a> ($<a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_ses</a>-</b>
<b><a href="postconf.5.html#smtpd_tls_always_issue_session_ids">sion_ids</a>)</b>
- Force the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server to issue a TLS session id,
+ Force the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server to issue a TLS session id,
even when TLS session caching is turned off.
<b><a href="postconf.5.html#tlsproxy_tls_ask_ccert">tlsproxy_tls_ask_ccert</a> ($<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>)</b>
@@ -199,7 +199,7 @@ TLSPROXY(8) TLSPROXY(8)
The verification depth for remote SMTP client certificates.
<b><a href="postconf.5.html#tlsproxy_tls_cert_file">tlsproxy_tls_cert_file</a> ($<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server RSA certificate in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server RSA certificate in PEM
format.
<b><a href="postconf.5.html#tlsproxy_tls_ciphers">tlsproxy_tls_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_ciphers">smtpd_tls_ciphers</a>)</b>
@@ -207,47 +207,47 @@ TLSPROXY(8) TLSPROXY(8)
will use with opportunistic TLS encryption.
<b><a href="postconf.5.html#tlsproxy_tls_dcert_file">tlsproxy_tls_dcert_file</a> ($<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA certificate in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA certificate in PEM
format.
<b><a href="postconf.5.html#tlsproxy_tls_dh1024_param_file">tlsproxy_tls_dh1024_param_file</a> ($<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>)</b>
- File with DH parameters that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
+ File with DH parameters that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
should use with non-export EDH ciphers.
<b><a href="postconf.5.html#tlsproxy_tls_dh512_param_file">tlsproxy_tls_dh512_param_file</a> ($<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>)</b>
- File with DH parameters that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
+ File with DH parameters that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
should use with export-grade EDH ciphers.
<b><a href="postconf.5.html#tlsproxy_tls_dkey_file">tlsproxy_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA private key in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA private key in PEM
format.
<b><a href="postconf.5.html#tlsproxy_tls_eccert_file">tlsproxy_tls_eccert_file</a> ($<a href="postconf.5.html#smtpd_tls_eccert_file">smtpd_tls_eccert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server ECDSA certificate in
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server ECDSA certificate in
PEM format.
<b><a href="postconf.5.html#tlsproxy_tls_eckey_file">tlsproxy_tls_eckey_file</a> ($<a href="postconf.5.html#smtpd_tls_eckey_file">smtpd_tls_eckey_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server ECDSA private key in
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server ECDSA private key in
PEM format.
<b><a href="postconf.5.html#tlsproxy_tls_eecdh_grade">tlsproxy_tls_eecdh_grade</a> ($<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a>)</b>
- The Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server security grade for ephemeral
+ The Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server security grade for ephemeral
elliptic-curve Diffie-Hellman (EECDH) key exchange.
<b><a href="postconf.5.html#tlsproxy_tls_exclude_ciphers">tlsproxy_tls_exclude_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a>)</b>
- List of ciphers or cipher types to exclude from the <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
+ List of ciphers or cipher types to exclude from the <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
server cipher list at all TLS security levels.
<b><a href="postconf.5.html#tlsproxy_tls_fingerprint_digest">tlsproxy_tls_fingerprint_digest</a> ($<a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a>)</b>
- The message digest algorithm to construct remote SMTP
+ The message digest algorithm to construct remote SMTP
client-certificate fingerprints.
<b><a href="postconf.5.html#tlsproxy_tls_key_file">tlsproxy_tls_key_file</a> ($<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server RSA private key in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server RSA private key in PEM
format.
<b><a href="postconf.5.html#tlsproxy_tls_loglevel">tlsproxy_tls_loglevel</a> ($<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a>)</b>
- Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server logging of TLS
+ Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server logging of TLS
activity.
<b><a href="postconf.5.html#tlsproxy_tls_mandatory_ciphers">tlsproxy_tls_mandatory_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_mandatory_ciphers</a>)</b>
@@ -256,7 +256,7 @@ TLSPROXY(8) TLSPROXY(8)
<b><a href="postconf.5.html#tlsproxy_tls_mandatory_exclude_ciphers">tlsproxy_tls_mandatory_exclude_ciphers</a> ($<a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_manda</a>-</b>
<b><a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">tory_exclude_ciphers</a>)</b>
- Additional list of ciphers or cipher types to exclude from the
+ Additional list of ciphers or cipher types to exclude from the
<a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server cipher list at mandatory TLS security levels.
<b><a href="postconf.5.html#tlsproxy_tls_mandatory_protocols">tlsproxy_tls_mandatory_protocols</a> ($<a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a>)</b>
@@ -264,67 +264,74 @@ TLSPROXY(8) TLSPROXY(8)
with mandatory TLS encryption.
<b><a href="postconf.5.html#tlsproxy_tls_protocols">tlsproxy_tls_protocols</a> ($<a href="postconf.5.html#smtpd_tls_protocols">smtpd_tls_protocols</a>)</b>
- List of TLS protocols that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server will
+ List of TLS protocols that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server will
exclude or include with opportunistic TLS encryption.
<b><a href="postconf.5.html#tlsproxy_tls_req_ccert">tlsproxy_tls_req_ccert</a> ($<a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a>)</b>
- With mandatory TLS encryption, require a trusted remote SMTP
+ 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#tlsproxy_tls_security_level">tlsproxy_tls_security_level</a> ($<a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a>)</b>
- The SMTP TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server;
+ The SMTP TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> 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#tlsproxy_tls_chain_files">tlsproxy_tls_chain_files</a> ($<a href="postconf.5.html#smtpd_tls_chain_files">smtpd_tls_chain_files</a>)</b>
- Files with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server keys and certificate
+ Files with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server keys and certificate
chains in PEM format.
+ Available in Postfix version 3.9 and later:
+
+ <b><a href="postconf.5.html#tlsproxy_tls_enable_rpk">tlsproxy_tls_enable_rpk</a> ($<a href="postconf.5.html#smtpd_tls_enable_rpk">smtpd_tls_enable_rpk</a>)</b>
+ Request that remote SMTP clients send an <a href="https://tools.ietf.org/html/rfc7250">RFC7250</a> raw public key
+ instead of an X.509 certificate, when asking or requiring client
+ authentication.
+
<b>STARTTLS CLIENT CONTROLS</b>
- These settings are clones of Postfix SMTP client settings. They allow
+ These settings are clones of Postfix SMTP client settings. They allow
<a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> to load the same certificate and private key information as
- the Postfix SMTP client, before dropping privileges, so that the key
+ the Postfix SMTP client, before dropping privileges, so that the key
files can be kept read-only for root. Some settings may be overruled by
information in a <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client request.
Available in Postfix version 3.4 and later:
<b><a href="postconf.5.html#tlsproxy_client_CAfile">tlsproxy_client_CAfile</a> ($<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>)</b>
- A file containing CA certificates of root CAs trusted to sign
- either remote TLS server certificates or intermediate CA cer-
+ A file containing CA certificates of root CAs trusted to sign
+ either remote TLS server certificates or intermediate CA cer-
tificates.
<b><a href="postconf.5.html#tlsproxy_client_CApath">tlsproxy_client_CApath</a> ($<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a>)</b>
- Directory with PEM format Certification Authority certificates
- that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client uses to verify a remote TLS
+ Directory with PEM format Certification Authority certificates
+ that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client uses to verify a remote TLS
server certificate.
<b><a href="postconf.5.html#tlsproxy_client_chain_files">tlsproxy_client_chain_files</a> ($<a href="postconf.5.html#smtp_tls_chain_files">smtp_tls_chain_files</a>)</b>
- Files with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client keys and certificate
+ Files with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client keys and certificate
chains in PEM format.
<b><a href="postconf.5.html#tlsproxy_client_cert_file">tlsproxy_client_cert_file</a> ($<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA certificate in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA certificate in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_key_file">tlsproxy_client_key_file</a> ($<a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA private key in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client RSA private key in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_dcert_file">tlsproxy_client_dcert_file</a> ($<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA certificate in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA certificate in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_dkey_file">tlsproxy_client_dkey_file</a> ($<a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA private key in PEM
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client DSA private key in PEM
format.
<b><a href="postconf.5.html#tlsproxy_client_eccert_file">tlsproxy_client_eccert_file</a> ($<a href="postconf.5.html#smtp_tls_eccert_file">smtp_tls_eccert_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA certificate in
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA certificate in
PEM format.
<b><a href="postconf.5.html#tlsproxy_client_eckey_file">tlsproxy_client_eckey_file</a> ($<a href="postconf.5.html#smtp_tls_eckey_file">smtp_tls_eckey_file</a>)</b>
- File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA private key in
+ File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client ECDSA private key in
PEM format.
<b><a href="postconf.5.html#tlsproxy_client_fingerprint_digest">tlsproxy_client_fingerprint_digest</a> ($<a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a>)</b>
@@ -332,7 +339,7 @@ TLSPROXY(8) TLSPROXY(8)
certificate fingerprints.
<b><a href="postconf.5.html#tlsproxy_client_loglevel">tlsproxy_client_loglevel</a> ($<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a>)</b>
- Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client logging of TLS
+ Enable additional Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client logging of TLS
activity.
<b><a href="postconf.5.html#tlsproxy_client_loglevel_parameter">tlsproxy_client_loglevel_parameter</a> (<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a>)</b>
@@ -343,43 +350,43 @@ TLSPROXY(8) TLSPROXY(8)
The verification depth for remote TLS server certificates.
<b><a href="postconf.5.html#tlsproxy_client_use_tls">tlsproxy_client_use_tls</a> ($<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>)</b>
- Opportunistic mode: use TLS when a remote server announces TLS
+ Opportunistic mode: use TLS when a remote server announces TLS
support.
<b><a href="postconf.5.html#tlsproxy_client_enforce_tls">tlsproxy_client_enforce_tls</a> ($<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>)</b>
- Enforcement mode: require that SMTP servers use TLS encryption.
+ Enforcement mode: require that SMTP servers use TLS encryption.
<b><a href="postconf.5.html#tlsproxy_client_per_site">tlsproxy_client_per_site</a> ($<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>)</b>
- Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
- usage policy by next-hop destination and by remote TLS server
+ Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
+ usage policy by next-hop destination and by remote TLS server
hostname.
Available in Postfix version 3.4-3.6:
<b><a href="postconf.5.html#tlsproxy_client_level">tlsproxy_client_level</a> ($<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>)</b>
- The default TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
+ The default TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
client.
<b><a href="postconf.5.html#tlsproxy_client_policy">tlsproxy_client_policy</a> ($<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>)</b>
- Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
+ Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
security policy by next-hop destination.
Available in Postfix version 3.7 and later:
<b><a href="postconf.5.html#tlsproxy_client_security_level">tlsproxy_client_security_level</a> ($<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>)</b>
- The default TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
+ The default TLS security level for the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a>
client.
<b><a href="postconf.5.html#tlsproxy_client_policy_maps">tlsproxy_client_policy_maps</a> ($<a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>)</b>
- Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
+ Optional lookup tables with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> client TLS
security policy by next-hop destination.
<b>OBSOLETE STARTTLS SUPPORT CONTROLS</b>
- These parameters are supported for compatibility with <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy
+ These parameters are supported for compatibility with <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy
parameters.
<b><a href="postconf.5.html#tlsproxy_use_tls">tlsproxy_use_tls</a> ($<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a>)</b>
- Opportunistic TLS: announce STARTTLS support to remote SMTP
+ Opportunistic TLS: announce STARTTLS support to remote SMTP
clients, but do not require that clients use TLS encryption.
<b><a href="postconf.5.html#tlsproxy_enforce_tls">tlsproxy_enforce_tls</a> ($<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>)</b>
@@ -387,11 +394,11 @@ TLSPROXY(8) TLSPROXY(8)
and require that clients use TLS encryption.
<b><a href="postconf.5.html#tlsproxy_client_use_tls">tlsproxy_client_use_tls</a> ($<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a>)</b>
- Opportunistic mode: use TLS when a remote server announces TLS
+ Opportunistic mode: use TLS when a remote server announces TLS
support.
<b><a href="postconf.5.html#tlsproxy_client_enforce_tls">tlsproxy_client_enforce_tls</a> ($<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>)</b>
- Enforcement mode: require that SMTP servers use TLS encryption.
+ Enforcement mode: require that SMTP servers use TLS encryption.
<b>RESOURCE CONTROLS</b>
<b><a href="postconf.5.html#tlsproxy_watchdog_timeout">tlsproxy_watchdog_timeout</a> (10s)</b>
@@ -400,7 +407,7 @@ TLSPROXY(8) TLSPROXY(8)
<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-
+ 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#process_id">process_id</a> (read-only)</b>
@@ -413,7 +420,7 @@ TLSPROXY(8) TLSPROXY(8)
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix 3.3 and later:
diff --git a/html/trivial-rewrite.8.html b/html/trivial-rewrite.8.html
index 1bcd8e7..7b1e3e3 100644
--- a/html/trivial-rewrite.8.html
+++ b/html/trivial-rewrite.8.html
@@ -134,9 +134,11 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
Available in Postfix 2.2 and later:
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients at all when
- this parameter is empty; otherwise, rewrite message headers and
- append the specified domain name to incomplete addresses.
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
+ <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
+ ers.
<b>ROUTING CONTROLS</b>
The following is applicable to Postfix version 2.0 and later. Earlier
@@ -155,13 +157,14 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<b><a href="postconf.5.html#relay_transport">relay_transport</a> (relay)</b>
The default mail delivery transport and next-hop destination for
- remote delivery to domains listed with $<a href="postconf.5.html#relay_domains">relay_domains</a>.
+ the relay domain address class: recipient domains that match
+ $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#default_transport">default_transport</a> (smtp)</b>
The default mail delivery transport and next-hop destination for
- destinations that do not match $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>,
- $<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>, $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mail</a>-
- <a href="postconf.5.html#virtual_mailbox_domains">box_domains</a>, or $<a href="postconf.5.html#relay_domains">relay_domains</a>.
+ the default domain class: recipient domains that do not match
+ $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>, $<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>, $<a href="postconf.5.html#virtual_alias_domains">vir</a>-
+ <a href="postconf.5.html#virtual_alias_domains">tual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, or $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' output)</b>
A list of Postfix features where the pattern "example.com" also
@@ -169,8 +172,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
explicit ".example.com" pattern.
<b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b>
- The next-hop destination(s) for non-local mail; overrides
- non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses.
+ The next-hop destination(s) for non-local mail; takes precedence
+ over non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses.
<b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
Optional lookup tables with mappings from recipient address to
diff --git a/html/virtual.5.html b/html/virtual.5.html
index 7e9061e..c1c6ece 100644
--- a/html/virtual.5.html
+++ b/html/virtual.5.html
@@ -18,101 +18,102 @@ VIRTUAL(5) VIRTUAL(5)
<b>postmap -q - /etc/postfix/virtual</b> &lt;<i>inputfile</i>
<b>DESCRIPTION</b>
- The optional <a href="virtual.5.html"><b>virtual</b>(5)</a> alias table rewrites recipient addresses for
- all local, all virtual, and all remote mail destinations. This is
- unlike the <a href="aliases.5.html"><b>aliases</b>(5)</a> table which is used only for <a href="local.8.html"><b>local</b>(8)</a> delivery.
- This feature is implemented in the Postfix <a href="cleanup.8.html"><b>cleanup</b>(8)</a> daemon before
- mail is queued.
+ The optional <a href="virtual.5.html"><b>virtual</b>(5)</a> alias table (<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>) applies to all
+ recipients: <a href="local.8.html">local(8)</a>, virtual, and remote. This feature is implemented
+ in the Postfix <a href="cleanup.8.html"><b>cleanup</b>(8)</a> daemon before mail is queued.
- Virtual aliasing is recursive; to terminate recursion for a specific
+ This is unlike the <a href="aliases.5.html"><b>aliases</b>(5)</a> table (<a href="postconf.5.html#alias_maps">alias_maps</a>) which applies only to
+ <a href="local.8.html"><b>local</b>(8)</a> recipients.
+
+ Virtual aliasing is recursive; to terminate recursion for a specific
address, alias that address to itself.
- The main applications of virtual aliasing are:
+ The main applications of <a href="ADDRESS_REWRITING_README.html#virtual">virtual aliasing</a> are:
<b>o</b> To redirect mail for one address to one or more addresses.
- <b>o</b> To implement virtual alias domains where all addresses are
+ <b>o</b> To implement virtual alias domains where all addresses are
aliased to addresses in other domains.
- Virtual alias domains are not to be confused with the virtual
+ Virtual alias domains are not to be confused with the virtual
mailbox domains that are implemented with the Postfix <a href="virtual.8.html"><b>virtual</b>(8)</a>
- mail delivery agent. With <a href="ADDRESS_CLASS_README.html#virtual_mailbox_class">virtual mailbox domains</a>, each recipi-
+ mail delivery agent. With <a href="ADDRESS_CLASS_README.html#virtual_mailbox_class">virtual mailbox domains</a>, each recipi-
ent address can have its own mailbox.
- Virtual aliasing is applied only to recipient envelope addresses, and
- does not affect message headers. Use <a href="canonical.5.html"><b>canonical</b>(5)</a> mapping to rewrite
+ Virtual aliasing is applied only to recipient envelope addresses, and
+ does not affect message headers. Use <a href="canonical.5.html"><b>canonical</b>(5)</a> mapping to rewrite
header and envelope addresses in general.
- Normally, the <a href="virtual.5.html"><b>virtual</b>(5)</a> alias table is specified as a text file that
+ Normally, the <a href="virtual.5.html"><b>virtual</b>(5)</a> alias table is specified as a text file that
serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file
- in <b>dbm</b> or <b>db</b> format, is used for fast searching by the mail system.
+ in <b>dbm</b> or <b>db</b> format, is used for fast searching by the mail system.
Execute the command "<b>postmap /etc/postfix/virtual</b>" to rebuild an
indexed file after changing the corresponding text file.
- When the table is provided via other means such as NIS, LDAP or SQL,
+ When the table is provided via other means such as NIS, LDAP or SQL,
the same lookups are done as for ordinary indexed files.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
- directed to a TCP-based server. In those case, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
+ directed to a TCP-based server. In those case, the lookups are done in
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
<b>CASE FOLDING</b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b>TABLE FORMAT</b>
The input format for the <a href="postmap.1.html"><b>postmap</b>(1)</a> command is as follows:
<i>pattern address, address, ...</i>
- When <i>pattern</i> matches a mail address, replace it by the corre-
+ When <i>pattern</i> matches a mail address, replace it by the corre-
sponding <i>address</i>.
blank lines and comments
- Empty lines and whitespace-only lines are ignored, as are lines
+ Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
multi-line text
- A logical line starts with non-whitespace text. A line that
+ A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
<b>TABLE SEARCH ORDER</b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
sequence of query patterns as described below.
Each query pattern is sent to each specified lookup table before trying
the next query pattern, until a match is found.
<i>user</i>@<i>domain address, address, ...</i>
- Redirect mail for <i>user</i>@<i>domain</i> to <i>address</i>. This form has the
+ Redirect mail for <i>user</i>@<i>domain</i> to <i>address</i>. This form has the
highest precedence.
<i>user address, address, ...</i>
- Redirect mail for <i>user</i>@<i>site</i> to <i>address</i> when <i>site</i> is equal to
- $<b><a href="postconf.5.html#myorigin">myorigin</a></b>, when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is
+ Redirect mail for <i>user</i>@<i>site</i> to <i>address</i> when <i>site</i> is equal to
+ $<b><a href="postconf.5.html#myorigin">myorigin</a></b>, when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is
listed in $<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b> or $<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a></b>.
- This functionality overlaps with the functionality of the local
- <i>aliases</i>(5) database. The difference is that <a href="virtual.5.html"><b>virtual</b>(5)</a> mapping
+ This functionality overlaps with the functionality of the local
+ <i>aliases</i>(5) database. The difference is that <a href="virtual.5.html"><b>virtual</b>(5)</a> mapping
can be applied to non-local addresses.
@<i>domain address, address, ...</i>
- Redirect mail for other users in <i>domain</i> to <i>address</i>. This form
+ Redirect mail for other users in <i>domain</i> to <i>address</i>. This form
has the lowest precedence.
- Note: @<i>domain</i> is a wild-card. With this form, the Postfix SMTP
- server accepts mail for any recipient in <i>domain</i>, regardless of
- whether that recipient exists. This may turn your mail system
- into a backscatter source: Postfix first accepts mail for
- non-existent recipients and then tries to return that mail as
+ Note: @<i>domain</i> is a wild-card. With this form, the Postfix SMTP
+ server accepts mail for any recipient in <i>domain</i>, regardless of
+ whether that recipient exists. This may turn your mail system
+ into a backscatter source: Postfix first accepts mail for
+ non-existent recipients and then tries to return that mail as
"undeliverable" to the often forged sender address.
- To avoid backscatter with mail for a wild-card domain, replace
- the wild-card mapping with explicit 1:1 mappings, or add a
+ To avoid backscatter with mail for a wild-card domain, replace
+ the wild-card mapping with explicit 1:1 mappings, or add a
<a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> restriction for that domain:
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
@@ -128,11 +129,11 @@ VIRTUAL(5) VIRTUAL(5)
<b>RESULT ADDRESS REWRITING</b>
The lookup result is subject to address rewriting:
- <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
- the same <i>user</i> in <i>otherdomain</i>. This works only for the first
+ <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
+ the same <i>user</i> in <i>otherdomain</i>. This works only for the first
address in a multi-address lookup result.
- <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
+ <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
without "@domain".
<b>o</b> When "<b><a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a>=yes</b>", append "<b>.$<a href="postconf.5.html#mydomain">mydomain</a></b>" to addresses
@@ -140,26 +141,26 @@ VIRTUAL(5) VIRTUAL(5)
<b>ADDRESS EXTENSION</b>
When a mail address localpart contains the optional recipient delimiter
- (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
+ (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>user+foo</i>, <i>user</i>, and @<i>domain</i>.
- The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
+ The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
unmatched address extension (<i>+foo</i>) is propagated to the result of a ta-
ble lookup.
<b>VIRTUAL ALIAS DOMAINS</b>
- Besides virtual aliases, the virtual alias table can also be used to
- implement virtual alias domains. With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, all
+ Besides virtual aliases, the virtual alias table can also be used to
+ implement <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domains</a>. With a virtual alias domain, all
recipient addresses are aliased to addresses in other domains.
- Virtual alias domains are not to be confused with the virtual mailbox
- domains that are implemented with the Postfix <a href="virtual.8.html"><b>virtual</b>(8)</a> mail delivery
- agent. With <a href="ADDRESS_CLASS_README.html#virtual_mailbox_class">virtual mailbox domains</a>, each recipient address can have
+ Virtual alias domains are not to be confused with the virtual mailbox
+ domains that are implemented with the Postfix <a href="virtual.8.html"><b>virtual</b>(8)</a> mail delivery
+ agent. With virtual mailbox domains, each recipient address can have
its own mailbox.
- With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the virtual domain has its own user name
- space. Local (i.e. non-virtual) usernames are not visible in a virtual
- alias domain. In particular, local <a href="aliases.5.html"><b>aliases</b>(5)</a> and local mailing lists
+ With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the virtual domain has its own user name
+ space. Local (i.e. non-virtual) usernames are not visible in a virtual
+ alias domain. In particular, local <a href="aliases.5.html"><b>aliases</b>(5)</a> and local mailing lists
are not visible as <i>localname@virtual-alias.domain</i>.
Support for a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> looks like:
@@ -167,7 +168,7 @@ VIRTUAL(5) VIRTUAL(5)
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
- Note: some systems use <b>dbm</b> databases instead of <b>hash</b>. See the output
+ Note: some systems use <b>dbm</b> databases instead of <b>hash</b>. See the output
from "<b>postconf -m</b>" for available database types.
/etc/postfix/virtual:
@@ -177,46 +178,46 @@ VIRTUAL(5) VIRTUAL(5)
<i>user2@virtual-alias.domain address2, address3</i>
The <i>virtual-alias.domain anything</i> entry is required for a virtual alias
- domain. <b>Without this entry, mail is rejected with "relay access</b>
+ domain. <b>Without this entry, mail is rejected with "relay access</b>
<b>denied", or bounces with "mail loops back to myself".</b>
- Do not specify <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> names in the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#mydestination">mydestination</a></b>
+ Do not specify <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> names in the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#mydestination">mydestination</a></b>
or <b><a href="postconf.5.html#relay_domains">relay_domains</a></b> configuration parameters.
- With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the Postfix SMTP server accepts mail for
+ With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the Postfix SMTP server accepts mail for
<i>known-user@virtual-alias.domain</i>, and rejects mail for <i>unknown-user</i>@<i>vir-</i>
<i>tual-alias.domain</i> as undeliverable.
- Instead of specifying the virtual alias domain name via the <b><a href="postconf.5.html#virtual_alias_maps">vir</a>-</b>
- <b><a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a></b> table, you may also specify it via the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#virtual_alias_domains">vir-</b>
+ Instead of specifying the virtual alias domain name via the <b><a href="postconf.5.html#virtual_alias_maps">vir</a>-</b>
+ <b><a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a></b> table, you may also specify it via the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#virtual_alias_domains">vir-</b>
<b>tual_alias_domains</a></b> configuration parameter. This latter parameter uses
the same syntax as the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#mydestination">mydestination</a></b> configuration parameter.
<b>REGULAR EXPRESSION TABLES</b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to the entire
- address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
- ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
+ Each pattern is a regular expression that is applied to the entire
+ address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
+ ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
broken up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
- Results are the same as with indexed file lookups, with the additional
- feature that parenthesized substrings from the pattern can be interpo-
+ Results are the same as with indexed file lookups, with the additional
+ feature that parenthesized substrings from the pattern can be interpo-
lated as <b>$1</b>, <b>$2</b> and so on.
<b>TCP-BASED TABLES</b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
available in Postfix 2.5 and later.
- Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
- mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
+ Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
+ mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
stituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Results are the same as with indexed file lookups.
@@ -230,8 +231,9 @@ VIRTUAL(5) VIRTUAL(5)
Use the "<b>postfix reload</b>" command after a configuration change.
<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 addresses.
+ Optional lookup tables with aliases that apply to all recipi-
+ ents: <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote; this is unlike <a href="postconf.5.html#alias_maps">alias_maps</a>
+ that apply only to <a href="local.8.html"><b>local</b>(8)</a> recipients.
<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 the final destination for the specified list of vir-
@@ -245,8 +247,8 @@ VIRTUAL(5) VIRTUAL(5)
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The network interface addresses that this mail system receives
- mail on.
+ The local network interface addresses that this mail system
+ receives mail on.
<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>, localhost)</b>
The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
@@ -263,8 +265,9 @@ VIRTUAL(5) VIRTUAL(5)
set to "-".
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The network interface addresses that this mail system receives
- mail on by way of a proxy or network address translation unit.
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
+ tion unit.
<b>SEE ALSO</b>
<a href="cleanup.8.html">cleanup(8)</a>, canonicalize and enqueue mail
diff --git a/makedefs b/makedefs
index 005e4b3..1932e36 100644
--- a/makedefs
+++ b/makedefs
@@ -35,6 +35,7 @@
# Specifies one or more non-default object libraries. Postfix
# 3.0 and later specify some of their database library
# dependencies with AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB,
+# AUXLIBS_MONGODB,
# AUXLIBS_MYSQL, AUXLIBS_PCRE, AUXLIBS_PGSQL, AUXLIBS_SDBM,
# and AUXLIBS_SQLITE, respectively.
# .IP \fBCC=\fIcompiler_command\fR
@@ -184,6 +185,9 @@
# New York, NY 10011, USA
#--
+# Override all LC_* settings and LANG for reproducibility.
+LC_ALL=C; export LC_ALL
+
# By now all shells must have functions.
error() {
@@ -1242,7 +1246,7 @@ DEFINED_MAP_TYPES=`
# Propagate AUXLIBS_FOO or merge them into global AUXLIBS (i.e. SYSLIBS).
-PLUGGABLE_MAPS="CDB LDAP LMDB MYSQL PCRE PGSQL SDBM SQLITE"
+PLUGGABLE_MAPS="CDB LDAP LMDB MONGODB MYSQL PCRE PGSQL SDBM SQLITE"
case "$dynamicmaps" in
yes) for name in $PLUGGABLE_MAPS
diff --git a/man/Makefile.in b/man/Makefile.in
index f98402c..40a5236 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -17,7 +17,7 @@ CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \
man5/cidr_table.5 man5/tcp_table.5 man5/header_checks.5 \
man5/body_checks.5 man5/ldap_table.5 man5/lmdb_table.5 \
- man5/memcache_table.5 man5/mysql_table.5 \
+ man5/memcache_table.5 man5/mongodb_table.5 man5/mysql_table.5 \
man5/pgsql_table.5 man5/master.5 man5/nisplus_table.5 \
man5/generic.5 man5/bounce.5 man5/postfix-wrapper.5 \
man5/sqlite_table.5 man5/socketmap_table.5
@@ -316,6 +316,11 @@ man5/memcache_table.5: ../proto/memcache_table
(cmp -s junk $? || mv junk $?) && rm -f junk
../mantools/srctoman - $? >$@
+man5/mongodb_table.5: ../proto/mongodb_table
+ ../mantools/fixman ../proto/postconf.proto $? >junk && \
+ (cmp -s junk $? || mv junk $?) && rm -f junk
+ ../mantools/srctoman - $? >$@
+
man5/mysql_table.5: ../proto/mysql_table
../mantools/fixman ../proto/postconf.proto $? >junk && \
(cmp -s junk $? || mv junk $?) && rm -f junk
diff --git a/man/man1/makedefs.1 b/man/man1/makedefs.1
index 70c848e..c921ac2 100644
--- a/man/man1/makedefs.1
+++ b/man/man1/makedefs.1
@@ -38,6 +38,7 @@ of the make(1) command.
Specifies one or more non\-default object libraries. Postfix
3.0 and later specify some of their database library
dependencies with AUXLIBS_CDB, AUXLIBS_LDAP, AUXLIBS_LMDB,
+AUXLIBS_MONGODB,
AUXLIBS_MYSQL, AUXLIBS_PCRE, AUXLIBS_PGSQL, AUXLIBS_SDBM,
and AUXLIBS_SQLITE, respectively.
.IP \fBCC=\fIcompiler_command\fR
diff --git a/man/man1/postcat.1 b/man/man1/postcat.1
index eb3025b..f6541eb 100644
--- a/man/man1/postcat.1
+++ b/man/man1/postcat.1
@@ -88,7 +88,7 @@ The text below provides only a parameter summary. See
The default location of the Postfix main.cf and master.cf
configuration files.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a privileged Postfix
+The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
environment overrides.
.IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/man/man1/postconf.1 b/man/man1/postconf.1
index e422429..4121806 100644
--- a/man/man1/postconf.1
+++ b/man/man1/postconf.1
@@ -12,7 +12,7 @@ Postfix configuration utility
.ti -4
\fBManaging main.cf:\fR
-\fBpostconf\fR [\fB\-dfhHnopvx\fR] [\fB\-c \fIconfig_dir\fR]
+\fBpostconf\fR [\fB\-dfhHnopqvx\fR] [\fB\-c \fIconfig_dir\fR]
[\fB\-C \fIclass,...\fR] [\fIparameter ...\fR]
\fBpostconf\fR [\fB\-epv\fR] [\fB\-c \fIconfig_dir\fR]
@@ -27,7 +27,7 @@ Postfix configuration utility
.ti -4
\fBManaging master.cf service entries:\fR
-\fBpostconf\fR \fB\-M\fR [\fB\-fovx\fR] [\fB\-c \fIconfig_dir\fR]
+\fBpostconf\fR \fB\-M\fR [\fB\-foqvx\fR] [\fB\-c \fIconfig_dir\fR]
[\fIservice\fR[\fB/\fItype\fR]\fI ...\fR]
\fBpostconf\fR \fB\-M\fR [\fB\-ev\fR] [\fB\-c \fIconfig_dir\fR]
@@ -42,7 +42,7 @@ Postfix configuration utility
.ti -4
\fBManaging master.cf service fields:\fR
-\fBpostconf\fR \fB\-F\fR [\fB\-fhHovx\fR] [\fB\-c \fIconfig_dir\fR]
+\fBpostconf\fR \fB\-F\fR [\fB\-fhHoqvx\fR] [\fB\-c \fIconfig_dir\fR]
[\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR]
\fBpostconf\fR \fB\-F\fR [\fB\-ev\fR] [\fB\-c \fIconfig_dir\fR]
@@ -51,7 +51,7 @@ Postfix configuration utility
.ti -4
\fBManaging master.cf service parameters:\fR
-\fBpostconf\fR \fB\-P\fR [\fB\-fhHovx\fR] [\fB\-c \fIconfig_dir\fR]
+\fBpostconf\fR \fB\-P\fR [\fB\-fhHoqvx\fR] [\fB\-c \fIconfig_dir\fR]
[\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR]
\fBpostconf\fR \fB\-P\fR [\fB\-ev\fR] [\fB\-c \fIconfig_dir\fR]
@@ -299,6 +299,11 @@ Memcache database client. This is described in
\fBmemcache_table\fR(5).
This feature is available with Postfix 2.9 and later.
+.IP "\fBmongodb\fR"
+MongoDB database client. This is described in
+\fBmongodb_table\fR(5).
+
+This feature is available with Postfix 3.9 and later.
.IP "\fBmysql\fR (read\-only)"
MySQL database client. Available on systems with support
for MySQL databases. This is described in \fBmysql_table\fR(5).
@@ -458,6 +463,10 @@ service type fields that are omitted will be handled as "*"
wildcard fields.
This feature is available with Postfix 2.11 and later.
+.IP \fB\-q\fR
+Do not log warnings for deprecated or unused parameters.
+
+This feature is available with Postfix 3.9 and later.
.IP "\fB\-t\fR [\fItemplate_file\fR]"
Display the templates for text that appears at the beginning
of delivery status notification (DSN) messages, without
diff --git a/man/man1/postdrop.1 b/man/man1/postdrop.1
index 23d6012..9dffd68 100644
--- a/man/man1/postdrop.1
+++ b/man/man1/postdrop.1
@@ -78,7 +78,7 @@ environment parameter.
The default location of the Postfix main.cf and master.cf
configuration files.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a privileged Postfix
+The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
environment overrides.
.IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/man/man1/postfix.1 b/man/man1/postfix.1
index c3ad0d8..da39dc5 100644
--- a/man/man1/postfix.1
+++ b/man/man1/postfix.1
@@ -317,7 +317,7 @@ postfix\-wrapper(5), Postfix multi\-instance API
Table\-driven mechanisms:
access(5), Postfix SMTP access control table
-aliases(5), Postfix alias database
+aliases(5), Postfix local aliasing
canonical(5), Postfix input address rewriting
generic(5), Postfix output address rewriting
header_checks(5), body_checks(5), Postfix content inspection
@@ -330,6 +330,7 @@ cidr_table(5), Associate CIDR pattern with value
ldap_table(5), Postfix LDAP client
lmdb_table(5), Postfix LMDB database driver
memcache_table(5), Postfix memcache client
+mongodb_table(5), Postfix MongoDB client
mysql_table(5), Postfix MYSQL client
nisplus_table(5), Postfix NIS+ client
pcre_table(5), Associate PCRE pattern with value
diff --git a/man/man1/postkick.1 b/man/man1/postkick.1
index 6cd0ef6..779a353 100644
--- a/man/man1/postkick.1
+++ b/man/man1/postkick.1
@@ -66,7 +66,7 @@ configuration files.
How long the \fBpostkick\fR(1) command waits for a request to enter the
Postfix daemon process input buffer before giving up.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a privileged Postfix
+The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
environment overrides.
.IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/man/man1/postlock.1 b/man/man1/postlock.1
index cd468e7..6c07319 100644
--- a/man/man1/postlock.1
+++ b/man/man1/postlock.1
@@ -99,7 +99,7 @@ The delay between attempts to fork() a child process.
The default location of the Postfix main.cf and master.cf
configuration files.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a privileged Postfix
+The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
environment overrides.
.SH "SEE ALSO"
diff --git a/man/man1/postlog.1 b/man/man1/postlog.1
index 52bd815..d9723e7 100644
--- a/man/man1/postlog.1
+++ b/man/man1/postlog.1
@@ -94,6 +94,12 @@ The name of an optional logfile that is written by the Postfix
\fBpostlogd\fR(8) service.
.IP "\fBpostlog_service_name (postlog)\fR"
The name of the \fBpostlogd\fR(8) service entry in master.cf.
+.PP
+Available in Postfix 3.9 and later:
+.IP "\fBmaillog_file_permissions (0600)\fR"
+The file access permissions that will be set when the file
+$maillog_file is created for the first time, or when the file is
+created after an existing file is rotated.
.SH "SEE ALSO"
.na
.nf
diff --git a/man/man1/postsuper.1 b/man/man1/postsuper.1
index 885330f..8c5da03 100644
--- a/man/man1/postsuper.1
+++ b/man/man1/postsuper.1
@@ -46,7 +46,7 @@ from standard input. For example, to delete all mail
with exactly one recipient \fBuser@example.com\fR:
.sp
.nf
-postqueue \-j | jq -r '
+postqueue \-j | jq \-r '
# See JSON OBJECT FORMAT section in the postqueue(1) manpage
select(.recipients[0].address == "user@example.com")
| select(.recipients[1].address == null)
@@ -54,7 +54,7 @@ postqueue \-j | jq -r '
' | postsuper \-d \-
.fi
.sp
-(note the "jq -r" option), or the historical form:
+(note the "jq \-r" option), or the historical form:
.sp
.nf
mailq | tail \-n +2 | grep \-v '^ *(' | awk 'BEGIN { RS = "" }
@@ -302,7 +302,7 @@ the hash_queue_names parameter.
The names of queue directories that are split across multiple
subdirectory levels.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a privileged Postfix
+The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
environment overrides.
.IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/man/man1/posttls-finger.1 b/man/man1/posttls-finger.1
index 1e22a03..3cba972 100644
--- a/man/man1/posttls-finger.1
+++ b/man/man1/posttls-finger.1
@@ -109,7 +109,7 @@ fingerprints (with DANE TLSA records the algorithm is specified
in the DNS). In Postfix versions prior to 3.6, the default value
was "md5".
.IP "\fB\-f\fR"
-Lookup the associated DANE TLSA RRset even when a hostname is not an
+Look up the associated DANE TLSA RRset even when a hostname is not an
alias and its address records lie in an unsigned zone. See
smtp_tls_force_insecure_host_tlsa_lookup for details.
.IP "\fB\-F \fICAfile.pem\fR (default: none)"
@@ -270,6 +270,15 @@ is typically provided on port 465 by servers that are compatible with
the SMTP\-in\-SSL protocol, rather than the STARTTLS protocol.
The destination \fIdomain\fR:\fIport\fR must of course provide such
a service.
+.IP "\fB\-x\fR"
+Prefer RFC7250 non\-X.509 raw public key (RPK) server credentials. By
+default only X.509 certificates are accepted. This is analogous to
+setting \fBsmtp_tls_enable_rpk = yes\fR in the smtp(8) client. At the
+fingerprint security level, when raw public keys are enabled, only
+public key (and not certificate) fingerprints will be compared against
+the specified list of \fImatch\fR arguments. Certificate fingerprints
+are fragile when raw public keys are solicited, the server may at some
+point in time start returning only the public key.
.IP "\fB\-X\fR"
Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode,
for program development only.
diff --git a/man/man1/sendmail.1 b/man/man1/sendmail.1
index 22affe6..e3bc7a6 100644
--- a/man/man1/sendmail.1
+++ b/man/man1/sendmail.1
@@ -440,9 +440,10 @@ daemon processes.
.IP "\fBqueue_directory (see 'postconf -d' output)\fR"
The location of the Postfix top\-level queue directory.
.IP "\fBremote_header_rewrite_domain (empty)\fR"
-Don't rewrite message headers from remote clients at all when
-this parameter is empty; otherwise, rewrite message headers and
-append the specified domain name to incomplete addresses.
+Rewrite or add message headers in mail from remote clients if
+the remote_header_rewrite_domain parameter value is non\-empty,
+updating incomplete addresses with the domain specified in the
+remote_header_rewrite_domain parameter, and adding missing headers.
.IP "\fBsyslog_facility (mail)\fR"
The syslog facility of Postfix logging.
.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
diff --git a/man/man1/smtp-source.1 b/man/man1/smtp-source.1
index 014ee10..238bc28 100644
--- a/man/man1/smtp-source.1
+++ b/man/man1/smtp-source.1
@@ -48,7 +48,7 @@ when the listen queue is full.
Don't disconnect after sending a message; send the next
message over the same connection.
.IP "\fB\-f \fIfrom\fR"
-Use the specified sender address (default: <foo@myhostname>).
+Use the specified sender address (default: <foo@my\-hostname>).
.IP "\fB\-F \fIfile\fR"
Send the pre\-formatted message header and body in the
specified \fIfile\fR, while prepending '.' before lines that
@@ -60,31 +60,49 @@ include message headers.
Speak LMTP rather than SMTP.
.IP "\fB\-m \fImessage_count\fR"
Send the specified number of messages (default: 1).
-.IP "\fB\-M \fImyhostname\fR"
+.IP "\fB\-M \fImy\-hostname\fR"
Use the specified hostname or [address] in the HELO command
and in the default sender and recipient addresses, instead
of the machine hostname.
.IP "\fB\-N\fR"
-Prepend a non\-repeating sequence number to each recipient
-address. This avoids the artificial 100% hit rate in the
-resolve and rewrite client caches and exercises the
-trivial\-rewrite daemon, better approximating Postfix
-performance under real\-life work\-loads.
+Generate each recipient address by appending a number (a
+per\-process recipient counter) to the recipient address
+localpart specified with the \fB\-t\fR option.
+
+Note: to use the number as an address extension, specify
+an explicit address delimiter at the end of the recipient
+localpart, as in "\fB\-t localpart+@domain\fR" or "\fB\-t
+localpart+\fR", where "\fB+\fR" is a Postfix recipient
+address delimiter.
+
+Benefits:
+.RS
+.IP \(bu
+A non\-constant recipient address avoids an unrealistic 100%
+cache hit rate in clients of the Postfix trivial\-rewrite
+service, better approximating performance under real\-life
+work\-loads.
+.IP \(bu
+A fixed recipient address local\-part with a non\-constant
+address extension avoids the need to configure a large
+number of valid recipient addresses in the receiving Postfix
+server.
+.RE
.IP \fB\-o\fR
Old mode: don't send HELO, and don't send message headers.
.IP "\fB\-r \fIrecipient_count\fR"
-Send the specified number of recipients per transaction (default: 1).
-Recipient names are generated by prepending a number to the
-recipient address.
+Send the specified number of recipients per transaction
+(default: 1), and generate recipient addresses as described
+under the \fB\-N\fR option.
.IP "\fB\-R \fIinterval\fR"
-Wait for a random period of time 0 <= n <= interval between messages.
+Wait a random time (0 <= n <= \fIinterval\fR) between messages.
Suspending one thread does not affect other delivery threads.
.IP "\fB\-s \fIsession_count\fR"
Run the specified number of SMTP sessions in parallel (default: 1).
.IP "\fB\-S \fIsubject\fR"
Send mail with the named subject line (default: none).
.IP "\fB\-t \fIto\fR"
-Use the specified recipient address (default: <foo@myhostname>).
+Use the specified recipient address (default: <foo@my\-hostname>).
.IP "\fB\-T \fIwindowsize\fR"
Override the default TCP window size. To work around
broken TCP window scaling implementations, specify a
diff --git a/man/man5/access.5 b/man/man5/access.5
index 07725be..e2eb677 100644
--- a/man/man5/access.5
+++ b/man/man5/access.5
@@ -62,7 +62,7 @@ are lines whose first non\-whitespace character is a `#'.
.IP "multi\-line text"
A logical line starts with non\-whitespace text. A line that
starts with whitespace continues a logical line.
-.SH "EMAIL ADDRESS PATTERNS"
+.SH "EMAIL ADDRESS PATTERNS IN INDEXED TABLES"
.na
.nf
.ad
@@ -99,7 +99,7 @@ When a mail address localpart contains the optional recipient delimiter
(e.g., \fIuser+foo\fR@\fIdomain\fR), the lookup order becomes:
\fIuser+foo\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR, \fIdomain\fR,
\fIuser+foo\fR@, and \fIuser\fR@.
-.SH "HOST NAME/ADDRESS PATTERNS"
+.SH "HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES"
.na
.nf
.ad
diff --git a/man/man5/aliases.5 b/man/man5/aliases.5
index a5da906..ed6a10f 100644
--- a/man/man5/aliases.5
+++ b/man/man5/aliases.5
@@ -13,9 +13,13 @@ Postfix local alias database format
.SH DESCRIPTION
.ad
.fi
-The \fBaliases\fR(5) table provides a system\-wide mechanism to
-redirect mail for local recipients. The redirections are
-processed by the Postfix \fBlocal\fR(8) delivery agent.
+The optional \fBaliases\fR(5) table (alias_maps) redirects
+mail for local recipients. The redirections are processed
+by the Postfix \fBlocal\fR(8) delivery agent.
+
+This is unlike \fBvirtual\fR(5) aliasing (virtual_alias_maps)
+which applies to all recipients: local(8), virtual, and remote,
+and which is implemented by the \fBcleanup\fR(8) daemon.
Normally, the \fBaliases\fR(5) table is specified as a text file
that serves as input to the \fBpostalias\fR(1) command. The
@@ -165,7 +169,9 @@ The text below provides only a parameter summary. See
The alias databases for \fBlocal\fR(8) delivery that are updated with
"\fBnewaliases\fR" or with "\fBsendmail \-bi\fR".
.IP "\fBalias_maps (see 'postconf -d' output)\fR"
-The alias databases that are used for \fBlocal\fR(8) delivery.
+Optional lookup tables with aliases that apply only to \fBlocal\fR(8)
+recipients; this is unlike virtual_alias_maps that apply to all
+recipients: \fBlocal\fR(8), virtual, and remote.
.IP "\fBallow_mail_to_commands (alias, forward)\fR"
Restrict \fBlocal\fR(8) mail delivery to external commands.
.IP "\fBallow_mail_to_files (alias, forward)\fR"
diff --git a/man/man5/canonical.5 b/man/man5/canonical.5
index e987664..8776f3b 100644
--- a/man/man5/canonical.5
+++ b/man/man5/canonical.5
@@ -231,17 +231,14 @@ key to the lookup result.
.PP
Other parameters of interest:
.IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives
-mail on.
+The local network interface addresses that this mail system
+receives mail on.
.IP "\fBlocal_header_rewrite_clients (permit_inet_interfaces)\fR"
-Rewrite message header addresses in mail from these clients and
-update incomplete addresses with the domain name in $myorigin or
-$mydomain; 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 remote_header_rewrite_domain
-parameter.
+Rewrite or add message headers in mail from these clients,
+updating incomplete addresses with the domain name in $myorigin or
+$mydomain, and adding missing headers.
.IP "\fBproxy_interfaces (empty)\fR"
-The network interface addresses that this mail system receives mail
+The remote network interface addresses that this mail system receives mail
on by way of a proxy or network address translation unit.
.IP "\fBmasquerade_classes (envelope_sender, header_sender, header_recipient)\fR"
What addresses are subject to address masquerading.
@@ -263,9 +260,10 @@ Enable special treatment for owner\-\fIlistname\fR entries in the
\fIlistname\fR\-request address localparts when the recipient_delimiter
is set to "\-".
.IP "\fBremote_header_rewrite_domain (empty)\fR"
-Don't rewrite message headers from remote clients at all when
-this parameter is empty; otherwise, rewrite message headers and
-append the specified domain name to incomplete addresses.
+Rewrite or add message headers in mail from remote clients if
+the remote_header_rewrite_domain parameter value is non\-empty,
+updating incomplete addresses with the domain specified in the
+remote_header_rewrite_domain parameter, and adding missing headers.
.SH "SEE ALSO"
.na
.nf
diff --git a/man/man5/generic.5 b/man/man5/generic.5
index 6e891eb..b474530 100644
--- a/man/man5/generic.5
+++ b/man/man5/generic.5
@@ -214,10 +214,10 @@ key to the lookup result.
.PP
Other parameters of interest:
.IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives
-mail on.
+The local network interface addresses that this mail system
+receives mail on.
.IP "\fBproxy_interfaces (empty)\fR"
-The network interface addresses that this mail system receives mail
+The remote network interface addresses that this mail system receives mail
on by way of a proxy or network address translation unit.
.IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR"
The list of domains that are delivered via the $local_transport
diff --git a/man/man5/header_checks.5 b/man/man5/header_checks.5
index 31ac7dc..92c1de9 100644
--- a/man/man5/header_checks.5
+++ b/man/man5/header_checks.5
@@ -417,34 +417,24 @@ be examined before they are deleted. Examples are: \fBBcc:\fR,
.nf
.ad
.fi
-.IP \fBbody_checks\fR
-Lookup tables with content filter rules for message body lines.
-These filters see one physical line at a time, in chunks of
-at most \fB$line_length_limit\fR bytes.
-.IP \fBbody_checks_size_limit\fP
-The amount of content per message body segment (attachment) that is
-subjected to \fB$body_checks\fR filtering.
-.IP \fBheader_checks\fR
-.IP "\fBmime_header_checks\fR (default: \fB$header_checks\fR)"
-.IP "\fBnested_header_checks\fR (default: \fB$header_checks\fR)"
-Lookup tables with content filter rules for message header lines:
-respectively, these are applied to the initial message headers
-(not including MIME headers), to the MIME headers anywhere in
-the message, and to the initial headers of attached messages.
-.sp
-Note: these filters see one logical message header at a time, even
-when a message header spans multiple lines. Message headers that
-are longer than \fB$header_size_limit\fR characters are truncated.
-.IP \fBdisable_mime_input_processing\fR
-While receiving mail, give no special treatment to MIME related
-message headers; all text after the initial message headers is
-considered to be part of the message body. This means that
-\fBheader_checks\fR is applied to all the initial message headers,
-and that \fBbody_checks\fR is applied to the remainder of the
-message.
-.sp
-Note: when used in this manner, \fBbody_checks\fR will process
-a multi\-line message header one line at a time.
+.IP "\fBbody_checks (empty)\fR"
+Optional lookup tables for content inspection as specified in
+the \fBbody_checks\fR(5) manual page.
+.IP "\fBbody_checks_size_limit (51200)\fR"
+How much text in a message body segment (or attachment, if you
+prefer to use that term) is subjected to body_checks inspection.
+.IP "\fBheader_checks (empty)\fR"
+Optional lookup tables for content inspection of primary non\-MIME
+message headers, as specified in the \fBheader_checks\fR(5) manual page.
+.IP "\fBmime_header_checks ($header_checks)\fR"
+Optional lookup tables for content inspection of MIME related
+message headers, as described in the \fBheader_checks\fR(5) manual page.
+.IP "\fBnested_header_checks ($header_checks)\fR"
+Optional lookup tables for content inspection of non\-MIME message
+headers in attached messages, as described in the \fBheader_checks\fR(5)
+manual page.
+.IP "\fBdisable_mime_input_processing (no)\fR"
+Turn off MIME processing while receiving mail.
.SH "EXAMPLES"
.na
.nf
diff --git a/man/man5/master.5 b/man/man5/master.5
index 48fd4fd..469ccdf 100644
--- a/man/man5/master.5
+++ b/man/man5/master.5
@@ -225,10 +225,16 @@ personalities via master.cf.
.IP \fB\-v\fR
Increase the verbose logging level. Specify multiple \fB\-v\fR
options to make a Postfix daemon process increasingly verbose.
-.IP "Other command\-line arguments"
+.IP "\fBCommand\-line arguments that start with {\fR"
+With Postfix 3.0 and later specify "{" and "}" around command
+arguments that start with "{". The outer "{" and "}" are
+removed from the input, together with any leading or trailing
+whitespace.
+.IP "\fBOther command\-line arguments\fR"
Specify "{" and "}" around command arguments that contain
-whitespace (Postfix 3.0 and later). Whitespace
-after "{" and before "}" is ignored.
+whitespace (Postfix 3.0 and later). The outer "{" and "}"
+are removed from the input, together with any leading or
+trailing whitespace.
.SH "SEE ALSO"
.na
.nf
diff --git a/man/man5/mongodb_table.5 b/man/man5/mongodb_table.5
new file mode 100644
index 0000000..cfbedf3
--- /dev/null
+++ b/man/man5/mongodb_table.5
@@ -0,0 +1,259 @@
+.TH MONGODB_TABLE 5
+.ad
+.fi
+.SH NAME
+mongodb_table
+\-
+Postfix MongoDB client configuration
+.SH "SYNOPSIS"
+.na
+.nf
+\fBpostmap \-q "\fIstring\fB" mongodb:/etc/postfix/\fIfilename\fR
+
+\fBpostmap \-q \- mongodb:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
+.SH DESCRIPTION
+.ad
+.fi
+The Postfix mail system uses optional tables for address
+rewriting or mail routing. These tables are usually in
+\fBdbm\fR or \fBdb\fR format.
+
+Alternatively, lookup tables can be specified as MongoDB
+databases. In order to use MongoDB lookups, define a MongoDB
+source as a lookup table in main.cf, for example:
+.nf
+ alias_maps = mongodb:/etc/postfix/mongodb\-aliases.cf
+.fi
+
+In this example, the file /etc/postfix/mongodb\-aliases.cf
+has the same format as the Postfix main.cf file, and can
+specify the parameters described below. It is also possible
+to have the configuration in main.cf; see "OBSOLETE MAIN.CF
+PARAMETERS" below.
+
+It is strongly recommended to use proxy:mongodb, in order
+to reduce the number of database connections. For example:
+.nf
+ alias_maps = proxy:mongodb:/etc/postfix/mongodb\-aliases.cf
+.fi
+
+Note: when using proxy:mongodb:/\fIfile\fR, the file must
+be readable by the unprivileged postfix user (specified
+with the Postfix mail_owner configuration parameter).
+.SH "MONGODB PARAMETERS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBuri\fR"
+The URI of mongo server/cluster that Postfix will try to
+connect to and query from. Please see
+.nf
+https://www.mongodb.com/docs/manual/reference/connection\-string/
+.fi
+
+Example:
+.nf
+ uri = mongodb+srv://user:pass@loclhost:27017/mail
+.fi
+.IP "\fBdbname\fR"
+Name of the database to read the information from.
+Example:
+.nf
+ dbname = mail
+.fi
+.IP "\fBcollection\fR"
+Name of the collection (table) to read the information from.
+Example:
+.nf
+ collection = mailbox
+.fi
+.IP "\fBquery_filter\fR"
+The MongoDB query template used to search the database,
+where \fB%s\fR is a substitute for the email address that
+Postfix is trying to resolve. Please see:
+.nf
+https://www.mongodb.com/docs/manual/tutorial/query\-documents/
+.fi
+
+Example:
+.nf
+ query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1}
+.fi
+
+This parameter supports the following '%' expansions:
+.RS
+.IP "\fB%%\fR"
+This is replaced by a literal '%' character.
+.IP "\fB%s\fR"
+This is replaced by the input key. The %s must appear in
+quotes, because all Postfix queries are strings containing
+(parts from) a domain or email address. Postfix makes no
+numerical queries.
+.IP "\fB%u\fR"
+When the input key is an address of the form user@domain,
+\fB%u\fR is replaced by the local part of the address.
+Otherwise, \fB%u\fR is replaced by the entire search string.
+.IP "\fB%d\fR"
+When the input key is an address of the form user@domain,
+\fB%d\fR is replaced by the domain part of the address.
+.IP "\fB%[1\-9]\fR"
+The patterns %1, %2, ... %9 are replaced by the corresponding
+most significant component of the input key's domain. If
+the input key is \fIuser@mail.example.com\fR, then %1 is
+\fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR.
+.RE
+.IP
+In the above substitutions, characters will be quoted as
+required by RFC 4627. For example, each double quote or
+backslash character will be escaped with a backslash
+characacter.
+.IP "\fBprojection\fR"
+Advanced MongoDB query projections. Please see:
+.nf
+https://www.mongodb.com/docs/manual/tutorial/project\-fields\-from\-query\-results/
+.fi
+
+.RS
+.IP \(bu
+If \fBprojection\fR is non\-empty, then \fBresult_attribute\fR
+must be empty.
+.IP \(bu
+This implementation can extract information only from result
+fields that have type \fBstring\fR (UTF8), \fBinteger\fR
+(int32, int64) and \fBarray\fR. Other result fields will
+be ignored with a warning. Please see:
+.nf
+https://mongoc.org/libbson/current/bson_type_t.html
+.fi
+.IP \(bu
+As with \fBresult_attribute\fR, the top\-level _id field
+(type OID) is automatically removed from projection results.
+.RE
+.IP "\fBresult_attribute\fR"
+Comma or whitespace separated list with the names of fields
+to be returned in a lookup result.
+
+.RS
+.IP \(bu
+If \fBresult_attribute\fR is non\-empty, then \fBprojection\fR
+must be empty.
+.IP \(bu
+As with \fBprojection\fR, the top\-level _id field (type
+OID) is automatically removed from lookup results.
+.RE
+.IP "\fBresult_format (default: \fB%s\fR)\fR"
+Format template applied to the result from \fBprojection\fR
+or \fBresult_attribute\fR. Most commonly used to append (or
+prepend) text to the result. This parameter supports the
+following '%' expansions:
+.RS
+.IP "\fB%%\fR"
+This is replaced by a literal '%' character.
+.IP "\fB%s\fR"
+This is replaced by the value of the result attribute. When
+result is empty it is skipped.
+.IP "\fB%u\fR
+When the result attribute value is an address of the form
+user@domain, \fB%u\fR is replaced by the local part of the
+address. When the result has an empty localpart it is
+skipped.
+.IP "\fB%d\fR"
+When a result attribute value is an address of the form
+user@domain, \fB%d\fR is replaced by the domain part of the
+attribute value. When the result is unqualified it is
+skipped.
+.IP "\fB%[SUD1\-9]\fR"
+The upper\-case and decimal digit expansions interpolate the
+parts of the input key rather than the result. Their behavior
+is identical to that described with \fBquery_filter\fR, and
+in fact because the input key is known in advance, lookups
+whose key does not contain all the information specified
+in the result template are suppressed and return no results.
+.RE
+.IP
+For example, using "result_format = smtp:[%s]" allows one
+to use a mailHost attribute as the basis of a transport(5)
+table. After applying the result format, multiple values
+are concatenated as comma separated strings. The expansion_limit
+parameter explained below allows one to restrict the number
+of values in the result, which is especially useful for
+maps that should return a single value.
+
+The default value \fB%s\fR specifies that each
+attribute value should be used as is.
+
+NOTE: DO NOT put quotes around the result format! The result
+is not a JSON string.
+.IP "\fBdomain (default: no domain list)\fR"
+This is a list of domain names, paths to files, or "type:table"
+databases. When specified, only fully qualified search keys
+with a *non\-empty* localpart and a matching domain are
+eligible for lookup: 'user' lookups, bare domain lookups
+and "@domain" lookups are not performed. This can significantly
+reduce the query load on the backend database. Example:
+.nf
+ domain = postfix.org, hash:/etc/postfix/searchdomains
+.fi
+.IP "\fBexpansion_limit (default: 0)\fR"
+A limit on the total number of result elements returned (as
+a comma separated list) by a lookup against the map. A
+setting of zero disables the limit. Lookups fail with a
+temporary error if the limit is exceeded. Setting the limit
+to 1 ensures that lookups do not return multiple values.
+.SH "OBSOLETE MAIN.CF PARAMETERS"
+.na
+.nf
+.ad
+.fi
+MongoDB parameters can also be defined in main.cf. Specify
+as MongoDB source a name that doesn't begin with a slash
+or a dot. The MongoDB parameters will then be accessible
+as the name you've given the source in its definition, an
+underscore, and the name of the parameter. For example, if
+a map is specified as "mongodb:\fImongodb_source\fR", the
+"uri" parameter would be defined in main.cf as
+"\fImongodb_source\fR_uri".
+
+Note: with this form, passwords are written in main.cf,
+which is normally world\-readable, and '$' in a mongodb
+parameter setting needs to be written as '$$'.
+.SH "SEE ALSO"
+.na
+.nf
+postmap(1), Postfix lookup table maintenance
+postconf(5), configuration parameters
+.SH "README FILES"
+.na
+.nf
+.ad
+.fi
+Use "\fBpostconf readme_directory\fR" or "\fBpostconf
+html_directory\fR" to locate this information.
+.na
+.nf
+DATABASE_README, Postfix lookup table overview
+MONGODB_README, Postfix MONGODB client guide
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH HISTORY
+.ad
+.fi
+MongoDB support was introduced with Postfix version 3.9.
+.SH "AUTHOR(S)"
+.na
+.nf
+Hamid Maadani (hamid@dexo.tech)
+Dextrous Technologies, LLC
+
+Edited by:
+Wietse Venema
+porcupine.org
+
+Based on prior work by:
+Stephan Ferraro
+Aionda GmbH
diff --git a/man/man5/mysql_table.5 b/man/man5/mysql_table.5
index 2b01aca..aebb949 100644
--- a/man/man5/mysql_table.5
+++ b/man/man5/mysql_table.5
@@ -89,6 +89,24 @@ The database name on the servers. Example:
.nf
dbname = customer_database
.fi
+.IP "\fBcharset (default: utf8mb4)\fR"
+The default MySQL client character set; this also implies
+the collation order.
+
+This parameter is available with Postfix 3.9 and later.
+With earlier Postfix versions, the default was chosen by
+the MySQL implementation (\fButf8mb4\fR as of MySQL 8.0,
+\fBlatin1\fR historically).
+.IP "\fBidle_interval (default: 60)\fR"
+The number of seconds after which an idle database connection
+will be closed.
+
+This feature is available in Postfix 3.9 and later.
+.IP "\fBretry_interval (default: 60)\fR"
+The number of seconds that a database connection will be
+skipped after an error.
+
+This feature is available in Postfix 3.9 and later.
.IP "\fBquery\fR"
The SQL query template used to search the database, where \fB%s\fR
is a substitute for the address Postfix is trying to resolve,
diff --git a/man/man5/pcre_table.5 b/man/man5/pcre_table.5
index a9fd7b6..b5adb94 100644
--- a/man/man5/pcre_table.5
+++ b/man/man5/pcre_table.5
@@ -206,9 +206,14 @@ in\-memory file:
Postfix parses the result as if it is a file in /etc/postfix.
-Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
-Postfix from trying to do \fI$name\fR expansion as it
-evaluates a parameter value.
+Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
+to keep Postfix from trying to do \fI$name\fR expansion as
+it evaluates a parameter value.
+
+Note: when using \fI$name\fR inside an inlined pattern, use
+\eQ\fI$name\fR\eE to disable metacharacters such as '.' in
+the \fI$name\fR expansion. Otherwise, the pattern may have
+unexpected matches.
.SH "EXAMPLE SMTPD ACCESS MAP"
.na
.nf
diff --git a/man/man5/pgsql_table.5 b/man/man5/pgsql_table.5
index 00a2da3..869a635 100644
--- a/man/man5/pgsql_table.5
+++ b/man/man5/pgsql_table.5
@@ -90,10 +90,21 @@ is:
.nf
encoding = UTF8
.fi
+
Historically, the database client was hard coded to use
LATIN1 in an attempt to disable multibyte character support.
This feature is available in Postfix 3.8 and later.
+.IP "\fBidle_interval (default: 60)\fR"
+The number of seconds after which an idle database connection
+will be closed.
+
+This feature is available in Postfix 3.9 and later.
+.IP "\fBretry_interval (default: 60)\fR"
+The number of seconds that a database connection will be
+skipped after an error.
+
+This feature is available in Postfix 3.9 and later.
.IP "\fBquery\fR"
The SQL query template used to search the database, where \fB%s\fR
is a substitute for the address Postfix is trying to resolve,
diff --git a/man/man5/postconf.5 b/man/man5/postconf.5
index 196a700..cf96e48 100644
--- a/man/man5/postconf.5
+++ b/man/man5/postconf.5
@@ -358,8 +358,13 @@ alias_database = hash:/etc/mail/aliases
.ad
.ft R
.SH alias_maps (default: see "postconf \-d" output)
-The alias databases that are used for \fBlocal\fR(8) delivery. See
-\fBaliases\fR(5) for syntax details.
+Optional lookup tables with aliases that apply only to \fBlocal\fR(8)
+recipients; this is unlike virtual_alias_maps that apply to all
+recipients: \fBlocal\fR(8), virtual, and remote.
+The table format and lookups are documented in \fBaliases\fR(5). For an
+overview of Postfix address manipulations see the ADDRESS_REWRITING_README
+document.
+.PP
Specify zero or more "type:name" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
until a match is found.
@@ -1773,16 +1778,25 @@ name of the message delivery transport.
This feature is available in Postfix 2.4 and later.
.SH default_transport (default: smtp)
The default mail delivery transport and next\-hop destination for
-destinations that do not match $mydestination, $inet_interfaces,
+the default domain class: recipient domains that do not match
+$mydestination, $inet_interfaces,
$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
-or $relay_domains. This information can be overruled with the
-sender_dependent_default_transport_maps parameter and with the
-\fBtransport\fR(5) table.
+or $relay_domains. This information will not be used when
+sender_dependent_default_transport_maps returns a result, and may
+be overridden with the \fBtransport\fR(5) table.
.PP
-In order of decreasing precedence, the nexthop destination is taken
-from $sender_dependent_default_transport_maps, $default_transport,
-$sender_dependent_relayhost_maps, $relayhost, or from the recipient
+For recipient domains in the default domain class:
+.IP \(bu
+In order of decreasing precedence, the delivery transport
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport.
+.IP \(bu
+In order of decreasing precedence, the nexthop destination
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
domain.
+.br
.PP
Specify a string of the form \fItransport:nexthop\fR, where \fItransport\fR
is the name of a mail delivery transport defined in master.cf.
@@ -2367,6 +2381,19 @@ logfiles with the queue file names of mail that is queued for those
destinations.
.PP
This feature is available in Postfix 2.0 and later.
+.SH force_mime_input_conversion (default: no)
+Convert body content that claims to be 8\-bit into quoted\-printable,
+before header_checks, body_checks, Milters, and before after\-queue
+content filters. This feature does not affect messages that are
+sent into smtpd_proxy_filter.
+.PP
+The typical use case is an MTA that applies this conversion
+before signing outbound messages, so that the signatures will remain
+valid when a message is later delivered to an MTA that does not
+announce 8BITMIME support, or when a message line exceeds the SMTP
+length limit.
+.PP
+This feature is available in Postfix >= 3.9.
.SH fork_attempts (default: 5)
The maximal number of attempts to fork() a child process.
.SH fork_delay (default: 1s)
@@ -2416,7 +2443,7 @@ The entire recipient localpart.
The address extension delimiter that was found in the recipient
address (Postfix 2.11 and later), or the 'first' delimiter specified
with the system\-wide recipient address extension delimiter (Postfix
-3.5.22, 3.5.12, 3.7.8, 3.8.3 and later). Historically, this was
+3.5.22, 3.6.12, 3.7.8, 3.8.3 and later). Historically, this was
always the system\-wide recipient
address extension delimiter (Postfix 2.10 and earlier).
.br
@@ -2628,31 +2655,55 @@ number of messages delivered per second.
.PP
Specify 0 to disable the feature. Valid delays are 0..10.
.SH inet_interfaces (default: all)
-The local network interface addresses that this mail system receives
-mail on. Specify "all" to receive mail on all network
-interfaces (default), and "loopback\-only" to receive mail
-on loopback network interfaces only (Postfix version 2.2 and later). The
-parameter also controls delivery of mail to user@[ip.address].
+The local network interface addresses that this mail system
+receives mail on. Specify "all" to receive mail on all network
+interfaces (default), "loopback\-only" to receive mail on loopback
+network interfaces only (Postfix version 2.2 and later), or zero
+or more IPv4 or IPv6 addresses (IPv6 is supported in Postfix version
+2.2 and later). The parameter also controls whether Postfix will
+accept mail for user@[ip.address], and prevents Postfix
+from delivering mail to a host that has equal or larger MX preference.
+Specify an empty value if Postfix does not receive mail over the
+network, or if all network listeners have an explicit IP address
+in master.cf.
.PP
Note 1: you need to stop and start Postfix when this parameter changes.
.PP
Note 2: address information may be enclosed inside [],
but this form is not required here.
.PP
-When inet_interfaces specifies just one IPv4 and/or IPv6 address
-that is not a loopback address, the Postfix SMTP client will use
-this address as the IP source address for outbound mail. Support
-for IPv6 is available in Postfix version 2.2 and later.
+When smtp_bind_address and/or smtp_bind_address6 are not
+specified, the inet_interfaces setting may constrain the source IP
+address for an outbound SMTP or LMTP connection as described below.
+.PP
+The following text is specific to SMTP and IPv4. The same
+reasoning applies to the IPv6 protocol, and to the Postfix LMTP
+client. To disable IPv4 or IPv6 support in the Postfix SMTP and
+LMTP client, use inet_protocols.
+.IP \(bu
+When inet_interfaces specifies one IPv4 address, and that
+is not a loopback address, the Postfix SMTP client uses that as the
+source address for outbound IPv4 connections.
+.IP \(bu
+Otherwise, the Postfix SMTP client does not constrain the
+source IPv4 address, and connects using a system\-chosen source IPv4
+address. This includes the cases where inet_interfaces is empty,
+where it specifies \fBall\fR, or where it contains no IPv4 address,
+one IPv4 address that is a loopback address, or multiple IPv4
+addresses.
+.br
.PP
-On a multi\-homed firewall with separate Postfix instances listening on the
-"inside" and "outside" interfaces, this can prevent each instance from
-being able to reach remote SMTP servers on the "other side" of the
-firewall. Setting
-smtp_bind_address to 0.0.0.0 avoids the potential problem for
-IPv4, and setting smtp_bind_address6 to :: solves the problem
-for IPv6.
+A Postfix SMTP client may fail to reach some remote SMTP servers
+when the client source IP address is constrained explicitly with
+smtp_bind_address or smtp_bind_address6, or implicitly with
+inet_interfaces. This can happen when Postfix runs on a multi\-homed
+system such as a firewall, the Postfix SMTP source client IP address
+is constrained to one specific network interface, and the remote
+SMTP server must be reached through a different interface. Setting
+smtp_bind_address to 0.0.0.0 avoids the potential problem for IPv4,
+and setting smtp_bind_address6 to :: solves the problem for IPv6.
.PP
-A better solution for multi\-homed firewalls is to leave inet_interfaces
+A better solution for multi\-homed systems is to leave inet_interfaces
at the default value and instead use explicit IP addresses in
the master.cf SMTP server definitions. This preserves the Postfix
SMTP client's
@@ -2679,7 +2730,7 @@ inet_interfaces = 192.168.1.2, 127.0.0.1
.fi
.ad
.ft R
-.SH inet_protocols (default: see 'postconf \-d output')
+.SH inet_protocols (default: see 'postconf \-d' output)
The Internet protocols Postfix will attempt to use when making
or accepting connections. Specify one or more of "ipv4"
or "ipv6", separated by whitespace or commas. The form
@@ -3093,6 +3144,9 @@ This feature is available in Postfix 2.11 and later.
The LMTP\-specific version of the smtp_enforce_tls configuration
parameter. See there for details.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+lmtp_tls_security_level instead.
+.PP
This feature is available in Postfix 2.3 and later.
.SH lmtp_fallback_relay (default: empty)
Optional list of relay hosts for LMTP destinations that can't be
@@ -3289,6 +3343,9 @@ Optional Postfix LMTP client lookup tables with one username:password entry
per host or domain. If a remote host or domain has no username:password
entry, then the Postfix LMTP client will not attempt to authenticate
to the remote host.
+.SH lmtp_sasl_password_result_delimiter (default: :)
+The LMTP\-specific version of the smtp_sasl_password_result_delimiter
+configuration parameter. See there for details.
.SH lmtp_sasl_path (default: empty)
Implementation\-specific information that is passed through to
the SASL plug\-in implementation that is selected with
@@ -3437,6 +3494,11 @@ parameter. See there for details.
.PP
This feature is available in Postfix 2.6 and later, when Postfix is
compiled and linked with OpenSSL 1.0.0 or later.
+.SH lmtp_tls_enable_rpk (default: yes)
+The LMTP\-specific version of the smtp_tls_enable_rpk
+configuration parameter. See there for details.
+.PP
+This feature is available in Postfix 3.9 and later.
.SH lmtp_tls_enforce_peername (default: yes)
The LMTP\-specific version of the smtp_tls_enforce_peername
configuration parameter. See there for details.
@@ -3482,7 +3544,7 @@ The LMTP\-specific version of the smtp_tls_mandatory_exclude_ciphers
configuration parameter. See there for details.
.PP
This feature is available in Postfix 2.3 and later.
-.SH lmtp_tls_mandatory_protocols (default: see postconf \-d output)
+.SH lmtp_tls_mandatory_protocols (default: see 'postconf \-d' output)
The LMTP\-specific version of the smtp_tls_mandatory_protocols
configuration parameter. See there for details.
.PP
@@ -3496,13 +3558,16 @@ This feature is available in Postfix 2.3 and later.
The LMTP\-specific version of the smtp_tls_per_site configuration
parameter. See there for details.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+lmtp_tls_policy_maps instead.
+.PP
This feature is available in Postfix 2.3 and later.
.SH lmtp_tls_policy_maps (default: empty)
The LMTP\-specific version of the smtp_tls_policy_maps
configuration parameter. See there for details.
.PP
This feature is available in Postfix 2.3 and later.
-.SH lmtp_tls_protocols (default: see postconf \-d output)
+.SH lmtp_tls_protocols (default: see 'postconf \-d' output)
The LMTP\-specific version of the smtp_tls_protocols configuration
parameter. See there for details.
.PP
@@ -3556,6 +3621,9 @@ This feature is available in Postfix 3.0 and later.
The LMTP\-specific version of the smtp_use_tls configuration
parameter. See there for details.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+lmtp_tls_security_level instead.
+.PP
This feature is available in Postfix 2.3 and later.
.SH lmtp_xforward_timeout (default: 300s)
The Postfix LMTP client time limit for sending the XFORWARD command,
@@ -3803,7 +3871,8 @@ whitespace or comma. Tables will be searched in the specified order
until a match is found.
.PP
If this parameter is non\-empty (the default), then the Postfix SMTP
-server will reject mail for unknown local users.
+server will reject mail for unknown local users. Other Postfix
+interfaces may still accept an "unknown" recipient.
.PP
To turn off local recipient checking in the Postfix SMTP server,
specify "local_recipient_maps =" (i.e. empty).
@@ -3989,6 +4058,10 @@ Remote client protocol. Available in Postfix version 2.2 and later.
.IP "\fBDOMAIN\fR"
The domain part of the recipient address.
.br
+.IP "\fBENVID\fR"
+The optional RFC 3461 envelope ID. Available in Postfix version
+3.9 and later
+.br
.IP "\fBEXTENSION\fR"
The optional address extension.
.br
@@ -4141,6 +4214,15 @@ logrotate". The command is run with the rotated logfile name as its
first argument.
.PP
This feature is available in Postfix 3.4 and later.
+.SH maillog_file_permissions (default: 0600)
+The file access permissions that will be set when the file
+$maillog_file is created for the first time, or when the file is
+created after an existing file is rotated. Specify one of: \fB0600\fR
+(only super\-user read/write access), \fB0640\fR (adds 'group' read
+access), or \fB0644\fR (also adds 'other' read access). The leading
+\&'0' is optional.
+.PP
+This feature is available in Postfix 3.9 and later.
.SH maillog_file_prefixes (default: /var, /dev/stdout)
A list of allowed prefixes for a maillog_file value. This is a
safety feature to contain the damage from a single configuration
@@ -5249,9 +5331,9 @@ it passes the test, before it can talk to a real Postfix SMTP server.
.PP
This feature is available in Postfix 2.8.
.SH postscreen_bare_newline_ttl (default: 30d)
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful "bare newline" SMTP protocol test. During this
-time, the client IP address is excluded from this test. The default
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a "bare newline" SMTP protocol test, before it
+address is required to pass that test again. The default
is long because a remote SMTP client must disconnect after it passes
the test,
before it can talk to a real Postfix SMTP server.
@@ -5411,18 +5493,19 @@ defined with the postscreen_dnsbl_sites parameter.
Specify a negative value to enable this feature. When a client
passes the postscreen_dnsbl_allowlist_threshold without having
failed other tests, all pending or disabled tests are flagged as
-completed with a time\-to\-live value equal to postscreen_dnsbl_ttl.
-When a test was already completed, its time\-to\-live value is updated
-if it was less than postscreen_dnsbl_ttl.
+completed with an expiration time based on the DNS reply TTL.
+When a test was already completed, its expiration time is updated
+if it was less than the value based on the DNS reply TTL. See
+also postscreen_dnsbl_max_ttl and postscreen_dnsbl_min_ttl.
.PP
This feature is available in Postfix 3.6 and later.
.PP
Available as postscreen_dnsbl_whitelist_threshold in Postfix 2.11
\- 3.5.
.SH postscreen_dnsbl_max_ttl (default: ${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)
-The maximum amount of time that \fBpostscreen\fR(8) will use the
-result from a successful DNS\-based reputation test before a
-client IP address is required to pass that test again. If the DNS
+The maximum amount of time that \fBpostscreen\fR(8) remembers that a
+client IP address passed a DNS\-based reputation test, before it is
+required to pass that test again. If the DNS
reply specifies a shorter TTL value, that value will be used unless
it would be smaller than postscreen_dnsbl_min_ttl.
.PP
@@ -5434,9 +5517,9 @@ The default time unit is h (hours).
This feature is available in Postfix 3.1. The default setting
is backwards\-compatible with older Postfix versions.
.SH postscreen_dnsbl_min_ttl (default: 60s)
-The minimum amount of time that \fBpostscreen\fR(8) will use the
-result from a successful DNS\-based reputation test before a
-client IP address is required to pass that test again. If the DNS
+The minimum amount of time that \fBpostscreen\fR(8) remembers that a
+client IP address passed a DNS\-based reputation test, before it
+is required to pass that test again. If the DNS
reply specifies a larger TTL value, that value will be used unless
it would be larger than postscreen_dnsbl_max_ttl.
.PP
@@ -5559,9 +5642,9 @@ The default time unit is s (seconds).
.PP
This feature is available in Postfix 3.0.
.SH postscreen_dnsbl_ttl (default: 1h)
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful DNS\-based reputation test before a client
-IP address is required to pass that test again.
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a DNS\-based reputation test, before it is required
+to pass that test again.
.PP
Specify a non\-zero time value (an integral value plus an optional
one\-letter suffix that specifies the time unit). Time units: s
@@ -5628,9 +5711,9 @@ value to disable this feature.
.PP
This feature is available in Postfix 2.8.
.SH postscreen_greet_ttl (default: 1d)
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful PREGREET test. During this time, the client IP address
-is excluded from this test. The default is relatively short, because
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a PREGREET test, before it is required to pass
+that test again. The default is relatively short, because
a good client can immediately talk to a real Postfix SMTP server.
.PP
Specify a non\-zero time value (an integral value plus an optional
@@ -5688,9 +5771,9 @@ test, before it can talk to a real Postfix SMTP server.
.PP
This feature is available in Postfix 2.8.
.SH postscreen_non_smtp_command_ttl (default: 30d)
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful "non_smtp_command" SMTP protocol test. During this
-time, the client IP address is excluded from this test. The default
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a "non_smtp_command" SMTP protocol test, before
+it is required to pass that test again. The default
is long because a client must disconnect after it passes the test,
before it can talk to a real Postfix SMTP server.
.PP
@@ -5732,9 +5815,9 @@ server.
.PP
This feature is available in Postfix 2.8.
.SH postscreen_pipelining_ttl (default: 30d)
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful "pipelining" SMTP protocol test. During this time, the
-client IP address is excluded from this test. The default is
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a "pipelining" SMTP protocol test, before it is
+required to pass that test again. The default is
long because a good client must disconnect after it passes the test,
before it can talk to a real Postfix SMTP server.
.PP
@@ -6408,11 +6491,19 @@ relay_recipient_maps = hash:/etc/postfix/relay_recipients
This feature is available in Postfix 2.0 and later.
.SH relay_transport (default: relay)
The default mail delivery transport and next\-hop destination for
-remote delivery to domains listed with $relay_domains. In order of
-decreasing precedence, the nexthop destination is taken from
-$relay_transport, $sender_dependent_relayhost_maps, $relayhost, or
-from the recipient domain. This information can be overruled with
-the \fBtransport\fR(5) table.
+the relay domain address class: recipient domains that match
+$relay_domains.
+.PP
+For recipient domains in the relay domain address class:
+.IP \(bu
+In order of decreasing precedence, the message delivery
+transport is taken from 1) $transport_maps, 2) $relay_transport.
+.IP \(bu
+In order of decreasing precedence, the nexthop destination
+is taken from 1) $transport_maps, 2) $relay_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain.
+.br
.PP
Specify a string of the form \fItransport:nexthop\fR, where \fItransport\fR
is the name of a mail delivery transport defined in master.cf.
@@ -6424,21 +6515,37 @@ file.
.PP
This feature is available in Postfix 2.0 and later.
.SH relayhost (default: empty)
-The next\-hop destination(s) for non\-local mail; overrides non\-local
-domains in recipient addresses. This information is overruled with
-relay_transport, sender_dependent_default_transport_maps,
-default_transport, sender_dependent_relayhost_maps
-and with the \fBtransport\fR(5) table.
+The next\-hop destination(s) for non\-local mail; takes precedence
+over non\-local domains in recipient addresses. This information
+will not be used when the sender matches $sender_dependent_relayhost_maps.
+.PP
+In order of decreasing precedence:
+.IP \(bu
+For recipient domains in the relay domain address class
+(domains matching $relay_domains), the nexthop destination is taken
+from 1) $transport_maps, 2) $relay_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain.
+.IP \(bu
+For recipient domains in the default domain address class
+(domains that do not match $mydestination, $inet_interfaces,
+$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
+or $relay_domains), the nexthop destination is taken from 1)
+$transport_maps, 2) $sender_dependent_default_transport_maps or
+$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost
+or the recipient domain.
+.br
.PP
On an intranet, specify the organizational domain name. If your
internal DNS uses no MX records, specify the name of the intranet
gateway host instead.
.PP
-In the case of SMTP or LMTP delivery, specify one or more destinations
-in the form of a domain name, hostname, hostname:port, [hostname]:port,
-[hostaddress] or [hostaddress]:port, separated by comma or whitespace.
-The form [hostname] turns off MX lookups. Multiple destinations are
-supported in Postfix 3.5 and later.
+In the case of SMTP delivery, specify one or more destinations in
+the form of a domain name, hostname, hostname:service, [hostname]:service,
+[hostaddress] or [hostaddress]:service, separated by comma or whitespace.
+The form [hostname] turns off MX or SRV lookups. Multiple destinations
+are supported in Postfix 3.5 and later. Each destination is tried
+in the specified order.
.PP
If you're connected via UUCP, see the UUCP_README file for useful
information.
@@ -6719,9 +6826,21 @@ address and @domain. A lookup result of DUNNO terminates the search
without overriding the global default_transport parameter setting.
This information is overruled with the \fBtransport\fR(5) table.
.PP
-Specify zero or more "type:name" lookup tables, separated by
-whitespace or comma. Tables will be searched in the specified order
-until a match is found.
+This setting affects only the default domain address class
+(recipient domains that do not match $mydestination, $inet_interfaces,
+$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
+or $relay_domains):
+.IP \(bu
+In order of decreasing precedence, the delivery transport
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport.
+.IP \(bu
+In order of decreasing precedence, the nexthop destination
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain.
+.br
.PP
Note: this overrides default_transport, not transport_maps, and
therefore the expected syntax is that of default_transport, not the
@@ -6729,6 +6848,10 @@ syntax of transport_maps. Specifically, this does not support the
transport_maps syntax for null transport, null nexthop, or null
email addresses.
.PP
+Specify zero or more "type:name" lookup tables, separated by
+whitespace or comma. Tables will be searched in the specified order
+until a match is found.
+.PP
For safety reasons, this feature does not allow $number
substitutions in regular expression maps.
.PP
@@ -6738,9 +6861,24 @@ A sender\-dependent override for the global relayhost parameter
setting. The tables are searched by the envelope sender address and
@domain. A lookup result of DUNNO terminates the search without
overriding the global relayhost parameter setting (Postfix 2.6 and
-later). This information is overruled with relay_transport,
-sender_dependent_default_transport_maps, default_transport and with
-the \fBtransport\fR(5) table.
+later).
+.PP
+In order of decreasing precedence:
+.IP \(bu
+For recipient domains in the relay domain address class
+(domains matching $relay_domains), the nexthop destination is taken
+from 1) $transport_maps, 2) $relay_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain.
+.IP \(bu
+For recipient domains in the default domain address class
+(domains that do not match mydestination, $inet_interfaces,
+$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
+$relay_domains), the nexthop destination is taken from 1)
+$transport_maps, 2) $sender_dependent_default_transport_maps or
+$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost
+or the recipient domain.
+.br
.PP
Specify zero or more "type:name" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
@@ -6871,12 +7009,45 @@ Notes for mail delivery between sites that have both IPv4 and
IPv6 connectivity:
.IP \(bu
The setting "smtp_address_preference = ipv6" is unsafe.
-It can fail to deliver mail when there is an outage that affects
-IPv6, while the destination is still reachable over IPv4.
+All deliveries will suffer delays during an IPv6 outage, even
+while the destination is still reachable over IPv4. Mail may be
+stuck in the queue with Postfix versions < 3.3 that do not
+implement "smtp_balance_inet_protocols". For similar reasons, the
+setting "smtp_address_preference = ipv4" is also unsafe.
.IP \(bu
The setting "smtp_address_preference = any" is safe. With
-this, mail will eventually be delivered even if there is an outage
+this, and "smtp_balance_inet_protocols = yes" (the default), only
+half of deliveries will suffer delays if there is an outage
that affects IPv6 or IPv4, as long as it does not affect both.
+.IP \(bu
+The setting "smtp_address_preference = ipv4" is not a
+solution for remote servers that flag email received over IPv6 as
+more 'spammy' (the client IPv6 address has a bad or missing PTR or
+AAAA record, bad network neighbors, etc.). Instead, configure Postfix
+to receive mail over both IPv4 and IPv6, and to deliver mail over
+only IPv4.
+.sp
+.in +4
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ inet_protocols = all
+.fi
+.ad
+.ft R
+.in -4
+.sp
+.in +4
+.nf
+.na
+.ft C
+/etc/postfix/master.cf
+ smtp ...other fields... smtp \-o inet_protocols=ipv4
+.fi
+.ad
+.ft R
+.in -4
.br
.PP
This feature is available in Postfix 2.8 and later.
@@ -7919,12 +8090,21 @@ lookup is done only when sender\-dependent authentication is enabled.
If no username:password entry is found, then the Postfix SMTP client
will not attempt to authenticate to the remote host.
.PP
+Use smtp_sasl_password_result_delimiter to specify an
+alternative separator between username and password.
+.PP
The Postfix SMTP client opens the lookup table before going to
chroot jail, so you can leave the password file in /etc/postfix.
.PP
Specify zero or more "type:name" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
until a match is found.
+.SH smtp_sasl_password_result_delimiter (default: :)
+The delimiter between username and password in sasl_passwd_maps lookup
+results. Specify one non\-whitespace character that does not appear in
+the username.
+.PP
+This feature is available in Postfix >= 3.9.
.SH smtp_sasl_path (default: empty)
Implementation\-specific information that the Postfix SMTP client
passes through to
@@ -8507,6 +8687,89 @@ to anyone else.
.PP
This feature is available in Postfix 2.6 and later, when Postfix is
compiled and linked with OpenSSL 1.0.0 or later.
+.SH smtp_tls_enable_rpk (default: no)
+Request that remote SMTP servers send an RFC7250 raw public key
+instead of an X.509 certificate. This feature and the enable_rpk
+policy attribute are ignored when there is no raw public key support
+in the local TLS implementation.
+.IP \(bu
+At the "may", "encrypt" and "fingerprint" security levels,
+with parameter setting "smtp_tls_enable_rpk = yes" or with "enable_rpk
+= yes" in a policy entry, the Postfix SMTP client will indicate in
+the TLS handshake that it prefers to receive a raw server public
+key, but it will still accept a server public key certificate.
+.IP \(bu
+At the "fingerprint" security level, with parameter setting
+"smtp_tls_enable_rpk = yes" or with "enable_rpk = yes" in a policy
+entry, server authentication based on certificate fingerprints
+becomes more fragile. Even if the server private key and certificate
+remain unchanged, the remote SMTP server will fail fingerprint
+authentication (won't match the configured list of fingerprints)
+when it starts sending a raw public key instead of a certificate,
+after its TLS implementation is updated with raw public key support.
+Therefore, \fBDO NOT\fR enable raw public keys to remote destinations
+authenticated by server \fBcertificate\fR fingerprints. You should
+enable raw public keys only for servers matched via their public
+key fingerprint.
+.IP \(bu
+At the "verify" and "secure" security levels, the Postfix
+SMTP client always ignores the parameter setting smtp_tls_enable_rpk
+or the enable_rpk policy attribute.
+.IP \(bu
+At the opportunistic "dane" security level, the Postfix
+SMTP client ignores the parameter setting smtp_tls_enable_rpk or
+the enable_rpk policy attribute (but it will respect them when it
+falls back to the "may" or "encrypt" level). When all valid TLSA
+records specify only server public keys (no certificates) and the
+local TLS implementation supports raw public keys, the client will
+indicate in the TLS handshake that it prefers to receive a raw
+public key, but it will still accept a public key certificate.
+.IP \(bu
+At the mandatory "dane\-only" security level, the Postfix
+SMTP client always ignores the parameter setting smtp_tls_enable_rpk
+or the enable_rpk policy attribute. When all valid TLSA records
+specify only server public keys (no certificates) and the local TLS
+implementation supports raw public keys, the client will indicate
+in the TLS handshake that it prefers to receive a raw public key,
+but it will still accept a public key certificate.
+.br
+.PP
+The Postfix SMTP client is always willing to send raw public keys
+to servers that solicit them when a client certificate is configured
+and the local TLS implementation supports raw public keys.
+.PP
+Sample commands to compute certificate and public key SHA256 digests:
+.PP
+.nf
+.na
+.ft C
+# SHA256 digest of the first certificate in "cert.pem"
+$ openssl x509 \-in cert.pem \-outform DER | openssl dgst \-sha256 \-c
+.fi
+.ad
+.ft R
+.PP
+.nf
+.na
+.ft C
+# SHA256 digest of the SPKI of the first certificate in "cert.pem"
+$ openssl x509 \-in cert.pem \-pubkey \-noout |
+ openssl pkey \-pubin \-outform DER | openssl dgst \-sha256 \-c
+.fi
+.ad
+.ft R
+.PP
+.nf
+.na
+.ft C
+# SHA256 digest of the SPKI of the first private key in "pkey.pem"
+$ openssl pkey \-in pkey.pem \-pubout \-outform DER |
+ openssl dgst \-sha256 \-c
+.fi
+.ad
+.ft R
+.PP
+This feature is available in Postfix 3.9 and later.
.SH smtp_tls_enforce_peername (default: yes)
With mandatory TLS encryption, require that the remote SMTP
server hostname matches the information in the remote SMTP server
@@ -8762,7 +9025,9 @@ With Postfix 2.8 and earlier, log the summary message and unconditionally
log trust\-chain verification errors.
.br
.IP ""
-2 Also log levels during TLS negotiation.
+2 Also enable verbose logging in the Postfix TLS
+library, log session cache operations, and enable OpenSSL logging
+of the progress of the SSL handshake.
.br
.IP ""
3 Also log the hexadecimal and ASCII dump of the
@@ -8997,7 +9262,9 @@ and smtp_tls_enforce_peername settings.
.br
.IP "MAY"
Try to use TLS if the server announces support,
-otherwise use an unencrypted connection. This has less precedence
+otherwise use an unencrypted connection; after a failed TLS handshake
+or TLS session, fall back to plaintext if the message has spent
+minimal_backoff_time in the mail queue. This level has less precedence
than a more specific result (including \fBNONE\fR) from the alternate
host or next\-hop lookup key, and has less precedence than the more
specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername
@@ -9084,28 +9351,35 @@ No TLS. No additional attributes are supported at this level.
Opportunistic TLS. Since sending in the clear is acceptable,
demanding stronger than default TLS security merely reduces
interoperability. The optional "ciphers", "exclude", and "protocols"
-attributes (available for opportunistic TLS with Postfix >= 2.6)
-and "connection_reuse" attribute (Postfix >= 3.4) override the
+attributes (available for opportunistic TLS with Postfix >= 2.6) and
+"connection_reuse" attribute (Postfix >= 3.4) override the
"smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols",
-and
-"smtp_tls_connection_reuse" configuration parameters. In the policy table,
-multiple ciphers, protocols or excluded ciphers must be separated by colons,
-as attribute values may not contain whitespace or commas. When opportunistic
-TLS handshakes fail, Postfix retries the connection with TLS disabled.
-This allows mail delivery to sites with non\-interoperable TLS
-implementations.
+and "smtp_tls_connection_reuse" configuration parameters. In the policy
+table, multiple ciphers, protocols or excluded ciphers must be separated
+by colons, as attribute values may not contain whitespace or commas. At
+this level and higher, the optional "servername" attribute (available
+with Postfix >= 3.4) overrides the global "smtp_tls_servername"
+parameter, enabling per\-destination configuration of the SNI extension
+sent to the remote SMTP server. The optional "enable_rpk" attribute
+(Postfix >= 3.9) overrides the main.cf smtp_tls_enable_rpk parameter.
+When opportunistic TLS handshakes fail, Postfix retries the connection
+with TLS disabled. This allows mail delivery to sites with
+non\-interoperable TLS implementations.
.br
.IP "\fBencrypt\fR"
-Mandatory TLS encryption. At this level
-and higher, the optional "protocols" attribute overrides the main.cf
+Mandatory TLS encryption. Mail is delivered only if the remote SMTP
+server offers STARTTLS and the TLS handshake succeeds. At this level and
+higher, the optional "protocols" attribute overrides the main.cf
smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute
-overrides the main.cf smtp_tls_mandatory_ciphers parameter, the
-optional "exclude" attribute (Postfix >= 2.6) overrides the main.cf
+overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional
+"exclude" attribute (Postfix >= 2.6) overrides the main.cf
smtp_tls_mandatory_exclude_ciphers parameter, and the optional
-"connection_reuse" attribute (Postfix >= 3.4) overrides the
-main.cf smtp_tls_connection_reuse parameter. In the policy table,
-multiple ciphers, protocols or excluded ciphers must be separated by colons,
-as attribute values may not contain whitespace or commas.
+"connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. In the policy table, multiple
+ciphers, protocols or excluded ciphers must be separated by colons, as
+attribute values may not contain whitespace or commas. The optional
+"enable_rpk" attribute (Postfix >= 3.9) overrides the main.cf
+smtp_tls_enable_rpk parameter.
.br
.IP "\fBdane\fR"
Opportunistic DANE TLS. The TLS policy for the destination is
@@ -9144,10 +9418,10 @@ Certificate fingerprint
verification. Available with Postfix 2.5 and later. At this security
level, there are no trusted Certification Authorities. The certificate
trust chain, expiration date, ... are not checked. Instead,
-the optional "match" attribute, or else the main.cf
+the optional policy table "match" attribute, or else the main.cf
\fBsmtp_tls_fingerprint_cert_match\fR parameter, lists the certificate
-fingerprints or the public key fingerprint (Postfix 2.9 and later)
-of the valid server certificate. The digest
+fingerprints or the public key fingerprints (Postfix 2.9 and later)
+of acceptable server certificates. The digest
algorithm used to calculate the fingerprint is selected by the
\fBsmtp_tls_fingerprint_digest\fR parameter. Multiple fingerprints can
be combined with a "|" delimiter in a single match attribute, or multiple
@@ -9158,45 +9432,58 @@ digits. The optional "ciphers", "exclude", and "protocols" attributes
"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
configuration parameters. The optional "connection_reuse" attribute
(Postfix >= 3.4) overrides the main.cf smtp_tls_connection_reuse
-parameter.
+parameter. The optional "enable_rpk" attribute (Postfix >= 3.9)
+overrides the main.cf smtp_tls_enable_rpk parameter.
.br
.IP "\fBverify\fR"
-Mandatory TLS verification. At this security
-level, DNS MX lookups are trusted to be secure enough, and the name
-verified in the server certificate is usually obtained indirectly via
-unauthenticated DNS MX lookups. The optional "match" attribute overrides
-the main.cf smtp_tls_verify_cert_match parameter. In the policy table,
-multiple match patterns and strategies must be separated by colons.
-In practice explicit control over matching is more common with the
-"secure" policy, described below. The optional "ciphers", "exclude",
-and "protocols" attributes (Postfix >= 2.6) override the
-"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
-"smtp_tls_mandatory_protocols" configuration parameters. The optional
-"connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf
-smtp_tls_connection_reuse parameter.
+Mandatory TLS verification. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups are presumed to be
+secure enough, and the name verified in the server certificate is
+potentially obtained via unauthenticated DNS MX lookups. The optional
+"match" attribute overrides the main.cf smtp_tls_verify_cert_match
+parameter. In the policy table, multiple match patterns and strategies
+must be separated by colons. In practice explicit control over matching
+is more common with the "secure" policy, described below. The optional
+"ciphers", "exclude", and "protocols" attributes (Postfix >= 2.6)
+override the "smtp_tls_mandatory_ciphers",
+"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+configuration parameters. With Postfix >= 2.11 the optional "tafile"
+policy table attribute modifies trust chain verification in the same
+manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
+attribute may be specified multiple times to load multiple trust\-anchor
+files. The optional "connection_reuse" attribute (Postfix >= 3.4)
+overrides the main.cf smtp_tls_connection_reuse parameter.
.br
.IP "\fBsecure\fR"
-Secure\-channel TLS. At this security level, DNS
-MX lookups, though potentially used to determine the candidate next\-hop
-gateway IP addresses, are \fBnot\fR trusted to be secure enough for TLS
-peername verification. Instead, the default name verified in the server
-certificate is obtained directly from the next\-hop, or is explicitly
-specified via the optional "match" attribute which overrides the
-main.cf smtp_tls_secure_cert_match parameter. In the policy table,
-multiple match patterns and strategies must be separated by colons.
-The match attribute is most useful when multiple domains are supported by
-a common server: the policy entries for additional domains specify matching
-rules for the primary domain certificate. While transport table overrides
-that route the secondary domains to the primary nexthop also allow secure
-verification, they risk delivery to the wrong destination when domains
-change hands or are re\-assigned to new gateways. With the "match"
-attribute approach, routing is not perturbed, and mail is deferred if
-verification of a new MX host fails. The optional "ciphers", "exclude",
-and "protocols" attributes (Postfix >= 2.6) override the
-"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
-"smtp_tls_mandatory_protocols" configuration parameters. The optional
-"connection_reuse" attribute (Postfix >= 3.4) overrides the main.cf
-smtp_tls_connection_reuse parameter.
+Secure certificate verification. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups, though potentially
+used to determine the candidate next\-hop gateway IP addresses, are
+\fBnot\fR presumed to be secure enough for TLS peername verification.
+Instead, the default name verified in the server certificate is obtained
+directly from the next\-hop, or is explicitly specified via the optional
+"match" attribute which overrides the main.cf smtp_tls_secure_cert_match
+parameter. In the policy table, multiple match patterns and strategies
+must be separated by colons. The match attribute is most useful when
+multiple domains are supported by a common server: the policy entries
+for additional domains specify matching rules for the primary domain
+certificate. While transport table overrides that route the secondary
+domains to the primary nexthop also allow secure verification, they risk
+delivery to the wrong destination when domains change hands or are
+re\-assigned to new gateways. With the "match" attribute approach,
+routing is not perturbed, and mail is deferred if verification of a new
+MX host fails. The optional "ciphers", "exclude", and "protocols"
+attributes (Postfix >= 2.6) override the "smtp_tls_mandatory_ciphers",
+"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+configuration parameters. With Postfix >= 2.11 the "tafile" attribute
+optionally modifies trust chain verification in the same manner as the
+"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be
+specified multiple times to load multiple trust\-anchor files. The
+optional "connection_reuse" attribute (Postfix >= 3.4) overrides the
+main.cf smtp_tls_connection_reuse parameter.
.br
.br
.PP
@@ -9243,7 +9530,7 @@ DNS forgery. Do not use the "hostname" strategy for secure\-channel
configurations in environments where DNS security is not assured.
.PP
This feature is available in Postfix 2.3 and later.
-.SH smtp_tls_protocols (default: see postconf \-d output)
+.SH smtp_tls_protocols (default: see 'postconf \-d' output)
TLS protocols that the Postfix SMTP client will use with
opportunistic TLS encryption. In main.cf the values are separated by
whitespace, commas or colons. In the policy table "protocols" attribute
@@ -9406,7 +9693,9 @@ destinations via smtp_tls_policy_maps.
.br
.IP "\fBmay\fR"
Opportunistic TLS. Use TLS if this is supported by the remote
-SMTP server, otherwise use plaintext. Since
+SMTP server, otherwise use plaintext; after a failed TLS handshake
+or TLS session, fall back to plaintext if the message has spent
+minimal_backoff_time in the mail queue. Since
sending in the clear is acceptable, demanding stronger than default TLS
security merely reduces interoperability.
The "smtp_tls_ciphers" and "smtp_tls_protocols" (Postfix >= 2.6)
@@ -10127,9 +10416,8 @@ pubkey_fingerprint } }
The commas are optional.
.br
.IP "\fBcheck_client_access \fItype:table\fR\fR"
-Search the specified access database for the client hostname,
-parent domains, client IP address, or networks obtained by stripping
-least significant octets. See the \fBaccess\fR(5) manual page for details.
+Search the specified access database for the client hostname
+or IP address. See the \fBaccess\fR(5) manual page for details.
.br
.IP "\fBcheck_client_a_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the IP addresses for the
@@ -10156,8 +10444,7 @@ available in Postfix 2.7 and later.
.br
.IP "\fBcheck_reverse_client_hostname_access \fItype:table\fR\fR"
Search the specified access database for the unverified reverse
-client hostname, parent domains, client IP address, or networks
-obtained by stripping least significant octets. See the \fBaccess\fR(5)
+client hostname or IP address. See the \fBaccess\fR(5)
manual page for details. Note: a result of "OK" is not allowed for
safety reasons. Instead, use DUNNO in order to exclude specific
hosts from denylists. This feature is available in Postfix 2.6
@@ -10684,6 +10971,9 @@ Note 2: when invoked via "\fBsendmail \-bs\fR", Postfix will never offer
STARTTLS due to insufficient privileges to access the server private
key. This is intended behavior.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+smtpd_tls_security_level instead.
+.PP
This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use smtpd_tls_security_level instead.
.SH smtpd_error_sleep_time (default: 1s)
@@ -10720,8 +11010,8 @@ restriction that matches wins.
The following restrictions are specific to the domain name information
received with the ETRN command.
.IP "\fBcheck_etrn_access \fItype:table\fR\fR"
-Search the specified access database for the ETRN domain name
-or its parent domains. See the \fBaccess\fR(5) manual page for details.
+Search the specified access database for the ETRN domain name.
+See the \fBaccess\fR(5) manual page for details.
.br
.br
.PP
@@ -10752,7 +11042,7 @@ The smtpd_expansion_filter value is not subject to Postfix configuration
parameter $name expansion.
.PP
This feature is available in Postfix 2.0 and later.
-.SH smtpd_forbid_bare_newline (default: Postfix < 3.9: no)
+.SH smtpd_forbid_bare_newline (default: Postfix >= 3.9: normalize)
Reject or restrict input lines from an SMTP client that end in
<LF> instead of the standard <CR><LF>. Such line
endings are commonly allowed with UNIX\-based SMTP servers, but they
@@ -10761,7 +11051,7 @@ vulnerable to
SMTP smuggling.
.PP
Specify one of the following values (case does not matter):
-.IP "\fBnormalize\fR"
+.IP "\fBnormalize\fR (default for Postfix >= 3.9)"
Require the standard
End\-of\-DATA sequence <CR><LF>.<CR><LF>.
Otherwise, allow command or message content lines ending in the
@@ -10780,6 +11070,17 @@ with the standard End\-of\-DATA sequence
Such clients
can be excluded with smtpd_forbid_bare_newline_exclusions.
.br
+.IP "\fBnote\fR"
+Same as "normalize", but also notes in
+the log whether the Postfix SMTP server received any lines with
+"bare <LF>". The information is formatted as "disconnect
+from name[address] ... notes=bare_lf". The notes value is
+expected to become a list of comma\-separated names.
+.br
+.br
+This
+feature is available in Postfix 3.9 and later.
+.br
.IP "\fByes\fR"
Compatibility alias for \fBnormalize\fR.
.br
@@ -10808,9 +11109,8 @@ of BDAT violations, BDAT can be selectively disabled with
smtpd_discard_ehlo_keyword_address_maps, or globally disabled with
smtpd_discard_ehlo_keywords).
.br
-.IP "\fBno\fR (default)"
-Do not require the standard
-End\-of\-DATA
+.IP "\fBno\fR (default for Postfix < 3.9)"
+Do not require the standard End\-of\-DATA
sequence <CR><LF>.<CR><LF>. Always process
a bare <LF> as if the client sent <CR><LF>. This
option is fully backwards compatible, but is not recommended for
@@ -10904,9 +11204,8 @@ This feature is available in Postfix >= 3.9, 3.8.5, 3.7.10,
Disconnect remote SMTP clients that violate RFC 2920 (or 5321)
command pipelining constraints. The server replies with "554 5.5.0
Error: SMTP protocol synchronization" and logs the unexpected remote
-SMTP client input. Specify "smtpd_forbid_unauth_pipelining = yes"
-to enable. This feature is enabled by default with Postfix >=
-3.9.
+SMTP client input. This feature is enabled by default with Postfix
+>= 3.9. Specify "smtpd_forbid_unauth_pipelining = no" to disable.
.PP
This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20.
@@ -10964,7 +11263,7 @@ The following restrictions are specific to the hostname information
received with the HELO or EHLO command.
.IP "\fBcheck_helo_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the HELO or EHLO
-hostname or parent domains, and execute the corresponding action.
+hostname, and execute the corresponding action.
Note: specify "smtpd_helo_required = yes" to fully enforce this
restriction (without "smtpd_helo_required = yes", a client can
simply skip check_helo_access by not sending HELO or EHLO).
@@ -11430,8 +11729,7 @@ The following restrictions are specific to the recipient address
that is received with the RCPT TO command.
.IP "\fBcheck_recipient_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the resolved RCPT
-TO address, domain, parent domains, or localpart@, and execute the
-corresponding action.
+TO address, and execute the corresponding action.
.br
.IP "\fBcheck_recipient_a_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the IP addresses for
@@ -11809,7 +12107,7 @@ Continue long lines by starting the next line with whitespace.
The same restrictions are available as documented under
smtpd_recipient_restrictions.
.PP
-This feature is available in Postix 2.10 and later.
+This feature is available in Postfix 2.10 and later.
.SH smtpd_restriction_classes (default: empty)
User\-defined aliases for groups of access restrictions. The aliases
can be specified in smtpd_recipient_restrictions etc., and on the
@@ -12089,8 +12387,7 @@ The following restrictions are specific to the sender address
received with the MAIL FROM command.
.IP "\fBcheck_sender_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the MAIL FROM
-address, domain, parent domains, or localpart@, and execute the
-corresponding action.
+address, and execute the corresponding action.
.br
.IP "\fBcheck_sender_a_access \fItype:table\fR\fR"
Search the specified \fBaccess\fR(5) database for the IP addresses for
@@ -12903,6 +13200,59 @@ Postfix uses ciphers with forward secrecy.
This feature is available in Postfix 2.6 and later, when it is
compiled and linked with OpenSSL 1.0.0 or later on platforms
where EC algorithms have not been disabled by the vendor.
+.SH smtpd_tls_enable_rpk (default: no)
+Request that remote SMTP clients send an RFC7250 raw public key
+instead of an X.509 certificate, when asking for or requiring client
+authentication. This feature is ignored when there is no raw public
+key support in the local TLS implementation.
+.PP
+The Postfix SMTP server will log a warning when "smtpd_tls_enable_rpk
+= yes", but the remote SMTP client sends a certificate, the
+certificate's public key fingerprint does not match a check_ccert_access
+table, while the certificate fingerprint does match a check_ccert_access
+table. The remote SMTP client would lose access when it starts
+sending a raw public key instead of a certificate, after its TLS
+implementation is updated with raw public key support.
+.PP
+The Postfix SMTP server always sends a raw public key instead
+of a certificate, if solicited by the remote SMTP client and the
+local TLS implementation supports raw public keys. If the client
+sends a server name indication with an SNI TLS extension, and
+tls_server_sni_maps is configured, the server will extract a raw
+public key from the indicated certificate.
+.PP
+Sample commands to compute certificate and public key SHA256 digests:
+.PP
+.nf
+.na
+.ft C
+# SHA256 digest of the first certificate in "cert.pem"
+$ openssl x509 \-in cert.pem \-outform DER | openssl dgst \-sha256 \-c
+.fi
+.ad
+.ft R
+.PP
+.nf
+.na
+.ft C
+# SHA256 digest of the SPKI of the first certificate in "cert.pem"
+$ openssl x509 \-in cert.pem \-pubkey \-noout |
+ openssl pkey \-pubin \-outform DER | openssl dgst \-sha256 \-c
+.fi
+.ad
+.ft R
+.PP
+.nf
+.na
+.ft C
+# SHA256 digest of the SPKI of the first private key in "pkey.pem"
+$ openssl pkey \-in pkey.pem \-pubout \-outform DER |
+ openssl dgst \-sha256 \-c
+.fi
+.ad
+.ft R
+.PP
+This feature is available in Postfix 3.9 and later.
.SH smtpd_tls_exclude_ciphers (default: empty)
List of ciphers or cipher types to exclude from the SMTP server
cipher list at all TLS security levels. Excluding valid ciphers
@@ -13064,7 +13414,9 @@ earlier, log the summary message, peer certificate summary information
and unconditionally log trust\-chain verification errors.
.br
.IP ""
-2 Also log levels during TLS negotiation.
+2 Also enable verbose logging in the Postfix TLS
+library, log session cache operations, and enable OpenSSL logging
+of the progress of the SSL handshake.
.br
.IP ""
3 Also log hexadecimal and ASCII dump of TLS negotiation
@@ -13233,7 +13585,7 @@ smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
.ft R
.PP
This feature is available in Postfix 2.3 and later.
-.SH smtpd_tls_protocols (default: see postconf \-d output)
+.SH smtpd_tls_protocols (default: see 'postconf \-d' output)
TLS protocols accepted by the Postfix SMTP server with opportunistic
TLS encryption. If the list is empty, the server supports all available
TLS protocol versions. A non\-empty value is a list of protocol names to
@@ -13466,6 +13818,9 @@ Note: when invoked via "\fBsendmail \-bs\fR", Postfix will never offer
STARTTLS due to insufficient privileges to access the server private
key. This is intended behavior.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+smtpd_tls_security_level instead.
+.PP
This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use smtpd_tls_security_level instead.
.SH smtputf8_autodetect_classes (default: sendmail, verify)
@@ -13822,8 +14177,7 @@ via the tls_config_file parameter. When empty, or when the
selected name is not present in the configuration file, the default
application name ("openssl_conf") is used as a fallback.
.PP
-This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6,
-3.6.10, and 3.5.20.
+This feature is available in Postfix >= 3.9.
.SH tls_daemon_random_bytes (default: 32)
The number of pseudo\-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8)
process requests from the \fBtlsmgr\fR(8) server in order to seed its
@@ -14540,6 +14894,9 @@ Enforcement mode: require that SMTP servers use TLS encryption.
See smtp_enforce_tls for further details. Use
tlsproxy_client_security_level instead.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_client_security_level instead.
+.PP
This feature is available in Postfix 3.4 and later.
.SH tlsproxy_client_fingerprint_digest (default: $smtp_tls_fingerprint_digest)
The message digest algorithm used to construct remote TLS server
@@ -14575,6 +14932,9 @@ Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS
usage policy by next\-hop destination and by remote TLS server
hostname. See smtp_tls_per_site for further details.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_client_policy_maps instead.
+.PP
This feature is available in Postfix 3.4 and later.
.SH tlsproxy_client_policy (default: $smtp_tls_policy_maps)
Optional lookup tables with the Postfix \fBtlsproxy\fR(8) client TLS
@@ -14606,12 +14966,18 @@ Opportunistic mode: use TLS when a remote server announces TLS
support. See smtp_use_tls for further details. Use
tlsproxy_client_security_level instead.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_client_security_level instead.
+.PP
This feature is available in Postfix 3.4 and later.
.SH tlsproxy_enforce_tls (default: $smtpd_enforce_tls)
Mandatory TLS: announce STARTTLS support to remote SMTP clients, and
require that clients use TLS encryption. See smtpd_enforce_tls for
further details. Use tlsproxy_tls_security_level instead.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_tls_security_level instead.
+.PP
This feature is available in Postfix 2.8 and later.
.SH tlsproxy_service_name (default: tlsproxy)
The name of the \fBtlsproxy\fR(8) service entry in master.cf. This
@@ -14678,6 +15044,8 @@ File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
should use with non\-export EDH ciphers. See smtpd_tls_dh1024_param_file
for further details.
.PP
+This feature is deprecated as of Postfix 3.9. Do not specify.
+.PP
This feature is available in Postfix 2.8 and later.
.SH tlsproxy_tls_dh512_param_file (default: $smtpd_tls_dh512_param_file)
File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
@@ -14720,7 +15088,15 @@ The Postfix \fBtlsproxy\fR(8) server security grade for ephemeral
elliptic\-curve Diffie\-Hellman (EECDH) key exchange. See
smtpd_tls_eecdh_grade for further details.
.PP
+This feature is deprecated as of Postfix 3.9. Do not specify.
+.PP
This feature is available in Postfix 2.8 and later.
+.SH tlsproxy_tls_enable_rpk (default: $smtpd_tls_enable_rpk)
+Request that remote SMTP clients send an RFC7250 raw public key
+instead of an X.509 certificate, when asking or requiring client
+authentication. See $smtpd_tls_enable_rpk for details.
+.PP
+This feature is available in Postfix 3.9 and later.
.SH tlsproxy_tls_exclude_ciphers (default: $smtpd_tls_exclude_ciphers)
List of ciphers or cipher types to exclude from the \fBtlsproxy\fR(8)
server cipher list at all TLS security levels. See
@@ -14799,6 +15175,9 @@ Opportunistic TLS: announce STARTTLS support to remote SMTP clients,
but do not require that clients use TLS encryption. See smtpd_use_tls
for further details. Use tlsproxy_tls_security_level instead.
.PP
+This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_tls_security_level instead.
+.PP
This feature is available in Postfix 2.8 and later.
.SH tlsproxy_watchdog_timeout (default: 10s)
How much time a \fBtlsproxy\fR(8) process may take to process local
@@ -14952,7 +15331,13 @@ This feature is available in Postfix 2.5 and later.
.SH transport_maps (default: empty)
Optional lookup tables with mappings from recipient address to
(message delivery transport, next\-hop destination). See \fBtransport\fR(5)
-for details.
+for syntax details.
+.PP
+This information may override the message delivery transport
+and/or next\-hop destination that are specified with $local_transport,
+$virtual_transport, $relay_transport, $default_transport,
+$sender_dependent_relayhost_maps, $relayhost,
+$sender_dependent_default_transport_maps, or the recipient domain.
.PP
Specify zero or more "type:table" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
@@ -15421,8 +15806,10 @@ from each original recipient.
.PP
This feature is available in Postfix 2.1 and later.
.SH virtual_alias_maps (default: $virtual_maps)
-Optional lookup tables that alias specific mail addresses or domains
-to other local or remote addresses. The table format and lookups
+Optional lookup tables with aliases that apply to all recipients:
+\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+only to \fBlocal\fR(8) recipients.
+The table format and lookups
are documented in \fBvirtual\fR(5). For an overview of Postfix address
manipulations see the ADDRESS_REWRITING_README document.
.PP
diff --git a/man/man5/regexp_table.5 b/man/man5/regexp_table.5
index 9eeefe4..e969821 100644
--- a/man/man5/regexp_table.5
+++ b/man/man5/regexp_table.5
@@ -163,9 +163,14 @@ in\-memory file:
Postfix parses the result as if it is a file in /etc/postfix.
-Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
-Postfix from trying to do \fI$name\fR expansion as it
-evaluates a parameter value.
+Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
+to keep Postfix from trying to do \fI$name\fR expansion as
+it evaluates a parameter value.
+
+Note: when using \fI$name\fR inside an inlined pattern,
+this will not disable metacharacters such as '.' in the
+\fI$name\fR expansion. To prevent unexpected matches, use
+a pcre: table, and specify \eQ\fI$name\fR\eE.
.SH "EXAMPLE SMTPD ACCESS MAP"
.na
.nf
diff --git a/man/man5/relocated.5 b/man/man5/relocated.5
index fbc85a3..e1d7863 100644
--- a/man/man5/relocated.5
+++ b/man/man5/relocated.5
@@ -147,8 +147,8 @@ domains that no longer exist.
.PP
Other parameters of interest:
.IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives
-mail on.
+The local network interface addresses that this mail system
+receives mail on.
.IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR"
The list of domains that are delivered via the $local_transport
mail delivery transport.
@@ -156,7 +156,7 @@ mail delivery transport.
The domain name that locally\-posted mail appears to come
from, and that locally posted mail is delivered to.
.IP "\fBproxy_interfaces (empty)\fR"
-The network interface addresses that this mail system receives mail
+The remote network interface addresses that this mail system receives mail
on by way of a proxy or network address translation unit.
.SH "SEE ALSO"
.na
diff --git a/man/man5/socketmap_table.5 b/man/man5/socketmap_table.5
index c53db3d..e5671dd 100644
--- a/man/man5/socketmap_table.5
+++ b/man/man5/socketmap_table.5
@@ -19,7 +19,7 @@ Postfix socketmap table lookup client
.ad
.fi
The Postfix mail system uses optional tables for address
-rewriting. mail routing or policy lookup.
+rewriting, mail routing or policy lookup.
The Postfix socketmap client expects TCP endpoint names of
the form \fBinet:\fIhost\fB:\fIport\fB:\fIname\fR, or
diff --git a/man/man5/virtual.5 b/man/man5/virtual.5
index 5a66c7f..e03a500 100644
--- a/man/man5/virtual.5
+++ b/man/man5/virtual.5
@@ -16,13 +16,14 @@ Postfix virtual alias table format
.SH DESCRIPTION
.ad
.fi
-The optional \fBvirtual\fR(5) alias table rewrites recipient
-addresses for all local, all virtual, and all remote mail
-destinations.
-This is unlike the \fBaliases\fR(5) table which is used
-only for \fBlocal\fR(8) delivery. This feature is implemented
+The optional \fBvirtual\fR(5) alias table (virtual_alias_maps)
+applies to all recipients: local(8), virtual, and remote.
+This feature is implemented
in the Postfix \fBcleanup\fR(8) daemon before mail is queued.
+This is unlike the \fBaliases\fR(5) table (alias_maps) which
+applies only to \fBlocal\fR(8) recipients.
+
Virtual aliasing is recursive; to terminate recursion for
a specific address, alias that address to itself.
@@ -270,8 +271,9 @@ this topic. See the Postfix \fBmain.cf\fR file for syntax details
and for default values. Use the "\fBpostfix reload\fR" command after
a configuration change.
.IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
-Optional lookup tables that alias specific mail addresses or domains
-to other local or remote addresses.
+Optional lookup tables with aliases that apply to all recipients:
+\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+only to \fBlocal\fR(8) recipients.
.IP "\fBvirtual_alias_domains ($virtual_alias_maps)\fR"
Postfix is the final destination for the specified list of virtual
alias domains, that is, domains for which all addresses are aliased
@@ -282,8 +284,8 @@ key to the lookup result.
.PP
Other parameters of interest:
.IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives
-mail on.
+The local network interface addresses that this mail system
+receives mail on.
.IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR"
The list of domains that are delivered via the $local_transport
mail delivery transport.
@@ -296,7 +298,7 @@ Enable special treatment for owner\-\fIlistname\fR entries in the
\fIlistname\fR\-request address localparts when the recipient_delimiter
is set to "\-".
.IP "\fBproxy_interfaces (empty)\fR"
-The network interface addresses that this mail system receives mail
+The remote network interface addresses that this mail system receives mail
on by way of a proxy or network address translation unit.
.SH "SEE ALSO"
.na
diff --git a/man/man8/cleanup.8 b/man/man8/cleanup.8
index bc51c31..0f4ee68 100644
--- a/man/man8/cleanup.8
+++ b/man/man8/cleanup.8
@@ -286,10 +286,10 @@ that is received by the Postfix mail system.
Available in Postfix version 2.1 and later:
.IP "\fBsender_bcc_maps (empty)\fR"
Optional BCC (blind carbon\-copy) address lookup tables, indexed
-by sender address.
+by envelope sender address.
.IP "\fBrecipient_bcc_maps (empty)\fR"
Optional BCC (blind carbon\-copy) address lookup tables, indexed by
-recipient address.
+envelope recipient address.
.SH "ADDRESS TRANSFORMATION CONTROLS"
.na
.nf
@@ -329,8 +329,9 @@ remote domains.
.PP
Available in Postfix version 2.0 and later:
.IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
-Optional lookup tables that alias specific mail addresses or domains
-to other local or remote address.
+Optional lookup tables with aliases that apply to all recipients:
+\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+only to \fBlocal\fR(8) recipients.
.PP
Available in Postfix version 2.2 and later:
.IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR"
@@ -342,9 +343,10 @@ mapping.
What addresses are subject to sender_canonical_maps address
mapping.
.IP "\fBremote_header_rewrite_domain (empty)\fR"
-Don't rewrite message headers from remote clients at all when
-this parameter is empty; otherwise, rewrite message headers and
-append the specified domain name to incomplete addresses.
+Rewrite or add message headers in mail from remote clients if
+the remote_header_rewrite_domain parameter value is non\-empty,
+updating incomplete addresses with the domain specified in the
+remote_header_rewrite_domain parameter, and adding missing headers.
.SH "RESOURCE AND RATE CONTROLS"
.na
.nf
@@ -395,7 +397,7 @@ The maximal length of an email address after virtual alias expansion.
Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
.IP "\fBsmtputf8_enable (yes)\fR"
Enable preliminary SMTPUTF8 support for the protocols described
-in RFC 6531..6533.
+in RFC 6531, RFC 6532, and RFC 6533.
.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR"
Detect that a message requires SMTPUTF8 support for the specified
mail origin classes.
@@ -465,6 +467,12 @@ Available in Postfix 3.5 and later:
.IP "\fBinfo_log_address_format (external)\fR"
The email address form that will be used in non\-debug logging
(info, warning, etc.).
+.PP
+Available in Postfix 3.9 and later:
+.IP "\fBforce_mime_input_conversion (no)\fR"
+Convert body content that claims to be 8\-bit into quoted\-printable,
+before header_checks, body_checks, Milters, and before after\-queue
+content filters.
.SH "FILES"
.na
.nf
diff --git a/man/man8/dnsblog.8 b/man/man8/dnsblog.8
index bf55548..6c6cef3 100644
--- a/man/man8/dnsblog.8
+++ b/man/man8/dnsblog.8
@@ -55,7 +55,8 @@ configuration files.
How much time a Postfix daemon process may take to handle a
request before it is terminated by a built\-in watchdog timer.
.IP "\fBpostscreen_dnsbl_sites (empty)\fR"
-Optional list of DNS allow/denylist domains, filters and weight
+Optional list of patterns with DNS allow/denylist domains, filters
+and weight
factors.
.IP "\fBipc_timeout (3600s)\fR"
The time limit for sending or receiving information over an internal
diff --git a/man/man8/local.8 b/man/man8/local.8
index ca9c6c8..84736cb 100644
--- a/man/man8/local.8
+++ b/man/man8/local.8
@@ -223,27 +223,30 @@ are replaced with underscores. The list of acceptable characters
is specified with the \fBcommand_expansion_filter\fR configuration
parameter.
.IP \fBSHELL\fR
-The recipient user's login shell.
+The envelope recipient user's login shell.
.IP \fBHOME\fR
-The recipient user's home directory.
+The envelope recipient user's home directory.
.IP \fBUSER\fR
-The bare recipient name.
+The bare envelope recipient name.
.IP \fBEXTENSION\fR
-The optional recipient address extension.
+The optional envelope recipient address extension.
.IP \fBDOMAIN\fR
-The recipient address domain part.
+The envelope recipient address domain part.
.IP \fBLOGNAME\fR
-The bare recipient name.
+The bare envelope recipient name.
.IP \fBLOCAL\fR
-The entire recipient address localpart (text to the left of the
-rightmost @ character).
+The entire envelope recipient address localpart (text to
+the left of the rightmost @ character).
.IP \fBORIGINAL_RECIPIENT\fR
-The entire recipient address, before any address rewriting
-or aliasing (Postfix 2.5 and later).
+The entire envelope recipient address, before any address
+rewriting or aliasing (Postfix 2.5 and later).
.IP \fBRECIPIENT\fR
-The entire recipient address.
+The entire envelope recipient address.
.IP \fBSENDER\fR
-The entire sender address.
+The entire envelope sender address.
+.IP \fBENVID\fR
+The optional RFC 3461 envelope ID. Available as of Postfix
+3.9.
.PP
Additional remote client information is made available via
the following environment variables:
@@ -449,7 +452,9 @@ mailbox_transport, mailbox_command_maps, mailbox_command,
home_mailbox, mail_spool_directory, fallback_transport_maps,
fallback_transport, and luser_relay.
.IP "\fBalias_maps (see 'postconf -d' output)\fR"
-The alias databases that are used for \fBlocal\fR(8) delivery.
+Optional lookup tables with aliases that apply only to \fBlocal\fR(8)
+recipients; this is unlike virtual_alias_maps that apply to all
+recipients: \fBlocal\fR(8), virtual, and remote.
.IP "\fBforward_path (see 'postconf -d' output)\fR"
The \fBlocal\fR(8) delivery agent search list for finding a .forward
file with user\-specified delivery methods.
diff --git a/man/man8/master.8 b/man/man8/master.8
index 8c37de4..87fd648 100644
--- a/man/man8/master.8
+++ b/man/man8/master.8
@@ -151,13 +151,13 @@ The directory with Postfix support programs and daemon programs.
The external command to execute when a Postfix daemon program is
invoked with the \-D option.
.IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives
-mail on.
-.IP "\fBinet_protocols (see 'postconf -d output')\fR"
+The local network interface addresses that this mail system
+receives mail on.
+.IP "\fBinet_protocols (see 'postconf -d' output)\fR"
The Internet protocols Postfix will attempt to use when making
or accepting connections.
.IP "\fBimport_environment (see 'postconf -d' output)\fR"
-The list of environment parameters that a privileged Postfix
+The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
environment overrides.
.IP "\fBmail_owner (postfix)\fR"
diff --git a/man/man8/pipe.8 b/man/man8/pipe.8
index 8e54eaf..efb9e0e 100644
--- a/man/man8/pipe.8
+++ b/man/man8/pipe.8
@@ -240,6 +240,11 @@ the domain is \fIdomain\fR.
This information is modified by the \fBh\fR flag for case folding.
.sp
This feature is available as of Postfix 2.5.
+.IP \fB${envid}\fR
+This macro expands to the RFC 3461 envelope ID if available,
+otherwise the empty string.
+.sp
+This feature is available as of Postfix 3.9.
.IP \fB${extension}\fR
This macro expands to the extension part of a recipient address.
For example, with an address \fIuser+foo@domain\fR the extension is
diff --git a/man/man8/postlogd.8 b/man/man8/postlogd.8
index 9168a34..aeb95c7 100644
--- a/man/man8/postlogd.8
+++ b/man/man8/postlogd.8
@@ -41,10 +41,10 @@ set this permission on programs other than \fBpostdrop\fR(1),
.nf
.ad
.fi
-Changes to \fBmain.cf\fR are picked up automatically, as
-\fBpostlogd\fR(8) processes run for only a limited amount
-of time. Use the command "\fBpostfix reload\fR" to speed
-up a change.
+Changes to \fBmain.cf\fR are not picked up automatically,
+because \fBpostlogd\fR(8) terminates only after reaching
+the \fBmax_idle\fR time limit.
+Use the command "\fBpostfix reload\fR" to speed up a change.
The text below provides only a parameter summary. See
\fBpostconf\fR(5) for more details including examples.
@@ -66,6 +66,12 @@ The master.cf service name of a Postfix daemon process.
.IP "\fBpostlogd_watchdog_timeout (10s)\fR"
How much time a \fBpostlogd\fR(8) process may take to process a request
before it is terminated by a built\-in watchdog timer.
+.PP
+Available in Postfix 3.9 and later:
+.IP "\fBmaillog_file_permissions (0600)\fR"
+The file access permissions that will be set when the file
+$maillog_file is created for the first time, or when the file is
+created after an existing file is rotated.
.SH "SEE ALSO"
.na
.nf
diff --git a/man/man8/postscreen.8 b/man/man8/postscreen.8
index 556a865..0231b0a 100644
--- a/man/man8/postscreen.8
+++ b/man/man8/postscreen.8
@@ -323,25 +323,29 @@ Persistent storage for the \fBpostscreen\fR(8) server decisions.
The amount of time that \fBpostscreen\fR(8) will cache an expired
temporary allowlist entry before it is removed.
.IP "\fBpostscreen_bare_newline_ttl (30d)\fR"
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful "bare newline" SMTP protocol test.
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a "bare newline" SMTP protocol test, before it
+address is required to pass that test again.
.IP "\fBpostscreen_dnsbl_max_ttl (${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)\fR"
-The maximum amount of time that \fBpostscreen\fR(8) will use the
-result from a successful DNS\-based reputation test before a
-client IP address is required to pass that test again.
+The maximum amount of time that \fBpostscreen\fR(8) remembers that a
+client IP address passed a DNS\-based reputation test, before it is
+required to pass that test again.
.IP "\fBpostscreen_dnsbl_min_ttl (60s)\fR"
-The minimum amount of time that \fBpostscreen\fR(8) will use the
-result from a successful DNS\-based reputation test before a
-client IP address is required to pass that test again.
+The minimum amount of time that \fBpostscreen\fR(8) remembers that a
+client IP address passed a DNS\-based reputation test, before it
+is required to pass that test again.
.IP "\fBpostscreen_greet_ttl (1d)\fR"
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful PREGREET test.
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a PREGREET test, before it is required to pass
+that test again.
.IP "\fBpostscreen_non_smtp_command_ttl (30d)\fR"
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful "non_smtp_command" SMTP protocol test.
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a "non_smtp_command" SMTP protocol test, before
+it is required to pass that test again.
.IP "\fBpostscreen_pipelining_ttl (30d)\fR"
-The amount of time that \fBpostscreen\fR(8) will use the result from
-a successful "pipelining" SMTP protocol test.
+The amount of time that \fBpostscreen\fR(8) remembers that a client
+IP address passed a "pipelining" SMTP protocol test, before it is
+required to pass that test again.
.SH "RESOURCE CONTROLS"
.na
.nf
diff --git a/man/man8/proxymap.8 b/man/man8/proxymap.8
index e734a2b..ff0d759 100644
--- a/man/man8/proxymap.8
+++ b/man/man8/proxymap.8
@@ -43,7 +43,7 @@ proxymap server processes.
.IP \(bu
To provide single\-updater functionality for lookup tables
that do not reliably support multiple writers (i.e. all
-file\-based tables).
+file\-based tables that are not based on \fBlmdb\fR).
.PP
The \fBproxymap\fR(8) server implements the following requests:
.IP "\fBopen\fR \fImaptype:mapname flags\fR"
diff --git a/man/man8/qmgr.8 b/man/man8/qmgr.8
index a24af71..ca1fd4c 100644
--- a/man/man8/qmgr.8
+++ b/man/man8/qmgr.8
@@ -234,7 +234,7 @@ A transport\-specific override for the default_recipient_refill_limit
parameter value, where \fItransport\fR is the master.cf name of
the message delivery transport.
.IP "\fBdefault_recipient_refill_delay (5s)\fR"
-The default per\-transport maximum delay between recipients refills.
+The default per\-transport maximum delay between refilling recipients.
.IP "\fBtransport_recipient_refill_delay ($default_recipient_refill_delay)\fR"
A transport\-specific override for the default_recipient_refill_delay
parameter value, where \fItransport\fR is the master.cf name of
diff --git a/man/man8/qmqpd.8 b/man/man8/qmqpd.8
index 9ee6267..0f0a82b 100644
--- a/man/man8/qmqpd.8
+++ b/man/man8/qmqpd.8
@@ -75,7 +75,7 @@ filtering, or address mapping.
Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
.IP "\fBsmtputf8_enable (yes)\fR"
Enable preliminary SMTPUTF8 support for the protocols described
-in RFC 6531..6533.
+in RFC 6531, RFC 6532, and RFC 6533.
.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR"
Detect that a message requires SMTPUTF8 support for the specified
mail origin classes.
diff --git a/man/man8/smtp.8 b/man/man8/smtp.8
index e53a377..0145350 100644
--- a/man/man8/smtp.8
+++ b/man/man8/smtp.8
@@ -1,14 +1,16 @@
-.TH SMTP 8
+.TH SMTP, LMTP 8
.ad
.fi
.SH NAME
-smtp
+smtp, lmtp
\-
Postfix SMTP+LMTP client
.SH "SYNOPSIS"
.na
.nf
\fBsmtp\fR [generic Postfix daemon options] [flags=DORX]
+
+\fBlmtp\fR [generic Postfix daemon options] [flags=DORX]
.SH DESCRIPTION
.ad
.fi
@@ -17,7 +19,9 @@ delivery protocols. It processes message delivery requests from
the queue manager. Each request specifies a queue file, a sender
address, a domain or host to deliver to, and recipient information.
This program expects to be run from the \fBmaster\fR(8) process
-manager.
+manager. The process name, \fBsmtp\fR or \fBlmtp\fR, controls
+the protocol, and the names of the configuration parameters
+that will be used.
The SMTP+LMTP client updates the queue file and marks recipients
as finished, or it informs the queue manager that delivery should
@@ -25,13 +29,9 @@ be tried again at a later time. Delivery status reports are sent
to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as
appropriate.
-The SMTP+LMTP client looks up a list of mail exchanger addresses for
-the destination host, sorts the list by preference, and connects
-to each listed address until it finds a server that responds.
-
-When a server is not reachable, or when mail delivery fails due
-to a recoverable error condition, the SMTP+LMTP client will try to
-deliver the mail to an alternate host.
+The server lookup strategy is different for SMTP and LMTP,
+as described in the sections "SMTP SERVER LOOKUP" and "LMTP
+SERVER LOOKUP".
After a successful mail transaction, a connection may be saved
to the \fBscache\fR(8) connection cache server, so that it
@@ -41,48 +41,62 @@ By default, connection caching is enabled temporarily for
destinations that have a high volume of mail in the active
queue. Connection caching can be enabled permanently for
specific destinations.
-.SH "SMTP DESTINATION SYNTAX"
+.SH "SMTP SERVER LOOKUP"
.na
.nf
.ad
.fi
-The Postfix SMTP+LMTP client supports multiple destinations
+The Postfix SMTP client supports multiple destinations
separated by comma or whitespace (Postfix 3.5 and later).
+Each destination is tried in the specified order.
+
SMTP destinations have the following form:
.IP \fIdomainname\fR
-.IP \fIdomainname\fR:\fIport\fR
+.IP \fIdomainname\fR:\fIservice\fR
Look up the mail exchangers for the specified domain, and
-connect to the specified port (default: \fBsmtp\fR).
+connect to the specified service (default: \fBsmtp\fR).
+Optionally, mail exchangers may be looked up with SRV queries
+instead of MX; this requires that \fIservice\fR is given
+in symbolic form.
.IP [\fIhostname\fR]
-.IP [\fIhostname\fR]:\fIport\fR
-Look up the address(es) of the specified host, and connect to
-the specified port (default: \fBsmtp\fR).
+.IP [\fIhostname\fR]:\fIservice\fR
+Look up the address(es) for the specified host, and connect to
+the specified service (default: \fBsmtp\fR).
.IP [\fIaddress\fR]
-.IP [\fIaddress\fR]:\fIport\fR
+.IP [\fIaddress\fR]:\fIservice\fR
Connect to the host at the specified address, and connect
-to the specified port (default: \fBsmtp\fR). An IPv6 address
+to the specified service (default: \fBsmtp\fR). An IPv6 address
must be formatted as [\fBipv6\fR:\fIaddress\fR].
-.SH "LMTP DESTINATION SYNTAX"
+.SH "LMTP SERVER LOOKUP"
.na
.nf
.ad
.fi
-The Postfix SMTP+LMTP client supports multiple destinations
+The Postfix LMTP client supports multiple destinations
separated by comma or whitespace (Postfix 3.5 and later).
+Each destination is tried in the specified order.
+
LMTP destinations have the following form:
.IP \fBunix\fR:\fIpathname\fR
Connect to the local UNIX\-domain server that is bound to the specified
\fIpathname\fR. If the process runs chrooted, an absolute pathname
is interpreted relative to the Postfix queue directory.
+.IP \fBinet\fR:\fIdomainname\fR
+.IP \fBinet\fR:\fIdomainname\fR:\fIservice\fR
+Look up the LMTP servers for the specified domain and service
+(default: \fBlmtp\fR).
+This form is supported when SRV lookups are enabled, and
+requires that \fIservice\fR is in symbolic form.
.IP \fBinet\fR:\fIhostname\fR
-.IP \fBinet\fR:\fIhostname\fR:\fIport\fR
+.IP \fBinet\fR:\fIhostname\fR:\fIservice\fR
+Look up the address(es) for the specified host, and connect to
+the specified service (default: \fBlmtp\fR). When SRV lookups
+are enabled, use the form \fB[\fIhostname\fB]\fR to force
+address lookups.
.IP \fBinet\fR:[\fIaddress\fR]
-.IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR
-Connect to the specified TCP port on the specified local or
-remote host. If no port is specified, connect to the port defined as
-\fBlmtp\fR in \fBservices\fR(4).
-If no such service is found, the \fBlmtp_tcp_port\fR configuration
-parameter (default value of 24) will be used.
+.IP \fBinet\fR:[\fIaddress\fR]:\fIservice\fR
+Connect to the specified local or remote host and service
+(default: \fBlmtp\fR).
An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR].
.SH "SINGLE-RECIPIENT DELIVERY"
.na
@@ -146,6 +160,8 @@ This feature is available as of Postfix 3.5.
.SH "SECURITY"
.na
.nf
+.ad
+.fi
The SMTP+LMTP client is moderately security\-sensitive. It
talks to SMTP or LMTP servers and to DNS servers on the
network. The SMTP+LMTP client can be run chrooted at fixed
@@ -199,11 +215,10 @@ address and TCP port.
.nf
.ad
.fi
-Before Postfix version 2.3, the LMTP client is a separate
-program that implements only a subset of the functionality
-available with SMTP: there is no support for TLS, and
-connections are cached in\-process, making it ineffective
-when the client is used for multiple domains.
+Postfix versions 2.3 and later implement the SMTP and LMTP
+client with the same program, and choose the protocol and
+configuration parameters based on the process name, \fBsmtp\fR
+or \fBlmtp\fR.
Most smtp_\fIxxx\fR configuration parameters have an
lmtp_\fIxxx\fR "mirror" parameter for the equivalent LMTP
@@ -464,6 +479,11 @@ Available in Postfix version 2.9 and later:
.IP "\fBsmtp_send_dummy_mail_auth (no)\fR"
Whether or not to append the "AUTH=<>" option to the MAIL
FROM command in SASL\-authenticated SMTP sessions.
+.PP
+Available in Postfix version 3.9 and later:
+.IP "\fBsmtp_sasl_password_result_delimiter (:)\fR"
+The delimiter between username and password in sasl_passwd_maps lookup
+results.
.SH "STARTTLS SUPPORT CONTROLS"
.na
.nf
@@ -566,7 +586,7 @@ The message digest algorithm used to construct remote SMTP server
certificate fingerprints.
.PP
Available in Postfix version 2.6 and later:
-.IP "\fBsmtp_tls_protocols (see postconf -d output)\fR"
+.IP "\fBsmtp_tls_protocols (see 'postconf -d' output)\fR"
TLS protocols that the Postfix SMTP client will use with
opportunistic TLS encryption.
.IP "\fBsmtp_tls_ciphers (medium)\fR"
@@ -647,6 +667,11 @@ Optional configuration file with baseline OpenSSL settings.
.IP "\fBtls_config_name (empty)\fR"
The application name passed by Postfix to OpenSSL library
initialization functions.
+.PP
+Available in Postfix version 3.9 and later:
+.IP "\fBsmtp_tls_enable_rpk (no)\fR"
+Request that remote SMTP servers send an RFC7250 raw public key
+instead of an X.509 certificate.
.SH "OBSOLETE STARTTLS CONTROLS"
.na
.nf
@@ -843,9 +868,9 @@ sub\-second delay values.
.IP "\fBdisable_dns_lookups (no)\fR"
Disable DNS lookups in the Postfix SMTP and LMTP clients.
.IP "\fBinet_interfaces (all)\fR"
-The local network interface addresses that this mail system receives
-mail on.
-.IP "\fBinet_protocols (see 'postconf -d output')\fR"
+The local network interface addresses that this mail system
+receives mail on.
+.IP "\fBinet_protocols (see 'postconf -d' output)\fR"
The Internet protocols Postfix will attempt to use when making
or accepting connections.
.IP "\fBipc_timeout (3600s)\fR"
diff --git a/man/man8/smtpd.8 b/man/man8/smtpd.8
index 6f72084..4569f1f 100644
--- a/man/man8/smtpd.8
+++ b/man/man8/smtpd.8
@@ -502,7 +502,7 @@ fingerprints or public key fingerprints (Postfix 2.9 and later) for
\fBcheck_ccert_access\fR and \fBpermit_tls_clientcerts\fR.
.PP
Available in Postfix version 2.6 and later:
-.IP "\fBsmtpd_tls_protocols (see postconf -d output)\fR"
+.IP "\fBsmtpd_tls_protocols (see 'postconf -d' output)\fR"
TLS protocols accepted by the Postfix SMTP server with opportunistic
TLS encryption.
.IP "\fBsmtpd_tls_ciphers (medium)\fR"
@@ -571,6 +571,12 @@ Optional configuration file with baseline OpenSSL settings.
.IP "\fBtls_config_name (empty)\fR"
The application name passed by Postfix to OpenSSL library
initialization functions.
+.PP
+Available in Postfix version 3.9 and later:
+.IP "\fBsmtpd_tls_enable_rpk (no)\fR"
+Request that remote SMTP clients send an RFC7250 raw public key
+instead of an X.509 certificate, when asking for or requiring client
+authentication.
.SH "OBSOLETE STARTTLS CONTROLS"
.na
.nf
@@ -706,12 +712,12 @@ Parameters concerning known/unknown local recipients:
The list of domains that are delivered via the $local_transport
mail delivery transport.
.IP "\fBinet_interfaces (all)\fR"
-The local network interface addresses that this mail system receives
-mail on.
+The local network interface addresses that this mail system
+receives mail on.
.IP "\fBproxy_interfaces (empty)\fR"
The remote network interface addresses that this mail system receives mail
on by way of a proxy or network address translation unit.
-.IP "\fBinet_protocols (see 'postconf -d output')\fR"
+.IP "\fBinet_protocols (see 'postconf -d' output)\fR"
The Internet protocols Postfix will attempt to use when making
or accepting connections.
.IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR"
@@ -742,8 +748,9 @@ Postfix is the final destination for the specified list of virtual
alias domains, that is, domains for which all addresses are aliased
to addresses in other local or remote domains.
.IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
-Optional lookup tables that alias specific mail addresses or domains
-to other local or remote addresses.
+Optional lookup tables with aliases that apply to all recipients:
+\fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+only to \fBlocal\fR(8) recipients.
.IP "\fBunknown_virtual_alias_reject_code (550)\fR"
The Postfix SMTP server reply code when a recipient address matches
$virtual_alias_domains, and $virtual_alias_maps specifies a list
@@ -863,7 +870,7 @@ Disconnect remote SMTP clients that violate RFC 2920 (or 5321)
command pipelining constraints.
.PP
Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later:
-.IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR"
+.IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: normalize)\fR"
Reject or restrict input lines from an SMTP client that end in
<LF> instead of the standard <CR><LF>.
.IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR"
diff --git a/man/man8/tlsproxy.8 b/man/man8/tlsproxy.8
index 6913b7b..4677dc4 100644
--- a/man/man8/tlsproxy.8
+++ b/man/man8/tlsproxy.8
@@ -255,6 +255,12 @@ parameters smtpd_use_tls and smtpd_enforce_tls.
.IP "\fBtlsproxy_tls_chain_files ($smtpd_tls_chain_files)\fR"
Files with the Postfix \fBtlsproxy\fR(8) server keys and certificate
chains in PEM format.
+.PP
+Available in Postfix version 3.9 and later:
+.IP "\fBtlsproxy_tls_enable_rpk ($smtpd_tls_enable_rpk)\fR"
+Request that remote SMTP clients send an RFC7250 raw public key
+instead of an X.509 certificate, when asking or requiring client
+authentication.
.SH "STARTTLS CLIENT CONTROLS"
.na
.nf
diff --git a/man/man8/trivial-rewrite.8 b/man/man8/trivial-rewrite.8
index e41da71..f2c39fb 100644
--- a/man/man8/trivial-rewrite.8
+++ b/man/man8/trivial-rewrite.8
@@ -142,9 +142,10 @@ Enable the rewriting of "site!user" into "user@site".
.PP
Available in Postfix 2.2 and later:
.IP "\fBremote_header_rewrite_domain (empty)\fR"
-Don't rewrite message headers from remote clients at all when
-this parameter is empty; otherwise, rewrite message headers and
-append the specified domain name to incomplete addresses.
+Rewrite or add message headers in mail from remote clients if
+the remote_header_rewrite_domain parameter value is non\-empty,
+updating incomplete addresses with the domain specified in the
+remote_header_rewrite_domain parameter, and adding missing headers.
.SH "ROUTING CONTROLS"
.na
.nf
@@ -163,10 +164,12 @@ The default mail delivery transport and next\-hop destination for
final delivery to domains listed with $virtual_mailbox_domains.
.IP "\fBrelay_transport (relay)\fR"
The default mail delivery transport and next\-hop destination for
-remote delivery to domains listed with $relay_domains.
+the relay domain address class: recipient domains that match
+$relay_domains.
.IP "\fBdefault_transport (smtp)\fR"
The default mail delivery transport and next\-hop destination for
-destinations that do not match $mydestination, $inet_interfaces,
+the default domain class: recipient domains that do not match
+$mydestination, $inet_interfaces,
$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
or $relay_domains.
.IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR"
@@ -174,8 +177,8 @@ A list of Postfix features where the pattern "example.com" also
matches subdomains of example.com,
instead of requiring an explicit ".example.com" pattern.
.IP "\fBrelayhost (empty)\fR"
-The next\-hop destination(s) for non\-local mail; overrides non\-local
-domains in recipient addresses.
+The next\-hop destination(s) for non\-local mail; takes precedence
+over non\-local domains in recipient addresses.
.IP "\fBtransport_maps (empty)\fR"
Optional lookup tables with mappings from recipient address to
(message delivery transport, next\-hop destination).
diff --git a/mantools/check-see-postconf-d-output b/mantools/check-see-postconf-d-output
new file mode 100755
index 0000000..d74c4f1
--- /dev/null
+++ b/mantools/check-see-postconf-d-output
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# check-see-postconf-d-output - find missing is misplaced quotes
+
+grep -r "see *'*postconf -d'* *output'*" proto html man |
+ grep -v "see 'postconf -d' output"
diff --git a/mantools/check-snapshot-nonprod b/mantools/check-snapshot-nonprod
new file mode 100755
index 0000000..e18f6aa
--- /dev/null
+++ b/mantools/check-snapshot-nonprod
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+version=$(basename $(env - pwd)) || exit 1
+case "$version" in
+postfix-[0-9]*.[0-9]*.[0-9]*)
+ test -f conf/makedefs.out || {
+ echo "Error: no conf/makedefs.out" 1>&2; exit 1; }
+ grep 'CCARGS.*-DSNAPSHOT' conf/makedefs.out && {
+ echo "Error: stable release builds with -DSNAPSHOT" 1>&2, exit 1; }
+ grep 'CCARGS.*-DNONPROD' conf/makedefs.out && {
+ echo "Error: stable release builds with -DNONPROD" 1>&2, exit 1; }
+ ;;
+esac
diff --git a/mantools/dehtml b/mantools/dehtml
index cc120de..9a3be6f 100755
--- a/mantools/dehtml
+++ b/mantools/dehtml
@@ -3,7 +3,7 @@
for i
do
case $i in
- /*) lynx -dump file://localhost$i;;
- *) lynx -dump file://localhost`pwd`/$i;;
+ /*) lynx -width=256 -dump file://localhost$i;;
+ *) lynx -width=256 -dump file://localhost`pwd`/$i;;
esac
-done
+done | grep -v 'file://localhost/'
diff --git a/mantools/postlink b/mantools/postlink
index 89b0fa4..6ca24c6 100755
--- a/mantools/postlink
+++ b/mantools/postlink
@@ -169,6 +169,7 @@ while (<>) {
s;\bdisable_dns_lookups\b;<a href="postconf.5.html#disable_dns_lookups">$&</a>;g;
s;\bdisable_mime_input_processing\b;<a href="postconf.5.html#disable_mime_input_processing">$&</a>;g;
s;\bdisable_mime_output_conversion\b;<a href="postconf.5.html#disable_mime_output_conversion">$&</a>;g;
+ s;\bforce_mime_input_conversion\b;<a href="postconf.5.html#force_mime_input_conversion">$&</a>;g;
s;\bdisable_verp_bounces\b;<a href="postconf.5.html#disable_verp_bounces">$&</a>;g;
s;\bdisable_vrfy_command\b;<a href="postconf.5.html#disable_vrfy_command">$&</a>;g;
s;\bdont_remove\b;<a href="postconf.5.html#dont_remove">$&</a>;g;
@@ -231,6 +232,8 @@ while (<>) {
s;\blmtp_min_data_rate\b;<a href="postconf.5.html#lmtp_min_data_rate">$&</a>;g;
s;\blmtp_reply_filter\b;<a href="postconf.5.html#lmtp_reply_filter">$&</a>;g;
s;\blmtp_sasl_password_maps\b;<a href="postconf.5.html#lmtp_sasl_password_maps">$&</a>;g;
+ s;\bsmtp_sasl_password_result_delimiter\b;<a href="postconf.5.html#smtp_sasl_password_result_delimiter">$&</a>;g;
+ s;\blmtp_sasl_password_result_delimiter\b;<a href="postconf.5.html#lmtp_sasl_password_result_delimiter">$&</a>;g;
s;\blmtp_send_dummy_mail_auth\b;<a href="postconf.5.html#lmtp_send_dummy_mail_auth">$&</a>;g;
s;\blmtp_balance_inet_protocols\b;<a href="postconf.5.html#lmtp_balance_inet_protocols">$&</a>;g;
s;\blmtp_sender_dependent_authentication\b;<a href="postconf.5.html#lmtp_sender_dependent_authentication">$&</a>;g;
@@ -273,6 +276,7 @@ while (<>) {
s;\blmtp_tls_loglevel\b;<a href="postconf.5.html#lmtp_tls_loglevel">$&</a>;g;
s;\blmtp_tls_session_cache_database\b;<a href="postconf.5.html#lmtp_tls_session_cache_database">$&</a>;g;
s;\blmtp_tls_session_cache_timeout\b;<a href="postconf.5.html#lmtp_tls_session_cache_timeout">$&</a>;g;
+ s;\blmtp_tls_enable_rpk\b;<a href="postconf.5.html#lmtp_tls_enable_rpk">$&</a>;g;
s;\blmtp_tls_wrappermode\b;<a href="postconf.5.html#lmtp_tls_wrappermode">$&</a>;g;
s;\blmtp_generic_maps\b;<a href="postconf.5.html#lmtp_generic_maps">$&</a>;g;
s;\blmtp_pix_workaround_threshold_time\b;<a href="postconf.5.html#lmtp_pix_workaround_threshold_time">$&</a>;g;
@@ -699,6 +703,7 @@ while (<>) {
s;\bsmtp_tls_block_early_mail_reply\b;<a href="postconf.5.html#smtp_tls_block_early_mail_reply">$&</a>;g;
s;\bsmtp_tls_dane_insecure_mx_policy\b;<a href="postconf.5.html#smtp_tls_dane_insecure_mx_policy">$&</a>;g;
s;\bsmtp_tls_force_insecure_host_tlsa_lookup\b;<a href="postconf.5.html#smtp_tls_force_insecure_host_tlsa_lookup">$&</a>;g;
+ s;\bsmtp_tls_enable_rpk\b;<a href="postconf.5.html#smtp_tls_enable_rpk">$&</a>;g;
s;\bsmtp_tls_wrappermode\b;<a href="postconf.5.html#smtp_tls_wrappermode">$&</a>;g;
s;\bsmtp_use_tls\b;<a href="postconf.5.html#smtp_use_tls">$&</a>;g;
s;\bsmtp_header_checks\b;<a href="postconf.5.html#smtp_header_checks">$&</a>;g;
@@ -752,6 +757,7 @@ while (<>) {
s;\bsmtpd_tls_ses[-</bB>]*\n*[ <bB>]*sion_cache_database\b;<a href="postconf.5.html#smtpd_tls_session_cache_database">$&</a>;g;
s;\bsmtpd_tls_ses[-</bB>]*\n*[ <bB>]*sion_cache_timeout\b;<a href="postconf.5.html#smtpd_tls_session_cache_timeout">$&</a>;g;
s;\bsmtpd_tls_always_issue_ses[-</bB>]*\n*[ <bB>]*sion_ids\b;<a href="postconf.5.html#smtpd_tls_always_issue_session_ids">$&</a>;g;
+ s;\bsmtpd_tls_enable_rpk\b;<a href="postconf.5.html#smtpd_tls_enable_rpk">$&</a>;g;
s;\bsmtpd_tls_wrappermode\b;<a href="postconf.5.html#smtpd_tls_wrappermode">$&</a>;g;
s;\bsmtpd_use_tls\b;<a href="postconf.5.html#smtpd_use_tls">$&</a>;g;
s;\bsmtpd_reject_footer\b;<a href="postconf.5.html#smtpd_reject_footer">$&</a>;g;
@@ -889,6 +895,7 @@ while (<>) {
s/[<bB>]*lmdb[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ <bB>]*ble[<\/bB>]*\(5\)/<a href="lmdb_table.5.html">$&<\/a>/g;
s/[<bB>]*mas[-<\/bB>]*\n* *[<bB>]*ter[<\/bB>]*\(5\)/<a href="master.5.html">$&<\/a>/g;
s/[<bB>]*mem[-<\/bB>]*\n* *[<bB>]*cache[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ <bB>]*ble[<\/bB>]*\(5\)/<a href="memcache_table.5.html">$&<\/a>/g;
+ s/[<bB>]*mongodb[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ <bB>]*ble[<\/bB>]*\(5\)/<a href="mongodb_table.5.html">$&<\/a>/g;
s/[<bB>]*mysql[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ <bB>]*ble[<\/bB>]*\(5\)/<a href="mysql_table.5.html">$&<\/a>/g;
s/[<bB>]*nisplus[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ <bB>]*ble[<\/bB>]*\(5\)/<a href="nisplus_table.5.html">$&<\/a>/g;
s/[<bB>]*pcre[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ <bB>]*ble[<\/bB>]*\(5\)/<a href="pcre_table.5.html">$&<\/a>/g;
@@ -1124,6 +1131,7 @@ while (<>) {
s;\btlsproxy_tls_protocols\b;<a href="postconf.5.html#tlsproxy_tls_protocols">$&</a>;g;
s;\btlsproxy_tls_req_ccert\b;<a href="postconf.5.html#tlsproxy_tls_req_ccert">$&</a>;g;
s;\btlsproxy_tls_security_level\b;<a href="postconf.5.html#tlsproxy_tls_security_level">$&</a>;g;
+ s;\btlsproxy_tls_enable_rpk\b;<a href="postconf.5.html#tlsproxy_tls_enable_rpk">$&</a>;g;
s;\btlsproxy_use_tls\b;<a href="postconf.5.html#tlsproxy_use_tls">$&</a>;g;
s;\btlsproxy_client_CAfile\b;<a href="postconf.5.html#tlsproxy_client_CAfile">$&</a>;g;
@@ -1160,6 +1168,7 @@ while (<>) {
s;\bmail[-</bB>]*\n*[ <bB>]*log_file_compressor\b;<a href="postconf.5.html#maillog_file_compressor">$&</a>;g;
s;\bmail[-</bB>]*\n*[ <bB>]*log_file_prefixes\b;<a href="postconf.5.html#maillog_file_prefixes">$&</a>;g;
s;\bmail[-</bB>]*\n*[ <bB>]*log_file_rotate_suffix\b;<a href="postconf.5.html#maillog_file_rotate_suffix">$&</a>;g;
+ s;\bmail[-</bB>]*\n*[ <bB>]*log_file_permissions\b;<a href="postconf.5.html#maillog_file_permissions">$&</a>;g;
s;\bpostlog_service_name\b;<a href="postconf.5.html#postlog_service_name">$&</a>;g;
s;\bpostlogd_watchdog_timeout\b;<a href="postconf.5.html#postlogd_watchdog_timeout">$&</a>;g;
@@ -1228,6 +1237,8 @@ while (<>) {
s/\b"*hold"* *queues*\b/<a href="QSHAPE_README.html#hold_queue">$&<\/a>/g;
s/\b("*hold"*),/<a href="QSHAPE_README.html#hold_queue">$1<\/a>,/g;
s/\b(postfix *tls)\b/<a href="postfix-tls.1.html">$1<\/a>/g;
+ s/\b(local\s*aliasing)\b/<a href="ADDRESS_REWRITING_README.html#aliases">$1<\/a>/g;
+ s/\b(virtual\s*aliasing)\b/<a href="ADDRESS_REWRITING_README.html#virtual">$1<\/a>/g;
# Hyperlink map types.
@@ -1242,6 +1253,7 @@ while (<>) {
s/\b(ldap[is]?):/<a href="ldap_table.5.html">$1<\/a>:/g;
s/\b(lmdb):/<a href="lmdb_table.5.html">$1<\/a>:/g;
s/\b(memcache):/<a href="memcache_table.5.html">$1<\/a>:/g;
+ s/\b(mongodb):/<a href="mongodb_table.5.html">$1<\/a>:/g;
s/\b(mysql):/<a href="mysql_table.5.html">$1<\/a>:/g;
s/\b(nisplus):/<a href="nisplus_table.5.html">$1<\/a>:/g;
s/\b(pcre):/<a href="pcre_table.5.html">$1<\/a>:/g;
diff --git a/postfix-install b/postfix-install
index f6780e7..563ee27 100644
--- a/postfix-install
+++ b/postfix-install
@@ -176,6 +176,7 @@
# post-install(1) post-installation procedure
# FILES
# $config_directory/main.cf, Postfix installation configuration.
+# $config_directory/makedefs.out, Postfix 'make makefiles' options.
# $meta_directory/postfix-files, installation control file.
# $config_directory/install.cf, obsolete configuration file.
# LICENSE
@@ -192,6 +193,10 @@
# Google, Inc.
# 111 8th Avenue
# New York, NY 10011, USA
+#
+# Wietse Venema
+# porcupine.org
+# Amawalk, NY 10501, USA
#--
# Initialize.
@@ -520,7 +525,7 @@ test -f $CONFIG_DIRECTORY/main.cf && {
case "$junk" in
"") eval unset $name;;
esac
- eval : \${$name=\`bin/postconf -c $CONFIG_DIRECTORY -hx $name\`} ||
+ eval : \${$name=\`bin/postconf -qc $CONFIG_DIRECTORY -hx $name\`} ||
exit 1
done
}
@@ -861,7 +866,7 @@ do
esac
done
-bin/postconf -c $CONFIG_DIRECTORY -e \
+bin/postconf -qc $CONFIG_DIRECTORY -e \
"daemon_directory = $daemon_directory" \
"data_directory = $data_directory" \
"command_directory = $command_directory" \
diff --git a/proto/ADDRESS_CLASS_README.html b/proto/ADDRESS_CLASS_README.html
index 7a30535..5deac11 100644
--- a/proto/ADDRESS_CLASS_README.html
+++ b/proto/ADDRESS_CLASS_README.html
@@ -52,20 +52,25 @@ address classes are very important for the operation of Postfix. </p>
<ul>
<li> <p> The list of domains that are a member of that address
-class: for example, all local domains, or all relay domains. </p>
+class. </p>
+
+<p> Examples: all local domains, or all relay domains. </p>
+
+<li> <p> The default delivery transport for domains in that address
+class. </p>
+
+<p> Examples: local_transport or relay_transport (these point
+to services defined in master.cf). </p>
-<li> <p> The default delivery transport for that address class. For
-example, the local,
-virtual or relay delivery transport (delivery transports are defined
-in master.cf). This helps to keep Postfix configurations simple,
-by avoiding the need for explicit routing information in transport
-maps. </p>
+<p> Benefit: this avoids the need for explicit routing information
+in transport maps. </p>
<li> <p> The list of valid recipient addresses for that address
-class. The Postfix SMTP server rejects invalid recipients with
-"User unknown in &lt;name of address class here&gt; table". This
-helps to keep the Postfix queue free of undeliverable MAILER-DAEMON
-messages. </p>
+class. </p>
+
+<p> Benefit: the Postfix SMTP server rejects an invalid recipient
+with "User unknown in &lt;name of address class&gt; table", and
+avoids sending a MAILER-DAEMON message with backscatter spam. </p>
</ul>
@@ -92,12 +97,12 @@ This domain class also includes mail for <i>user@[ipaddress]</i>
when the IP address is listed with the inet_interfaces or
proxy_interfaces parameters. </p>
-<li> <p> Valid recipient addresses are listed with the local_recipient_maps
-parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP
-server rejects invalid recipients with "User unknown in local
-recipient table". If the local_recipient_maps parameter value is
-empty, then the Postfix SMTP server accepts any address in the
-local domain class. </p>
+<li> <p> Valid recipient addresses for those domains are
+listed with the local_recipient_maps parameter, as described in
+LOCAL_RECIPIENT_README. The Postfix SMTP server rejects invalid recipients
+with "User unknown in local recipient table". If the local_recipient_maps
+parameter value is empty, then the Postfix SMTP server accepts any
+address in the local domain class. </p>
<li> <p> The mail delivery transport is specified with the
local_transport parameter. The default value is <b>local:$myhostname</b>
@@ -111,21 +116,25 @@ class. </p>
<ul>
<li> <p> Purpose: hosted domains where each recipient address is
-aliased to an address in a different domain, for example, a local
-UNIX system account or a remote address. A
+aliased to an address in a different domain class, for example, a
+local UNIX system account or a remote address. A
virtual alias example is given in the VIRTUAL_README file. </p>
<li> <p> Domain names are listed in virtual_alias_domains. The
default value is $virtual_alias_maps for Postfix 1.1 compatibility.
</p>
-<li> <p> Valid recipient addresses are listed with the virtual_alias_maps
-parameter. The Postfix SMTP server rejects invalid recipients with
-"User unknown in virtual alias table". The default value is
-$virtual_maps for Postfix 1.1 compatibility. </p>
+<li> <p> Valid recipient addresses for those domains are listed with the
+virtual_alias_maps parameter. The Postfix SMTP server rejects invalid
+recipients with "User unknown in virtual alias table". The default
+value is $virtual_maps for Postfix 1.1 compatibility. </p>
-<li> <p> There is no mail delivery transport parameter. Every
-address must be aliased to an address in some other domain. </p>
+<blockquote ><p> Note: for historical reasons, virtual_alias_maps
+apply to recipients in all domain classes, not only the virtual
+alias domain class. </p> </blockquote>
+
+<li> <p> There is no configurable mail delivery transport. Every
+address must be aliased to an address in some other domain class. </p>
</ul>
@@ -136,18 +145,19 @@ class. </p>
<li> <p> Purpose: final delivery for hosted domains where each
recipient address can have its own mailbox, and where users do not
-need to have a UNIX system account. A virtual mailbox example is
+need to have a UNIX system account. A virtual mailbox example is
given in the VIRTUAL_README file. </p>
<li> <p> Domain names are listed with the virtual_mailbox_domains
parameter. The default value is $virtual_mailbox_maps for Postfix
1.1 compatibility. </p>
-<li> <p> Valid recipient addresses are listed with the virtual_mailbox_maps
-parameter. The Postfix SMTP server rejects invalid recipients with
-"User unknown in virtual mailbox table". If this parameter value
-is empty, the Postfix SMTP server accepts all recipients for domains
-listed in $virtual_mailbox_domains. </p>
+<li> <p> Valid recipient addresses for those domains are listed
+with the virtual_mailbox_maps parameter. The Postfix SMTP server
+rejects invalid recipients with "User unknown in virtual mailbox
+table". If this parameter value is empty, the Postfix SMTP server
+accepts all recipients for domains listed in $virtual_mailbox_domains.
+</p>
<li> <p> The mail delivery transport is specified with the
virtual_transport parameter. The default value is <b>virtual</b>
@@ -169,11 +179,12 @@ file. </p>
<li> <p> Domain names are listed with the relay_domains parameter.
</p>
-<li> <p> Valid recipient addresses are listed with the relay_recipient_maps
-parameter. The Postfix SMTP server rejects invalid recipients with
-"User unknown in relay recipient table". If this parameter value
-is empty, the Postfix SMTP server accepts all recipients for domains
-listed with the relay_domains parameter. </p>
+<li> <p> Valid recipient addresses for those domains are listed
+with the relay_recipient_maps parameter. The Postfix SMTP server
+rejects invalid recipients with "User unknown in relay recipient
+table". If this parameter value is empty, the Postfix SMTP server
+accepts all recipients for domains listed with the relay_domains
+parameter. </p>
<li> <p> The mail delivery transport is specified with the
relay_transport parameter. The default value is <b>relay</b> which
diff --git a/proto/ADDRESS_REWRITING_README.html b/proto/ADDRESS_REWRITING_README.html
index c858410..631a7d3 100644
--- a/proto/ADDRESS_REWRITING_README.html
+++ b/proto/ADDRESS_REWRITING_README.html
@@ -94,9 +94,7 @@ as invalid </a>
<ul>
-<li> <a href="#resolve"> Resolve address to destination </a>
-
-<li> <a href="#transport"> Mail transport switch </a>
+<li> <a href="#resolve"> Resolve address to (transport, next-hop destination) </a>
<li> <a href="#relocated"> Relocated users table </a>
@@ -312,8 +310,8 @@ find what you need. </p>
<table border="1">
<tr> <th nowrap> Address manipulation </th> <th nowrap> Scope </th>
-<th> Daemon </th> <th nowrap> Global turn-on control </th> <th nowrap> Selective
-turn-off control </th> </tr>
+<th> Daemon </th> <th nowrap> Turn-on controls </th> <th nowrap>
+Turn-off controls </th> </tr>
<tr> <td> <a href="#standard"> Rewrite addresses to standard form</a>
</td> <td nowrap> all mail </td> <td> trivial-<br>rewrite(8) </td>
@@ -340,13 +338,12 @@ sender_bcc_maps, recipient_bcc_maps </td> <td> receive_override_options
nowrap> all mail </td> <td> cleanup(8) </td> <td> virtual_alias_maps
</td> <td> receive_override_options </td> </tr>
-<tr> <td> <a href="#resolve"> Resolve address to destination </a>
-</td> <td nowrap> all mail </td> <td> trivial-<br>rewrite(8) </td>
-<td> none </td> <td> none </td> </tr>
-
-<tr> <td> <a href="#transport"> Mail transport switch</a> </td>
-<td nowrap> all mail </td> <td> trivial-<br>rewrite(8) </td> <td>
-transport_maps </td> <td> none </td> </tr>
+<tr> <td> <a href="#resolve"> Resolve address to (transport, next-hop
+destination) </a> </td> <td nowrap> all mail </td> <td>
+trivial-<br>rewrite(8) </td> <td> local_transport, virtual_transport,
+relay_transport, default_transport, relayhost,
+sender_dependent_relayhost_maps, sender_dependent_default_transport_maps
+</td> <td> content_filter </td> </tr>
<tr> <td> <a href="#relocated"> Relocated users table</a> </td>
<td nowrap> all mail </td> <td> trivial-<br>rewrite(8) </td> <td>
@@ -774,6 +771,11 @@ may be a more appropriate vehicle. See the VIRTUAL_README document
for an overview of methods to host virtual domains with Postfix.
</p>
+<p> Note: virtual aliasing (virtual_alias_maps) applies to all
+recipients: local(8), virtual, and remote. <!-- wrap filler -->
+This is unlike local aliasing (alias_maps) which applies only to
+local(8) recipients. </p>
+
<p> Virtual aliasing is disabled by default. To enable, edit the
virtual_alias_maps parameter in the main.cf file and
specify one or more lookup tables, separated by whitespace or
@@ -833,9 +835,8 @@ trivial-rewrite(8) server. </p>
<ul>
-<li> <a href="#resolve"> Resolve address to destination </a>
-
-<li> <a href="#transport"> Mail transport switch</a>
+<li> <a href="#resolve"> Resolve address to (transport, next-hop
+destination) </a>
<li> <a href="#relocated"> Relocated users table</a>
@@ -873,67 +874,108 @@ via the local(8) delivery agent: </p>
step in more detail, with specific examples or with pointers to
documentation with examples. </p>
-<h3> <a name="resolve"> Resolve address to destination </a> </h3>
+<h3> <a name="resolve"> Resolve address to (transport, next-hop
+destination) </a> </h3>
<p> The Postfix qmgr(8) queue manager selects new mail from the
-incoming queue or old mail from the deferred queue, and asks the
-trivial-rewrite(8) address rewriting and resolving daemon where it
-should be delivered. </p>
+incoming queue or old mail from the deferred queue. First it
+looks for overrides: </p>
+
+<ul>
-<p> As of version 2.0, Postfix distinguishes four major address
-classes. Each class has its own list of domain names, and each
-class has its own default delivery method, as shown in the table
-below. See the ADDRESS_CLASS_README document for the fine details.
-Postfix versions before 2.0 only distinguish between local delivery
-and everything else. </p>
+<li> <p> The REDIRECT action in access(5), header_checks(5) or
+body_checks(5) overrides all recipients of the message, and overrides
+a content_filter setting, and FILTER action in access(5),
+header_checks(5) or body_checks(5). The REDIRECT action was implemented
+as a short-cut to retaliate for abuse. </p>
+
+<li> <p> A content_filter setting and FILTER action in access(5),
+header_checks(5) or body_checks(5) provide their own (transport,
+next-hop destination) information. This bypasses all the steps that
+are described in the remainder of this section. </p>
+
+</ul>
+
+<p> When there is no content filter override, the qmgr(8) queue
+manager asks the trivial-rewrite(8) address rewriting and resolving
+daemon for each recipient how to deliver it (which message delivery
+transport) and where to deliver it (what next-hop destination). </p>
+
+<p> As of version 2.0, Postfix distinguishes four major domain
+classes. Each class has its own list of recipient domain names, and
+each class has its own delivery method, as shown in the table below.
+See the ADDRESS_CLASS_README document for the fine details. Postfix
+versions before 2.0 only distinguish between local delivery and
+everything else. </p>
+
+<p> Note that the table does not match recipients against
+virtual_alias_domains. The reason is that all valid recipients in
+a virtual alias domain must be aliased to an address in a different
+domain. All other recipients in a virtual alias domain are by
+definition undeliverable, and do not need to be considered here.
+</p>
<blockquote>
<table border="1">
-<tr><th align="left">Destination domain list </th> <th
-align="left">Default delivery method </th> <th>Availability
-</th> </tr>
+<tr> <th align="left">Domain class</th> <th align="left">Recipient
+domain match </th> <th> Delivery method </th> <th>Availability </th>
+</tr>
-<tr><td>$mydestination, $inet_interfaces, $proxy_interfaces </td>
-<td>$local_transport </td> <td>Postfix 1.0</td></tr>
+<tr><td>Local</td> <td>mydestination, inet_interfaces, proxy_interfaces
+</td> <td>local_transport </td> <td>Postfix 1.0</td></tr>
-<tr><td>$virtual_mailbox_domains </td> <td>$virtual_transport </td>
-<td>Postfix 2.0</td> </tr>
+<tr><td>Virtual mailbox</td> <td>virtual_mailbox_domains </td>
+<td>virtual_transport </td> <td>Postfix 2.0</td> </tr>
-<tr><td>$relay_domains </td> <td>$relay_transport </td> <td>Postfix
-2.0</td> </tr>
+<tr><td>Relay</td> <td>relay_domains </td> <td>relay_transport
+</td> <td>Postfix 2.0</td> </tr>
-<tr><td>none </td> <td>$default_transport </td> <td>Postfix 1.0</td>
-</tr>
+<tr><td>Default</td><td> none </td> <td>default_transport </td>
+<td>Postfix 1.0</td> </tr>
</table>
</blockquote>
-<h3> <a name="transport"> Mail transport switch </a> </h3>
+<p> The delivery methods in the above table may include a next-hop
+destination in addition to a delivery transport. This may override
+the next-hop destination that is by default taken from the recipient
+domain. </p>
-<p> Once the trivial-rewrite(8) daemon has determined a default
-delivery method it searches the optional transport(5) table for
-information that overrides the message destination and/or delivery
-method. Typical use of the transport(5) table is to send mail to
-a system
-that is not connected to the Internet, or to use a special SMTP
-client configuration for destinations that have special requirements.
-See, for example, the STANDARD_CONFIGURATION_README and UUCP_README
-documents, and the examples in the transport(5) manual page. </p>
+<p> Over time, features have been added to override the above
+transport and/or next-hop destination information. The following
+table lists where a transport or next-hop destination may be taken
+from, depending on the recipient domain class. </p>
-<p> Transport table lookups are disabled by default. To enable,
-edit the transport_maps parameter in the main.cf file and specify
-one or more lookup tables, separated by whitespace or commas. </p>
+<blockquote>
-<p> Example: </p>
+<table border="1">
+
+<tr> <th>Domain class</th> <th>Transport sources (in order of
+descending precedence)</th> <th> Next hop sources (in order of
+descending precedence)</th> </tr>
+
+<tr> <td> Local </td> <td> transport_maps, local_transport</td>
+<td> transport_maps, local_transport, recipient domain</td> </tr>
+
+<tr> <td> Virtual mailbox </td> <td> transport_maps,
+virtual_transport</td> <td> transport_maps, virtual_transport,
+recipient domain</td> </tr>
+
+<tr> <td> Relay </td> <td> transport_maps, relay_transport</td>
+<td> transport_maps, relay_transport, sender_dependent_relayhost_maps,
+relayhost, recipient domain</td> </tr>
+
+<tr> <td> Default </td> <td> transport_maps,
+sender_dependent_default_transport_maps, default_transport</td>
+<td> transport_maps, sender_dependent_default_transport_maps,
+default_transport, sender_dependent_relayhost_maps, relayhost,
+recipient domain</td> </tr>
+
+</table>
-<blockquote>
-<pre>
-/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
-</pre>
</blockquote>
<h3> <a name="relocated"> Relocated users table </a> </h3>
@@ -1019,6 +1061,11 @@ direct mail for standard aliases such as postmaster to real people.
The table can also be used to map "Firstname.Lastname" addresses
to login names. </p>
+<p> Note: local aliasing (alias_maps) applies only to local(8)
+recipients. This is unlike virtual aliasing (virtual_alias_maps)
+which applies to all recipients: local(8), virtual, and remote.
+</p>
+
<p> Alias lookups are enabled by default. The default configuration
depends on the operating system environment, but it is typically
one of the following: </p>
diff --git a/proto/COMPATIBILITY_README.html b/proto/COMPATIBILITY_README.html
index e4e91e1..9f88927 100644
--- a/proto/COMPATIBILITY_README.html
+++ b/proto/COMPATIBILITY_README.html
@@ -61,24 +61,24 @@ default setting append_dot_mydomain=yes </a> </p>
<li> <p> <a href="#chroot"> Using backwards-compatible default setting
chroot=y</a> </p>
+<li><p> <a href="#relay_restrictions"> Using backwards-compatible
+default setting "smtpd_relay_restrictions = (empty)"</a> </p>
+
+<li> <p> <a href="#smtputf8_enable"> Using backwards-compatible
+default setting smtputf8_enable=no</a> </p>
+
</ul>
<p> Logged with compatibility_level &lt; 2: </p>
<ul>
-<li><p> <a href="#relay_restrictions"> Using backwards-compatible
-default setting "smtpd_relay_restrictions = (empty)"</a> </p>
-
<li> <p> <a href="#mynetworks_style"> Using backwards-compatible
default setting mynetworks_style=subnet </a> </p>
<li> <p> <a href="#relay_domains"> Using backwards-compatible default
setting relay_domains=$mydestination </a> </p>
-<li> <p> <a href="#smtputf8_enable"> Using backwards-compatible
-default setting smtputf8_enable=no</a> </p>
-
</ul>
<p> Logged with compatibility_level &lt; 3.6: </p>
@@ -241,6 +241,48 @@ administrator should make the backwards-compatible setting
</pre>
</blockquote>
+<h2> <a name="smtputf8_enable"> Using backwards-compatible default
+setting smtputf8_enable=no</a> </h2>
+
+<p> The smtputf8_enable default value has changed from "no" to "yes".
+With the new "yes" setting, the Postfix SMTP server rejects non-ASCII
+addresses from clients that don't request SMTPUTF8 support, after
+Postfix is updated from an older version. The backwards-compatibility
+safety net is designed to prevent such surprises. </p>
+
+<p> As long as the smtputf8_enable parameter is left at its implicit
+default value, and the compatibility_level setting is
+less than 1, Postfix logs a warning each time an SMTP command uses a
+non-ASCII address localpart without requesting SMTPUTF8 support: </p>
+
+<blockquote>
+<pre>
+postfix/smtpd[27560]: using backwards-compatible default setting
+ smtputf8_enable=no to accept non-ASCII sender address
+ "??@example.org" from localhost[127.0.0.1]
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+postfix/smtpd[27560]: using backwards-compatible default setting
+ smtputf8_enable=no to accept non-ASCII recipient address
+ "??@example.com" from localhost[127.0.0.1]
+</pre>
+</blockquote>
+
+<p> If the address should not be rejected, and the client cannot
+be updated to use SMTPUTF8, then the system administrator should
+make the backwards-compatible setting "smtputf8_enable = no" permanent
+in main.cf:
+
+<blockquote>
+<pre>
+# <b>postconf smtputf8_enable=no</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
<h2> <a name="mynetworks_style"> Using backwards-compatible default
setting mynetworks_style=subnet</a> </h2>
@@ -352,48 +394,6 @@ administrator should make the backwards-compatible setting
<p> Instead of $mydestination, it may be better to specify an
explicit list of domain names. </p>
-<h2> <a name="smtputf8_enable"> Using backwards-compatible default
-setting smtputf8_enable=no</a> </h2>
-
-<p> The smtputf8_enable default value has changed from "no" to "yes".
-With the new "yes" setting, the Postfix SMTP server rejects non-ASCII
-addresses from clients that don't request SMTPUTF8 support, after
-Postfix is updated from an older version. The backwards-compatibility
-safety net is designed to prevent such surprises. </p>
-
-<p> As long as the smtputf8_enable parameter is left at its implicit
-default value, and the compatibility_level setting is
-less than 1, Postfix logs a warning each time an SMTP command uses a
-non-ASCII address localpart without requesting SMTPUTF8 support: </p>
-
-<blockquote>
-<pre>
-postfix/smtpd[27560]: using backwards-compatible default setting
- smtputf8_enable=no to accept non-ASCII sender address
- "??@example.org" from localhost[127.0.0.1]
-</pre>
-</blockquote>
-
-<blockquote>
-<pre>
-postfix/smtpd[27560]: using backwards-compatible default setting
- smtputf8_enable=no to accept non-ASCII recipient address
- "??@example.com" from localhost[127.0.0.1]
-</pre>
-</blockquote>
-
-<p> If the address should not be rejected, and the client cannot
-be updated to use SMTPUTF8, then the system administrator should
-make the backwards-compatible setting "smtputf8_enable = no" permanent
-in main.cf:
-
-<blockquote>
-<pre>
-# <b>postconf smtputf8_enable=no</b>
-# <b>postfix reload</b>
-</pre>
-</blockquote>
-
<h2> <a name="smtpd_digest"> Using backwards-compatible
default setting smtpd_tls_fingerprint_digest=md5</a> </h2>
diff --git a/proto/DATABASE_README.html b/proto/DATABASE_README.html
index 2302cc3..e9d0c18 100644
--- a/proto/DATABASE_README.html
+++ b/proto/DATABASE_README.html
@@ -59,7 +59,7 @@ documentation: </p>
alias_maps = hash:/etc/postfix/aliases (local aliasing)
header_checks = regexp:/etc/postfix/header_checks (content filtering)
transport_maps = hash:/etc/postfix/transport (routing table)
- virtual_alias_maps = hash:/etc/postfix/virtual (address rewriting)
+ virtual_alias_maps = hash:/etc/postfix/virtual (virtual aliasing)
</pre>
</blockquote>
@@ -349,6 +349,11 @@ ldap_table(5). </dd>
<dd> Memcache database client. Configuration details are given in
memcache_table(5). </dd>
+<dt> <b>mongodb</b> (read-only) </dt>
+
+<dd> MongoDB database client. Configuration details are given in
+mongodb_table(5), with examples in MONGODB_README. </dd>
+
<dt> <b>mysql</b> (read-only) </dt>
<dd> MySQL database client. Configuration details are given in
diff --git a/proto/DEPRECATION_README.html b/proto/DEPRECATION_README.html
new file mode 100644
index 0000000..1ded555
--- /dev/null
+++ b/proto/DEPRECATION_README.html
@@ -0,0 +1,411 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix Replacements for Deprecated Features </title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
+Replacements for Deprecated Features</h1>
+
+<hr>
+
+<h2>Purpose of this document </h2>
+
+<p> This document describes Postfix features that are deprecated
+(will be removed) or that have already been removed. It also has
+tips for making an existing Postfix configuration more future-proof.
+</p>
+
+<p> Overview: </p>
+
+<ul>
+
+<li> <a href="#why"> Why deprecate? </a>
+
+<li> <a href="#process"> Deprecation process </a>
+
+<li> <a href="#features"> Deprecated features </a>
+
+</ul>
+
+<h2> <a name="why"> Why deprecate? </a> </h2>
+
+<p> Sometimes, a Postfix feature needs to be replaced with a different
+one. To give an example: </p>
+
+<ul>
+
+<li> <p> The initial Postfix TLS implementation used multiple boolean
+parameters: one parameter to enable opportunistic TLS (for example,
+"smtp_enforce_tls = yes") and one parameter to enable mandatory TLS
+(for example, "smtp_require_tls = yes"). </p>
+
+<li> <p> As we added support more features such as fingerprint,
+dane, and so on, we decided not to add more boolean parameters.
+Instead we introduced one configuration parameter to select from
+multiple deployment models (for example, smtp_tls_security_level =
+may | encrypt | dane, etc...). </p>
+
+</ul>
+
+<!--
+
+<p> Over time it has become clear that 'level' is too rigid, so this may
+have to change again. Wietse and Viktor have been discussing a way to
+specify a range with minimum properties that are required (e.g., encrypt)
+and nice-to-have properties if they are available (dane or mta-sts). </p>
+
+-->
+
+<p> Having both the "old" and "new" way to configure Postfix is
+convenient for existing Postfix installations, because their
+configuration does not break after an upgrade to a new version.
+Unfortunately, there are also disadvantages. Having multiple ways
+to do similar things is not only confusing for newcomers, it also
+makes Postfix harder to change. </p>
+
+<h2> <a name="process"> Deprecation process </a> </h2>
+
+<p> The basic process steps are: </p>
+
+<ol>
+
+<li> <p> Inform humans that a feature will be removed, and suggest
+replacements, in logging and documentation. </p>
+
+<li> <p> Remove the feature, and update logging and documentation. </p>
+
+</ol>
+
+<p> Disclaimer: it has taken 20 years for some features to be
+removed. This past is not a guarantee for the future. </p>
+
+<h2> <a name="features"> Deprecated features </a> </h2>
+
+<p> The table summarizes removed or deprecated features and
+replacements. Click on the "obsolete feature" name for a more
+detailed description. </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th> Obsolete feature name </th> <th> Warning as <br> of version
+</th> <th> Removed <br> in version </th> <th> Replacement </th>
+</tr>
+
+<tr> <td> <a href="#disable_dns_lookups"> disable_dns_lookups </a>
+</td> <td align="center"> 3.9 </td> <td align="center"> - </td>
+<td> smtp_dns_support_level </td> </tr>
+
+<tr> <td> <a href="#xxx_enforce_tls"> <i>xxx</i>_use_tls </a> </td>
+<td align="center"> 3.9 </td> <td align="center"> - </td> <td>
+<i>xxx</i>_tls_security_level </td> </tr>
+
+<tr> <td> <a href="#xxx_enforce_tls"> <i>xxx</i>_enforce_tls </a>
+</td> <td align="center"> 3.9 </td> <td align="center"> - </td>
+<td> <i>xxx</i>_tls_security_level </td> </tr>
+
+<tr> <td> <a href="#xxx_per_site"> <i>xxx</i>_per_site </a> </td>
+<td align="center"> 3.9 </td> <td align="center"> - </td> <td>
+<i>xxx</i>_policy_maps </td> </tr>
+
+<tr> <td> <a href="#smtpd_tls_dh1024_param_file">
+smtpd_tls_dh1024_param_file </a> </td> <td align="center"> 3.9 </td>
+<td align="center"> - </td> <td> do not specify (leave at default)
+</td> </tr>
+
+<tr> <td> <a href="#smtpd_tls_eecdh_grade"> smtpd_tls_eecdh_grade
+</a> </td> <td align="center"> 3.9 </td> <td align="center"> - </td>
+<td> do not specify (leave at default) </td> </tr>
+
+<tr> <td> <a href="#permit_mx_backup"> permit_mx_backup </a> </td>
+<td align="center"> 3.9 </td> <td align="center"> - </td> <td>
+relay_domains </td> </tr>
+
+<tr> <td> <a href="#check_relay_domains"> check_relay_domains </a>
+</td> <td align="center"> 2.2 </td> <td align="center"> 3.9 </td>
+<td> permit_mynetworks, reject_unauth_destination </td> </tr>
+
+<tr> <td> <a href="#reject_maps_rbl"> reject_maps_rbl </a> </td>
+<td align="center"> 2.1 </td> <td align="center"> 3.9 </td> <td>
+reject_rbl_client </td> </tr>
+
+<tr> <td> <a href="#permit_naked_ip_address"> permit_naked_ip_address
+</a> </td> <td align="center"> 2.0 </td> <td align="center"> 3.9
+</td> <td> permit_mynetworks, permit_sasl_authenticated </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="disable_dns_lookups"> Obsolete DNS on/off configuration
+</a> </h3>
+
+<p> The postconf(1) command logs the following: </p>
+
+<ul>
+
+<li> support for parameter "disable_dns_lookups" will be removed; instead, specify "smtp_dns_support_level"
+
+</ul>
+
+<p> Replace obsolete configuration with its replacement: </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th width="33%"> Goal </th> <th width="33%"> Obsolete configuration
+</th> <th> Replacement configuration </th> </tr>
+
+<tr> <td> To disable DNS lookups in the Postfix SMTP/LMTP client
+</td> <td> disable_dns_lookups = yes </td> <td> smtp_dns_support_level
+= disabled </td> </tr>
+
+<tr> <td> To enable DNS lookups in the Postfix SMTP/LMTP client </td> <td>
+disable_dns_lookups = no </td> <td>
+Leave smtp_dns_support_level at the implicit default which is empty, unless
+you need a higher support level such as DNSSEC. </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="xxx_use_tls"> Obsolete opportunistic TLS configuration
+</a> </h3>
+
+<p> The postconf(1) command logs one of the following: </p>
+
+<ul>
+
+<li> support for parameter "lmtp_use_tls" will be removed; instead, specify "lmtp_tls_security_level"
+
+<li> support for parameter "smtp_use_tls" will be removed; instead, specify "smtp_tls_security_level"
+
+<li> support for parameter "smtpd_use_tls" will be removed; instead, specify "smtpd_tls_security_level"
+
+</ul>
+
+<p> There are similarly-named parameters and warnings for postscreen(8)
+and tlsproxy(8), but those parameters should rarely be specified
+by hand. </p>
+
+<p> Replace obsolete configuration with its replacement: </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th width="33%"> Goal </th> <th width="33%"> Obsolete configuration </th> <th> Replacement configuration </th> </tr>
+
+<tr> <td> To turn off TLS </td> <td> <i>xxx</i>_use_tls = no </td>
+<td> <i>xxx</i>_security_level = none </td> </tr>
+
+<tr> <td> To turn on opportunistic TLS </td> <td> <i>xxx</i>_use_tls
+= yes </td> <td> <i>xxx</i>_security_level = may </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="xxx_enforce_tls"> Obsolete mandatory TLS configuration
+</a> </h3>
+
+<p> The postconf(1) command logs one of the following: </p>
+
+<ul>
+
+<li> support for parameter "lmtp_enforce_tls" will be removed; instead, specify "lmtp_tls_security_level"
+
+<li> support for parameter "smtp_enforce_tls" will be removed; instead, specify "smtp_tls_security_level"
+
+<li> support for parameter "smtpd_enforce_tls" will be removed; instead, specify "smtpd_tls_security_level"
+
+</ul>
+
+<p> There are similarly-named parameters and warnings for postscreen(8)
+and tlsproxy(8), but those parameters should rarely be specified
+by hand. </p>
+
+<p> Replace obsolete configuration with its replacement: </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th width="33%"> Goal </th> <th width="33%"> Obsolete configuration </th> <th> Replacement configuration </th> </tr>
+
+<tr> <td> To turn off mandatory TLS </td> <td> <i>xxx</i>_enforce_tls
+= no </td> <td> <i>xxx</i>_security_level = may </td> </tr>
+
+<tr> <td> To turn on mandatory TLS </td> <td> <i>xxx</i>_enforce_tls
+= yes </td> <td> <i>xxx</i>_security_level = encrypt </td> </tr>
+
+</table>
+
+</blockquote>
+
+<h3> <a name="xxx_per_site"> Obsolete TLS policy table configuration
+</a> </h3>
+
+<p> The postconf(1) command logs one of the following: </p>
+
+<ul>
+
+<li> support for parameter "lmtp_tls_per_site" will be removed;
+instead, specify "lmtp_tls_policy_maps"
+
+<li> support for parameter "smtp_tls_per_site" will be removed;
+instead, specify "smtp_tls_policy_maps"
+
+</ul>
+
+<p> There is similarly-named parameter and warning for tlsproxy(8),
+but that parameter should rarely be specified by hand. </p>
+
+<p> Unfortunately, this is more than a name change: the table format
+has changed too, as has the table search process. There is no simple
+conversion of the obsolete form to its replacement. </p>
+
+<h3> <a name="check_relay_domains"> check_relay_domains </a> </h3>
+
+<p> Depending on the Postfix version, the Postfix SMTP daemon logs
+following warning: </p>
+
+<ul>
+
+<li> support for restriction "check_relay_domains" has been removed
+in Postfix 3.9"; instead, specify "reject_unauth_destination"
+
+<li> support for restriction "check_relay_domains" will be removed
+from Postfix; use "reject_unauth_destination" instead
+
+</ul>
+
+<p> This feature was removed because it would relay based on the
+client domain name, which is not robust. </p>
+
+<p> Recommended configuration to prevent an "open relay" problem
+with the SMTP service on port 25:
+</p>
+
+<blockquote>
+<pre>
+main.cf:
+ smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination
+ ...other restrictions...
+</pre>
+</blockquote>
+
+<p> Or equivalent in smtpd_relay_restrictions. </p>
+
+<h3> <a name="permit_mx_backup"> permit_mx_backup</a> </h3>
+
+<p> The Postfix version 3.9 and later SMTP daemon logs the following
+warning: </p>
+
+<ul>
+
+<li> support for restriction "permit_mx_backup" will be removed
+from Postfix; instead, specify "relay_domains"
+
+</ul>
+
+<p> This feature will be removed because it is too difficult to
+configure recipient address validation, making Postfix a source of
+backscatter bounces. </p>
+
+<p> To specify the domains that Postfix will provide MX backup
+service for, see <a href="STANDARD_CONFIGURATION_README.html#backup">
+Configuring Postfix as primary or backup MX host for a remote
+site</a>. </p>
+
+<h3> <a name="reject_maps_rbl"> reject_maps_rbl</a> </h3>
+
+<p> Depending on the Postfix version, the SMTP daemon logs one of
+the following warnings: </p>
+
+<ul>
+
+<li> support for restriction "reject_maps_rbl" has been removed in
+Postfix 3.9"; instead, specify "reject_rbl_client domain-name"
+
+<li> support for restriction "reject_maps_rbl" will be removed from
+Postfix; use "reject_rbl_client domain-name" instead
+
+</ul>
+
+<p> This feature was replaced because "MAPS RBL" is the name of a
+specific reputation service. The reject_rbl_client feature provides
+a superset of the reject_maps_rbl functionality. </p>
+
+<p> Recommended configuration: </p>
+
+<blockquote>
+<pre>
+main.cf:
+ smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination
+ reject_rbl_client <i>domain-name</i>
+ ...other restrictions...
+</pre>
+</blockquote>
+
+<p> Where <i>domain-name</i> is the domain name of a DNS reputation service. </p>
+
+<h3> <a name="permit_naked_ip_address"> permit_naked_ip_address</a> </h3>
+
+<p> Depending on the Postfix version, the SMTP daemon logs one of
+the following warnings: </p>
+
+<ul>
+
+<li> support for restriction "permit_naked_ip_address" has been
+removed in Postfix 3.9"; instead, specify "permit_mynetworks" or
+"permit_sasl_authenticated"
+
+<li> restriction permit_naked_ip_address is deprecated. Use
+permit_mynetworks or permit_sasl_authenticated instead
+
+</ul>
+
+<p> This feature was removed because it was easy to get a false
+match when smtpd_recipient_restrictions was intended to match a
+remote SMTP client IP address. </p>
+
+<p> Recommended configuration: </p>
+
+<blockquote>
+<pre>
+main.cf:
+ smtpd_recipient_restrictions =
+ permit_mynetworks,
+ permit_sasl_authenticated,
+ reject_unauth_destination
+ reject_rbl_client <i>domain-name</i>
+ ...other restrictions...
+</pre>
+</blockquote>
+
+<p> That is, no restriction on HELO or EHLO syntax. Such restrictions
+ar rarely useful nowadays.
+
+</body>
+
+</html>
diff --git a/proto/INSTALL.html b/proto/INSTALL.html
index 4686f03..50249b2 100644
--- a/proto/INSTALL.html
+++ b/proto/INSTALL.html
@@ -605,6 +605,9 @@ describe how to build Postfix with support for optional features:
<tr> <td> LDAP database</td> <td>LDAP_README</td> <td> Postfix
1.0 </td> </tr>
+<tr> <td> MongoDB database</td> <td>MONGODB_README</td> <td> Postfix
+3.9 </td> </tr>
+
<tr> <td> MySQL database</td> <td>MYSQL_README</td> <td> Postfix
1.0 </td> </tr>
diff --git a/proto/LOCAL_RECIPIENT_README.html b/proto/LOCAL_RECIPIENT_README.html
index a06b81f..2cb3fb2 100644
--- a/proto/LOCAL_RECIPIENT_README.html
+++ b/proto/LOCAL_RECIPIENT_README.html
@@ -57,7 +57,8 @@ all names or addresses of local recipients. A recipient address is
local when its domain matches $mydestination, $inet_interfaces or
$proxy_interfaces. If a local username or address is not listed in
$local_recipient_maps, then the Postfix SMTP server will reject
-the address with "User unknown in local recipient table". </p>
+the address with "User unknown in local recipient table". Other
+Postfix interfaces may still accept an "unknown" recipient. </p>
<p> The default setting, shown below, assumes that you use the
default Postfix local(8) delivery agent for local delivery, where
diff --git a/proto/MAILLOG_README.html b/proto/MAILLOG_README.html
index da1c1a8..13c1091 100644
--- a/proto/MAILLOG_README.html
+++ b/proto/MAILLOG_README.html
@@ -63,10 +63,16 @@ Postfix version. </p>
/var/log/postfix.log. See also the "<a href="#logrotate">Logfile
rotation</a>" section below for logfile management. </p>
+<p> In the example below, specifying maillog_file_permissions is
+optional (Postfix 3.9 and later). The default value is 0600, i.e.,
+only the super-user can access the file; the value 0644 also
+adds 'group' and 'other' read access. </p>
+
<blockquote>
<pre>
# postfix stop
# postconf maillog_file=/var/log/postfix.log
+# postconf maillog_file_permissions=0644 # (Postfix 3.9 and later)
# postfix start
</pre>
</blockquote>
@@ -124,6 +130,10 @@ old logfile. </p>
program is configured with the maillog_file_compressor parameter
(default: gzip). </p>
+<li> <p> The next time it logs an event, postlogd(8) will create a
+new logfile, with permissions specified with the maillog_file_permissions
+parameter (default: 0600). </p>
+
</ul>
<p> Notes: </p>
diff --git a/proto/MILTER_README.html b/proto/MILTER_README.html
index d40d24c..9f9833b 100644
--- a/proto/MILTER_README.html
+++ b/proto/MILTER_README.html
@@ -630,7 +630,7 @@ main.cf: items separated by space or comma. There is one difference:
clients </a></h3>
<p> The smtpd_milter_maps feature supports different Milter settings
-for different client IP addresses. Lookup results override the the
+for different client IP addresses. Lookup results override the
global smtpd_milters setting, and have the same syntax. For example,
to disable Milter settings for local address ranges: </p>
diff --git a/proto/MONGODB_README.html b/proto/MONGODB_README.html
new file mode 100644
index 0000000..f5e1d5f
--- /dev/null
+++ b/proto/MONGODB_README.html
@@ -0,0 +1,263 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>Postfix MongoDB Howto</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head>
+<body>
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix MongoDB Howto</h1>
+<hr>
+
+<h2>MongoDB Support in Postfix</h2>
+
+<p> Postfix can use MongoDB as a source for any of its lookups:
+aliases(5), virtual(5), canonical(5), etc. This allows you to keep
+information for your mail service in a replicated noSQL database
+with fine-grained access controls. By not storing it locally on the
+mail server, the administrators can maintain it from anywhere, and
+the users can control whatever bits of it you think appropriate.
+You can have multiple mail servers using the same information,
+without the hassle and delay of having to copy it to each. </p>
+
+<p> Topics covered in this document:</p>
+
+<ul>
+<li><a href="#build">Building Postfix with MongoDB support</a>
+<li><a href="#config">Configuring MongoDB lookups</a>
+<li><a href="#example_virtual">Example: virtual alias maps</a>
+<li><a href="#example_mailing_list">Example: Mailing lists</a>
+<li><a href="#example_projections">Example: MongoDB projections</a>
+<li><a href="#feedback">Feedback</a>
+<li><a href="#credits">Credits</a>
+</ul>
+
+<h2><a name="build">Building Postfix with MongoDB support</a></h2>
+
+<p>These instructions assume that you build Postfix from source
+code as described in the INSTALL document. Some modification may
+be required if you build Postfix from a vendor-specific source
+package. </p>
+
+<p>The Postfix MongoDB client requires the <b>mongo-c-driver</b>
+library. This can be built from source code from <a
+href="https://github.com/mongodb/mongo-c-driver/releases">the
+mongod-c project</a>, or this can be installed as a binary package
+from your OS distribution, typically named <b>mongo-c-driver</b>,
+<b>mongo-c-driver-devel</b> or <b>libmongoc-dev</b>.
+Installing the mongo-c-driver library may also install <b>libbson</b>
+as a dependency. </p>
+
+<p> To build Postfix with mongodb map support, add to the CCARGS
+environment variable the options -DHAS_MONGODB and -I for the
+directory containing the mongodb headers, and specify the AUXLIBS_MONGODB
+with the libmongoc and libbson libraries, for example:</p>
+
+<blockquote>
+<pre>
+% make tidy
+% make -f Makefile.init makefiles \
+ CCARGS="$CCARGS -DHAS_MONGODB -I/usr/include/libmongoc-1.0 \
+ -I/usr/include/libbson-1.0" \
+ AUXLIBS_MONGODB="-lmongoc-1.0 -lbson-1.0"
+</pre>
+</blockquote>
+
+<p>The 'make tidy' command is needed only if you have previously
+built Postfix without MongoDB support. </p>
+
+<p>If your MongoDB shared library is in a directory that the RUN-TIME
+linker does not know about, add a "-Wl,-R,/path/to/directory" option
+after "-lbson-1.0". Then, just run 'make'.</p>
+
+<h2><a name="config">Configuring MongoDB lookups</a></h2>
+
+<p> In order to use MongoDB lookups, define a MongoDB source as a
+table lookup in main.cf, for example: </p>
+
+<blockquote>
+<pre>
+alias_maps = hash:/etc/aliases, proxy:mongodb:/etc/postfix/mongo-aliases.cf
+</pre>
+</blockquote>
+
+<p> The file /etc/postfix/mongo-aliases.cf can specify a number of
+parameters. For a complete description, see the mongodb_table(5)
+manual page. </p>
+
+<h2><a name="example_virtual">Example: virtual(5) alias maps</a></h2>
+
+<p> Here's a basic example for using MongoDB to look up virtual(5)
+aliases. Assume that in main.cf, you have: </p>
+
+<blockquote>
+<pre>
+virtual_alias_maps = hash:/etc/postfix/virtual_aliases,
+ proxy:mongodb:/etc/postfix/mongo-virtual-aliases.cf
+</pre>
+</blockquote>
+
+<p> and in mongodb:/etc/postfix/mongo-virtual-aliases.cf you have: </p>
+
+<blockquote>
+<pre>
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+result_attribute = username
+</pre>
+</blockquote>
+
+<p>This example assumes mailbox names are stored in a MongoDB backend,
+in a format like:</p>
+
+<blockquote>
+<pre>
+{ "username": "user@example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+</pre>
+</blockquote>
+
+<p>Upon receiving mail for "admin@example.com" that isn't found in the
+/etc/postfix/virtual_aliases database, Postfix will search the
+MongoDB server/cluster listening at port 27017 on some_server. It
+will connect using the provided credentials, and search for any
+entries whose username is, or alias field has "admin@example.com".
+It will return the username attribute of those found, and build a
+list of their email addresses. </p>
+
+<p> Notes: </p>
+
+<ul>
+
+<li><p> As with <b>projection</b> (see below), the Postfix mongodb
+client automatically removes the top-level '_id' field from a
+result_attribute result. </p> </li>
+
+<li><p> The Postfix mongodb client will only parse result fields
+with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
+ignored, with a warning in the logs. </p> </li>
+
+</ul>
+
+<h2><a name="example_mailing_list">Example: Mailing lists</a></h2>
+
+<p>When it comes to mailing lists, one way of implementing one would
+be as below:</p>
+
+<blockquote>
+<pre>
+{ "name": "dev@example.com", "active": 1, "address":
+ [ "hamid@example.com", "wietse@example.com", "viktor@example.com" ] }
+</pre>
+</blockquote>
+
+<p>using the filter below, will result in a comma separated string
+with all email addresses in this list. </p>
+
+<blockquote>
+<pre>
+query_filter = {"name": "%s", "active": 1}
+result_attribute = address
+</pre>
+</blockquote>
+
+<p> Notes: </p>
+
+<ul>
+
+<li><p> As with <b>projection</b> (see below), the Postfix mongodb
+client automatically removes the top-level '_id' field from a
+result_attribute result. </p> </li>
+
+<li><p> The Postfix mongodb client will only parse result fields
+with data types UTF8, INT32, INT64 and ARRAY. Other fields will be
+ignored, with a warning in the logs. </p> </li>
+
+</ul>
+
+<h2><a name="example_projections">Example: advanced projections</a></h2>
+
+<p>This module also supports the use of more complex MongoDB
+projections. There may be some use cases where operations such as
+concatenation are necessary to be performed on the data retrieved
+from the database. Although it is encouraged to keep the database
+design simple enough so this is not necessary, postfix supports the
+use of MongoDB projections to achieve the goal. </p>
+
+<p>Consider the example below:</p>
+
+<blockquote>
+<pre>
+{ "username": "user@example.com",
+ "local_part": "user",
+ "domain": "example.com",
+ "alias": [
+ {"address": "admin@example.com"},
+ {"address": "abuse@example.com"}
+ ],
+ "active": 1
+}
+</pre>
+</blockquote>
+
+<p>virtual_mailbox_maps can be created using below parameters in a
+mongodb:/etc/postfix/mongo-virtual-mailboxes.cf file:</p>
+
+<blockquote>
+<pre>
+uri = mongodb+srv://user_name:password@some_server
+dbname = mail
+collection = mailbox
+query_filter = {"$or": [{"username":"%s"}, {"alias.address": "%s"}], "active": 1}
+projection = { "mail_path": {"$concat": ["$domain", "/", "$local_part"]} }
+</pre>
+</blockquote>
+
+<p>This will return 'example.com/user' path built from the database fields. </p>
+
+<p>A couple of considerations when using projections:</p>
+
+<ul>
+
+<li><p>As with <b>result_attribute</b>, the Postfix mongodb client
+automatically removes the top-level '_id' field from a projection
+result. </p></li>
+
+<li><p> The Postfix mongodb client will only parse fields with data
+types UTF8, INT32, INT64 and ARRAY. Other fields will be ignored,
+with a warning in the logs. It is suggested to exclude any unnecessary
+fields when using a projection. </p></li>
+
+</ul>
+
+<h2><a name="feedback">Feedback</a></h2>
+
+<p> If you have questions, send them to postfix-users@postfix.org.
+Please include relevant information about your Postfix setup:
+MongoDB-related output from postconf, which libraries you built
+with, and such. If your question involves your database contents,
+please include the applicable bits of some database entries. </p>
+
+<h2><a name="credits">Credits</a></h2>
+
+<ul>
+
+<li> Stephan Ferraro (Aionda GmbH) implemented an early version of the
+Postfix MongoDB client.
+
+<li> Hamid Maadani (Dextrous Technologies, LLC) added support for
+projections and %<i>letter</i> interpolation, and added documentation.
+
+<li> Wietse Venema adopted and restructured the code and documentation.
+
+</ul>
+
+</body>
+
+</html>
diff --git a/proto/Makefile.in b/proto/Makefile.in
index 511bd44..f02ab14 100644
--- a/proto/Makefile.in
+++ b/proto/Makefile.in
@@ -19,6 +19,7 @@ HTML = ../html/ADDRESS_CLASS_README.html \
../html/CONTENT_INSPECTION_README.html \
../html/DATABASE_README.html ../html/DB_README.html \
../html/DEBUG_README.html \
+ ../html/DEPRECATION_README.html \
../html/DSN_README.html \
../html/ETRN_README.html ../html/FILTER_README.html \
../html/FORWARD_SECRECY_README.html \
@@ -30,6 +31,7 @@ HTML = ../html/ADDRESS_CLASS_README.html \
../html/LMDB_README.html \
../html/MEMCACHE_README.html \
../html/MILTER_README.html \
+ ../html/MONGODB_README.html \
../html/MULTI_INSTANCE_README.html \
../html/MYSQL_README.html ../html/NFS_README.html \
../html/OVERVIEW.html \
@@ -68,6 +70,7 @@ README = ../README_FILES/ADDRESS_CLASS_README \
../README_FILES/DATABASE_README ../README_FILES/DB_README \
../README_FILES/DEBUG_README \
../README_FILES/DSN_README \
+ ../README_FILES/DEPRECATION_README \
../README_FILES/ETRN_README ../README_FILES/FILTER_README \
../README_FILES/FORWARD_SECRECY_README \
../README_FILES/INSTALL ../README_FILES/IPV6_README \
@@ -78,6 +81,7 @@ README = ../README_FILES/ADDRESS_CLASS_README \
../README_FILES/LMDB_README \
../README_FILES/MEMCACHE_README \
../README_FILES/MILTER_README \
+ ../README_FILES/MONGODB_README \
../README_FILES/MULTI_INSTANCE_README \
../README_FILES/MYSQL_README ../README_FILES/NFS_README \
../README_FILES/OVERVIEW \
@@ -198,6 +202,9 @@ clobber:
../html/DEBUG_README.html: DEBUG_README.html
$(DETAB) $? | $(POSTLINK) >$@
+../html/DEPRECATION_README.html: DEPRECATION_README.html
+ $(DETAB) $? | $(POSTLINK) >$@
+
../html/DSN_README.html: DSN_README.html
$(DETAB) $? | $(POSTLINK) >$@
@@ -240,6 +247,9 @@ clobber:
../html/MILTER_README.html: MILTER_README.html
$(DETAB) $? | $(POSTLINK) >$@
+../html/MONGODB_README.html: MONGODB_README.html
+ $(DETAB) $? | $(POSTLINK) >$@
+
../html/MULTI_INSTANCE_README.html: MULTI_INSTANCE_README.html
$(DETAB) $? | $(POSTLINK) >$@
@@ -381,6 +391,9 @@ clobber:
../README_FILES/DSN_README: DSN_README.html
$(DETAB) $? | $(HT2READ) >$@
+../README_FILES/DEPRECATION_README: DEPRECATION_README.html
+ $(DETAB) $? | $(HT2READ) >$@
+
../README_FILES/ETRN_README: ETRN_README.html
$(DETAB) $? | $(HT2READ) >$@
@@ -420,6 +433,9 @@ clobber:
../README_FILES/MILTER_README: MILTER_README.html
$(DETAB) $? | $(HT2READ) >$@
+../README_FILES/MONGODB_README: MONGODB_README.html
+ $(DETAB) $? | $(HT2READ) >$@
+
../README_FILES/MULTI_INSTANCE_README: MULTI_INSTANCE_README.html
$(DETAB) $? | $(HT2READ) >$@
diff --git a/proto/POSTSCREEN_README.html b/proto/POSTSCREEN_README.html
index eb9c9f5..afd5cd3 100644
--- a/proto/POSTSCREEN_README.html
+++ b/proto/POSTSCREEN_README.html
@@ -120,7 +120,7 @@ of time to deliver spam before their IP address becomes denylisted.
To speed up spam deliveries, zombies make compromises in their SMTP
protocol implementation. For example, they speak before their turn,
or they ignore responses from SMTP servers and continue sending
-mail even when the server tells them to go away. </p>
+commands even when the server tells them to go away. </p>
<p> postscreen(8) uses a variety of measurements to recognize
zombies. First, postscreen(8) determines if the remote SMTP client
@@ -159,7 +159,7 @@ overhead for legitimate clients. </p>
<h2> <a name="quick">Quick tests before everything else</a> </h2>
-<p> Before engaging in SMTP-level tests. postscreen(8) queries a
+<p> Before engaging in SMTP-level tests, postscreen(8) queries a
number of local deny and allowlists. These tests speed up the
handling of known clients. </p>
diff --git a/proto/TLS_README.html b/proto/TLS_README.html
index a390566..d6fe51b 100644
--- a/proto/TLS_README.html
+++ b/proto/TLS_README.html
@@ -2266,82 +2266,124 @@ describe the corresponding table syntax: </p>
additional attributes are supported at this level. </dd>
<dt><b>may</b></dt> <dd><a href="#client_tls_may">Opportunistic TLS</a>.
-The optional "ciphers", "exclude" and "protocols" attributes
-(available for opportunistic TLS with Postfix &ge; 2.6) override the
-"smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols"
-configuration parameters. At this level and higher, the optional
-"servername" attribute (available with Postfix &ge; 3.4) overrides the
-global "smtp_tls_servername" parameter, enabling per-destination
-configuration of the SNI extension sent to the remote SMTP server. </dd>
+The optional "ciphers", "exclude", and "protocols" attributes (available
+for opportunistic TLS with Postfix &ge; 2.6) and "connection_reuse"
+attribute (Postfix &ge; 3.4) override the "smtp_tls_ciphers",
+"smtp_tls_exclude_ciphers", "smtp_tls_protocols", and
+"smtp_tls_connection_reuse" configuration parameters. At this level and
+higher, the optional "servername" attribute (available with Postfix &ge;
+3.4) overrides the global "smtp_tls_servername" parameter, enabling
+per-destination configuration of the SNI extension sent to the remote
+SMTP server. The optional "enable_rpk" attribute (Postfix &ge; 3.9)
+overrides the main.cf smtp_tls_enable_rpk parameter. When opportunistic
+TLS handshakes fail, Postfix retries the connection with TLS disabled.
+This allows mail delivery to sites with non-interoperable TLS
+implementations.</dd>
<dt><b>encrypt</b></dt> <dd><a href="#client_tls_encrypt"> Mandatory encryption</a>.
-Mail is delivered only if the remote SMTP server offers STARTTLS
-and the TLS handshake succeeds. At this level and higher, the optional
+Mail is delivered only if the remote SMTP server offers STARTTLS and the
+TLS handshake succeeds. At this level and higher, the optional
"protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols
-parameter, the optional "ciphers" attribute overrides the
-main.cf smtp_tls_mandatory_ciphers parameter, and the optional
-"exclude" attribute (Postfix &ge; 2.6) overrides the main.cf
-smtp_tls_mandatory_exclude_ciphers parameter. </dd>
+parameter, the optional "ciphers" attribute overrides the main.cf
+smtp_tls_mandatory_ciphers parameter, the optional "exclude" attribute
+(Postfix &ge; 2.6) overrides the main.cf
+smtp_tls_mandatory_exclude_ciphers parameter, and the optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. The optional "enable_rpk" attribute
+(Postfix &ge; 3.9) overrides the main.cf smtp_tls_enable_rpk parameter.
+</dd>
<dt><b>dane</b></dt> <dd><a href="#client_tls_dane">Opportunistic DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
-DNSSEC. If no TLSA records are found, the effective security level
-used is <a href="#client_tls_may">may</a>. If TLSA records are
-found, but none are usable, the effective security level is <a
-href="#client_tls_encrypt">encrypt</a>. When usable TLSA records
-are obtained for the remote SMTP server, SSLv2+3 are automatically
-disabled (see smtp_tls_mandatory_protocols), and the server certificate
-must match the TLSA records. RFC 7672 (DANE) TLS authentication
-and DNSSEC support is available with Postfix 2.11 and later. </dd>
+DNSSEC. If no TLSA records are found, the effective security level used
+is <a href="#client_tls_may">may</a>. If TLSA records are found, but
+none are usable, the effective security level is <a
+href="#client_tls_encrypt">encrypt</a>. When usable TLSA records are
+obtained for the remote SMTP server, the server certificate must match
+the TLSA records (and the SNI name is unconditionally set to the TLSA
+<i>base domain</i>). RFC 7672 (DANE) TLS authentication and DNSSEC
+support is available with Postfix 2.11 and later. The optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. When the effective security level
+used is <a href="#client_tls_may">may</a>, the optional "ciphers",
+"exclude", and "protocols" attributes (Postfix &ge; 2.6) override the
+"smtp_tls_ciphers", "smtp_tls_exclude_ciphers", and "smtp_tls_protocols"
+configuration parameters. When the effective security level used is <a
+href="#client_tls_encrypt">encrypt</a>, the optional "ciphers",
+"exclude", and "protocols" attributes (Postfix &ge; 2.6) override the
+"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
+"smtp_tls_mandatory_protocols" configuration parameters. </dd>
<dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>.
The TLS policy for the destination is obtained via TLSA records in
-DNSSEC. If no TLSA records are found, or none are usable, no
-connection is made to the server. When usable TLSA records are
-obtained for the remote SMTP server, SSLv2+3 are automatically disabled
-(see smtp_tls_mandatory_protocols), and the server certificate must
-match the TLSA records. RFC 7672 (DANE) TLS authentication and
-DNSSEC support is available with Postfix 2.11 and later. </dd>
+DNSSEC. If no TLSA records are found, or none are usable, no connection
+is made to the server. When usable TLSA records are obtained for the
+remote SMTP server, the server certificate must match the TLSA records.
+RFC 7672 (DANE) TLS authentication and DNSSEC support is available with
+Postfix 2.11 and later. The optional "ciphers", "exclude", and
+"protocols" attributes (Postfix &ge; 2.6) override the
+"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
+"smtp_tls_mandatory_protocols" configuration parameters. The optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. </dd>
<dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
-fingerprint verification.</a> Available with Postfix 2.5 and
-later. At this security level, there are no trusted Certification
-Authorities. The certificate trust chain, expiration date, ... are
-not checked. Instead, the optional <b>match</b> attribute, or else
-the main.cf <b>smtp_tls_fingerprint_cert_match</b> parameter, lists
-the server certificate fingerprints or public key fingerprints
-(Postfix 2.9 and later). The
-digest algorithm used to calculate fingerprints is selected by the
-<b>smtp_tls_fingerprint_digest</b> parameter. Multiple fingerprints can
-be combined with a "|" delimiter in a single match attribute, or multiple
-match attributes can be employed. The ":" character is not used as a
-delimiter as it occurs between each pair of fingerprint (hexadecimal)
-digits. </dd>
+fingerprint verification.</a> Available with Postfix 2.5 and later. At
+this security level, there are no trusted Certification Authorities. The
+certificate trust chain, expiration date, ... are not checked. Instead,
+the optional "match" attribute, or else the main.cf
+<b>smtp_tls_fingerprint_cert_match</b> parameter, lists the certificate
+fingerprints or the public key fingerprints (Postfix 2.9 and later) of
+acceptable server certificates. The digest algorithm used to calculate
+the fingerprint is selected by the <b>smtp_tls_fingerprint_digest</b>
+parameter. Multiple fingerprints can be combined with a "|" delimiter in
+a single match attribute, or multiple match attributes can be employed.
+The ":" character is not used as a delimiter as it occurs between each
+pair of fingerprint (hexadecimal) digits. The optional "ciphers",
+"exclude", and "protocols" attributes (Postfix &ge; 2.6) override the
+"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
+"smtp_tls_mandatory_protocols" configuration parameters. The optional
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. The optional "enable_rpk"
+attribute (Postfix &ge; 3.9) overrides the main.cf smtp_tls_enable_rpk
+parameter. </dd>
<dt><b>verify</b></dt> <dd><a href="#client_tls_verify">Mandatory
-server certificate verification</a>. Mail is delivered only if the
-TLS handshake succeeds, if the remote SMTP server certificate can
-be validated (not expired or revoked, and signed by a trusted
-Certification Authority), and if the server certificate name matches
-the optional "match" attribute (or the main.cf smtp_tls_verify_cert_match
-parameter value when no optional "match" attribute is specified).
-With Postfix &ge; 2.11 the "tafile" attribute optionally modifies
-trust chain verification in the same manner as the
-"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute
-may be specified multiple times to load multiple trust-anchor
-files. </dd>
+server certificate verification</a>. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups are presumed to be
+secure enough, and the name verified in the server certificate is
+potentially obtained via unauthenticated DNS MX lookups. The server
+certificate name must match either the optional "match" attribute, or
+else the main.cf smtp_tls_verify_cert_match parameter value. With
+Postfix &ge; 2.11 the "tafile" attribute optionally modifies trust chain
+verification in the same manner as the "smtp_tls_trust_anchor_file"
+parameter. The "tafile" attribute may be specified multiple times to
+load multiple trust-anchor files. The optional "connection_reuse"
+attribute (Postfix &ge; 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. </dd>
<dt><b>secure</b></dt> <dd><a href="#client_tls_secure">Secure certificate
-verification.</a> Mail is delivered only if the TLS handshake succeeds,
-and DNS forgery resistant remote SMTP certificate verification succeeds
-(not expired or revoked, and signed by a trusted Certification Authority),
-and if the server certificate name matches the optional "match" attribute
-(or the main.cf smtp_tls_secure_cert_match parameter value when no optional
-"match" attribute is specified). With Postfix &ge; 2.11 the "tafile"
-attribute optionally modifies trust chain verification in the same manner
-as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute
-may be specified multiple times to load multiple trust-anchor
-files. </dd>
+verification.</a>
+Mail is delivered only if the TLS handshake succeeds, the remote SMTP
+server certificate chain can be validated, and a DNS name in the
+certificate matches the specified match criteria. At this security
+level, DNS MX lookups, though potentially used to determine the
+candidate next-hop gateway IP addresses, are <b>not</b> presumed to be
+secure enough for TLS peername verification. Instead, the default name
+verified in the server certificate is obtained directly from the
+next-hop, or is explicitly specified via the optional "match" attribute
+which overrides the main.cf smtp_tls_secure_cert_match parameter. The
+optional "ciphers", "exclude", and "protocols" attributes (Postfix &ge;
+2.6) override the "smtp_tls_mandatory_ciphers",
+"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+configuration parameters. With Postfix &ge; 2.11 the "tafile" attribute
+optionally modifies trust chain verification in the same manner as the
+"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be
+specified multiple times to load multiple trust-anchor files. The
+optional "connection_reuse" attribute (Postfix &ge; 3.4) overrides the
+main.cf smtp_tls_connection_reuse parameter. </dd>
</dl>
diff --git a/proto/access b/proto/access
index 0fe2a89..a3787a3 100644
--- a/proto/access
+++ b/proto/access
@@ -52,7 +52,7 @@
# .IP "multi-line text"
# A logical line starts with non-whitespace text. A line that
# starts with whitespace continues a logical line.
-# EMAIL ADDRESS PATTERNS
+# EMAIL ADDRESS PATTERNS IN INDEXED TABLES
# .ad
# .fi
# With lookups from indexed files such as DB or DBM, or from networked
@@ -85,7 +85,7 @@
# (e.g., \fIuser+foo\fR@\fIdomain\fR), the lookup order becomes:
# \fIuser+foo\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR, \fIdomain\fR,
# \fIuser+foo\fR@, and \fIuser\fR@.
-# HOST NAME/ADDRESS PATTERNS
+# HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES
# .ad
# .fi
# With lookups from indexed files such as DB or DBM, or from networked
diff --git a/proto/aliases b/proto/aliases
index d2d3f19..f48a00b 100644
--- a/proto/aliases
+++ b/proto/aliases
@@ -7,9 +7,13 @@
# .fi
# \fBnewaliases\fR
# DESCRIPTION
-# The \fBaliases\fR(5) table provides a system-wide mechanism to
-# redirect mail for local recipients. The redirections are
-# processed by the Postfix \fBlocal\fR(8) delivery agent.
+# The optional \fBaliases\fR(5) table (alias_maps) redirects
+# mail for local recipients. The redirections are processed
+# by the Postfix \fBlocal\fR(8) delivery agent.
+#
+# This is unlike \fBvirtual\fR(5) aliasing (virtual_alias_maps)
+# which applies to all recipients: local(8), virtual, and remote,
+# and which is implemented by the \fBcleanup\fR(8) daemon.
#
# Normally, the \fBaliases\fR(5) table is specified as a text file
# that serves as input to the \fBpostalias\fR(1) command. The
@@ -149,7 +153,9 @@
# The alias databases for \fBlocal\fR(8) delivery that are updated with
# "\fBnewaliases\fR" or with "\fBsendmail -bi\fR".
# .IP "\fBalias_maps (see 'postconf -d' output)\fR"
-# The alias databases that are used for \fBlocal\fR(8) delivery.
+# Optional lookup tables with aliases that apply only to \fBlocal\fR(8)
+# recipients; this is unlike virtual_alias_maps that apply to all
+# recipients: \fBlocal\fR(8), virtual, and remote.
# .IP "\fBallow_mail_to_commands (alias, forward)\fR"
# Restrict \fBlocal\fR(8) mail delivery to external commands.
# .IP "\fBallow_mail_to_files (alias, forward)\fR"
diff --git a/proto/canonical b/proto/canonical
index 6364d3e..5ffc8d1 100644
--- a/proto/canonical
+++ b/proto/canonical
@@ -207,17 +207,14 @@
# .PP
# Other parameters of interest:
# .IP "\fBinet_interfaces (all)\fR"
-# The network interface addresses that this mail system receives
-# mail on.
+# The local network interface addresses that this mail system
+# receives mail on.
# .IP "\fBlocal_header_rewrite_clients (permit_inet_interfaces)\fR"
-# Rewrite message header addresses in mail from these clients and
-# update incomplete addresses with the domain name in $myorigin or
-# $mydomain; 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 remote_header_rewrite_domain
-# parameter.
+# Rewrite or add message headers in mail from these clients,
+# updating incomplete addresses with the domain name in $myorigin or
+# $mydomain, and adding missing headers.
# .IP "\fBproxy_interfaces (empty)\fR"
-# The network interface addresses that this mail system receives mail
+# The remote network interface addresses that this mail system receives mail
# on by way of a proxy or network address translation unit.
# .IP "\fBmasquerade_classes (envelope_sender, header_sender, header_recipient)\fR"
# What addresses are subject to address masquerading.
@@ -239,9 +236,10 @@
# \fIlistname\fR-request address localparts when the recipient_delimiter
# is set to "-".
# .IP "\fBremote_header_rewrite_domain (empty)\fR"
-# Don't rewrite message headers from remote clients at all when
-# this parameter is empty; otherwise, rewrite message headers and
-# append the specified domain name to incomplete addresses.
+# Rewrite or add message headers in mail from remote clients if
+# the remote_header_rewrite_domain parameter value is non-empty,
+# updating incomplete addresses with the domain specified in the
+# remote_header_rewrite_domain parameter, and adding missing headers.
# SEE ALSO
# cleanup(8), canonicalize and enqueue mail
# postmap(1), Postfix lookup table manager
diff --git a/proto/generic b/proto/generic
index fdeb1ea..dc0ad41 100644
--- a/proto/generic
+++ b/proto/generic
@@ -188,10 +188,10 @@
# .PP
# Other parameters of interest:
# .IP "\fBinet_interfaces (all)\fR"
-# The network interface addresses that this mail system receives
-# mail on.
+# The local network interface addresses that this mail system
+# receives mail on.
# .IP "\fBproxy_interfaces (empty)\fR"
-# The network interface addresses that this mail system receives mail
+# The remote network interface addresses that this mail system receives mail
# on by way of a proxy or network address translation unit.
# .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR"
# The list of domains that are delivered via the $local_transport
diff --git a/proto/header_checks b/proto/header_checks
index 1aa6f5a..9a6b55c 100644
--- a/proto/header_checks
+++ b/proto/header_checks
@@ -418,34 +418,24 @@
# CONFIGURATION PARAMETERS
# .ad
# .fi
-# .IP \fBbody_checks\fR
-# Lookup tables with content filter rules for message body lines.
-# These filters see one physical line at a time, in chunks of
-# at most \fB$line_length_limit\fR bytes.
-# .IP \fBbody_checks_size_limit\fP
-# The amount of content per message body segment (attachment) that is
-# subjected to \fB$body_checks\fR filtering.
-# .IP \fBheader_checks\fR
-# .IP "\fBmime_header_checks\fR (default: \fB$header_checks\fR)"
-# .IP "\fBnested_header_checks\fR (default: \fB$header_checks\fR)"
-# Lookup tables with content filter rules for message header lines:
-# respectively, these are applied to the initial message headers
-# (not including MIME headers), to the MIME headers anywhere in
-# the message, and to the initial headers of attached messages.
-# .sp
-# Note: these filters see one logical message header at a time, even
-# when a message header spans multiple lines. Message headers that
-# are longer than \fB$header_size_limit\fR characters are truncated.
-# .IP \fBdisable_mime_input_processing\fR
-# While receiving mail, give no special treatment to MIME related
-# message headers; all text after the initial message headers is
-# considered to be part of the message body. This means that
-# \fBheader_checks\fR is applied to all the initial message headers,
-# and that \fBbody_checks\fR is applied to the remainder of the
-# message.
-# .sp
-# Note: when used in this manner, \fBbody_checks\fR will process
-# a multi-line message header one line at a time.
+# .IP "\fBbody_checks (empty)\fR"
+# Optional lookup tables for content inspection as specified in
+# the \fBbody_checks\fR(5) manual page.
+# .IP "\fBbody_checks_size_limit (51200)\fR"
+# How much text in a message body segment (or attachment, if you
+# prefer to use that term) is subjected to body_checks inspection.
+# .IP "\fBheader_checks (empty)\fR"
+# Optional lookup tables for content inspection of primary non-MIME
+# message headers, as specified in the \fBheader_checks\fR(5) manual page.
+# .IP "\fBmime_header_checks ($header_checks)\fR"
+# Optional lookup tables for content inspection of MIME related
+# message headers, as described in the \fBheader_checks\fR(5) manual page.
+# .IP "\fBnested_header_checks ($header_checks)\fR"
+# Optional lookup tables for content inspection of non-MIME message
+# headers in attached messages, as described in the \fBheader_checks\fR(5)
+# manual page.
+# .IP "\fBdisable_mime_input_processing (no)\fR"
+# Turn off MIME processing while receiving mail.
# EXAMPLES
# .ad
# .fi
diff --git a/proto/master b/proto/master
index 28040b6..67477fd 100644
--- a/proto/master
+++ b/proto/master
@@ -219,10 +219,16 @@
# .IP \fB-v\fR
# Increase the verbose logging level. Specify multiple \fB-v\fR
# options to make a Postfix daemon process increasingly verbose.
-# .IP "Other command-line arguments"
+# .IP "\fBCommand-line arguments that start with {\fR"
+# With Postfix 3.0 and later specify "{" and "}" around command
+# arguments that start with "{". The outer "{" and "}" are
+# removed from the input, together with any leading or trailing
+# whitespace.
+# .IP "\fBOther command-line arguments\fR"
# Specify "{" and "}" around command arguments that contain
-# whitespace (Postfix 3.0 and later). Whitespace
-# after "{" and before "}" is ignored.
+# whitespace (Postfix 3.0 and later). The outer "{" and "}"
+# are removed from the input, together with any leading or
+# trailing whitespace.
# SEE ALSO
# master(8), process manager
# postconf(5), configuration parameters
diff --git a/proto/mongodb_table b/proto/mongodb_table
new file mode 100644
index 0000000..81dfc8e
--- /dev/null
+++ b/proto/mongodb_table
@@ -0,0 +1,240 @@
+#++
+# NAME
+# mongodb_table 5
+# SUMMARY
+# Postfix MongoDB client configuration
+# SYNOPSIS
+# \fBpostmap -q "\fIstring\fB" mongodb:/etc/postfix/\fIfilename\fR
+#
+# \fBpostmap -q - mongodb:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
+# DESCRIPTION
+# The Postfix mail system uses optional tables for address
+# rewriting or mail routing. These tables are usually in
+# \fBdbm\fR or \fBdb\fR format.
+#
+# Alternatively, lookup tables can be specified as MongoDB
+# databases. In order to use MongoDB lookups, define a MongoDB
+# source as a lookup table in main.cf, for example:
+# .nf
+# alias_maps = mongodb:/etc/postfix/mongodb-aliases.cf
+# .fi
+#
+# In this example, the file /etc/postfix/mongodb-aliases.cf
+# has the same format as the Postfix main.cf file, and can
+# specify the parameters described below. It is also possible
+# to have the configuration in main.cf; see "OBSOLETE MAIN.CF
+# PARAMETERS" below.
+#
+# It is strongly recommended to use proxy:mongodb, in order
+# to reduce the number of database connections. For example:
+# .nf
+# alias_maps = proxy:mongodb:/etc/postfix/mongodb-aliases.cf
+# .fi
+#
+# Note: when using proxy:mongodb:/\fIfile\fR, the file must
+# be readable by the unprivileged postfix user (specified
+# with the Postfix mail_owner configuration parameter).
+# MONGODB PARAMETERS
+# .ad
+# .fi
+# .IP "\fBuri\fR"
+# The URI of mongo server/cluster that Postfix will try to
+# connect to and query from. Please see
+# .nf
+# https://www.mongodb.com/docs/manual/reference/connection-string/
+# .fi
+#
+# Example:
+# .nf
+# uri = mongodb+srv://user:pass@loclhost:27017/mail
+# .fi
+# .IP "\fBdbname\fR"
+# Name of the database to read the information from.
+# Example:
+# .nf
+# dbname = mail
+# .fi
+# .IP "\fBcollection\fR"
+# Name of the collection (table) to read the information from.
+# Example:
+# .nf
+# collection = mailbox
+# .fi
+# .IP "\fBquery_filter\fR"
+# The MongoDB query template used to search the database,
+# where \fB%s\fR is a substitute for the email address that
+# Postfix is trying to resolve. Please see:
+# .nf
+# https://www.mongodb.com/docs/manual/tutorial/query-documents/
+# .fi
+#
+# Example:
+# .nf
+# query_filter = {"$or": [{"username": "%s"}, {"alias.address": "%s"}], "active": 1}
+# .fi
+#
+# This parameter supports the following '%' expansions:
+# .RS
+# .IP "\fB%%\fR"
+# This is replaced by a literal '%' character.
+# .IP "\fB%s\fR"
+# This is replaced by the input key. The %s must appear in
+# quotes, because all Postfix queries are strings containing
+# (parts from) a domain or email address. Postfix makes no
+# numerical queries.
+# .IP "\fB%u\fR"
+# When the input key is an address of the form user@domain,
+# \fB%u\fR is replaced by the local part of the address.
+# Otherwise, \fB%u\fR is replaced by the entire search string.
+# .IP "\fB%d\fR"
+# When the input key is an address of the form user@domain,
+# \fB%d\fR is replaced by the domain part of the address.
+# .IP "\fB%[1-9]\fR"
+# The patterns %1, %2, ... %9 are replaced by the corresponding
+# most significant component of the input key's domain. If
+# the input key is \fIuser@mail.example.com\fR, then %1 is
+# \fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR.
+# .RE
+# .IP
+# In the above substitutions, characters will be quoted as
+# required by RFC 4627. For example, each double quote or
+# backslash character will be escaped with a backslash
+# characacter.
+# .IP "\fBprojection\fR"
+# Advanced MongoDB query projections. Please see:
+# .nf
+# https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/
+# .fi
+#
+# .RS
+# .IP \(bu
+# If \fBprojection\fR is non-empty, then \fBresult_attribute\fR
+# must be empty.
+# .IP \(bu
+# This implementation can extract information only from result
+# fields that have type \fBstring\fR (UTF8), \fBinteger\fR
+# (int32, int64) and \fBarray\fR. Other result fields will
+# be ignored with a warning. Please see:
+# .nf
+# https://mongoc.org/libbson/current/bson_type_t.html
+# .fi
+# .IP \(bu
+# As with \fBresult_attribute\fR, the top-level _id field
+# (type OID) is automatically removed from projection results.
+# .RE
+# .IP "\fBresult_attribute\fR"
+# Comma or whitespace separated list with the names of fields
+# to be returned in a lookup result.
+#
+# .RS
+# .IP \(bu
+# If \fBresult_attribute\fR is non-empty, then \fBprojection\fR
+# must be empty.
+# .IP \(bu
+# As with \fBprojection\fR, the top-level _id field (type
+# OID) is automatically removed from lookup results.
+# .RE
+# .IP "\fBresult_format (default: \fB%s\fR)\fR"
+# Format template applied to the result from \fBprojection\fR
+# or \fBresult_attribute\fR. Most commonly used to append (or
+# prepend) text to the result. This parameter supports the
+# following '%' expansions:
+# .RS
+# .IP "\fB%%\fR"
+# This is replaced by a literal '%' character.
+# .IP "\fB%s\fR"
+# This is replaced by the value of the result attribute. When
+# result is empty it is skipped.
+# .IP "\fB%u\fR
+# When the result attribute value is an address of the form
+# user@domain, \fB%u\fR is replaced by the local part of the
+# address. When the result has an empty localpart it is
+# skipped.
+# .IP "\fB%d\fR"
+# When a result attribute value is an address of the form
+# user@domain, \fB%d\fR is replaced by the domain part of the
+# attribute value. When the result is unqualified it is
+# skipped.
+# .IP "\fB%[SUD1-9]\fR"
+# The upper-case and decimal digit expansions interpolate the
+# parts of the input key rather than the result. Their behavior
+# is identical to that described with \fBquery_filter\fR, and
+# in fact because the input key is known in advance, lookups
+# whose key does not contain all the information specified
+# in the result template are suppressed and return no results.
+# .RE
+# .IP
+# For example, using "result_format = smtp:[%s]" allows one
+# to use a mailHost attribute as the basis of a transport(5)
+# table. After applying the result format, multiple values
+# are concatenated as comma separated strings. The expansion_limit
+# parameter explained below allows one to restrict the number
+# of values in the result, which is especially useful for
+# maps that should return a single value.
+#
+# The default value \fB%s\fR specifies that each
+# attribute value should be used as is.
+#
+# NOTE: DO NOT put quotes around the result format! The result
+# is not a JSON string.
+# .IP "\fBdomain (default: no domain list)\fR"
+# This is a list of domain names, paths to files, or "type:table"
+# databases. When specified, only fully qualified search keys
+# with a *non-empty* localpart and a matching domain are
+# eligible for lookup: 'user' lookups, bare domain lookups
+# and "@domain" lookups are not performed. This can significantly
+# reduce the query load on the backend database. Example:
+# .nf
+# domain = postfix.org, hash:/etc/postfix/searchdomains
+# .fi
+# .IP "\fBexpansion_limit (default: 0)\fR"
+# A limit on the total number of result elements returned (as
+# a comma separated list) by a lookup against the map. A
+# setting of zero disables the limit. Lookups fail with a
+# temporary error if the limit is exceeded. Setting the limit
+# to 1 ensures that lookups do not return multiple values.
+# OBSOLETE MAIN.CF PARAMETERS
+# .ad
+# .fi
+# MongoDB parameters can also be defined in main.cf. Specify
+# as MongoDB source a name that doesn't begin with a slash
+# or a dot. The MongoDB parameters will then be accessible
+# as the name you've given the source in its definition, an
+# underscore, and the name of the parameter. For example, if
+# a map is specified as "mongodb:\fImongodb_source\fR", the
+# "uri" parameter would be defined in main.cf as
+# "\fImongodb_source\fR_uri".
+#
+# Note: with this form, passwords are written in main.cf,
+# which is normally world-readable, and '$' in a mongodb
+# parameter setting needs to be written as '$$'.
+# SEE ALSO
+# postmap(1), Postfix lookup table maintenance
+# postconf(5), configuration parameters
+# README FILES
+# .ad
+# .fi
+# Use "\fBpostconf readme_directory\fR" or "\fBpostconf
+# html_directory\fR" to locate this information.
+# .na
+# .nf
+# DATABASE_README, Postfix lookup table overview
+# MONGODB_README, Postfix MONGODB client guide
+# LICENSE
+# .ad
+# .fi
+# The Secure Mailer license must be distributed with this software.
+# HISTORY
+# MongoDB support was introduced with Postfix version 3.9.
+# AUTHOR(S)
+# Hamid Maadani (hamid@dexo.tech)
+# Dextrous Technologies, LLC
+#
+# Edited by:
+# Wietse Venema
+# porcupine.org
+#
+# Based on prior work by:
+# Stephan Ferraro
+# Aionda GmbH
+#--
diff --git a/proto/mysql_table b/proto/mysql_table
index a018e58..31e626f 100644
--- a/proto/mysql_table
+++ b/proto/mysql_table
@@ -79,6 +79,24 @@
# .nf
# dbname = customer_database
# .fi
+# .IP "\fBcharset (default: utf8mb4)\fR"
+# The default MySQL client character set; this also implies
+# the collation order.
+#
+# This parameter is available with Postfix 3.9 and later.
+# With earlier Postfix versions, the default was chosen by
+# the MySQL implementation (\fButf8mb4\fR as of MySQL 8.0,
+# \fBlatin1\fR historically).
+# .IP "\fBidle_interval (default: 60)\fR"
+# The number of seconds after which an idle database connection
+# will be closed.
+#
+# This feature is available in Postfix 3.9 and later.
+# .IP "\fBretry_interval (default: 60)\fR"
+# The number of seconds that a database connection will be
+# skipped after an error.
+#
+# This feature is available in Postfix 3.9 and later.
# .IP "\fBquery\fR"
# The SQL query template used to search the database, where \fB%s\fR
# is a substitute for the address Postfix is trying to resolve,
diff --git a/proto/pcre_table b/proto/pcre_table
index 0f58c2b..e4c6607 100644
--- a/proto/pcre_table
+++ b/proto/pcre_table
@@ -190,9 +190,14 @@
#
# Postfix parses the result as if it is a file in /etc/postfix.
#
-# Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
-# Postfix from trying to do \fI$name\fR expansion as it
-# evaluates a parameter value.
+# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
+# to keep Postfix from trying to do \fI$name\fR expansion as
+# it evaluates a parameter value.
+#
+# Note: when using \fI$name\fR inside an inlined pattern, use
+# \eQ\fI$name\fR\eE to disable metacharacters such as '.' in
+# the \fI$name\fR expansion. Otherwise, the pattern may have
+# unexpected matches.
# EXAMPLE SMTPD ACCESS MAP
# # Protect your outgoing majordomo exploders
# /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead
diff --git a/proto/pgsql_table b/proto/pgsql_table
index 0a2897a..b4364fb 100644
--- a/proto/pgsql_table
+++ b/proto/pgsql_table
@@ -80,10 +80,21 @@
# .nf
# encoding = UTF8
# .fi
+#
# Historically, the database client was hard coded to use
# LATIN1 in an attempt to disable multibyte character support.
#
# This feature is available in Postfix 3.8 and later.
+# .IP "\fBidle_interval (default: 60)\fR"
+# The number of seconds after which an idle database connection
+# will be closed.
+#
+# This feature is available in Postfix 3.9 and later.
+# .IP "\fBretry_interval (default: 60)\fR"
+# The number of seconds that a database connection will be
+# skipped after an error.
+#
+# This feature is available in Postfix 3.9 and later.
# .IP "\fBquery\fR"
# The SQL query template used to search the database, where \fB%s\fR
# is a substitute for the address Postfix is trying to resolve,
diff --git a/proto/postconf.proto b/proto/postconf.proto
index f52f37f..d13719b 100644
--- a/proto/postconf.proto
+++ b/proto/postconf.proto
@@ -489,8 +489,14 @@ alias_database = hash:/etc/mail/aliases
%PARAM alias_maps see "postconf -d" output
<p>
-The alias databases that are used for local(8) delivery. See
-aliases(5) for syntax details.
+Optional lookup tables with aliases that apply only to local(8)
+recipients; this is unlike virtual_alias_maps that apply to all
+recipients: local(8), virtual, and remote.
+The table format and lookups are documented in aliases(5). For an
+overview of Postfix address manipulations see the ADDRESS_REWRITING_README
+document. </p>
+
+<p>
Specify zero or more "type:name" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
until a match is found.
@@ -1315,19 +1321,30 @@ name of the message delivery transport.
<p>
The default mail delivery transport and next-hop destination for
-destinations that do not match $mydestination, $inet_interfaces,
+the default domain class: recipient domains that do not match
+$mydestination, $inet_interfaces,
$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
-or $relay_domains. This information can be overruled with the
-sender_dependent_default_transport_maps parameter and with the
-transport(5) table. </p>
+or $relay_domains. This information will not be used when
+sender_dependent_default_transport_maps returns a result, and may
+be overridden with the transport(5) table. </p>
-<p>
-In order of decreasing precedence, the nexthop destination is taken
-from $sender_dependent_default_transport_maps, $default_transport,
-$sender_dependent_relayhost_maps, $relayhost, or from the recipient
-domain.
+<p> For recipient domains in the default domain class: <p>
+
+<ul>
+
+<li> <p> In order of decreasing precedence, the delivery transport
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport.
</p>
+<li> <p> In order of decreasing precedence, the nexthop destination
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain. </p>
+
+</ul>
+
<p>
Specify a string of the form <i>transport:nexthop</i>, where <i>transport</i>
is the name of a mail delivery transport defined in master.cf.
@@ -1766,7 +1783,7 @@ forward_expansion_filter parameter. </p>
<dd>The address extension delimiter that was found in the recipient
address (Postfix 2.11 and later), or the 'first' delimiter specified
with the system-wide recipient address extension delimiter (Postfix
-3.5.22, 3.5.12, 3.7.8, 3.8.3 and later). Historically, this was
+3.5.22, 3.6.12, 3.7.8, 3.8.3 and later). Historically, this was
always the system-wide recipient
address extension delimiter (Postfix 2.10 and earlier). </dd>
@@ -1999,12 +2016,17 @@ Specify 0 to disable the feature. Valid delays are 0..10.
%PARAM inet_interfaces all
-<p> The local network interface addresses that this mail system receives
-mail on. Specify "all" to receive mail on all network
-interfaces (default), and "loopback-only" to receive mail
-on loopback network interfaces only (Postfix version 2.2 and later). The
-parameter also controls delivery of mail to <tt>user@[ip.address]</tt>.
-</p>
+<p> The local network interface addresses that this mail system
+receives mail on. Specify "all" to receive mail on all network
+interfaces (default), "loopback-only" to receive mail on loopback
+network interfaces only (Postfix version 2.2 and later), or zero
+or more IPv4 or IPv6 addresses (IPv6 is supported in Postfix version
+2.2 and later). The parameter also controls whether Postfix will
+accept mail for <tt>user@[ip.address]</tt>, and prevents Postfix
+from delivering mail to a host that has equal or larger MX preference.
+Specify an empty value if Postfix does not receive mail over the
+network, or if all network listeners have an explicit IP address
+in master.cf. </p>
<p>
Note 1: you need to stop and start Postfix when this parameter changes.
@@ -2013,22 +2035,44 @@ Note 1: you need to stop and start Postfix when this parameter changes.
<p> Note 2: address information may be enclosed inside <tt>[]</tt>,
but this form is not required here. </p>
-<p> When inet_interfaces specifies just one IPv4 and/or IPv6 address
-that is not a loopback address, the Postfix SMTP client will use
-this address as the IP source address for outbound mail. Support
-for IPv6 is available in Postfix version 2.2 and later. </p>
+<p> When smtp_bind_address and/or smtp_bind_address6 are not
+specified, the inet_interfaces setting may constrain the source IP
+address for an outbound SMTP or LMTP connection as described below.
+</p>
-<p>
-On a multi-homed firewall with separate Postfix instances listening on the
-"inside" and "outside" interfaces, this can prevent each instance from
-being able to reach remote SMTP servers on the "other side" of the
-firewall. Setting
-smtp_bind_address to 0.0.0.0 avoids the potential problem for
-IPv4, and setting smtp_bind_address6 to :: solves the problem
-for IPv6. </p>
+<p> The following text is specific to SMTP and IPv4. The same
+reasoning applies to the IPv6 protocol, and to the Postfix LMTP
+client. To disable IPv4 or IPv6 support in the Postfix SMTP and
+LMTP client, use inet_protocols. </p>
+
+<ul>
+
+<li> <p> When inet_interfaces specifies one IPv4 address, and that
+is not a loopback address, the Postfix SMTP client uses that as the
+source address for outbound IPv4 connections. </p>
+
+<li> <p> Otherwise, the Postfix SMTP client does not constrain the
+source IPv4 address, and connects using a system-chosen source IPv4
+address. This includes the cases where inet_interfaces is empty,
+where it specifies <b>all</b>, or where it contains no IPv4 address,
+one IPv4 address that is a loopback address, or multiple IPv4
+addresses. </p>
+
+</ul>
+
+<p> A Postfix SMTP client may fail to reach some remote SMTP servers
+when the client source IP address is constrained explicitly with
+smtp_bind_address or smtp_bind_address6, or implicitly with
+inet_interfaces. This can happen when Postfix runs on a multi-homed
+system such as a firewall, the Postfix SMTP source client IP address
+is constrained to one specific network interface, and the remote
+SMTP server must be reached through a different interface. Setting
+smtp_bind_address to 0.0.0.0 avoids the potential problem for IPv4,
+and setting smtp_bind_address6 to :: solves the problem for IPv6.
+</p>
<p>
-A better solution for multi-homed firewalls is to leave inet_interfaces
+A better solution for multi-homed systems is to leave inet_interfaces
at the default value and instead use explicit IP addresses in
the master.cf SMTP server definitions. This preserves the Postfix
SMTP client's
@@ -2056,7 +2100,7 @@ inet_interfaces = 127.0.0.1, [::1] (Postfix version 2.2 and later)
inet_interfaces = 192.168.1.2, 127.0.0.1
</pre>
-%PARAM inet_protocols see 'postconf -d output'
+%PARAM inet_protocols see 'postconf -d' output
<p> The Internet protocols Postfix will attempt to use when making
or accepting connections. Specify one or more of "ipv4"
@@ -2427,8 +2471,8 @@ until a match is found.
<p>
If this parameter is non-empty (the default), then the Postfix SMTP
-server will reject mail for unknown local users.
-</p>
+server will reject mail for unknown local users. Other Postfix
+interfaces may still accept an "unknown" recipient. </p>
<p>
To turn off local recipient checking in the Postfix SMTP server,
@@ -2689,6 +2733,11 @@ and later.</dd>
<dd>The domain part of the recipient address. </dd>
+<dt><b>ENVID</b></dt>
+
+<dd>The optional RFC 3461 envelope ID. Available in Postfix version
+3.9 and later</dd>
+
<dt><b>EXTENSION</b></dt>
<dd>The optional address extension. </dd>
@@ -3849,13 +3898,31 @@ This feature is available in Postfix 2.0 and later.
%PARAM relayhost
<p>
-The next-hop destination(s) for non-local mail; overrides non-local
-domains in recipient addresses. This information is overruled with
-relay_transport, sender_dependent_default_transport_maps,
-default_transport, sender_dependent_relayhost_maps
-and with the transport(5) table.
+The next-hop destination(s) for non-local mail; takes precedence
+over non-local domains in recipient addresses. This information
+will not be used when the sender matches $sender_dependent_relayhost_maps.
</p>
+<p> In order of decreasing precedence: </p>
+
+<ul>
+
+<li> <p> For recipient domains in the relay domain address class
+(domains matching $relay_domains), the nexthop destination is taken
+from 1) $transport_maps, 2) $relay_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain. <p>
+
+<li> <p> For recipient domains in the default domain address class
+(domains that do not match $mydestination, $inet_interfaces,
+$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
+or $relay_domains), the nexthop destination is taken from 1)
+$transport_maps, 2) $sender_dependent_default_transport_maps or
+$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost
+or the recipient domain. </p>
+
+</ul>
+
<p>
On an intranet, specify the organizational domain name. If your
internal DNS uses no MX records, specify the name of the intranet
@@ -3863,11 +3930,12 @@ gateway host instead.
</p>
<p>
-In the case of SMTP or LMTP delivery, specify one or more destinations
-in the form of a domain name, hostname, hostname:port, [hostname]:port,
-[hostaddress] or [hostaddress]:port, separated by comma or whitespace.
-The form [hostname] turns off MX lookups. Multiple destinations are
-supported in Postfix 3.5 and later.
+In the case of SMTP delivery, specify one or more destinations in
+the form of a domain name, hostname, hostname:service, [hostname]:service,
+[hostaddress] or [hostaddress]:service, separated by comma or whitespace.
+The form [hostname] turns off MX or SRV lookups. Multiple destinations
+are supported in Postfix 3.5 and later. Each destination is tried
+in the specified order.
</p>
<p>
@@ -4628,6 +4696,9 @@ If no username:password entry is found, then the Postfix SMTP client
will not attempt to authenticate to the remote host.
</p>
+<p> Use smtp_sasl_password_result_delimiter to specify an
+alternative separator between username and password. </p>
+
<p>
The Postfix SMTP client opens the lookup table before going to
chroot jail, so you can leave the password file in /etc/postfix.
@@ -4639,6 +4710,19 @@ whitespace or comma. Tables will be searched in the specified order
until a match is found.
</p>
+%PARAM lmtp_sasl_password_result_delimiter :
+
+<p> The LMTP-specific version of the smtp_sasl_password_result_delimiter
+configuration parameter. See there for details. </p>
+
+%PARAM smtp_sasl_password_result_delimiter :
+
+<p> The delimiter between username and password in sasl_passwd_maps lookup
+results. Specify one non-whitespace character that does not appear in
+the username. </p>
+
+<p> This feature is available in Postfix &ge; 3.9. </p>
+
%PARAM smtp_sasl_security_options noplaintext, noanonymous
<p> Postfix SMTP client SASL security options; as of Postfix 2.3
@@ -5219,9 +5303,8 @@ pubkey_fingerprint } } </dd>
<dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
-<dd>Search the specified access database for the client hostname,
-parent domains, client IP address, or networks obtained by stripping
-least significant octets. See the access(5) manual page for details. </dd>
+<dd>Search the specified access database for the client hostname
+or IP address. See the access(5) manual page for details. </dd>
<dt><b><a name="check_client_a_access">check_client_a_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
@@ -5252,8 +5335,7 @@ available in Postfix 2.7 and later. </dd>
<dt><b><a name="check_reverse_client_hostname_access">check_reverse_client_hostname_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified access database for the unverified reverse
-client hostname, parent domains, client IP address, or networks
-obtained by stripping least significant octets. See the access(5)
+client hostname or IP address. See the access(5)
manual page for details. Note: a result of "OK" is not allowed for
safety reasons. Instead, use DUNNO in order to exclude specific
hosts from denylists. This feature is available in Postfix 2.6
@@ -5726,8 +5808,8 @@ received with the ETRN command.
<dt><b><a name="check_etrn_access">check_etrn_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
-<dd>Search the specified access database for the ETRN domain name
-or its parent domains. See the access(5) manual page for details.
+<dd>Search the specified access database for the ETRN domain name.
+See the access(5) manual page for details.
</dd>
</dl>
@@ -5842,7 +5924,7 @@ received with the HELO or EHLO command.
<dt><b><a name="check_helo_access">check_helo_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified access(5) database for the HELO or EHLO
-hostname or parent domains, and execute the corresponding action.
+hostname, and execute the corresponding action.
Note: specify "smtpd_helo_required = yes" to fully enforce this
restriction (without "smtpd_helo_required = yes", a client can
simply skip check_helo_access by not sending HELO or EHLO). </dd>
@@ -6137,8 +6219,7 @@ that is received with the RCPT TO command.
<dt><b><a name="check_recipient_access">check_recipient_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified access(5) database for the resolved RCPT
-TO address, domain, parent domains, or localpart@, and execute the
-corresponding action. </dd>
+TO address, and execute the corresponding action. </dd>
<dt><b><a name="check_recipient_a_access">check_recipient_a_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
@@ -6388,7 +6469,7 @@ The same restrictions are available as documented under
smtpd_recipient_restrictions.
</p>
-<p> This feature is available in Postix 2.10 and later. </p>
+<p> This feature is available in Postfix 2.10 and later. </p>
%CLASS sasl-auth SASL Authentication
@@ -6652,8 +6733,7 @@ received with the MAIL FROM command.
<dt><b><a name="check_sender_access">check_sender_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>Search the specified access(5) database for the MAIL FROM
-address, domain, parent domains, or localpart@, and execute the
-corresponding action. </dd>
+address, and execute the corresponding action. </dd>
<dt><b><a name="check_sender_a_access">check_sender_a_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
@@ -6967,7 +7047,14 @@ while accessing the Postfix main.cf configuration file.
<p>
Optional lookup tables with mappings from recipient address to
(message delivery transport, next-hop destination). See transport(5)
-for details.
+for syntax details.
+</p>
+
+<p> This information may override the message delivery transport
+and/or next-hop destination that are specified with $local_transport,
+$virtual_transport, $relay_transport, $default_transport,
+$sender_dependent_relayhost_maps, $relayhost,
+$sender_dependent_default_transport_maps, or the recipient domain.
</p>
<p>
@@ -7224,8 +7311,10 @@ This feature is available in Postfix 2.1 and later.
%PARAM virtual_alias_maps $virtual_maps
<p>
-Optional lookup tables that alias specific mail addresses or domains
-to other local or remote addresses. The table format and lookups
+Optional lookup tables with aliases that apply to all recipients:
+local(8), virtual, and remote; this is unlike alias_maps that apply
+only to local(8) recipients.
+The table format and lookups
are documented in virtual(5). For an overview of Postfix address
manipulations see the ADDRESS_REWRITING_README document.
</p>
@@ -8457,13 +8546,24 @@ configure or operate a specific Postfix subsystem or feature.
<p>
The default mail delivery transport and next-hop destination for
-remote delivery to domains listed with $relay_domains. In order of
-decreasing precedence, the nexthop destination is taken from
-$relay_transport, $sender_dependent_relayhost_maps, $relayhost, or
-from the recipient domain. This information can be overruled with
-the transport(5) table.
+the relay domain address class: recipient domains that match
+$relay_domains. </p>
+
+<p> For recipient domains in the relay domain address class: </p>
+
+<ul>
+
+<li> <p> In order of decreasing precedence, the message delivery
+transport is taken from 1) $transport_maps, 2) $relay_transport.
</p>
+<li> <p> In order of decreasing precedence, the nexthop destination
+is taken from 1) $transport_maps, 2) $relay_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain. </p>
+
+</ul>
+
<p>
Specify a string of the form <i>transport:nexthop</i>, where <i>transport</i>
is the name of a mail delivery transport defined in master.cf.
@@ -9698,7 +9798,9 @@ if client certificate verification is not required. With Postfix 2.8 and
earlier, log the summary message, peer certificate summary information
and unconditionally log trust-chain verification errors. </dd>
-<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
+<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
+library, log session cache operations, and enable OpenSSL logging
+of the progress of the SSL handshake. </dd>
<dt> </dt> <dd> 3 Also log hexadecimal and ASCII dump of TLS negotiation
process. </dd>
@@ -9733,6 +9835,9 @@ but do not require that clients use TLS encryption. </p>
STARTTLS due to insufficient privileges to access the server private
key. This is intended behavior. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+smtpd_tls_security_level instead. </p>
+
<p> This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use smtpd_tls_security_level instead. </p>
@@ -9749,6 +9854,9 @@ server. This option is therefore off by default. </p>
STARTTLS due to insufficient privileges to access the server private
key. This is intended behavior. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+smtpd_tls_security_level instead. </p>
+
<p> This feature is available in Postfix 2.2 and later. With
Postfix 2.3 and later use smtpd_tls_security_level instead. </p>
@@ -10179,7 +10287,9 @@ verification errors if server certificate verification is not required.
With Postfix 2.8 and earlier, log the summary message and unconditionally
log trust-chain verification errors. </dd>
-<dt> </dt> <dd> 2 Also log levels during TLS negotiation. </dd>
+<dt> </dt> <dd> 2 Also enable verbose logging in the Postfix TLS
+library, log session cache operations, and enable OpenSSL logging
+of the progress of the SSL handshake. </dd>
<dt> </dt> <dd> 3 Also log the hexadecimal and ASCII dump of the
TLS negotiation process. </dd>
@@ -10330,11 +10440,13 @@ lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls,
and smtp_tls_enforce_peername settings. </dd>
<dt> MAY </dt> <dd> Try to use TLS if the server announces support,
-otherwise use an unencrypted connection. This has less precedence
+otherwise use an unencrypted connection; after a failed TLS handshake
+or TLS session, fall back to plaintext if the message has spent
+minimal_backoff_time in the mail queue. This level has less precedence
than a more specific result (including <b>NONE</b>) from the alternate
host or next-hop lookup key, and has less precedence than the more
specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername
-= yes". </dd>
+= yes". </dd>
<dt> MUST_NOPEERMATCH </dt> <dd> Require TLS encryption, but do not
require that the remote SMTP server hostname matches the information
@@ -10703,9 +10815,28 @@ is placed into the Postfix configuration directory. </p>
setting. The tables are searched by the envelope sender address and
@domain. A lookup result of DUNNO terminates the search without
overriding the global relayhost parameter setting (Postfix 2.6 and
-later). This information is overruled with relay_transport,
-sender_dependent_default_transport_maps, default_transport and with
-the transport(5) table. </p>
+later). </p>
+
+<p> In order of decreasing precedence: </p>
+
+<ul>
+
+<li> <p> For recipient domains in the relay domain address class
+(domains matching $relay_domains), the nexthop destination is taken
+from 1) $transport_maps, 2) $relay_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain. </p>
+
+<li> <p> For recipient domains in the default domain address class
+(domains that do not match mydestination, $inet_interfaces,
+$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
+$relay_domains), the nexthop destination is taken from 1)
+$transport_maps, 2) $sender_dependent_default_transport_maps or
+$default_transport, 3) $sender_dependent_relayhost_maps or $relayhost
+or the recipient domain. </p>
+
+</ul>
+
<p>
Specify zero or more "type:name" lookup tables, separated by
@@ -10868,6 +10999,9 @@ configuration parameter. See there for details. </p>
<p> The LMTP-specific version of the smtp_tls_per_site configuration
parameter. See there for details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+lmtp_tls_policy_maps instead. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
%PARAM lmtp_generic_maps
@@ -10973,6 +11107,9 @@ configuration parameter. See there for details. </p>
<p> The LMTP-specific version of the smtp_use_tls configuration
parameter. See there for details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+lmtp_tls_security_level instead. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
%PARAM lmtp_enforce_tls no
@@ -10980,6 +11117,9 @@ parameter. See there for details. </p>
<p> The LMTP-specific version of the smtp_enforce_tls configuration
parameter. See there for details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+lmtp_tls_security_level instead. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
%PARAM lmtp_tls_security_level
@@ -11350,28 +11490,35 @@ security are: </p>
<dd>Opportunistic TLS. Since sending in the clear is acceptable,
demanding stronger than default TLS security merely reduces
interoperability. The optional "ciphers", "exclude", and "protocols"
-attributes (available for opportunistic TLS with Postfix &ge; 2.6)
-and "connection_reuse" attribute (Postfix &ge; 3.4) override the
+attributes (available for opportunistic TLS with Postfix &ge; 2.6) and
+"connection_reuse" attribute (Postfix &ge; 3.4) override the
"smtp_tls_ciphers", "smtp_tls_exclude_ciphers", "smtp_tls_protocols",
-and
-"smtp_tls_connection_reuse" configuration parameters. In the policy table,
-multiple ciphers, protocols or excluded ciphers must be separated by colons,
-as attribute values may not contain whitespace or commas. When opportunistic
-TLS handshakes fail, Postfix retries the connection with TLS disabled.
-This allows mail delivery to sites with non-interoperable TLS
-implementations.</dd>
+and "smtp_tls_connection_reuse" configuration parameters. In the policy
+table, multiple ciphers, protocols or excluded ciphers must be separated
+by colons, as attribute values may not contain whitespace or commas. At
+this level and higher, the optional "servername" attribute (available
+with Postfix &ge; 3.4) overrides the global "smtp_tls_servername"
+parameter, enabling per-destination configuration of the SNI extension
+sent to the remote SMTP server. The optional "enable_rpk" attribute
+(Postfix &ge; 3.9) overrides the main.cf smtp_tls_enable_rpk parameter.
+When opportunistic TLS handshakes fail, Postfix retries the connection
+with TLS disabled. This allows mail delivery to sites with
+non-interoperable TLS implementations.</dd>
<dt><b><a href="TLS_README.html#client_tls_encrypt">encrypt</a></b></dt>
-<dd>Mandatory TLS encryption. At this level
-and higher, the optional "protocols" attribute overrides the main.cf
+<dd>Mandatory TLS encryption. Mail is delivered only if the remote SMTP
+server offers STARTTLS and the TLS handshake succeeds. At this level and
+higher, the optional "protocols" attribute overrides the main.cf
smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute
-overrides the main.cf smtp_tls_mandatory_ciphers parameter, the
-optional "exclude" attribute (Postfix &ge; 2.6) overrides the main.cf
+overrides the main.cf smtp_tls_mandatory_ciphers parameter, the optional
+"exclude" attribute (Postfix &ge; 2.6) overrides the main.cf
smtp_tls_mandatory_exclude_ciphers parameter, and the optional
-"connection_reuse" attribute (Postfix &ge; 3.4) overrides the
-main.cf smtp_tls_connection_reuse parameter. In the policy table,
-multiple ciphers, protocols or excluded ciphers must be separated by colons,
-as attribute values may not contain whitespace or commas. </dd>
+"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
+smtp_tls_connection_reuse parameter. In the policy table, multiple
+ciphers, protocols or excluded ciphers must be separated by colons, as
+attribute values may not contain whitespace or commas. The optional
+"enable_rpk" attribute (Postfix &ge; 3.9) overrides the main.cf
+smtp_tls_enable_rpk parameter. </dd>
<dt><b><a href="TLS_README.html#client_tls_dane">dane</a></b></dt>
<dd>Opportunistic DANE TLS. The TLS policy for the destination is
@@ -11416,10 +11563,10 @@ configuration parameters. The optional "connection_reuse" attribute
verification. Available with Postfix 2.5 and later. At this security
level, there are no trusted Certification Authorities. The certificate
trust chain, expiration date, ... are not checked. Instead,
-the optional "match" attribute, or else the main.cf
+the optional policy table "match" attribute, or else the main.cf
<b>smtp_tls_fingerprint_cert_match</b> parameter, lists the certificate
-fingerprints or the public key fingerprint (Postfix 2.9 and later)
-of the valid server certificate. The digest
+fingerprints or the public key fingerprints (Postfix 2.9 and later)
+of acceptable server certificates. The digest
algorithm used to calculate the fingerprint is selected by the
<b>smtp_tls_fingerprint_digest</b> parameter. Multiple fingerprints can
be combined with a "|" delimiter in a single match attribute, or multiple
@@ -11430,45 +11577,58 @@ digits. The optional "ciphers", "exclude", and "protocols" attributes
"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
configuration parameters. The optional "connection_reuse" attribute
(Postfix &ge; 3.4) overrides the main.cf smtp_tls_connection_reuse
-parameter. </dd>
+parameter. The optional "enable_rpk" attribute (Postfix &ge; 3.9)
+overrides the main.cf smtp_tls_enable_rpk parameter. </dd>
<dt><b><a href="TLS_README.html#client_tls_verify">verify</a></b></dt>
-<dd>Mandatory TLS verification. At this security
-level, DNS MX lookups are trusted to be secure enough, and the name
-verified in the server certificate is usually obtained indirectly via
-unauthenticated DNS MX lookups. The optional "match" attribute overrides
-the main.cf smtp_tls_verify_cert_match parameter. In the policy table,
-multiple match patterns and strategies must be separated by colons.
-In practice explicit control over matching is more common with the
-"secure" policy, described below. The optional "ciphers", "exclude",
-and "protocols" attributes (Postfix &ge; 2.6) override the
-"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
-"smtp_tls_mandatory_protocols" configuration parameters. The optional
-"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
-smtp_tls_connection_reuse parameter. </dd>
+<dd>Mandatory TLS verification. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups are presumed to be
+secure enough, and the name verified in the server certificate is
+potentially obtained via unauthenticated DNS MX lookups. The optional
+"match" attribute overrides the main.cf smtp_tls_verify_cert_match
+parameter. In the policy table, multiple match patterns and strategies
+must be separated by colons. In practice explicit control over matching
+is more common with the "secure" policy, described below. The optional
+"ciphers", "exclude", and "protocols" attributes (Postfix &ge; 2.6)
+override the "smtp_tls_mandatory_ciphers",
+"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+configuration parameters. With Postfix &ge; 2.11 the optional "tafile"
+policy table attribute modifies trust chain verification in the same
+manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
+attribute may be specified multiple times to load multiple trust-anchor
+files. The optional "connection_reuse" attribute (Postfix &ge; 3.4)
+overrides the main.cf smtp_tls_connection_reuse parameter. </dd>
<dt><b><a href="TLS_README.html#client_tls_secure">secure</a></b></dt>
-<dd>Secure-channel TLS. At this security level, DNS
-MX lookups, though potentially used to determine the candidate next-hop
-gateway IP addresses, are <b>not</b> trusted to be secure enough for TLS
-peername verification. Instead, the default name verified in the server
-certificate is obtained directly from the next-hop, or is explicitly
-specified via the optional "match" attribute which overrides the
-main.cf smtp_tls_secure_cert_match parameter. In the policy table,
-multiple match patterns and strategies must be separated by colons.
-The match attribute is most useful when multiple domains are supported by
-a common server: the policy entries for additional domains specify matching
-rules for the primary domain certificate. While transport table overrides
-that route the secondary domains to the primary nexthop also allow secure
-verification, they risk delivery to the wrong destination when domains
-change hands or are re-assigned to new gateways. With the "match"
-attribute approach, routing is not perturbed, and mail is deferred if
-verification of a new MX host fails. The optional "ciphers", "exclude",
-and "protocols" attributes (Postfix &ge; 2.6) override the
-"smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers", and
-"smtp_tls_mandatory_protocols" configuration parameters. The optional
-"connection_reuse" attribute (Postfix &ge; 3.4) overrides the main.cf
-smtp_tls_connection_reuse parameter. </dd>
+<dd>Secure certificate verification. Mail is delivered only if the TLS
+handshake succeeds, the remote SMTP server certificate chain can be
+validated, and a DNS name in the certificate matches the specified match
+criteria. At this security level, DNS MX lookups, though potentially
+used to determine the candidate next-hop gateway IP addresses, are
+<b>not</b> presumed to be secure enough for TLS peername verification.
+Instead, the default name verified in the server certificate is obtained
+directly from the next-hop, or is explicitly specified via the optional
+"match" attribute which overrides the main.cf smtp_tls_secure_cert_match
+parameter. In the policy table, multiple match patterns and strategies
+must be separated by colons. The match attribute is most useful when
+multiple domains are supported by a common server: the policy entries
+for additional domains specify matching rules for the primary domain
+certificate. While transport table overrides that route the secondary
+domains to the primary nexthop also allow secure verification, they risk
+delivery to the wrong destination when domains change hands or are
+re-assigned to new gateways. With the "match" attribute approach,
+routing is not perturbed, and mail is deferred if verification of a new
+MX host fails. The optional "ciphers", "exclude", and "protocols"
+attributes (Postfix &ge; 2.6) override the "smtp_tls_mandatory_ciphers",
+"smtp_tls_mandatory_exclude_ciphers", and "smtp_tls_mandatory_protocols"
+configuration parameters. With Postfix &ge; 2.11 the "tafile" attribute
+optionally modifies trust chain verification in the same manner as the
+"smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may be
+specified multiple times to load multiple trust-anchor files. The
+optional "connection_reuse" attribute (Postfix &ge; 3.4) overrides the
+main.cf smtp_tls_connection_reuse parameter. </dd>
</dl>
@@ -11724,7 +11884,7 @@ configuration parameter. See there for details. </p>
<p> This feature is available in Postfix 2.3 and later. </p>
-%PARAM lmtp_tls_mandatory_protocols see postconf -d output
+%PARAM lmtp_tls_mandatory_protocols see 'postconf -d' output
<p> The LMTP-specific version of the smtp_tls_mandatory_protocols
configuration parameter. See there for details. </p>
@@ -11831,7 +11991,9 @@ destinations via smtp_tls_policy_maps. </dd>
<dt><b><a href="TLS_README.html#client_tls_may">may</a></b></dt>
<dd> Opportunistic TLS. Use TLS if this is supported by the remote
-SMTP server, otherwise use plaintext. Since
+SMTP server, otherwise use plaintext; after a failed TLS handshake
+or TLS session, fall back to plaintext if the message has spent
+minimal_backoff_time in the mail queue. Since
sending in the clear is acceptable, demanding stronger than default TLS
security merely reduces interoperability.
The "smtp_tls_ciphers" and "smtp_tls_protocols" (Postfix &ge; 2.6)
@@ -12902,7 +13064,7 @@ the hostname and IP address. The logging format is "host[address]:port".
<p> This feature is available in Postfix 2.5 and later. </p>
-%PARAM smtp_tls_protocols see postconf -d output
+%PARAM smtp_tls_protocols see 'postconf -d' output
<p> TLS protocols that the Postfix SMTP client will use with
opportunistic TLS encryption. In main.cf the values are separated by
@@ -12982,7 +13144,7 @@ smtp_tls_protocols = !SSLv2, !SSLv3
<p> This feature is available in Postfix 2.6 and later. </p>
-%PARAM smtpd_tls_protocols see postconf -d output
+%PARAM smtpd_tls_protocols see 'postconf -d' output
<p> TLS protocols accepted by the Postfix SMTP server with opportunistic
TLS encryption. If the list is empty, the server supports all available
@@ -13048,7 +13210,7 @@ smtpd_tls_protocols = !SSLv2, !SSLv3
<p> This feature is available in Postfix 2.6 and later. </p>
-%PARAM lmtp_tls_protocols see postconf -d output
+%PARAM lmtp_tls_protocols see 'postconf -d' output
<p> The LMTP-specific version of the smtp_tls_protocols configuration
parameter. See there for details. </p>
@@ -14353,9 +14515,9 @@ receive a 421 response. </p>
%PARAM postscreen_greet_ttl 1d
-<p> The amount of time that postscreen(8) will use the result from
-a successful PREGREET test. During this time, the client IP address
-is excluded from this test. The default is relatively short, because
+<p> The amount of time that postscreen(8) remembers that a client
+IP address passed a PREGREET test, before it is required to pass
+that test again. The default is relatively short, because
a good client can immediately talk to a real Postfix SMTP server. </p>
<p> Specify a non-zero time value (an integral value plus an optional
@@ -14813,18 +14975,38 @@ address and @domain. A lookup result of DUNNO terminates the search
without overriding the global default_transport parameter setting.
This information is overruled with the transport(5) table. </p>
-<p>
-Specify zero or more "type:name" lookup tables, separated by
-whitespace or comma. Tables will be searched in the specified order
-until a match is found.
+<p> This setting affects only the default domain address class
+(recipient domains that do not match $mydestination, $inet_interfaces,
+$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
+or $relay_domains): </p>
+
+<ul>
+
+<li> <p> In order of decreasing precedence, the delivery transport
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport.
</p>
+<li> <p> In order of decreasing precedence, the nexthop destination
+is taken from 1) $transport_maps, 2)
+$sender_dependent_default_transport_maps or $default_transport, 3)
+$sender_dependent_relayhost_maps or $relayhost or the recipient
+domain. </p>
+
+</ul>
+
<p> Note: this overrides default_transport, not transport_maps, and
therefore the expected syntax is that of default_transport, not the
syntax of transport_maps. Specifically, this does not support the
transport_maps syntax for null transport, null nexthop, or null
email addresses. </p>
+<p>
+Specify zero or more "type:name" lookup tables, separated by
+whitespace or comma. Tables will be searched in the specified order
+until a match is found.
+</p>
+
<p> For safety reasons, this feature does not allow $number
substitutions in regular expression maps. </p>
@@ -14865,13 +15047,38 @@ IPv6 connectivity: </p>
<ul>
<li> <p> The setting "smtp_address_preference = ipv6" is unsafe.
-It can fail to deliver mail when there is an outage that affects
-IPv6, while the destination is still reachable over IPv4. </p>
+All deliveries will suffer delays during an IPv6 outage, even
+while the destination is still reachable over IPv4. Mail may be
+stuck in the queue with Postfix versions &lt; 3.3 that do not
+implement "smtp_balance_inet_protocols". For similar reasons, the
+setting "smtp_address_preference = ipv4" is also unsafe. </p>
<li> <p> The setting "smtp_address_preference = any" is safe. With
-this, mail will eventually be delivered even if there is an outage
+this, and "smtp_balance_inet_protocols = yes" (the default), only
+half of deliveries will suffer delays if there is an outage
that affects IPv6 or IPv4, as long as it does not affect both. </p>
+<li> <p> The setting "smtp_address_preference = ipv4" is not a
+solution for remote servers that flag email received over IPv6 as
+more 'spammy' (the client IPv6 address has a bad or missing PTR or
+AAAA record, bad network neighbors, etc.). Instead, configure Postfix
+to receive mail over both IPv4 and IPv6, and to deliver mail over
+only IPv4. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+ inet_protocols = all
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+/etc/postfix/master.cf
+ smtp ...other fields... smtp -o inet_protocols=ipv4
+</pre>
+</blockquote>
+
</ul>
<p> This feature is available in Postfix 2.8 and later. </p>
@@ -14938,9 +15145,10 @@ defined with the postscreen_dnsbl_sites parameter. </p>
<p> Specify a negative value to enable this feature. When a client
passes the postscreen_dnsbl_allowlist_threshold without having
failed other tests, all pending or disabled tests are flagged as
-completed with a time-to-live value equal to postscreen_dnsbl_ttl.
-When a test was already completed, its time-to-live value is updated
-if it was less than postscreen_dnsbl_ttl. </p>
+completed with an expiration time based on the DNS reply TTL.
+When a test was already completed, its expiration time is updated
+if it was less than the value based on the DNS reply TTL. See
+also postscreen_dnsbl_max_ttl and postscreen_dnsbl_min_ttl. </p>
<p> This feature is available in Postfix 3.6 and later. </p>
@@ -14966,9 +15174,9 @@ built-in SMTP protocol engine. </p>
%PARAM postscreen_dnsbl_ttl 1h
-<p> The amount of time that postscreen(8) will use the result from
-a successful DNS-based reputation test before a client
-IP address is required to pass that test again. </p>
+<p> The amount of time that postscreen(8) remembers that a client
+IP address passed a DNS-based reputation test, before it is required
+to pass that test again. </p>
<p> Specify a non-zero time value (an integral value plus an optional
one-letter suffix that specifies the time unit). Time units: s
@@ -14980,9 +15188,9 @@ replaced by postscreen_dnsbl_max_ttl in Postfix 3.1. </p>
%PARAM postscreen_dnsbl_min_ttl 60s
-<p> The minimum amount of time that postscreen(8) will use the
-result from a successful DNS-based reputation test before a
-client IP address is required to pass that test again. If the DNS
+<p> The minimum amount of time that postscreen(8) remembers that a
+client IP address passed a DNS-based reputation test, before it
+is required to pass that test again. If the DNS
reply specifies a larger TTL value, that value will be used unless
it would be larger than postscreen_dnsbl_max_ttl. </p>
@@ -14995,9 +15203,9 @@ The default time unit is s (seconds). </p>
%PARAM postscreen_dnsbl_max_ttl ${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h
-<p> The maximum amount of time that postscreen(8) will use the
-result from a successful DNS-based reputation test before a
-client IP address is required to pass that test again. If the DNS
+<p> The maximum amount of time that postscreen(8) remembers that a
+client IP address passed a DNS-based reputation test, before it is
+required to pass that test again. If the DNS
reply specifies a shorter TTL value, that value will be used unless
it would be smaller than postscreen_dnsbl_min_ttl. </p>
@@ -15043,9 +15251,9 @@ this test the next time the client connects. </dd>
%PARAM postscreen_pipelining_ttl 30d
-<p> The amount of time that postscreen(8) will use the result from
-a successful "pipelining" SMTP protocol test. During this time, the
-client IP address is excluded from this test. The default is
+<p> The amount of time that postscreen(8) remembers that a client
+IP address passed a "pipelining" SMTP protocol test, before it is
+required to pass that test again. The default is
long because a good client must disconnect after it passes the test,
before it can talk to a real Postfix SMTP server. </p>
@@ -15140,9 +15348,9 @@ feature. </dd>
%PARAM postscreen_non_smtp_command_ttl 30d
-<p> The amount of time that postscreen(8) will use the result from
-a successful "non_smtp_command" SMTP protocol test. During this
-time, the client IP address is excluded from this test. The default
+<p> The amount of time that postscreen(8) remembers that a client
+IP address passed a "non_smtp_command" SMTP protocol test, before
+it is required to pass that test again. The default
is long because a client must disconnect after it passes the test,
before it can talk to a real Postfix SMTP server. </p>
@@ -15233,9 +15441,9 @@ this test the next time the client connects. </dd>
%PARAM postscreen_bare_newline_ttl 30d
-<p> The amount of time that postscreen(8) will use the result from
-a successful "bare newline" SMTP protocol test. During this
-time, the client IP address is excluded from this test. The default
+<p> The amount of time that postscreen(8) remembers that a client
+IP address passed a "bare newline" SMTP protocol test, before it
+address is required to pass that test again. The default
is long because a remote SMTP client must disconnect after it passes
the test,
before it can talk to a real Postfix SMTP server. </p>
@@ -15542,6 +15750,9 @@ for details. </p>
require that clients use TLS encryption. See smtpd_enforce_tls for
further details. Use tlsproxy_tls_security_level instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_tls_security_level instead. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
%PARAM tlsproxy_tls_CAfile $smtpd_tls_CAfile
@@ -15616,6 +15827,8 @@ smtpd_tls_dcert_file for further details. </p>
should use with non-export EDH ciphers. See smtpd_tls_dh1024_param_file
for further details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Do not specify. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
%PARAM tlsproxy_tls_dh512_param_file $smtpd_tls_dh512_param_file
@@ -15668,6 +15881,8 @@ the "tlsproxy_tls_chain_files" parameter. </p>
elliptic-curve Diffie-Hellman (EECDH) key exchange. See
smtpd_tls_eecdh_grade for further details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Do not specify. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
%PARAM tlsproxy_tls_exclude_ciphers $smtpd_tls_exclude_ciphers
@@ -15772,6 +15987,9 @@ shared by all three services, namely smtpd_tls_session_cache_timeout. </p>
but do not require that clients use TLS encryption. See smtpd_use_tls
for further details. Use tlsproxy_tls_security_level instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_tls_security_level instead. </p>
+
<p> This feature is available in Postfix 2.8 and later. </p>
%PARAM smtpd_reject_footer
@@ -17575,6 +17793,9 @@ was previously called tlsproxy_client_level. </p>
usage policy by next-hop destination and by remote TLS server
hostname. See smtp_tls_per_site for further details. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_client_policy_maps instead. </p>
+
<p> This feature is available in Postfix 3.4 and later. </p>
%PARAM tlsproxy_client_policy $smtp_tls_policy_maps
@@ -17601,6 +17822,9 @@ was previously called tlsproxy_client_policy. </p>
support. See smtp_use_tls for further details. Use
tlsproxy_client_security_level instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_client_security_level instead. </p>
+
<p> This feature is available in Postfix 3.4 and later. </p>
%PARAM tlsproxy_client_enforce_tls $smtp_enforce_tls
@@ -17609,6 +17833,9 @@ tlsproxy_client_security_level instead. </p>
See smtp_enforce_tls for further details. Use
tlsproxy_client_security_level instead. </p>
+<p> This feature is deprecated as of Postfix 3.9. Specify
+tlsproxy_client_security_level instead. </p>
+
<p> This feature is available in Postfix 3.4 and later. </p>
%PARAM smtpd_tls_chain_files
@@ -18145,6 +18372,17 @@ default suffix, YYYYMMDD-HHMMSS, allows logs to be rotated frequently.
<p> This feature is available in Postfix 3.4 and later. </p>
+%PARAM maillog_file_permissions 0600
+
+<p> The file access permissions that will be set when the file
+$maillog_file is created for the first time, or when the file is
+created after an existing file is rotated. Specify one of: <b>0600</b>
+(only super-user read/write access), <b>0640</b> (adds 'group' read
+access), or <b>0644</b> (also adds 'other' read access). The leading
+'0' is optional. </p>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
%PARAM info_log_address_format external
<p> The email address form that will be used in non-debug logging
@@ -18495,6 +18733,140 @@ configuration parameter. See there for details. </p>
<p> This feature is available in Postfix 3.7 and later. </p>
+%PARAM smtpd_tls_enable_rpk no
+
+<p> Request that remote SMTP clients send an RFC7250 raw public key
+instead of an X.509 certificate, when asking for or requiring client
+authentication. This feature is ignored when there is no raw public
+key support in the local TLS implementation. </p>
+
+<p> The Postfix SMTP server will log a warning when "smtpd_tls_enable_rpk
+= yes", but the remote SMTP client sends a certificate, the
+certificate's public key fingerprint does not match a check_ccert_access
+table, while the certificate fingerprint does match a check_ccert_access
+table. The remote SMTP client would lose access when it starts
+sending a raw public key instead of a certificate, after its TLS
+implementation is updated with raw public key support. </p>
+
+<p> The Postfix SMTP server always sends a raw public key instead
+of a certificate, if solicited by the remote SMTP client and the
+local TLS implementation supports raw public keys. If the client
+sends a server name indication with an SNI TLS extension, and
+tls_server_sni_maps is configured, the server will extract a raw
+public key from the indicated certificate. </p>
+
+<p> Sample commands to compute certificate and public key SHA256 digests: </p>
+
+<pre>
+# SHA256 digest of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -pubkey -noout |
+ openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first private key in "pkey.pem"
+$ openssl pkey -in pkey.pem -pubout -outform DER |
+ openssl dgst -sha256 -c
+</pre>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+%PARAM tlsproxy_tls_enable_rpk $smtpd_tls_enable_rpk
+
+<p> Request that remote SMTP clients send an RFC7250 raw public key
+instead of an X.509 certificate, when asking or requiring client
+authentication. See $smtpd_tls_enable_rpk for details. </p>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+%PARAM smtp_tls_enable_rpk no
+
+<p> Request that remote SMTP servers send an RFC7250 raw public key
+instead of an X.509 certificate. This feature and the enable_rpk
+policy attribute are ignored when there is no raw public key support
+in the local TLS implementation. </p>
+
+<ul>
+
+<li> <p> At the "may", "encrypt" and "fingerprint" security levels,
+with parameter setting "smtp_tls_enable_rpk = yes" or with "enable_rpk
+= yes" in a policy entry, the Postfix SMTP client will indicate in
+the TLS handshake that it prefers to receive a raw server public
+key, but it will still accept a server public key certificate. </p>
+
+<li> <p> At the "fingerprint" security level, with parameter setting
+"smtp_tls_enable_rpk = yes" or with "enable_rpk = yes" in a policy
+entry, server authentication based on certificate fingerprints
+becomes more fragile. Even if the server private key and certificate
+remain unchanged, the remote SMTP server will fail fingerprint
+authentication (won't match the configured list of fingerprints)
+when it starts sending a raw public key instead of a certificate,
+after its TLS implementation is updated with raw public key support.
+Therefore, <b>DO NOT</b> enable raw public keys to remote destinations
+authenticated by server <b>certificate</b> fingerprints. You should
+enable raw public keys only for servers matched via their public
+key fingerprint. </p>
+
+<li> <p> At the "verify" and "secure" security levels, the Postfix
+SMTP client always ignores the parameter setting smtp_tls_enable_rpk
+or the enable_rpk policy attribute. </p>
+
+<li> <p> At the opportunistic "dane" security level, the Postfix
+SMTP client ignores the parameter setting smtp_tls_enable_rpk or
+the enable_rpk policy attribute (but it will respect them when it
+falls back to the "may" or "encrypt" level). When all valid TLSA
+records specify only server public keys (no certificates) and the
+local TLS implementation supports raw public keys, the client will
+indicate in the TLS handshake that it prefers to receive a raw
+public key, but it will still accept a public key certificate. </p>
+
+<li> <p> At the mandatory "dane-only" security level, the Postfix
+SMTP client always ignores the parameter setting smtp_tls_enable_rpk
+or the enable_rpk policy attribute. When all valid TLSA records
+specify only server public keys (no certificates) and the local TLS
+implementation supports raw public keys, the client will indicate
+in the TLS handshake that it prefers to receive a raw public key,
+but it will still accept a public key certificate. </p>
+
+</ul>
+
+<p>The Postfix SMTP client is always willing to send raw public keys
+to servers that solicit them when a client certificate is configured
+and the local TLS implementation supports raw public keys. </p>
+
+<p> Sample commands to compute certificate and public key SHA256 digests: </p>
+
+<pre>
+# SHA256 digest of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first certificate in "cert.pem"
+$ openssl x509 -in cert.pem -pubkey -noout |
+ openssl pkey -pubin -outform DER | openssl dgst -sha256 -c
+</pre>
+
+<pre>
+# SHA256 digest of the SPKI of the first private key in "pkey.pem"
+$ openssl pkey -in pkey.pem -pubout -outform DER |
+ openssl dgst -sha256 -c
+</pre>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
+%PARAM lmtp_tls_enable_rpk yes
+
+<p> The LMTP-specific version of the smtp_tls_enable_rpk
+configuration parameter. See there for details. </p>
+
+<p> This feature is available in Postfix 3.9 and later. </p>
+
%PARAM use_srv_lookup
<p> Enables discovery for the specified service(s) using DNS SRV
@@ -18629,8 +19001,7 @@ via the tls_config_file parameter. When empty, or when the
selected name is not present in the configuration file, the default
application name ("openssl_conf") is used as a fallback. </p>
-<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
-3.6.10, and 3.5.20. </p>
+<p> This feature is available in Postfix &ge; 3.9. </p>
%PARAM tls_config_file default
@@ -18719,7 +19090,7 @@ MinProtocol = TLSv1
<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20. </p>
-%PARAM smtpd_forbid_bare_newline Postfix &lt; 3.9: no
+%PARAM smtpd_forbid_bare_newline Postfix &ge; 3.9: normalize
<p> Reject or restrict input lines from an SMTP client that end in
&lt;LF&gt; instead of the standard &lt;CR&gt;&lt;LF&gt;. Such line
@@ -18732,7 +19103,8 @@ SMTP smuggling</a>. </p>
<dl compact>
-<dt> <b>normalize</b></dt> <dd> Require the standard
+<dt> <b>normalize</b> (default for Postfix &ge; 3.9) </dt>
+<dd> Require the standard
End-of-DATA sequence &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;.
Otherwise, allow command or message content lines ending in the
non-standard &lt;LF&gt;, and process them as if the client sent the
@@ -18744,6 +19116,13 @@ with the standard End-of-DATA sequence
&lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;. <br> <br> Such clients
can be excluded with smtpd_forbid_bare_newline_exclusions. </dd>
+<dt> <b>note</b> </dt> <dd> Same as "normalize", but also notes in
+the log whether the Postfix SMTP server received any lines with
+"bare &lt;LF&gt;". The information is formatted as "<tt>disconnect
+from name[address] ... notes=bare_lf</tt>". The notes value is
+expected to become a list of comma-separated names. <br> <br> This
+feature is available in Postfix 3.9 and later. </dd>
+
<dt> <b>yes</b> </dt> <dd> Compatibility alias for <b>normalize</b>. </dd>
<dt> <b>reject</b> </dt> <dd> Require the standard End-of-DATA
@@ -18762,8 +19141,8 @@ of BDAT violations, BDAT can be selectively disabled with
smtpd_discard_ehlo_keyword_address_maps, or globally disabled with
smtpd_discard_ehlo_keywords). </dd>
-<dt> <b>no</b> (default)</dt> <dd> Do not require the standard
-End-of-DATA
+<dt> <b>no</b> (default for Postfix &lt; 3.9) </dt>
+<dd> Do not require the standard End-of-DATA
sequence &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;. Always process
a bare &lt;LF&gt; as if the client sent &lt;CR&gt;&lt;LF&gt;. This
option is fully backwards compatible, but is not recommended for
@@ -18889,9 +19268,24 @@ implementation-dependent manner. </p>
<p> Disconnect remote SMTP clients that violate RFC 2920 (or 5321)
command pipelining constraints. The server replies with "554 5.5.0
Error: SMTP protocol synchronization" and logs the unexpected remote
-SMTP client input. Specify "smtpd_forbid_unauth_pipelining = yes"
-to enable. This feature is enabled by default with Postfix &ge;
-3.9. </p>
+SMTP client input. This feature is enabled by default with Postfix
+&ge; 3.9. Specify "smtpd_forbid_unauth_pipelining = no" to disable.
+</p>
<p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
3.6.10, and 3.5.20. </p>
+
+%PARAM force_mime_input_conversion no
+
+<p> Convert body content that claims to be 8-bit into quoted-printable,
+before header_checks, body_checks, Milters, and before after-queue
+content filters. This feature does not affect messages that are
+sent into smtpd_proxy_filter. </p>
+
+<p> The typical use case is an MTA that applies this conversion
+before signing outbound messages, so that the signatures will remain
+valid when a message is later delivered to an MTA that does not
+announce 8BITMIME support, or when a message line exceeds the SMTP
+length limit. </p>
+
+<p> This feature is available in Postfix &ge; 3.9. </p>
diff --git a/proto/regexp_table b/proto/regexp_table
index 1c38472..5e8c15f 100644
--- a/proto/regexp_table
+++ b/proto/regexp_table
@@ -147,9 +147,14 @@
#
# Postfix parses the result as if it is a file in /etc/postfix.
#
-# Note: if a rule contains \fB$\fR, specify \fB$$\fR to keep
-# Postfix from trying to do \fI$name\fR expansion as it
-# evaluates a parameter value.
+# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR
+# to keep Postfix from trying to do \fI$name\fR expansion as
+# it evaluates a parameter value.
+#
+# Note: when using \fI$name\fR inside an inlined pattern,
+# this will not disable metacharacters such as '.' in the
+# \fI$name\fR expansion. To prevent unexpected matches, use
+# a pcre: table, and specify \eQ\fI$name\fR\eE.
# EXAMPLE SMTPD ACCESS MAP
# # Disallow sender-specified routing. This is a must if you relay mail
# # for other domains.
diff --git a/proto/relocated b/proto/relocated
index a0a54ca..b517b35 100644
--- a/proto/relocated
+++ b/proto/relocated
@@ -125,8 +125,8 @@
# .PP
# Other parameters of interest:
# .IP "\fBinet_interfaces (all)\fR"
-# The network interface addresses that this mail system receives
-# mail on.
+# The local network interface addresses that this mail system
+# receives mail on.
# .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR"
# The list of domains that are delivered via the $local_transport
# mail delivery transport.
@@ -134,7 +134,7 @@
# The domain name that locally-posted mail appears to come
# from, and that locally posted mail is delivered to.
# .IP "\fBproxy_interfaces (empty)\fR"
-# The network interface addresses that this mail system receives mail
+# The remote network interface addresses that this mail system receives mail
# on by way of a proxy or network address translation unit.
# SEE ALSO
# trivial-rewrite(8), address resolver
diff --git a/proto/socketmap_table b/proto/socketmap_table
index be01054..52d1f47 100644
--- a/proto/socketmap_table
+++ b/proto/socketmap_table
@@ -13,7 +13,7 @@
# \fBpostmap -q - socketmap:unix:\fIpathname\fB:\fIname\fB <\fIinputfile\fR
# DESCRIPTION
# The Postfix mail system uses optional tables for address
-# rewriting. mail routing or policy lookup.
+# rewriting, mail routing or policy lookup.
#
# The Postfix socketmap client expects TCP endpoint names of
# the form \fBinet:\fIhost\fB:\fIport\fB:\fIname\fR, or
diff --git a/proto/stop b/proto/stop
index 0ad3511..beec6d2 100644
--- a/proto/stop
+++ b/proto/stop
@@ -1182,7 +1182,6 @@ Nexthop
OP
OTIFY
OpenSSL's
-Postix
Pt
SECG
SSLEAY
@@ -1577,3 +1576,37 @@ Korbar
ffdhe
srv
stderr
+charset
+latin
+utf
+mb
+SPKI
+certificate's
+pubout
+rpk
+sni
+Amawalk
+resychronization
+ENVID
+netcat
+probers
+lf
+EOD
+chunking
+allowlists
+FWS
+mongodb
+Aionda
+Ferraro
+GmbH
+Hamid
+LLC
+Maadani
+GTEST
+MONGODB
+MongoDB
+Sakaguchi
+Toshifumi
+envid
+manpages
+rr
diff --git a/proto/stop.double-cc b/proto/stop.double-cc
index 8efd133..bff4534 100644
--- a/proto/stop.double-cc
+++ b/proto/stop.double-cc
@@ -333,3 +333,5 @@ void void cleanup_milter_receive state count
Available in in Postfix version 2 3 3 7
length length of 0 31 0 127
address address string length
+ whether the standard End of DATA sequence CRLF CRLF is required and
+ Require CRLF CRLF
diff --git a/proto/stop.double-history b/proto/stop.double-history
index c1026c8..f6df421 100644
--- a/proto/stop.double-history
+++ b/proto/stop.double-history
@@ -12,7 +12,6 @@
Fix by Viktor Dukhovni Files tls tls h tls tls_dane c
Discovered by Benny Pedersen File postscreen postscreen c
proto postconf proto src tlsproxy tlsproxy c src smtpd smtpd c
- proto postconf proto src tlsproxy tlsproxy c src smtpd smtpd c
src tls tls h src tls tls_proxy_client_misc c src tls tls_misc c
src global mail_params h src smtp smtp c
attacks Fix by Viktor Dukhovni Files tls tls h tls_client c
@@ -25,18 +24,98 @@
arguments Files src dns dns h src dns dns_rr_eq_sa c
only a subset of all arguments Files src dns dns h
global mail_params h smtp smtp c smtpd smtpd c tls tls_misc c
- global mail_params h smtp smtp c smtpd smtpd c tls tls_misc c
tls tls_proxy_client_scan c tls tls_proxy h tlsproxy tlsproxy c
smtp smtp c smtpd smtpd c tls tls_misc c
- smtp smtp c smtpd smtpd c tls tls_misc c
proto proto SASL_README html proto SQLITE_README html
proto postconf proto global mail_params h smtp smtp c
smtpd smtpd c tls tls_misc c tls tls_proxy_client_misc c
tls tls_proxy h tlsproxy tlsproxy c
postfix postfix c postlog postlog c
- postfix postfix c postlog postlog c
util net_mask_top hc smtpd smtpd c smtpd smtpd_peer c
util inet_prefix_top hc smtpd smtpd c smtpd smtpd_peer c
File smtp smtp h
manpage File postscreen postscreen c
Files postconf postconf h postconf postconf_dbms c
+proto proto ADDRESS_REWRITING_README html
+ proto postconf proto proto ADDRESS_REWRITING_README html
+ cleanup cleanup c local local c smtpd smtpd c
+ postfix postfix c
+ aliasing Files proto aliases proto virtual postfix postfix c
+proto proto aliases proto virtual proto ADDRESS_REWRITING_README html
+ master master c postlog postlog c postlogd postlogd c
+ proto postconf proto proto aliases proto virtual
+ posttls finger posttls finger c smtp smtp c smtp smtp_proto c
+ tls tls_client c tls tls h tls tls_misc c
+ tls tls_proxy h tls tls_server c tlsproxy tlsproxy c
+ Cleanup removed some the the instances Files
+ clients Files posttls finger posttls finger c smtp smtp c
+ smtp smtp c smtp smtp_proto c tls tls_client c tls tls h
+ smtp smtp c smtpd smtpd c tls tls_client c tls tls h
+ smtp smtp_proto c tls tls h tls tls_proxy_client_misc c
+ tls tls_server c tlsproxy tlsproxy c
+ tlsproxy tlsproxy c
+ proto postconf proto smtp smtp c smtpd smtpd c
+ pipelining before the server greeting File smtpd smtpd c
+ before the server greeting File smtpd smtpd c
+ global mail_params h smtpd smtpd c proto postconf proto
+ Typo fix by Trent W Buck Files proto postconf proto proto stop
+ smtp smtp c smtp smtp h smtp smtp_params c smtp smtp_proto c
+ smtp smtp_tls_policy c smtpd smtpd c smtpd smtpd_check c
+ tls tls h tls tls_client c tls tls_dane c tls tls_fprint c
+ reported by Serg File smtp smtp h
+ smtp lmtp_params c smtp smtp c smtp smtp_params c
+ plaintext Problem reported by Serg File smtp smtp h
+ cleanup cleanup c cleanup cleanup_init c proto postconf proto
+ smtpd smtpd c
+ proto postconf proto postscreen postscreen c
+ global maillog_client c master master c smtp smtp c
+ src postalias postalias c src postmap postmap c
+ src postalias postalias c src postmap postmap c
+ src smtpd smtpd c src smtpd smtpd_check c
+ not proxymap or proxywrite File proxymap proxymap c
+ still has its all zero SIZE record File postcat postcat c
+ manpage text File smtp smtp c
+ manpage text Files smtp smtp c global mail_proto h
+ File proxymap proxymap c
+ on process name Files smtp smtp c global mail_proto h
+ client process name File proxymap proxymap c
+ available Files local command c local local c
+ ID if available File pipe pipe c
+ global smtp_stream h smtpd smtpd c
+ global smtp_stream c global smtp_stream h smtpd smtpd c
+ log the helo mail and rcpt information Files smtpd smtpd c
+ LF LF or LF CR LF before responding This increases
+ smtpd smtpd c global smtp_stream hc global cleanup_user h
+ smtpd smtpd c smtpd smtpd_check c
+ keep reading message content after an unexpected LF LF
+ forms Files proto postconf proto smtpd smtpd c
+ CR LF CR CR LF File global smtp_stream c
+ CR LF CR CR LF There is no smuggling vulnerability
+ sequence mail systems send CR LF CR CR LF instead
+ global mail_params h cleanup cleanup c cleanup cleanup_message c
+ Files smtpd smtpd c proto postconf proto RELEASE_NOTES
+ stable releases Files global smtp_stream hc smtpd smtpd c
+ Files global smtp_stream hc smtpd smtpd c
+ Files smtpd smtpd c proto postconf proto
+ names Files smtpd smtpd hc
+ or access control limitations Files smtpd smtpd hc
+ spam the log with a warning message File tlsmgr tlsmgr c
+ Cleanup tlsmgr c fix 20240124 File tlsmgr tlsmgr c
+ MX or SRV records File smtp smtp c
+ a list of comma separated names Files smtpd smtpd hc
+ dnsblog dnsblog c postkick postkick c postlock postlock c
+ postdrop postdrop c postsuper postsuper c sendmail sendmail c
+ postlogd postlogd c
+ qmgr qmgr c qmqpd qmqpd c trivial rewrite trivial rewrite c
+ strategies File smtp smtp c
+ postconf postconf c postconf postconf_dbms c postconf postconf h
+ postconf postconf c postconf postconf_unused c
+ postfix start start fg check reload status Files
+ Files postconf postconf c postconf postconf_unused c
+ the commands postfix start start fg check reload or
+ status Files postconf postconf c postconf postconf_dbms c
+ postconf postconf h conf postfix script conf post install
+ postconf postconf c postconf postconf_dbms c
+ File tlsmgr tlsmgr c
+ restrictions Files dns dns h dns dns_lookup c dns dns_rr c
+ systems 6 bytes for LP64 File dns dns h
diff --git a/proto/stop.double-install-proto-text b/proto/stop.double-install-proto-text
index 338286e..4e3f43d 100644
--- a/proto/stop.double-install-proto-text
+++ b/proto/stop.double-install-proto-text
@@ -39,3 +39,7 @@ root root you
shlib_directory shlib_directory
user foo domain user domain domain
virtual virtual alias domain anything right hand content does not matter
+ skipping unexpected LF LF in DATA from
+Inbound SMTP smuggling strip extra CR in CR LF CR CR LF
+Inbound SMTP smuggling don t strip extra CR in CR LF CR CR LF
+ CR LF CR CR LF to silence false alarms from test tools
diff --git a/proto/stop.double-proto-html b/proto/stop.double-proto-html
index c216f95..a4b2332 100644
--- a/proto/stop.double-proto-html
+++ b/proto/stop.double-proto-html
@@ -42,7 +42,6 @@ dd dd The default algorithm is b sha256 b with Postfix ge 3 6
dd No TLS TLS will not be used unless enabled for specific
Dec 4 04 30 09 hostname postfix smtpd 58549 NOQUEUE reject
default_transport uucp uucp gateway
- different client IP addresses Lookup results override the the global
Documentation Documentation is available as README files start with the file
done done
done done
@@ -202,8 +201,6 @@ smtp_tls_mandatory_protocols SSLv2 SSLv3 TLSv1 TLSv1 1
SSLv3 TLSv1 TLSv1 1 TLSv1 2 and TLSv1 3 Starting with
T 5 10 20 40 80 160 320 640 1280 1280
T A 5 10 20 40 80 160 320 320
- The and match and literally Without the the
- The matches literally Without the the would
Therefore 301 0301 0x301 and 0x0301 are all equivalent to
The syntax of name value value name value and name value
the the backed up domain tld domain This prevents your mail queue
@@ -246,3 +243,118 @@ dt dt b name value b Postfix ge 3 0 dt
parametername stress something something Other
p Note on OpenBSD systems specify dev dev arandom when dev dev urandom
user3 example net smtp smtp relay example net submission
+ virtual_alias_maps hash etc postfix virtual virtual aliasing
+system_wide_settings system_wide_settings
+ssl_library_settings ssl_library_settings
+initial_ssl_settings initial_ssl_settings
+postfix_settings postfix_settings
+postfix_ssl_settings postfix_ssl_settings
+baseline_postfix_settings baseline_postfix_settings
+ The and match and literally Without the the
+ The matches literally Without the the would
+ The example is simplified for educational purposes In reality my patterns list multiple domain names as domain domain
+ The matches literally Without the the would match any character
+ The and match and literally Without the the and would be grouping operators
+ The matches literally Without the the would match any character
+ pipeline all commands following EHLO for example MAIL RCPT BDAT BDAT MAIL RCPT BDAT without ever having to wait for a server response This means that with BDAT the Postfix SMTP server cannot distinguish between a well behaved client and a
+ NOTE Postfix 3 6 also introduces support for the level level and other operators to compare compatibility levels With the standard operators etc compatibility level 3 10 would be smaller than 3 9 which is undesirable
+ Otherwise the benefits of SMTP connection caching are minor it eliminates the latency of the TCP handshake SYN SYN ACK ACK plus the latency of the SMTP initial handshake 220 greeting EHLO command EHLO response With TLS encrypted
+ Otherwise the benefits of SMTP connection caching are minor it eliminates the latency of the TCP handshake SYN SYN ACK ACK plus the latency of the SMTP initial handshake 220 greeting EHLO command EHLO response With TLS encrypted
+ 3 Reject the mail by sending a suitable status code back to Postfix Postfix will send the mail back to the sender address
+ Line 8 NEVER NEVER NEVER use the t command line option here It will mis deliver mail like sending messages from a mailing list back to the mailing list
+ Line 8 NEVER NEVER NEVER use the t command line option here It will mis deliver mail like sending messages from a mailing list back to the mailing list
+Documentation Documentation is available as README files start with the file README_FILES AAAREADME as HTML web pages point your browser to html index html and as UNIX style manual pages
+ Parameters whose defaults can be specified in this way are listed below See the postconf 5 manpage for a description command nroff man man man5 postconf 5 less
+ Parameters whose defaults can be specified in this way are listed below See the postconf 5 manpage for a description command nroff man man man5 postconf 5 less
+mynetworks mynetworks 127 0 0 0 8 168 100 189 0 28 1 128 fe80 10 2001 240 587 64
+Postfix Postfix can use an LDAP directory as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated network database with fine grained access controls By not
+ If you re using the libraries from the UM distribution http www umich edu dirsvcs ldap ldap html or OpenLDAP http www openldap org something like this in the top level of your Postfix source tree should work
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop owner cn root dc your dc com
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop owner cn root dc your dc com
+ As of Postfix version 2 0 the Postfix SMTP server rejects mail for unknown recipients in local domains domains that match mydestination or the IP addresses in inet_interfaces or proxy_interfaces with User unknown in local recipient table
+ Postfix emulates a limited number of Sendmail macros as shown in the table Some macro values depend on whether a recipient is rejected rejected recipients are available on request by the Milter application Different macros are available at
+ Postfix has TWO sets of mail filters filters that are used for SMTP mail only specified with the smtpd_milters parameter and filters for non SMTP mail specified with the non_smtpd_milters parameter The non SMTP filters are primarily for
+ etc usr usr bin var var spool and so on This is especially an issue if you executed postfix install see above as an unprivileged user
+ etc usr usr bin var var spool and so on This is especially an issue if you executed postfix install see above as an unprivileged user
+ parametername stress something stress something or parametername stress something something Other parameters always evaluate as if the stress value is the empty string
+ parametername stress something stress something or parametername stress something something Other parameters always evaluate as if the stress value is the empty string
+ more CPU faster disks and more network bandwidth can deal with larger deferred queues but as a rule of thumb the deferred queue scales to somewhere between 100 000 and 1 000 000 messages with good performance unlikely above that limit
+ 31 sasldb Accounts are stored stored in a Cyrus SASL Berkeley DB database
+ assigned to the delivery slots might look like this 12131415 Hmm fine for sneaking in the single recipient mail but how do we sneak in the mail with more than one recipient Say if we have one four recipient mail followed by two two recipient
+ we see the hundred recipient job can accumulate ten free delivery slots and then we could preempt it and sneak in the ten recipient mail Wait wait wait Could we Aren t we overinflating the original one thousand recipient mail
+ The truth is that it turns out that it is not really necessary to wait until the jobs counter accumulates all the delivery slots in advance Say we have ten recipient mail followed by two two recipient mails If the preemption happened when enough
+ Disallowing RFC 822 address syntax example MAIL FROM the dude dude example com
+ 3 Reject the mail by sending a suitable SMTP status code back to Postfix Postfix passes the status back to the remote SMTP client This way Postfix does not have to send a bounce message
+ Lines 14 18 Define the list of valid addresses in the the backed up domain tld domain This prevents your mail queue from filling up with undeliverable MAILER DAEMON messages If you can t maintain a list of valid recipients then you must
+ The syntax of name value value name value and name value is explained at the beginning of the postconf 5 manual page
+ Use 521 SMTP reply codes Postfix 2 6 and later or 421 Postfix 2 3 2 5 to hang up on clients that that match botnet related RBLs see next bullet or that match selected non RBL restrictions such as SMTP access maps The Postfix SMTP
+ the next hop destination can have the Postfix specific form name name port name or name port
+ dt b a name no_unknown_recipient_checks no_unknown_recipient_checks a b dt
+ dt b a name check_ccert_access check_ccert_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_client_access check_client_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_client_a_access check_client_a_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_client_mx_access check_client_mx_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_client_ns_access check_client_ns_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_reverse_client_hostname_access check_reverse_client_hostname_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_reverse_client_hostname_a_access check_reverse_client_hostname_a_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_reverse_client_hostname_mx_access check_reverse_client_hostname_mx_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_reverse_client_hostname_ns_access check_reverse_client_hostname_ns_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_sasl_access check_sasl_access a i a href DATABASE_README html type table a i b dt
+ dt b a name permit_sasl_authenticated permit_sasl_authenticated a b dt
+ dt b a name permit_tls_all_clientcerts permit_tls_all_clientcerts a b dt
+ dt b a name reject_rbl_client reject_rbl_client i rbl_domain d d d d i a b dt
+ dt b a name permit_dnswl_client permit_dnswl_client i dnswl_domain d d d d i a b dt
+ dt b a name reject_rhsbl_client reject_rhsbl_client i rbl_domain d d d d i a b dt
+ dt b a name permit_rhswl_client permit_rhswl_client i rhswl_domain d d d d i a b dt
+ dt b a name reject_rhsbl_reverse_client reject_rhsbl_reverse_client i rbl_domain d d d d i a b dt
+ dt b a name reject_unknown_client_hostname reject_unknown_client_hostname a b with Postfix lt 2 3 reject_unknown_client dt
+ dt b a name reject_unknown_reverse_client_hostname reject_unknown_reverse_client_hostname a b dt
+ dt b a name reject_unknown_forward_client_hostname reject_unknown_forward_client_hostname a b dt
+ dt b a name check_policy_service check_policy_service i servername i a b dt
+ dt b a name reject_multi_recipient_bounce reject_multi_recipient_bounce a b dt
+ dt b a name check_etrn_access check_etrn_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_helo_access check_helo_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_helo_a_access check_helo_a_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_helo_mx_access check_helo_mx_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_helo_ns_access check_helo_ns_access a i a href DATABASE_README html type table a i b dt
+ dt b a name reject_invalid_helo_hostname reject_invalid_helo_hostname a b with Postfix lt 2 3 reject_invalid_hostname dt
+ dt b a name reject_non_fqdn_helo_hostname reject_non_fqdn_helo_hostname a b with Postfix lt 2 3 reject_non_fqdn_hostname dt
+ dt b a name reject_rhsbl_helo reject_rhsbl_helo i rbl_domain d d d d i a b dt
+ dt b a name reject_unknown_helo_hostname reject_unknown_helo_hostname a b with Postfix lt 2 3 reject_unknown_hostname dt
+ dt b a name check_recipient_access check_recipient_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_recipient_a_access check_recipient_a_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_recipient_mx_access check_recipient_mx_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_recipient_ns_access check_recipient_ns_access a i a href DATABASE_README html type table a i b dt
+ dt b a name reject_non_fqdn_recipient reject_non_fqdn_recipient a b dt
+ dt b a name reject_rhsbl_recipient reject_rhsbl_recipient i rbl_domain d d d d i a b dt
+ dt b a name reject_unauth_destination reject_unauth_destination a b dt
+ dt b a name reject_unknown_recipient_domain reject_unknown_recipient_domain a b dt
+ dt b a name reject_unlisted_recipient reject_unlisted_recipient a b with Postfix version 2 0 check_recipient_maps dt
+ dt b a name reject_unverified_recipient reject_unverified_recipient a b dt
+ dt b a name check_sender_access check_sender_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_sender_a_access check_sender_a_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_sender_mx_access check_sender_mx_access a i a href DATABASE_README html type table a i b dt
+ dt b a name check_sender_ns_access check_sender_ns_access a i a href DATABASE_README html type table a i b dt
+ dt b a name reject_authenticated_sender_login_mismatch reject_authenticated_sender_login_mismatch a b dt
+ dt b a name reject_known_sender_login_mismatch reject_known_sender_login_mismatch a b dt
+ dt b a name reject_rhsbl_sender reject_rhsbl_sender i rbl_domain d d d d i a b dt
+ dt b a name reject_sender_login_mismatch reject_sender_login_mismatch a b dt
+ dt b a name reject_unauthenticated_sender_login_mismatch reject_unauthenticated_sender_login_mismatch a b dt
+ dt b a name reject_unknown_sender_domain reject_unknown_sender_domain a b dt
+ dt b a name check_address_map check_address_map a i a href DATABASE_README html type table a i b dt
+ PARAM postscreen_dnsbl_max_ttl postscreen_dnsbl_ttl postscreen_dnsbl_ttl 1 h
+standard lt CR gt lt LF gt br br This maintains compatibility
+ lt CR gt lt LF gt lt CR gt lt LF gt br br Such clients
+ smtpd_forbid_bare_newline_reject_code br br This will reject
+ br br This will also reject some email from Microsoft services
+2045 Sections 2 7 and 2 8 br br Such clients can be excluded
+ br br This will also reject email from services that use BDAT
+RFC 2045 Sections 2 7 and 2 8 br br Such clients can be
+to become a list of comma separated names br br This feature
+the form of a domain name hostname hostname service hostname service
+expected to become a list of comma separated names br br This
+Postfix Postfix can use MongoDB as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated noSQL database with fine grained access controls By not storing it
+ CCARGS CCARGS DHAS_MONGODB I usr include libmongoc 1 0
+ dt dt dd 2 Also enable verbose logging in the Postfix TLS
diff --git a/proto/stop.spell-cc b/proto/stop.spell-cc
index 3da6690..097c7ac 100644
--- a/proto/stop.spell-cc
+++ b/proto/stop.spell-cc
@@ -1386,7 +1386,6 @@ th
tha
thash
THASH
-theadsafe
threadsafe
thusly
timecmp
@@ -1443,7 +1442,7 @@ tv
txn
TXT
Typechecking
-TYPECONNSTRING
+TYPECONNSTR
typedef
typedefs
TYPEINET
@@ -1801,3 +1800,42 @@ bitcount
bytecount
ipproto
cw
+uncreate
+MFLAGS
+CRED
+RPK
+RPKs
+SPKI
+peerpkey
+rpk
+ep
+inlined
+stringz
+Sarvepalli
+uXXXX
+Aionda
+Ferraro
+GmbH
+Hamid
+LLC
+Maadani
+MongoDB
+PRId
+bson
+dexo
+hamid
+itoa
+libmongoc
+mongdb
+mongo
+mongodb
+mongodbconf
+Dextrous
+Mongo
+SUD
+qtype
+depr
+dfhHnopqvx
+fhHoqvx
+foqvx
+ILP
diff --git a/proto/stop.spell-history b/proto/stop.spell-history
index 096da09..6b009ed 100644
--- a/proto/stop.spell-history
+++ b/proto/stop.spell-history
@@ -56,3 +56,23 @@ Valgrind
Florian
Piekert
refactored
+Fumiyasu
+SATOH
+INI
+Serg
+Kinzler
+smtpstone
+spammy
+Birta
+Levente
+MariaDB
+dehtml
+NONPROD
+LC
+Philosof
+MONGODB
+Refactored
+Vijay
+Sakaguchi
+Toshifumi
+mxonly
diff --git a/proto/stop.spell-proto-html b/proto/stop.spell-proto-html
index 1912240..79c1ce5 100644
--- a/proto/stop.spell-proto-html
+++ b/proto/stop.spell-proto-html
@@ -357,3 +357,20 @@ kDHE
srv
wraptls
api
+MinProtocol
+spammy
+concat
+hamid
+ina
+lbson
+libbson
+libmobgo
+libmongoc
+lmongoc
+mongo
+mongod
+noSQL
+srv
+viktor
+MONGODB
+MongoDB
diff --git a/proto/virtual b/proto/virtual
index 6e32881..e1935f0 100644
--- a/proto/virtual
+++ b/proto/virtual
@@ -10,13 +10,14 @@
#
# \fBpostmap -q - /etc/postfix/virtual <\fIinputfile\fR
# DESCRIPTION
-# The optional \fBvirtual\fR(5) alias table rewrites recipient
-# addresses for all local, all virtual, and all remote mail
-# destinations.
-# This is unlike the \fBaliases\fR(5) table which is used
-# only for \fBlocal\fR(8) delivery. This feature is implemented
+# The optional \fBvirtual\fR(5) alias table (virtual_alias_maps)
+# applies to all recipients: local(8), virtual, and remote.
+# This feature is implemented
# in the Postfix \fBcleanup\fR(8) daemon before mail is queued.
#
+# This is unlike the \fBaliases\fR(5) table (alias_maps) which
+# applies only to \fBlocal\fR(8) recipients.
+#
# Virtual aliasing is recursive; to terminate recursion for
# a specific address, alias that address to itself.
#
@@ -244,8 +245,9 @@
# and for default values. Use the "\fBpostfix reload\fR" command after
# a configuration change.
# .IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
-# Optional lookup tables that alias specific mail addresses or domains
-# to other local or remote addresses.
+# Optional lookup tables with aliases that apply to all recipients:
+# \fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+# only to \fBlocal\fR(8) recipients.
# .IP "\fBvirtual_alias_domains ($virtual_alias_maps)\fR"
# Postfix is the final destination for the specified list of virtual
# alias domains, that is, domains for which all addresses are aliased
@@ -256,8 +258,8 @@
# .PP
# Other parameters of interest:
# .IP "\fBinet_interfaces (all)\fR"
-# The network interface addresses that this mail system receives
-# mail on.
+# The local network interface addresses that this mail system
+# receives mail on.
# .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR"
# The list of domains that are delivered via the $local_transport
# mail delivery transport.
@@ -270,7 +272,7 @@
# \fIlistname\fR-request address localparts when the recipient_delimiter
# is set to "-".
# .IP "\fBproxy_interfaces (empty)\fR"
-# The network interface addresses that this mail system receives mail
+# The remote network interface addresses that this mail system receives mail
# on by way of a proxy or network address translation unit.
# SEE ALSO
# cleanup(8), canonicalize and enqueue mail
diff --git a/src/bounce/bounce_notify_util.c b/src/bounce/bounce_notify_util.c
index 781a525..2482359 100644
--- a/src/bounce/bounce_notify_util.c
+++ b/src/bounce/bounce_notify_util.c
@@ -773,15 +773,14 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
post_mail_fprintf(bounce, "X-%s-Queue-ID: %s",
bounce_info->mail_name, bounce_info->queue_id);
-#define IS_UTF8_ADDRESS(str, len) \
- ((str)[0] != 0 && !allascii(str) && valid_utf8_string((str), (len)))
+#define IS_UTF8_ADDRESS(str) \
+ ((str)[0] != 0 && !allascii(str) && valid_utf8_stringz(str))
/* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */
if (VSTRING_LEN(bounce_info->sender) > 0)
post_mail_fprintf(bounce, "X-%s-Sender: %s; %s",
bounce_info->mail_name, bounce_info->smtputf8
- && IS_UTF8_ADDRESS(STR(bounce_info->sender),
- VSTRING_LEN(bounce_info->sender)) ?
+ && IS_UTF8_ADDRESS(STR(bounce_info->sender)) ?
"utf-8" : "rfc822", STR(bounce_info->sender));
if (bounce_info->arrival_time > 0)
post_mail_fprintf(bounce, "Arrival-Date: %s",
@@ -800,8 +799,7 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
/* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */
post_mail_fprintf(bounce, "Final-Recipient: %s; %s",
bounce_info->smtputf8
- && IS_UTF8_ADDRESS(rcpt->address,
- strlen(rcpt->address)) ?
+ && IS_UTF8_ADDRESS(rcpt->address) ?
"utf-8" : "rfc822", rcpt->address);
/*
@@ -829,8 +827,7 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
/* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */
post_mail_fprintf(bounce, "Original-Recipient: %s; %s",
bounce_info->smtputf8
- && IS_UTF8_ADDRESS(rcpt->orig_addr,
- strlen(rcpt->orig_addr)) ?
+ && IS_UTF8_ADDRESS(rcpt->orig_addr) ?
"utf-8" : "rfc822", rcpt->orig_addr);
}
post_mail_fprintf(bounce, "Action: %s",
diff --git a/src/bounce/with-msgid-with-filter-no-thread.ref b/src/bounce/with-msgid-with-filter-no-thread.ref
index fa30ddf..adcd507 100644
--- a/src/bounce/with-msgid-with-filter-no-thread.ref
+++ b/src/bounce/with-msgid-with-filter-no-thread.ref
@@ -24,7 +24,7 @@ Reporting-MTA: dns; mail.example
Original-Envelope-Id: TEST-ENVID
X-Postfix-Queue-ID: msgid
X-Postfix-Sender: rfc822; sender@sender.example
-Arrival-Date: Sat, 5 Dec 2020 13:31:48 -0500 (EST)
+Arrival-Date: Sat, 05 Dec 2020 13:31:48 -0500 (EST)
Final-Recipient: rfc822; rcpt-address
Original-Recipient: rfc822; rcpt-orig_addr
diff --git a/src/bounce/with-msgid-with-filter-with-thread.ref b/src/bounce/with-msgid-with-filter-with-thread.ref
index 14d3373..ec3de87 100644
--- a/src/bounce/with-msgid-with-filter-with-thread.ref
+++ b/src/bounce/with-msgid-with-filter-with-thread.ref
@@ -26,7 +26,7 @@ Reporting-MTA: dns; mail.example
Original-Envelope-Id: TEST-ENVID
X-Postfix-Queue-ID: msgid
X-Postfix-Sender: rfc822; sender@sender.example
-Arrival-Date: Sat, 5 Dec 2020 13:31:48 -0500 (EST)
+Arrival-Date: Sat, 05 Dec 2020 13:31:48 -0500 (EST)
Final-Recipient: rfc822; rcpt-address
Original-Recipient: rfc822; rcpt-orig_addr
diff --git a/src/cleanup/Makefile.in b/src/cleanup/Makefile.in
index 8a3c18c..b74fe0a 100644
--- a/src/cleanup/Makefile.in
+++ b/src/cleanup/Makefile.in
@@ -88,7 +88,9 @@ milter_tests: cleanup_milter_test bug_tests \
cleanup_milter_test15g cleanup_milter_test15h cleanup_milter_test15i \
cleanup_milter_test16a cleanup_milter_test16b cleanup_milter_test17a \
cleanup_milter_test17b cleanup_milter_test17c cleanup_milter_test17d \
- cleanup_milter_test17e cleanup_milter_test17f cleanup_milter_test17g
+ cleanup_milter_test17e cleanup_milter_test17f cleanup_milter_test17g \
+ cleanup_milter_test18a cleanup_milter_test18b cleanup_milter_test18c \
+ cleanup_milter_test18d
root_tests:
@@ -671,6 +673,46 @@ cleanup_milter_test17g: cleanup_milter test-queue-file17 cleanup_milter.in17g \
diff cleanup_milter.ref17g2 cleanup_milter.tmp2
rm -f test-queue-file17g.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+cleanup_milter_test18a: cleanup_milter test-queue-file18 cleanup_milter.in18a \
+ cleanup_milter.ref18a1 ../postcat/postcat cleanup_milter.ref18a2
+ cp test-queue-file18 test-queue-file18a.tmp
+ chmod u+w test-queue-file18a.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter <cleanup_milter.in18a 2>cleanup_milter.tmp1
+ diff cleanup_milter.ref18a1 cleanup_milter.tmp1
+ $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18a.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref18a2 cleanup_milter.tmp2
+ rm -f test-queue-file18a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test18b: cleanup_milter test-queue-file18 cleanup_milter.in18b \
+ cleanup_milter.ref18b1 ../postcat/postcat cleanup_milter.ref18b2
+ cp test-queue-file18 test-queue-file18b.tmp
+ chmod u+w test-queue-file18b.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter <cleanup_milter.in18b 2>cleanup_milter.tmp1
+ diff cleanup_milter.ref18b1 cleanup_milter.tmp1
+ $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18b.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref18b2 cleanup_milter.tmp2
+ rm -f test-queue-file18b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test18c: cleanup_milter test-queue-file18 cleanup_milter.in18c \
+ cleanup_milter.ref18c1 ../postcat/postcat cleanup_milter.ref18c2
+ cp test-queue-file18 test-queue-file18c.tmp
+ chmod u+w test-queue-file18c.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter <cleanup_milter.in18c 2>cleanup_milter.tmp1
+ diff cleanup_milter.ref18c1 cleanup_milter.tmp1
+ $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18c.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref18c2 cleanup_milter.tmp2
+ rm -f test-queue-file18c.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
+cleanup_milter_test18d: cleanup_milter test-queue-file18 cleanup_milter.in18d \
+ cleanup_milter.ref18d1 ../postcat/postcat cleanup_milter.ref18d2
+ cp test-queue-file18 test-queue-file18d.tmp
+ chmod u+w test-queue-file18d.tmp
+ $(SHLIB_ENV) $(VALGRIND) ./cleanup_milter <cleanup_milter.in18d 2>cleanup_milter.tmp1
+ diff cleanup_milter.ref18d1 cleanup_milter.tmp1
+ $(SHLIB_ENV) $(VALGRIND) ../postcat/postcat -ov test-queue-file18d.tmp 2>/dev/null >cleanup_milter.tmp2
+ diff cleanup_milter.ref18d2 cleanup_milter.tmp2
+ rm -f test-queue-file18d.tmp cleanup_milter.tmp1 cleanup_milter.tmp2
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
diff --git a/src/cleanup/cleanup.c b/src/cleanup/cleanup.c
index 6fe61f8..5db42bd 100644
--- a/src/cleanup/cleanup.c
+++ b/src/cleanup/cleanup.c
@@ -262,10 +262,10 @@
/* Available in Postfix version 2.1 and later:
/* .IP "\fBsender_bcc_maps (empty)\fR"
/* Optional BCC (blind carbon-copy) address lookup tables, indexed
-/* by sender address.
+/* by envelope sender address.
/* .IP "\fBrecipient_bcc_maps (empty)\fR"
/* Optional BCC (blind carbon-copy) address lookup tables, indexed by
-/* recipient address.
+/* envelope recipient address.
/* ADDRESS TRANSFORMATION CONTROLS
/* .ad
/* .fi
@@ -303,8 +303,9 @@
/* .PP
/* Available in Postfix version 2.0 and later:
/* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
-/* Optional lookup tables that alias specific mail addresses or domains
-/* to other local or remote address.
+/* Optional lookup tables with aliases that apply to all recipients:
+/* \fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+/* only to \fBlocal\fR(8) recipients.
/* .PP
/* Available in Postfix version 2.2 and later:
/* .IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR"
@@ -316,9 +317,10 @@
/* What addresses are subject to sender_canonical_maps address
/* mapping.
/* .IP "\fBremote_header_rewrite_domain (empty)\fR"
-/* Don't rewrite message headers from remote clients at all when
-/* this parameter is empty; otherwise, rewrite message headers and
-/* append the specified domain name to incomplete addresses.
+/* Rewrite or add message headers in mail from remote clients if
+/* the remote_header_rewrite_domain parameter value is non-empty,
+/* updating incomplete addresses with the domain specified in the
+/* remote_header_rewrite_domain parameter, and adding missing headers.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@@ -365,7 +367,7 @@
/* Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
/* .IP "\fBsmtputf8_enable (yes)\fR"
/* Enable preliminary SMTPUTF8 support for the protocols described
-/* in RFC 6531..6533.
+/* in RFC 6531, RFC 6532, and RFC 6533.
/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR"
/* Detect that a message requires SMTPUTF8 support for the specified
/* mail origin classes.
@@ -433,6 +435,12 @@
/* .IP "\fBinfo_log_address_format (external)\fR"
/* The email address form that will be used in non-debug logging
/* (info, warning, etc.).
+/* .PP
+/* Available in Postfix 3.9 and later:
+/* .IP "\fBforce_mime_input_conversion (no)\fR"
+/* Convert body content that claims to be 8-bit into quoted-printable,
+/* before header_checks, body_checks, Milters, and before after-queue
+/* content filters.
/* FILES
/* /etc/postfix/canonical*, canonical mapping table
/* /etc/postfix/virtual*, virtual mapping table
diff --git a/src/cleanup/cleanup_addr.c b/src/cleanup/cleanup_addr.c
index fd8a511..f5e7d91 100644
--- a/src/cleanup/cleanup_addr.c
+++ b/src/cleanup/cleanup_addr.c
@@ -148,7 +148,7 @@ off_t cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
}
/* Fix 20140711: Auto-detect an UTF8 sender. */
if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
- && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+ && valid_utf8_stringz(STR(clean_addr))) {
state->smtputf8 |= SMTPUTF8_FLAG_SENDER;
/* Fix 20140713: request SMTPUTF8 support selectively. */
if (state->flags & CLEANUP_FLAG_AUTOUTF8)
@@ -216,7 +216,7 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
}
/* Fix 20140711: Auto-detect an UTF8 recipient. */
if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
- && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+ && valid_utf8_stringz(STR(clean_addr))) {
/* Fix 20140713: request SMTPUTF8 support selectively. */
if (state->flags & CLEANUP_FLAG_AUTOUTF8)
state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
@@ -275,7 +275,7 @@ void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc,
}
/* Fix 20140711: Auto-detect an UTF8 recipient. */
if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
- && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+ && valid_utf8_stringz(STR(clean_addr))) {
/* Fix 20140713: request SMTPUTF8 support selectively. */
if (state->flags & CLEANUP_FLAG_AUTOUTF8)
state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
diff --git a/src/cleanup/cleanup_init.c b/src/cleanup/cleanup_init.c
index 369a019..446ddf2 100644
--- a/src/cleanup/cleanup_init.c
+++ b/src/cleanup/cleanup_init.c
@@ -174,6 +174,7 @@ int var_auto_8bit_enc_hdr; /* auto-detect 8bit encoding header */
int var_always_add_hdrs; /* always add missing headers */
int var_virt_addrlen_limit; /* stop exponential growth */
char *var_hfrom_format; /* header_from_format */
+int var_force_mime_iconv; /* force mime downgrade on input */
int var_cleanup_mask_stray_cr_lf; /* replace stray CR or LF with space */
const CONFIG_INT_TABLE cleanup_int_table[] = {
@@ -191,6 +192,7 @@ const CONFIG_BOOL_TABLE cleanup_bool_table[] = {
VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off,
VAR_AUTO_8BIT_ENC_HDR, DEF_AUTO_8BIT_ENC_HDR, &var_auto_8bit_enc_hdr,
VAR_ALWAYS_ADD_HDRS, DEF_ALWAYS_ADD_HDRS, &var_always_add_hdrs,
+ VAR_FORCE_MIME_ICONV, DEF_FORCE_MIME_ICONV, &var_force_mime_iconv,
VAR_CLEANUP_MASK_STRAY_CR_LF, DEF_CLEANUP_MASK_STRAY_CR_LF, &var_cleanup_mask_stray_cr_lf,
0,
};
diff --git a/src/cleanup/cleanup_message.c b/src/cleanup/cleanup_message.c
index 1ee0a52..0d31598 100644
--- a/src/cleanup/cleanup_message.c
+++ b/src/cleanup/cleanup_message.c
@@ -1069,6 +1069,9 @@ void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t
*/
mime_options = 0;
if (var_disable_mime_input) {
+ if (var_force_mime_iconv)
+ msg_fatal("do not specify both %s=yes and %s=yes",
+ VAR_DISABLE_MIME_INPUT, VAR_FORCE_MIME_ICONV);
mime_options |= MIME_OPT_DISABLE_MIME;
} else {
/* Turn off content checks if bouncing or forwarding mail. */
@@ -1085,6 +1088,8 @@ void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t
|| *var_nesthdr_checks)
mime_options |= MIME_OPT_REPORT_NESTING;
}
+ if (var_force_mime_iconv)
+ mime_options |= MIME_OPT_DOWNGRADE;
}
state->mime_state = mime_state_alloc(mime_options,
cleanup_header_callback,
diff --git a/src/cleanup/cleanup_milter.c b/src/cleanup/cleanup_milter.c
index 491de25..a35344c 100644
--- a/src/cleanup/cleanup_milter.c
+++ b/src/cleanup/cleanup_milter.c
@@ -2444,6 +2444,7 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path)
long data_offset;
long rcpt_count;
long qmgr_opts;
+ const HEADER_OPTS *opts;
if (state->dst != 0) {
msg_warn("closing %s", cleanup_path);
@@ -2455,6 +2456,7 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path)
if ((state->dst = vstream_fopen(path, O_RDWR, 0)) == 0) {
msg_warn("open %s: %m", path);
} else {
+ var_drop_hdrs = "";
cleanup_path = mystrdup(path);
for (;;) {
if ((curr_offset = vstream_ftell(state->dst)) < 0)
@@ -2511,9 +2513,16 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path)
msg_fatal("file %s: vstream_ftell: %m", cleanup_path);
}
}
+ } else if (rec_type == REC_TYPE_NORM && state->hop_count == 0
+ && (opts = header_opts_find(STR(buf))) != 0
+ && opts->type == HDR_RECEIVED) {
+ state->hop_count += 1;
+ /* XXX Only the first line of the first Received: header. */
+ argv_add(state->auto_hdrs, STR(buf), ARGV_END);
}
if (state->append_rcpt_pt_offset > 0
&& state->append_hdr_pt_offset > 0
+ && state->hop_count > 0
&& (rec_type == REC_TYPE_END
|| state->append_meta_pt_offset > 0))
break;
diff --git a/src/cleanup/cleanup_milter.in18a b/src/cleanup/cleanup_milter.in18a
new file mode 100644
index 0000000..4e60fe4
--- /dev/null
+++ b/src/cleanup/cleanup_milter.in18a
@@ -0,0 +1,8 @@
+#verbose on
+open test-queue-file18a.tmp
+#
+# Update a prepended header.
+#
+upd_header 1 Header-Label new-header-value
+
+close
diff --git a/src/cleanup/cleanup_milter.in18b b/src/cleanup/cleanup_milter.in18b
new file mode 100644
index 0000000..5f8c12d
--- /dev/null
+++ b/src/cleanup/cleanup_milter.in18b
@@ -0,0 +1,8 @@
+#verbose on
+open test-queue-file18b.tmp
+#
+# Delete a prepended header.
+#
+del_header 1 Header-Label
+
+close
diff --git a/src/cleanup/cleanup_milter.in18c b/src/cleanup/cleanup_milter.in18c
new file mode 100644
index 0000000..bb78c94
--- /dev/null
+++ b/src/cleanup/cleanup_milter.in18c
@@ -0,0 +1,9 @@
+#verbose on
+open test-queue-file18c.tmp
+#
+# Update the first Received: header. This adds a new header, because
+# there is no header that was exposed to the Milter.
+#
+upd_header 1 Received whatever
+
+close
diff --git a/src/cleanup/cleanup_milter.in18d b/src/cleanup/cleanup_milter.in18d
new file mode 100644
index 0000000..607014d
--- /dev/null
+++ b/src/cleanup/cleanup_milter.in18d
@@ -0,0 +1,8 @@
+#verbose on
+open test-queue-file18d.tmp
+#
+# Delete our Received: header. This should do nothing.
+#
+del_header 1 Received
+
+close
diff --git a/src/cleanup/cleanup_milter.ref18a1 b/src/cleanup/cleanup_milter.ref18a1
new file mode 100644
index 0000000..eab5a83
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18a1
@@ -0,0 +1 @@
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/src/cleanup/cleanup_milter.ref18a2 b/src/cleanup/cleanup_milter.ref18a2
new file mode 100644
index 0000000..b5c0477
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18a2
@@ -0,0 +1,29 @@
+*** ENVELOPE RECORDS test-queue-file18a.tmp ***
+ 0 message_size: 342 290 1 0 342 0
+ 97 message_arrival_time: Tue Dec 12 14:29:04 2023
+ 116 create_time: Tue Dec 12 14:29:04 2023
+ 140 named_attribute: rewrite_context=local
+ 163 sender_fullname: Wietse Venema
+ 178 sender: user@example.com
+ 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com
+ 235 original_recipient: user@example.com
+ 253 recipient: user@example.com
+ 271 pointer_record: 0
+ 288 *** MESSAGE CONTENTS test-queue-file18a.tmp ***
+ 290 pointer_record: 653
+ 653 regular_text: Header-Label: new-header-value
+ 685 pointer_record: 318
+ 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000)
+ 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 438 regular_text: Subject: test
+ 453 padding: 0
+ 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org>
+ 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 550 regular_text: From: Wietse Venema <user@example.com>
+ 590 pointer_record: 0
+ 607 regular_text:
+ 609 regular_text: test
+ 615 pointer_record: 0
+ 632 *** HEADER EXTRACTED test-queue-file18a.tmp ***
+ 634 pointer_record: 0
+ 651 *** MESSAGE FILE END test-queue-file18a.tmp ***
diff --git a/src/cleanup/cleanup_milter.ref18b1 b/src/cleanup/cleanup_milter.ref18b1
new file mode 100644
index 0000000..eab5a83
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18b1
@@ -0,0 +1 @@
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/src/cleanup/cleanup_milter.ref18b2 b/src/cleanup/cleanup_milter.ref18b2
new file mode 100644
index 0000000..d3b4ed3
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18b2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file18b.tmp ***
+ 0 message_size: 342 290 1 0 342 0
+ 97 message_arrival_time: Tue Dec 12 14:29:04 2023
+ 116 create_time: Tue Dec 12 14:29:04 2023
+ 140 named_attribute: rewrite_context=local
+ 163 sender_fullname: Wietse Venema
+ 178 sender: user@example.com
+ 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com
+ 235 original_recipient: user@example.com
+ 253 recipient: user@example.com
+ 271 pointer_record: 0
+ 288 *** MESSAGE CONTENTS test-queue-file18b.tmp ***
+ 290 pointer_record: 318
+ 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000)
+ 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 438 regular_text: Subject: test
+ 453 padding: 0
+ 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org>
+ 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 550 regular_text: From: Wietse Venema <user@example.com>
+ 590 pointer_record: 0
+ 607 regular_text:
+ 609 regular_text: test
+ 615 pointer_record: 0
+ 632 *** HEADER EXTRACTED test-queue-file18b.tmp ***
+ 634 pointer_record: 0
+ 651 *** MESSAGE FILE END test-queue-file18b.tmp ***
diff --git a/src/cleanup/cleanup_milter.ref18c1 b/src/cleanup/cleanup_milter.ref18c1
new file mode 100644
index 0000000..eab5a83
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18c1
@@ -0,0 +1 @@
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/src/cleanup/cleanup_milter.ref18c2 b/src/cleanup/cleanup_milter.ref18c2
new file mode 100644
index 0000000..84a3449
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18c2
@@ -0,0 +1,29 @@
+*** ENVELOPE RECORDS test-queue-file18c.tmp ***
+ 0 message_size: 342 290 1 0 342 0
+ 97 message_arrival_time: Tue Dec 12 14:29:04 2023
+ 116 create_time: Tue Dec 12 14:29:04 2023
+ 140 named_attribute: rewrite_context=local
+ 163 sender_fullname: Wietse Venema
+ 178 sender: user@example.com
+ 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com
+ 235 original_recipient: user@example.com
+ 253 recipient: user@example.com
+ 271 pointer_record: 0
+ 288 *** MESSAGE CONTENTS test-queue-file18c.tmp ***
+ 290 regular_text: Header-Label: header-value
+ 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000)
+ 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 438 regular_text: Subject: test
+ 453 padding: 0
+ 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org>
+ 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 550 regular_text: From: Wietse Venema <user@example.com>
+ 590 pointer_record: 653
+ 653 regular_text: Received: whatever
+ 673 pointer_record: 607
+ 607 regular_text:
+ 609 regular_text: test
+ 615 pointer_record: 0
+ 632 *** HEADER EXTRACTED test-queue-file18c.tmp ***
+ 634 pointer_record: 0
+ 651 *** MESSAGE FILE END test-queue-file18c.tmp ***
diff --git a/src/cleanup/cleanup_milter.ref18d1 b/src/cleanup/cleanup_milter.ref18d1
new file mode 100644
index 0000000..eab5a83
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18d1
@@ -0,0 +1 @@
+./cleanup_milter: flags = enable_header_body_filter enable_milters
diff --git a/src/cleanup/cleanup_milter.ref18d2 b/src/cleanup/cleanup_milter.ref18d2
new file mode 100644
index 0000000..b436ba2
--- /dev/null
+++ b/src/cleanup/cleanup_milter.ref18d2
@@ -0,0 +1,27 @@
+*** ENVELOPE RECORDS test-queue-file18d.tmp ***
+ 0 message_size: 342 290 1 0 342 0
+ 97 message_arrival_time: Tue Dec 12 14:29:04 2023
+ 116 create_time: Tue Dec 12 14:29:04 2023
+ 140 named_attribute: rewrite_context=local
+ 163 sender_fullname: Wietse Venema
+ 178 sender: user@example.com
+ 196 named_attribute: dsn_orig_rcpt=rfc822;user@example.com
+ 235 original_recipient: user@example.com
+ 253 recipient: user@example.com
+ 271 pointer_record: 0
+ 288 *** MESSAGE CONTENTS test-queue-file18d.tmp ***
+ 290 regular_text: Header-Label: header-value
+ 318 regular_text: Received: by wzv.porcupine.org (Postfix, from userid 1000)
+ 378 regular_text: id 4SqTFD6TVpz4w4n; Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 438 regular_text: Subject: test
+ 453 padding: 0
+ 456 regular_text: Message-Id: <4SqTFD6TVpz4w4n@wzv.porcupine.org>
+ 505 regular_text: Date: Tue, 12 Dec 2023 14:29:04 -0500 (EST)
+ 550 regular_text: From: Wietse Venema <user@example.com>
+ 590 pointer_record: 0
+ 607 regular_text:
+ 609 regular_text: test
+ 615 pointer_record: 0
+ 632 *** HEADER EXTRACTED test-queue-file18d.tmp ***
+ 634 pointer_record: 0
+ 651 *** MESSAGE FILE END test-queue-file18d.tmp ***
diff --git a/src/cleanup/test-queue-file18 b/src/cleanup/test-queue-file18
new file mode 100644
index 0000000..42c46f1
--- /dev/null
+++ b/src/cleanup/test-queue-file18
Binary files differ
diff --git a/src/dns/Makefile.in b/src/dns/Makefile.in
index 3ebf75f..5ea09cf 100644
--- a/src/dns/Makefile.in
+++ b/src/dns/Makefile.in
@@ -11,7 +11,8 @@ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
INCL =
LIB = lib$(LIB_PREFIX)dns$(LIB_SUFFIX)
-TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa
+TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa \
+ dns_rr_test
LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
LIB_DIR = ../../lib
@@ -31,7 +32,7 @@ test: $(TESTPROG)
tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \
dns_rr_eq_sa_test no-a-test no-aaaa-test no-mx-test \
error-filter-test nullmx_test nxdomain_test mxonly_test \
- dnsbl_tests
+ dnsbl_tests dns_rr_tests
dnsbl_tests: \
dnsbl_ttl_127.0.0.2_bind_plain_test \
@@ -57,7 +58,7 @@ DNSBL_EXIST_REPLY_FIX = \
-e 's/ [0-9]* [0-9]* [0-9]* [0-9]* [0-9]*/ D D D D D/' \
-e 's/127.0.0.[0-9]*$$/127.0.0.D/' \
| uniq
-
+
root_tests:
$(LIB): $(OBJS)
@@ -240,6 +241,12 @@ dnsbl_ttl_127.0.0.2_priv_ncache_test: test_dns_lookup dnsbl_ttl_127.0.0.2_bind_p
diff dnsbl_ttl_127.0.0.2_bind_plain.ref dnsbl_ttl_127.0.0.2_priv_ncache.tmp
rm -f dnsbl_ttl_127.0.0.2_priv_ncache.tmp
+dns_rr_tests: dns_rr_test
+ $(SHLIB_ENV) $(VALGRIND) ./dns_rr_test
+
+dns_rr_test: dns_rr_test.o $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@@ -319,6 +326,19 @@ dns_rr_filter.o: ../../include/vstream.h
dns_rr_filter.o: ../../include/vstring.h
dns_rr_filter.o: dns.h
dns_rr_filter.o: dns_rr_filter.c
+dns_rr_test.o: ../../include/check_arg.h
+dns_rr_test.o: ../../include/msg.h
+dns_rr_test.o: ../../include/msg_vstream.h
+dns_rr_test.o: ../../include/myaddrinfo.h
+dns_rr_test.o: ../../include/mymalloc.h
+dns_rr_test.o: ../../include/sock_addr.h
+dns_rr_test.o: ../../include/stringops.h
+dns_rr_test.o: ../../include/sys_defs.h
+dns_rr_test.o: ../../include/vbuf.h
+dns_rr_test.o: ../../include/vstream.h
+dns_rr_test.o: ../../include/vstring.h
+dns_rr_test.o: dns.h
+dns_rr_test.o: dns_rr_test.c
dns_rr_to_pa.o: ../../include/check_arg.h
dns_rr_to_pa.o: ../../include/msg.h
dns_rr_to_pa.o: ../../include/myaddrinfo.h
diff --git a/src/dns/dns_lookup.c b/src/dns/dns_lookup.c
index c21b619..4cf9a5f 100644
--- a/src/dns/dns_lookup.c
+++ b/src/dns/dns_lookup.c
@@ -85,6 +85,12 @@
/* an invalid name is reported as a DNS_INVAL result, while
/* malformed replies are reported as transient errors.
/*
+/* Note: in dns_lookup*() results and queries, a name may start
+/* with a "*" label, which is valid according to RFC 1034
+/* section 4.3.3. Such a name will not pass valid_hostname()
+/* checks in the rest of Postfix, because it is not a valid
+/* host or domain name.
+/*
/* dns_get_h_errno() returns the last error. This deprecates
/* usage of the global h_errno variable. We should not rely
/* on that being updated.
@@ -300,7 +306,7 @@ typedef struct DNS_REPLY {
/*
* Use the threadsafe resolver API if available, not because it is
- * theadsafe, but because it has more functionality.
+ * threadsafe, but because it has more functionality.
*/
#ifdef USE_RES_NCALLS
static struct __res_state dns_res_state;
diff --git a/src/dns/dns_rr_test.c b/src/dns/dns_rr_test.c
new file mode 100644
index 0000000..7bbe769
--- /dev/null
+++ b/src/dns/dns_rr_test.c
@@ -0,0 +1,433 @@
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <stdlib.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <msg_vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstring.h>
+
+ /*
+ * DNS library.
+ */
+#include <dns.h>
+
+#define STR(x) vstring_str(x)
+
+ /*
+ * Test helpers. TODO: move eq_dns_rr() to testing/dns_rr_testers.c; need to
+ * verify that the expected difference is reported, or use a GTEST matcher.
+ */
+
+/* print_dns_rr - format as { qname, reply, flags } */
+
+static char *print_dns_rr(VSTRING *buf, DNS_RR *rr)
+{
+ static VSTRING *tmp;
+
+ if (tmp == 0)
+ tmp = vstring_alloc(100);
+ vstring_sprintf(buf, "{qname=%s, reply='%s', flags=0x%x}",
+ rr->qname, dns_strrecord(tmp, rr), rr->flags);
+ return (STR(buf));
+}
+
+/* eq_dns_rr - predicate that two lists are equivalent */
+
+static int eq_dns_rr(DNS_RR *got, DNS_RR *want)
+{
+ VSTRING *got_buf = 0;
+ VSTRING *want_buf = 0;
+
+#define EQ_DNS_RR_RETURN(val) do { \
+ if (got_buf) \
+ vstring_free(got_buf); \
+ if (want_buf) \
+ vstring_free(want_buf); \
+ return (val); \
+ } while (0)
+
+ /* Same length. */
+ if (got == 0 && want == 0)
+ EQ_DNS_RR_RETURN(1);
+ if (want == 0) {
+ msg_warn("got %s, want null",
+ print_dns_rr(got_buf = vstring_alloc(100), got));
+ }
+ if (got == 0) {
+ msg_warn("got null, want %s",
+ print_dns_rr(want_buf = vstring_alloc(100), want));
+ EQ_DNS_RR_RETURN(0);
+ }
+ /* Same query name, resource record, flags. */
+ if (strcmp(print_dns_rr(got_buf = vstring_alloc(100), got),
+ print_dns_rr(want_buf = vstring_alloc(100), want)) != 0) {
+ msg_warn("got %s, want %s", STR(want_buf), STR(got_buf));
+ EQ_DNS_RR_RETURN(0);
+ }
+ /* Same children. */
+ EQ_DNS_RR_RETURN(eq_dns_rr(got->next, want->next));
+}
+
+static int eq_dns_rr_free(DNS_RR *got, DNS_RR *want)
+{
+ int res = eq_dns_rr(got, want);
+
+ dns_rr_free(got);
+ dns_rr_free(want);
+ return (res);
+}
+
+ /*
+ * Tests and test cases.
+ */
+typedef struct TEST_CASE {
+ const char *label; /* identifies test case */
+ int (*fn) (void);
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+ /*
+ * Begin helper tests. TODO: move these to testing/dns_rr_testers_test.c.
+ */
+
+static int eq_dns_rr_qname_differ(void)
+{
+ DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 4);
+ DNS_RR *want = dns_rr_copy(got);
+
+ myfree(want->qname);
+ want->qname = mystrdup("qb");
+ return (!eq_dns_rr_free(got, want));
+}
+
+static int eq_dns_rr_reply_differ(void)
+{
+ DNS_RR *got = dns_rr_create("qa", "ra", T_SRV, C_IN, 3600, 1, 25, 1, "mxa", 4);
+ DNS_RR *want = dns_rr_copy(got);
+
+ want->port += 1;
+ return (!eq_dns_rr_free(got, want));
+}
+
+ /*
+ * End helper tests.
+ */
+
+ /*
+ * Begin DNS_RR tests.
+ */
+
+static int eq_dns_rr_flags_differ(void)
+{
+ DNS_RR *got = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *want = dns_rr_copy(got);
+
+ want->flags |= DNS_RR_FLAG_TRUNCATED;
+ return (!eq_dns_rr_free(got, want));
+}
+
+static int append_to_null_from_null(void)
+{
+ DNS_RR *got = dns_rr_append((DNS_RR *) 0, (DNS_RR *) 0);
+ DNS_RR *want = 0;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_elem_from_null(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *got, *want;
+
+ got = dns_rr_append(dns_rr_copy(a), (DNS_RR *) 0);
+
+ want = a;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int appent_to_null_from_elem(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *got, *want;
+
+ got = dns_rr_append((DNS_RR *) 0, dns_rr_copy(a));
+
+ want = a;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_elem_from_elem(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *got, *want;
+
+ got = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b));
+
+ (want = a)->next = b;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_elem_from_list(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *got, *want;
+
+ got = dns_rr_append(dns_rr_copy(a),
+ dns_rr_append(dns_rr_copy(b),
+ dns_rr_copy(c)));
+
+ ((want = a)->next = b)->next = c;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_list_from_elem(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *got, *want;
+
+ got = dns_rr_append(dns_rr_append(dns_rr_copy(a),
+ dns_rr_copy(b)),
+ dns_rr_copy(c));
+
+ ((want = a)->next = b)->next = c;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_list_from_list(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4);
+ DNS_RR *got, *want;
+
+ got = dns_rr_append(dns_rr_append(dns_rr_copy(a),
+ dns_rr_copy(b)),
+ dns_rr_append(dns_rr_copy(c),
+ dns_rr_copy(d)));
+
+ (((want = a)->next = b)->next = c)->next = d;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_propagates_flags(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4);
+ DNS_RR *left = dns_rr_append(dns_rr_copy(a), dns_rr_copy(b));
+ DNS_RR *rite = dns_rr_append(dns_rr_copy(c), dns_rr_copy(d));
+ DNS_RR *got, *want, *rr;
+
+ for (rr = rite; rr; rr = rr->next)
+ rr->flags |= DNS_RR_FLAG_TRUNCATED;
+
+ got = dns_rr_append(left, rite);
+
+ (((want = a)->next = b)->next = c)->next = d;
+ for (rr = want; rr; rr = rr->next)
+ rr->flags |= DNS_RR_FLAG_TRUNCATED;
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_list_from_list_truncate(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4);
+ DNS_RR *got, *want, *rr;
+
+ var_dns_rr_list_limit = 3;
+
+ ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
+ for (rr = want; rr; rr = rr->next)
+ rr->flags |= DNS_RR_FLAG_TRUNCATED;
+
+ got = dns_rr_append(dns_rr_append(a, b),
+ dns_rr_append(c, d));
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_list_from_elem_elem_truncate(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *d = dns_rr_create_noport("qd", "rd", T_MX, C_IN, 3600, 1, "mxd", 4);
+ DNS_RR *got, *want, *rr;
+
+ var_dns_rr_list_limit = 2;
+
+ (want = dns_rr_copy(a))->next = dns_rr_copy(b);
+ for (rr = want; rr; rr = rr->next)
+ rr->flags |= DNS_RR_FLAG_TRUNCATED;
+
+ got = dns_rr_append(a, b);
+ got = dns_rr_append(got, c); /* should be logged */
+ got = dns_rr_append(got, d); /* should be silent */
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_list_from_elem_truncate(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *got, *want, *rr;
+
+ var_dns_rr_list_limit = 2;
+
+ (want = dns_rr_copy(a))->next = dns_rr_copy(b);
+ for (rr = want; rr; rr = rr->next)
+ rr->flags |= DNS_RR_FLAG_TRUNCATED;
+
+ got = dns_rr_append(dns_rr_append(a, b), c);
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_elem_from_list_truncate(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *got, *want, *rr;
+
+ var_dns_rr_list_limit = 2;
+
+ (want = dns_rr_copy(a))->next = dns_rr_copy(b);
+ for (rr = want; rr; rr = rr->next)
+ rr->flags |= DNS_RR_FLAG_TRUNCATED;
+
+ got = dns_rr_append(a, dns_rr_append(b, c));
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_list_from_elem_exact_fit(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *got, *want;
+
+ var_dns_rr_list_limit = 3;
+
+ ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
+
+ got = dns_rr_append(dns_rr_append(a, b), c);
+
+ return (eq_dns_rr_free(got, want));
+}
+
+static int append_to_elem_from_list_exact_fit(void)
+{
+ DNS_RR *a = dns_rr_create_noport("qa", "ra", T_MX, C_IN, 3600, 1, "mxa", 4);
+ DNS_RR *b = dns_rr_create_noport("qb", "rb", T_MX, C_IN, 3600, 1, "mxb", 4);
+ DNS_RR *c = dns_rr_create_noport("qc", "rc", T_MX, C_IN, 3600, 1, "mxc", 4);
+ DNS_RR *got, *want;
+
+ var_dns_rr_list_limit = 3;
+
+ ((want = dns_rr_copy(a))->next = dns_rr_copy(b))->next = dns_rr_copy(c);
+
+ got = dns_rr_append(a, dns_rr_append(b, c));
+
+ return (eq_dns_rr_free(got, want));
+}
+
+ /*
+ * The test cases.
+ */
+static const TEST_CASE test_cases[] = {
+
+ /*
+ * Test eq_dns_rr; TODO: move to testing/dns_rr_testers_test.c
+ */
+ "eq_dns_rr qname differ", eq_dns_rr_qname_differ,
+ "eq_dns_rr reply differ", eq_dns_rr_reply_differ,
+ "eq_dns_rr flags differ", eq_dns_rr_flags_differ,
+
+ /*
+ * Test dns_rr_append() without truncation.
+ */
+ "append to null from null", append_to_null_from_null,
+ "append to null from element", appent_to_null_from_elem,
+ "append to element from null", append_to_elem_from_null,
+ "append to element from element", append_to_elem_from_elem,
+ "append to element from list", append_to_elem_from_list,
+ "append to list from element", append_to_list_from_elem,
+ "append to list from list", append_to_list_from_list,
+
+ /*
+ * Test dns_rr_append() flag propagation.
+ */
+ "append propagates flags", append_propagates_flags,
+
+ /*
+ * Test dns_rr_append() with truncation.
+ */
+ "append to list from list truncate", append_to_list_from_list_truncate,
+ "append to list from element element truncate", append_to_list_from_elem_elem_truncate,
+ "append to list from element truncate", append_to_list_from_elem_truncate,
+ "append to element from list truncate", append_to_elem_from_list_truncate,
+ "append to list from element exact fit", append_to_list_from_elem_exact_fit,
+ "append to element from list exact fit", append_to_elem_from_list_exact_fit,
+
+ /*
+ * TODO: tests dns_rr_sort(), dns_rr_srv_sort(), dns_rr_remove(),
+ * dns_rr_shuffle(), etc.
+ */
+ 0,
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+ VSTRING *res_buf = vstring_alloc(100);
+ int saved_limit = var_dns_rr_list_limit;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ msg_info("RUN %s", tp->label);
+ if (tp->fn() == 0) {
+ fail++;
+ msg_info("FAIL %s", tp->label);
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ var_dns_rr_list_limit = saved_limit;
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ vstring_free(res_buf);
+ exit(fail != 0);
+}
diff --git a/src/dns/mxonly_test.ref b/src/dns/mxonly_test.ref
index 44f22d6..e1e4bad 100644
--- a/src/dns/mxonly_test.ref
+++ b/src/dns/mxonly_test.ref
@@ -6,6 +6,6 @@
./test_dns_lookup: lookup porcupine.org type A flags RES_USE_DNSSEC
./test_dns_lookup: dns_query: porcupine.org (A): Host found but no data record of requested type
ad: 0, rr: porcupine.org. 3600 IN MX 10 spike.porcupine.org.
-ad: 0, rr: porcupine.org. 3600 IN MX 30 m1.porcupine.org.
ad: 0, rr: porcupine.org. 3600 IN MX 30 vz.porcupine.org.
+ad: 0, rr: porcupine.org. 3600 IN MX 40 m1.porcupine.org.
porcupine.org: fqdn: porcupine.org
diff --git a/src/dns/no-mx.ref b/src/dns/no-mx.ref
index 5adc7bf..527e0b8 100644
--- a/src/dns/no-mx.ref
+++ b/src/dns/no-mx.ref
@@ -1,15 +1,15 @@
./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 10 spike.porcupine.org.
-./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 30 m1.porcupine.org.
./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 30 vz.porcupine.org.
+./test_dns_lookup: dict_regexp_lookup: no-mx.reg: porcupine.org. 3600 IN MX 40 m1.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: dns_get_answer: type MX for porcupine.org
./test_dns_lookup: dns_query: porcupine.org (MX): OK
./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 10 spike.porcupine.org.
-./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 30 m1.porcupine.org.
./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 30 vz.porcupine.org.
+./test_dns_lookup: ignoring DNS RR: porcupine.org. 3600 IN MX 40 m1.porcupine.org.
./test_dns_lookup: lookup porcupine.org type MX flags RES_USE_DNSSEC
./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 10 spike.porcupine.org. = ignore
-./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 30 m1.porcupine.org. = ignore
./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 30 vz.porcupine.org. = ignore
+./test_dns_lookup: maps_find: DNS reply filter: regexp:no-mx.reg(0,lock|fold_fix): porcupine.org. 3600 IN MX 40 m1.porcupine.org. = ignore
./test_dns_lookup: warning: Error looking up name=porcupine.org type=MX: DNS reply filter drops all results (rcode=0)
diff --git a/src/dns/test_dns_lookup.c b/src/dns/test_dns_lookup.c
index f07c3ef..6970124 100644
--- a/src/dns/test_dns_lookup.c
+++ b/src/dns/test_dns_lookup.c
@@ -80,7 +80,7 @@ int main(int argc, char **argv)
var_dnssec_probe = "";
msg_vstream_init(argv[0], VSTREAM_ERR);
- while ((ch = GETOPT(argc, argv, "f:npvs")) > 0) {
+ while ((ch = GETOPT(argc, argv, "f:l:npvs")) > 0) {
switch (ch) {
case 'v':
msg_verbose++;
@@ -88,6 +88,9 @@ int main(int argc, char **argv)
case 'f':
dns_rr_filter_compile("DNS reply filter", optarg);
break;
+ case 'l':
+ var_dns_rr_list_limit = atoi(optarg);
+ break;
case 'n':
lflags |= DNS_REQ_FLAG_NCACHE_TTL;
break;
diff --git a/src/dnsblog/dnsblog.c b/src/dnsblog/dnsblog.c
index bc87c4b..7a4a446 100644
--- a/src/dnsblog/dnsblog.c
+++ b/src/dnsblog/dnsblog.c
@@ -43,7 +43,8 @@
/* How much time a Postfix daemon process may take to handle a
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBpostscreen_dnsbl_sites (empty)\fR"
-/* Optional list of DNS allow/denylist domains, filters and weight
+/* Optional list of patterns with DNS allow/denylist domains, filters
+/* and weight
/* factors.
/* .IP "\fBipc_timeout (3600s)\fR"
/* The time limit for sending or receiving information over an internal
diff --git a/src/global/Makefile.in b/src/global/Makefile.in
index 86390ed..c7a1d36 100644
--- a/src/global/Makefile.in
+++ b/src/global/Makefile.in
@@ -3,7 +3,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
canon_addr.c cfg_parser.c cleanup_strerror.c cleanup_strflags.c \
clnt_stream.c conv_time.c db_common.c debug_peer.c debug_process.c \
defer.c deliver_completed.c deliver_flock.c deliver_pass.c \
- deliver_request.c dict_ldap.c dict_mysql.c dict_pgsql.c \
+ deliver_request.c dict_ldap.c dict_mongodb.c dict_mysql.c dict_pgsql.c \
dict_proxy.c dict_sqlite.c domain_list.c dot_lockfile.c dot_lockfile_as.c \
dsb_scan.c dsn.c dsn_buf.c dsn_mask.c dsn_print.c dsn_util.c \
ehlo_mask.c ext_prop.c file_id.c flush_clnt.c header_opts.c \
@@ -80,13 +80,13 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
-MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o
+MAP_OBJ = dict_ldap.o dict_mysql.o dict_pgsql.o dict_sqlite.o dict_mongodb.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
deliver_completed.h deliver_flock.h deliver_pass.h deliver_request.h \
- dict_ldap.h dict_mysql.h dict_pgsql.h dict_proxy.h dict_sqlite.h domain_list.h \
+ dict_ldap.h dict_mysql.h dict_pgsql.h dict_mongodb.h dict_proxy.h dict_sqlite.h domain_list.h \
dot_lockfile.h dot_lockfile_as.h dsb_scan.h dsn.h dsn_buf.h \
dsn_mask.h dsn_print.h dsn_util.h ehlo_mask.h ext_prop.h \
file_id.h flush_clnt.h header_opts.h header_token.h input_transp.h \
@@ -136,7 +136,7 @@ LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
LIB_DIR = ../../lib
INC_DIR = ../../include
PLUGIN_MAP_SO = $(LIB_PREFIX)ldap$(LIB_SUFFIX) $(LIB_PREFIX)mysql$(LIB_SUFFIX) \
- $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX)
+ $(LIB_PREFIX)pgsql$(LIB_SUFFIX) $(LIB_PREFIX)sqlite$(LIB_SUFFIX) $(LIB_PREFIX)mongodb$(LIB_SUFFIX)
MAKES =
.c.o:; $(CC) $(SHLIB_CFLAGS) $(CFLAGS) -c $*.c
@@ -173,6 +173,9 @@ $(LIB_PREFIX)pgsql$(LIB_SUFFIX): dict_pgsql.o
$(LIB_PREFIX)sqlite$(LIB_SUFFIX): dict_sqlite.o
$(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_sqlite.o $(AUXLIBS_SQLITE)
+$(LIB_PREFIX)mongodb$(LIB_SUFFIX): dict_mongodb.o
+ $(PLUGIN_LD) $(SHLIB_RPATH) -o $@ dict_mongodb.o $(AUXLIBS_MONGODB)
+
update: $(LIB_DIR)/$(LIB) $(HDRS) $(PLUGIN_MAP_SO_UPDATE)
-for i in $(HDRS); \
do \
@@ -1210,6 +1213,24 @@ dict_memcache.o: dict_memcache.c
dict_memcache.o: dict_memcache.h
dict_memcache.o: memcache_proto.h
dict_memcache.o: string_list.h
+dict_mongodb.o: ../../include/argv.h
+dict_mongodb.o: ../../include/auto_clnt.h
+dict_mongodb.o: ../../include/check_arg.h
+dict_mongodb.o: ../../include/dict.h
+dict_mongodb.o: ../../include/match_list.h
+dict_mongodb.o: ../../include/msg.h
+dict_mongodb.o: ../../include/myflock.h
+dict_mongodb.o: ../../include/mymalloc.h
+dict_mongodb.o: ../../include/stringops.h
+dict_mongodb.o: ../../include/sys_defs.h
+dict_mongodb.o: ../../include/vbuf.h
+dict_mongodb.o: ../../include/vstream.h
+dict_mongodb.o: ../../include/vstring.h
+dict_mongodb.o: cfg_parser.h
+dict_mongodb.o: db_common.h
+dict_mongodb.o: dict_mongodb.c
+dict_mongodb.o: dict_mongodb.h
+dict_mongodb.o: string_list.h
dict_mysql.o: ../../include/argv.h
dict_mysql.o: ../../include/check_arg.h
dict_mysql.o: ../../include/dict.h
@@ -1861,6 +1882,7 @@ mail_dict.o: ../../include/vstream.h
mail_dict.o: ../../include/vstring.h
mail_dict.o: dict_ldap.h
mail_dict.o: dict_memcache.h
+mail_dict.o: dict_mongodb.h
mail_dict.o: dict_mysql.h
mail_dict.o: dict_pgsql.h
mail_dict.o: dict_proxy.h
@@ -1911,6 +1933,7 @@ mail_params.o: ../../include/htable.h
mail_params.o: ../../include/inet_addr_list.h
mail_params.o: ../../include/inet_proto.h
mail_params.o: ../../include/iostuff.h
+mail_params.o: ../../include/logwriter.h
mail_params.o: ../../include/midna_domain.h
mail_params.o: ../../include/mkmap.h
mail_params.o: ../../include/msg.h
diff --git a/src/global/dict_ldap.c b/src/global/dict_ldap.c
index a078721..7310a96 100644
--- a/src/global/dict_ldap.c
+++ b/src/global/dict_ldap.c
@@ -904,7 +904,7 @@ static int attrdesc_subtype(const char *a1, const char *a2)
/* url_attrs - attributes we want from LDAP URL */
-static char **url_attrs(DICT_LDAP *dict_ldap, LDAPURLDesc * url)
+static char **url_attrs(DICT_LDAP *dict_ldap, LDAPURLDesc *url)
{
static ARGV *attrs;
char **a1;
@@ -1234,7 +1234,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
* Don't frustrate future attempts to make Postfix UTF-8 transparent.
*/
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
- && !valid_utf8_string(name, strlen(name))) {
+ && !valid_utf8_stringz(name)) {
if (msg_verbose)
msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
myname, dict_ldap->parser->name, name);
diff --git a/src/global/dict_mongodb.c b/src/global/dict_mongodb.c
new file mode 100644
index 0000000..18144b7
--- /dev/null
+++ b/src/global/dict_mongodb.c
@@ -0,0 +1,570 @@
+/*++
+/* NAME
+/* dict_mongodb 3
+/* SUMMARY
+/* dictionary interface to mongodb, compatible with libmongoc-1.0
+/* SYNOPSIS
+/* #include <dict_mongodb.h>
+/*
+/* DICT *dict_mongodb_open(name, open_flags, dict_flags)
+/* const char *name;
+/* int open_flags;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_mongodb_open() opens a MongoDB database, providing a
+/* dictionary interface for Postfix mappings. The result is a
+/* pointer to the installed dictionary.
+/*
+/* Configuration parameters are described in mongodb_table(5).
+/*
+/* Arguments:
+/* .IP name
+/* Either the path to the MongoDB configuration file (if it
+/* starts with '/' or '.'), or the prefix which will be used
+/* to obtain main.cf configuration parameters for this search.
+/*
+/* In the first case, configuration parameters are specified
+/* in the file as \fIname\fR=\fIvalue\fR pairs.
+/*
+/* In the second case, the configuration parameters are prefixed
+/* with the value of \fIname\fR and an underscore, and they
+/* are specified in main.cf. For example, if this value is
+/* \fImongodbconf\fR, the parameters would look like
+/* \fImongodbconf_uri\fR, \fImongodbconf_collection\fR, and
+/* so on.
+/* .IP open_flags
+/* Must be O_RDONLY
+/* .IP dict_flags
+/* See dict_open(3).
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* HISTORY
+/* .ad
+/* .fi
+/* MongoDB support was added in Postfix 3.9.
+/* AUTHOR(S)
+/* Hamid Maadani (hamid@dexo.tech)
+/* Dextrous Technologies, LLC
+/*
+/* Edited by:
+/* Wietse Venema
+/* porcupine.org
+/*
+/* Based on prior work by:
+/* Stephan Ferraro
+/* Aionda GmbH
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#ifdef HAS_MONGODB
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h> /* C99 PRId64 */
+
+#include <bson/bson.h>
+#include <mongoc/mongoc.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <stringops.h>
+#include <auto_clnt.h>
+#include <vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <cfg_parser.h>
+#include <db_common.h>
+
+ /*
+ * Application-specific.
+ */
+#include <dict_mongodb.h>
+
+ /*
+ * Initial size for dynamically-allocated buffers.
+ */
+#ifndef BUFFER_SIZE
+#define BUFFER_SIZE 1024
+#endif
+
+#define INIT_VSTR(buf, len) do { \
+ if (buf == 0) \
+ buf = vstring_alloc(len); \
+ VSTRING_RESET(buf); \
+ VSTRING_TERMINATE(buf); \
+ } while (0)
+
+/* Structure of one mongodb dictionary handle. */
+typedef struct {
+ /* Initialized by dict_mongodb_open(). */
+ DICT dict; /* Parent class */
+ CFG_PARSER *parser; /* Configuration file parser */
+ mongoc_client_t *client; /* Mongo C client handle */
+ /* Initialized by mongodb_parse_config(). */
+ char *uri; /* mongodb+srv:/*localhost:27017 */
+ char *dbname; /* Database name */
+ char *collection; /* Collection name */
+ char *query_filter; /* db_common_expand() query template */
+ char *projection; /* Advanced MongoDB projection */
+ char *result_attribute; /* The key(s) to return the data for */
+ char *result_format; /* db_common_expand() result_template */
+ int expansion_limit; /* Result expansion limit */
+ void *ctx; /* db_common handle */
+} DICT_MONGODB;
+
+/* Per-process initialization. */
+static bool init_done = false;
+
+/* itoa - int64_t to string */
+
+static char *itoa(int64_t val)
+{
+ static char buf[21] = {0};
+ int ret;
+
+ /*
+ * XXX(Wietse) replaced custom code with standard library calls that
+ * handle zero, and negative values.
+ */
+#define PRId64_FORMAT "%" PRId64
+
+ ret = snprintf(buf, sizeof(buf), PRId64_FORMAT, val);
+ if (ret < 0)
+ msg_panic("itoa: output error for '%s'", PRId64_FORMAT);
+ if (ret >= sizeof(buf))
+ msg_panic("itoa: output for '%s' exceeds space %ld",
+ PRId64_FORMAT, sizeof(buf));
+ return (buf);
+}
+
+/* mongodb_parse_config - parse mongodb configuration file */
+
+static void mongodb_parse_config(DICT_MONGODB *dict_mongodb,
+ const char *mongodbcf)
+{
+ CFG_PARSER *p = dict_mongodb->parser;
+
+ /*
+ * Parse the configuration file.
+ */
+ dict_mongodb->uri = cfg_get_str(p, "uri", NULL, 1, 0);
+ dict_mongodb->dbname = cfg_get_str(p, "dbname", NULL, 1, 0);
+ dict_mongodb->collection = cfg_get_str(p, "collection", NULL, 1, 0);
+ dict_mongodb->query_filter = cfg_get_str(p, "query_filter", NULL, 1, 0);
+
+ /*
+ * One of projection and result_attribute must be specified. That is
+ * enforced in the caller.
+ */
+ dict_mongodb->projection = cfg_get_str(p, "projection", NULL, 0, 0);
+ dict_mongodb->result_attribute
+ = cfg_get_str(p, "result_attribute", NULL, 0, 0);
+ dict_mongodb->result_format
+ = cfg_get_str(dict_mongodb->parser, "result_format", "%s", 1, 0);
+ dict_mongodb->expansion_limit
+ = cfg_get_int(dict_mongodb->parser, "expansion_limit", 10, 0, 100);
+
+ /*
+ * db_common query parsing and domain pattern lookup.
+ */
+ dict_mongodb->ctx = 0;
+ (void) db_common_parse(&dict_mongodb->dict, &dict_mongodb->ctx,
+ dict_mongodb->query_filter, 1);
+ db_common_parse_domain(dict_mongodb->parser, dict_mongodb->ctx);
+}
+
+/* expand_value - expand lookup result value */
+
+static bool expand_value(DICT_MONGODB *dict_mongodb, const char *p,
+ const char *lookup_name,
+ VSTRING *resultString,
+ int *expansion, const char *key)
+{
+
+ /*
+ * If a lookup result cannot be processed due to an expansion limit
+ * error, return a DICT_ERR_RETRY error code and a 'false' result value.
+ * As documented for many dict_xxx() implementations, and expansion limit
+ * error is considered a temporary error.
+ */
+ if (dict_mongodb->expansion_limit > 0
+ && ++(*expansion) > dict_mongodb->expansion_limit) {
+ msg_warn("%s:%s: expansion limit exceeded for key: '%s'",
+ dict_mongodb->dict.type, dict_mongodb->dict.name, key);
+ dict_mongodb->dict.error = DICT_ERR_RETRY;
+ return (false);
+ }
+
+ /*
+ * XXX(Wietse) Added the dict_mongodb_lookup() lookup_name argument,
+ * because it selects code paths inside db_common_expand() that are
+ * specifically for lookup results instead of lookup keys, including
+ * %[SUD] substitution.
+ */
+ db_common_expand(dict_mongodb->ctx, dict_mongodb->result_format, p,
+ lookup_name, resultString, 0);
+ return (true);
+}
+
+/* get_result_string - convert lookup result to string, or set dict.error */
+
+static char *get_result_string(DICT_MONGODB *dict_mongodb,
+ VSTRING *resultString,
+ bson_iter_t *iter,
+ const char *lookup_name,
+ int *expansion,
+ const char *key)
+{
+ char *p = NULL;
+ bool got_one_result = false;
+
+ /*
+ * If a lookup result cannot be processed due to an error, return a
+ * non-zero error code and a NULL result value.
+ */
+ INIT_VSTR(resultString, BUFFER_SIZE);
+ while (dict_mongodb->dict.error == DICT_ERR_NONE && bson_iter_next(iter)) {
+ switch (bson_iter_type(iter)) {
+ case BSON_TYPE_UTF8:
+ p = (char *) bson_iter_utf8(iter, NULL);
+ if (!bson_utf8_validate(p, strlen(p), true)) {
+ msg_warn("%s:%s: invalid UTF-8 in lookup result '%s'",
+ dict_mongodb->dict.type, dict_mongodb->dict.name, p);
+ dict_mongodb->dict.error = DICT_ERR_RETRY;
+ break;
+ }
+ got_one_result |= expand_value(dict_mongodb, p, lookup_name,
+ resultString, expansion, key);
+ break;
+ case BSON_TYPE_INT64:
+ case BSON_TYPE_INT32:
+ p = itoa(bson_iter_as_int64(iter));
+ got_one_result |= expand_value(dict_mongodb, p, lookup_name,
+ resultString, expansion, key);
+ break;
+ case BSON_TYPE_ARRAY:
+ ; /* For pre-C23 Clang. */
+ const uint8_t *dataBuffer = NULL;
+ unsigned int len = 0;
+ bson_iter_t dataIter;
+ bson_t *data = NULL;
+
+ /*
+ * XXX(Wietse) are there any non-error cases, such as a valid but
+ * empty array, where bson_new_from_data() or bson_iter_init()
+ * would return null or false? If there are no such cases then we
+ * must handle null/false as an error.
+ */
+ bson_iter_array(iter, &len, &dataBuffer);
+ if ((data = bson_new_from_data(dataBuffer, len)) != 0
+ && bson_iter_init(&dataIter, data)) {
+ VSTRING *iterResult = vstring_alloc(BUFFER_SIZE);
+
+ if ((p = get_result_string(dict_mongodb, iterResult, &dataIter,
+ lookup_name, expansion, key)) != 0) {
+ vstring_sprintf_append(resultString, (got_one_result) ?
+ ",%s" : "%s", p);
+ got_one_result |= true;
+ }
+ vstring_free(iterResult);
+ }
+ bson_destroy(data);
+ break;
+ default:
+ /* Unexpected field type. As documented, warn and ignore. */
+ msg_warn("%s:%s: failed to retrieve value of '%s', "
+ "Unknown result type %d.", dict_mongodb->dict.type,
+ dict_mongodb->dict.name, bson_iter_key(iter),
+ bson_iter_type(iter));
+ break;
+ }
+ }
+ if (dict_mongodb->dict.error != DICT_ERR_NONE || !got_one_result)
+ return (0);
+ return (vstring_str(resultString));
+}
+
+/* dict_mongdb_quote - quote json string */
+
+static void dict_mongdb_quote(DICT *dict, const char *name, VSTRING *result)
+{
+ /* quote_for_json_append() will resize the result buffer as needed. */
+ (void) quote_for_json_append(result, name, -1);
+}
+
+/* dict_mongdb_append_result_attributes - projection builder */
+
+static int dict_mongdb_append_result_attribute(bson_t * projection,
+ const char *result_attribute)
+{
+ char *ra = mystrdup(result_attribute);
+ char *pp = ra;
+ char *cp;
+ int ok = 1;
+
+ while (ok && (cp = mystrtok(&pp, CHARS_COMMA_SP)) != 0)
+ ok = BSON_APPEND_INT32(projection, cp, 1);
+ myfree(ra);
+ return (ok);
+}
+
+/* dict_mongodb_lookup - find database entry using mongo query language */
+
+static const char *dict_mongodb_lookup(DICT *dict, const char *name)
+{
+ DICT_MONGODB *dict_mongodb = (DICT_MONGODB *) dict;
+ mongoc_collection_t *coll = NULL;
+ mongoc_cursor_t *cursor = NULL;
+ bson_iter_t iter;
+ const bson_t *doc = NULL;
+ bson_t *query = NULL;
+ bson_t *options = NULL;
+ bson_t *projection = NULL;
+ bson_error_t error;
+ char *result = NULL;
+ static VSTRING *queryString = NULL;
+ static VSTRING *resultString = NULL;
+ int domain_rc;
+ int expansion = 0;
+
+ dict_mongodb->dict.error = DICT_ERR_NONE;
+
+ /*
+ * If they specified a domain list for this map, then only search for
+ * addresses in domains on the list. This can significantly reduce the
+ * load on the database.
+ */
+ if ((domain_rc = db_common_check_domain(dict_mongodb->ctx, name)) == 0) {
+ if (msg_verbose)
+ msg_info("%s:%s: skipping lookup of '%s': domain mismatch",
+ dict_mongodb->dict.type, dict_mongodb->dict.name, name);
+ return (0);
+ } else if (domain_rc < 0) {
+ DICT_ERR_VAL_RETURN(dict, domain_rc, (char *) 0);
+ }
+
+ /*
+ * Ugly macros to make error and non-error handling code more readable.
+ * If code size is a concern, them an optimizing compiler can eliminate
+ * dead code or duplicated code.
+ */
+
+ /* Set an error code, and return null. */
+#define DICT_MONGODB_LOOKUP_ERR_RETURN(err) do { \
+ dict_mongodb->dict.error = (err); \
+ DICT_MONGODB_LOOKUP_RETURN((char *) 0); \
+} while (0);
+
+ /* Pass through any error, and return the specified value. */
+#define DICT_MONGODB_LOOKUP_RETURN(val) do { \
+ if (coll) mongoc_collection_destroy(coll); \
+ if (cursor) mongoc_cursor_destroy(cursor); \
+ if (query) bson_destroy(query); \
+ if (options) bson_destroy(options); \
+ if (projection) bson_destroy(projection); \
+ return (val); \
+ } while (0)
+
+ coll = mongoc_client_get_collection(dict_mongodb->client,
+ dict_mongodb->dbname,
+ dict_mongodb->collection);
+ if (!coll) {
+ msg_warn("%s:%s: failed to get collection [%s] from [%s]",
+ dict_mongodb->dict.type, dict_mongodb->dict.name,
+ dict_mongodb->collection, dict_mongodb->dbname);
+ DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
+ }
+
+ /*
+ * Use the specified result projection, or craft one from the
+ * result_attribute. Exclude the _id field from the result.
+ */
+ options = bson_new();
+ if (dict_mongodb->projection) {
+ projection = bson_new_from_json((uint8_t *) dict_mongodb->projection,
+ -1, &error);
+ if (!projection) {
+ msg_warn("%s:%s: failed to create a projection from '%s': %s",
+ dict_mongodb->dict.type, dict_mongodb->dict.name,
+ dict_mongodb->projection, error.message);
+ DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
+ }
+ if (!BSON_APPEND_INT32(projection, "_id", 0)
+ || !BSON_APPEND_DOCUMENT(options, "projection", projection)) {
+ msg_warn("%s:%s: failed to append a projection from '%s'",
+ dict_mongodb->dict.type, dict_mongodb->dict.name,
+ dict_mongodb->projection);
+ DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
+ }
+ } else if (dict_mongodb->result_attribute) {
+ bson_t res_attr;
+
+ if (!BSON_APPEND_DOCUMENT_BEGIN(options, "projection", &res_attr)
+ || !BSON_APPEND_INT32(&res_attr, "_id", 0)
+ || !dict_mongdb_append_result_attribute(&res_attr,
+ dict_mongodb->result_attribute)
+ || !bson_append_document_end(options, &res_attr)) {
+ msg_warn("%s:%s: failed to append a projection from '%s'",
+ dict_mongodb->dict.type, dict_mongodb->dict.name,
+ dict_mongodb->result_attribute);
+ DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
+ }
+ } else {
+ /* Can't happen. The configuration parser should reject this. */
+ msg_panic("%s:%s: empty 'projection' and 'result_attribute'",
+ dict_mongodb->dict.type, dict_mongodb->dict.name);
+ }
+
+ /*
+ * Expand filter template. This uses a quoting function to prevent
+ * metacharacter injection with parts from a crafted email address.
+ */
+ INIT_VSTR(queryString, BUFFER_SIZE);
+ if (!db_common_expand(dict_mongodb->ctx, dict_mongodb->query_filter,
+ name, 0, queryString, dict_mongdb_quote))
+ /* Suppress the actual lookup if the expansion is empty. */
+ DICT_MONGODB_LOOKUP_RETURN(0);
+
+ /* Create the query from the expanded query template. */
+ query = bson_new_from_json((uint8_t *) vstring_str(queryString),
+ -1, &error);
+ if (!query) {
+ msg_warn("%s:%s: failed to create a query from '%s': %s",
+ dict_mongodb->dict.type, dict_mongodb->dict.name,
+ vstring_str(queryString), error.message);
+ DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
+ }
+ /* Run the query. */
+ cursor = mongoc_collection_find_with_opts(coll, query, options, NULL);
+ if (mongoc_cursor_error(cursor, &error)) {
+ msg_warn("%s:%s: cursor error for '%s': %s",
+ dict_mongodb->dict.type, dict_mongodb->dict.name,
+ vstring_str(queryString), error.message);
+ DICT_MONGODB_LOOKUP_ERR_RETURN(DICT_ERR_RETRY);
+ }
+ /* Convert the lookup result to C string. */
+ INIT_VSTR(resultString, BUFFER_SIZE);
+ while (mongoc_cursor_next(cursor, &doc)) {
+ if (bson_iter_init(&iter, doc)) {
+ result = get_result_string(dict_mongodb, resultString, &iter,
+ name, &expansion, name);
+ }
+ }
+ DICT_MONGODB_LOOKUP_RETURN(result);
+}
+
+/* dict_mongodb_close - close MongoDB database */
+
+static void dict_mongodb_close(DICT *dict)
+{
+ DICT_MONGODB *dict_mongodb = (DICT_MONGODB *) dict;
+
+ cfg_parser_free(dict_mongodb->parser);
+ if (dict_mongodb->ctx) {
+ db_common_free_ctx(dict_mongodb->ctx);
+ }
+ myfree(dict_mongodb->uri);
+ myfree(dict_mongodb->dbname);
+ myfree(dict_mongodb->collection);
+ myfree(dict_mongodb->query_filter);
+
+ if (dict_mongodb->result_attribute) {
+ myfree(dict_mongodb->result_attribute);
+ }
+ if (dict_mongodb->result_format) {
+ myfree(dict_mongodb->result_format);
+ }
+ if (dict_mongodb->projection) {
+ myfree(dict_mongodb->projection);
+ }
+ if (dict_mongodb->client) {
+ mongoc_client_destroy(dict_mongodb->client);
+ }
+ dict_free(dict);
+}
+
+/* dict_mongodb_open - open MongoDB database connection */
+
+DICT *dict_mongodb_open(const char *name, int open_flags, int dict_flags)
+{
+ DICT_MONGODB *dict_mongodb;
+ CFG_PARSER *parser;
+ mongoc_uri_t *uri = 0;
+ bson_error_t error;
+
+ /* Sanity checks. */
+ if (open_flags != O_RDONLY) {
+ return (dict_surrogate(DICT_TYPE_MONGODB, name, open_flags, dict_flags,
+ "%s:%s: map requires O_RDONLY access mode",
+ DICT_TYPE_MONGODB, name));
+ }
+ /* Open the configuration file. */
+ if ((parser = cfg_parser_alloc(name)) == 0) {
+ return (dict_surrogate(DICT_TYPE_MONGODB, name, open_flags, dict_flags,
+ "open %s: %m", name));
+ }
+ /* Create the dictionary object. */
+ dict_mongodb = (DICT_MONGODB *) dict_alloc(DICT_TYPE_MONGODB, name,
+ sizeof(*dict_mongodb));
+ dict_mongodb->dict.lookup = dict_mongodb_lookup;
+ dict_mongodb->dict.close = dict_mongodb_close;
+ dict_mongodb->dict.flags = dict_flags;
+ dict_mongodb->parser = parser;
+ dict_mongodb->dict.owner = cfg_get_owner(dict_mongodb->parser);
+ dict_mongodb->client = NULL;
+
+ /* Parse config. */
+ mongodb_parse_config(dict_mongodb, name);
+ if (!dict_mongodb->projection == !dict_mongodb->result_attribute) {
+ dict_mongodb_close(&dict_mongodb->dict);
+ return (dict_surrogate(DICT_TYPE_MONGODB, name, open_flags, dict_flags,
+ "%s:%s: specify exactly one of 'projection' or 'result_attribute'",
+ DICT_TYPE_MONGODB, name));
+ }
+ /* One-time initialization of libmongoc 's internals. */
+ if (!init_done) {
+ mongoc_init();
+ init_done = true;
+ }
+#define DICT_MONGODB_OPEN_ERR_RETURN(d) do { \
+ DICT *_d = (d); \
+ if (uri) mongoc_uri_destroy(uri); \
+ dict_mongodb_close(&dict_mongodb->dict); \
+ return (_d); \
+ } while (0);
+
+ uri = mongoc_uri_new_with_error(dict_mongodb->uri, &error);
+ if (!uri)
+ DICT_MONGODB_OPEN_ERR_RETURN(dict_surrogate(DICT_TYPE_MONGODB, name,
+ open_flags, dict_flags,
+ "%s:%s: failed to parse URI '%s': %s",
+ DICT_TYPE_MONGODB, name,
+ dict_mongodb->uri, error.message));
+
+ dict_mongodb->client = mongoc_client_new_from_uri_with_error(uri, &error);
+ if (!dict_mongodb->client)
+ DICT_MONGODB_OPEN_ERR_RETURN(dict_surrogate(DICT_TYPE_MONGODB, name,
+ open_flags, dict_flags,
+ "%s:%s: failed to create client for '%s': %s",
+ DICT_TYPE_MONGODB, name,
+ dict_mongodb->uri,
+ error.message));
+
+ mongoc_uri_destroy(uri);
+ mongoc_client_set_error_api(dict_mongodb->client, MONGOC_ERROR_API_VERSION_2);
+ return (DICT_DEBUG (&dict_mongodb->dict));
+}
+
+#endif
diff --git a/src/global/dict_mongodb.h b/src/global/dict_mongodb.h
new file mode 100755
index 0000000..d5120cb
--- /dev/null
+++ b/src/global/dict_mongodb.h
@@ -0,0 +1,43 @@
+#ifndef _DICT_MONGODB_INCLUDED_
+#define _DICT_MONGODB_INCLUDED_
+
+/*++
+/* NAME
+/* dict_mongodb 3h
+/* SUMMARY
+/* dictionary interface to mongodb databases
+/* SYNOPSIS
+/* #include <dict_mongodb.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+
+ /*
+ * External interface.
+ */
+#define DICT_TYPE_MONGODB "mongodb"
+
+extern DICT *dict_mongodb_open(const char *, int, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Hamid Maadani (hamid@dexo.tech)
+/* Dextrous Technologies, LLC
+/*
+/* Edited by:
+/* Wietse Venema
+/* porcupine.org
+/*
+/* Based on prior work by:
+/* Stephan Ferraro
+/* Aionda GmbH
+/*--*/
+
+#endif
diff --git a/src/global/dict_mysql.c b/src/global/dict_mysql.c
index 3c8fe4f..133cc0d 100644
--- a/src/global/dict_mysql.c
+++ b/src/global/dict_mysql.c
@@ -83,6 +83,10 @@
#include <limits.h>
#include <errno.h>
+#if !defined(MYSQL_VERSION_ID) || MYSQL_VERSION_ID < 40000
+#error "MySQL versions <4 are no longer supported"
+#endif
+
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
@@ -147,9 +151,11 @@ typedef struct {
char *username;
char *password;
char *dbname;
+ char *charset;
+ int retry_interval;
+ int idle_interval;
ARGV *hosts;
PLMYSQL *pldb;
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
HOST *active_host;
char *tls_cert_file;
char *tls_key_file;
@@ -159,7 +165,6 @@ typedef struct {
#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
int tls_verify_cert;
#endif
-#endif
int require_result_set;
} DICT_MYSQL;
@@ -171,15 +176,15 @@ typedef struct {
#define TYPEINET (1<<1)
#define RETRY_CONN_MAX 100
-#define RETRY_CONN_INTV 60 /* 1 minute */
-#define IDLE_CONN_INTV 60 /* 1 minute */
+#define DEF_RETRY_INTV 60 /* 1 minute */
+#define DEF_IDLE_INTV 60 /* 1 minute */
/* internal function declarations */
static PLMYSQL *plmysql_init(ARGV *);
static int plmysql_query(DICT_MYSQL *, const char *, VSTRING *, MYSQL_RES **);
static void plmysql_dealloc(PLMYSQL *);
static void plmysql_close_host(HOST *);
-static void plmysql_down_host(HOST *);
+static void plmysql_down_host(HOST *, int);
static void plmysql_connect_single(DICT_MYSQL *, HOST *);
static const char *dict_mysql_lookup(DICT *, const char *);
DICT *dict_mysql_open(const char *, int, int);
@@ -205,13 +210,21 @@ static void dict_mysql_quote(DICT *dict, const char *name, VSTRING *result)
buflen = 2 * len + 1;
VSTRING_SPACE(result, buflen);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
- if (dict_mysql->active_host)
- mysql_real_escape_string(dict_mysql->active_host->db,
- vstring_end(result), name, len);
- else
+ if (dict_mysql->active_host == 0)
+ msg_panic("dict_mysql_quote: no active host");
+#if MYSQL_VERSION_ID >= 50706 && !defined(MARIADB_VERSION_ID)
+ mysql_real_escape_string_quote(dict_mysql->active_host->db,
+ vstring_end(result), name, len, '\'');
+#else
+ if (mysql_real_escape_string(dict_mysql->active_host->db,
+ vstring_end(result), name, len) ==
+ (unsigned long) -1) {
+ msg_warn("dict_mysql: host (%s) cannot escape input string: >%s<",
+ dict_mysql->active_host->hostname,
+ mysql_error(dict_mysql->active_host->db));
+ dict_mysql->active_host->stat = STATFAIL;
+ }
#endif
- mysql_escape_string(vstring_end(result), name, len);
VSTRING_SKIP(result);
}
@@ -231,7 +244,6 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
int numrows;
int expansion;
const char *r;
- db_quote_callback_t quote_func = dict_mysql_quote;
int domain_rc;
dict->error = 0;
@@ -241,7 +253,7 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
*/
#ifdef SNAPSHOT
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
- && !valid_utf8_string(name, strlen(name))) {
+ && !valid_utf8_stringz(name)) {
if (msg_verbose)
msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
myname, dict_mysql->parser->name, name);
@@ -291,11 +303,8 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
* quoting happens separately for each connection, we don't bother with
* quoting...
*/
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
- quote_func = 0;
-#endif
if (!db_common_expand(dict_mysql->ctx, dict_mysql->query,
- name, 0, query, quote_func))
+ name, 0, query, (db_quote_callback_t) 0))
return (0);
/* do the query - set dict->error & cleanup if there's an error */
@@ -439,8 +448,12 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
{
HOST *host;
MYSQL_RES *first_result = 0;
+
+ /* In case all hosts are down. */
int query_error = 1;
+ errno = ENOTSUP;
+
/*
* Helper to avoid spamming the log with warnings.
*/
@@ -454,8 +467,6 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
while ((host = dict_mysql_get_active(dict_mysql)) != NULL) {
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
-
/*
* The active host is used to escape strings in the context of the
* active connection's character encoding.
@@ -465,8 +476,14 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
VSTRING_TERMINATE(query);
db_common_expand(dict_mysql->ctx, dict_mysql->query,
name, 0, query, dict_mysql_quote);
+ /* Check for potential dict_mysql_quote() failure. */
+ if (host->stat == STATFAIL) {
+ plmysql_down_host(host, dict_mysql->retry_interval);
+ continue;
+ }
+ if (msg_verbose)
+ msg_info("expanded and quoted query: >%s<", vstring_str(query));
dict_mysql->active_host = 0;
-#endif
query_error = 0;
errno = 0;
@@ -546,7 +563,7 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
* See what we got.
*/
if (query_error) {
- plmysql_down_host(host);
+ plmysql_down_host(host, dict_mysql->retry_interval);
if (errno == 0)
errno = ENOTSUP;
if (first_result) {
@@ -559,7 +576,7 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
dict_mysql->dict.type, dict_mysql->dict.name,
host->hostname);
event_request_timer(dict_mysql_event, (void *) host,
- IDLE_CONN_INTV);
+ dict_mysql->idle_interval);
break;
}
}
@@ -581,7 +598,6 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
mysql_options(host->db, MYSQL_READ_DEFAULT_FILE, dict_mysql->option_file);
if (dict_mysql->option_group && dict_mysql->option_group[0])
mysql_options(host->db, MYSQL_READ_DEFAULT_GROUP, dict_mysql->option_group);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
if (dict_mysql->tls_key_file || dict_mysql->tls_cert_file ||
dict_mysql->tls_CAfile || dict_mysql->tls_CApath || dict_mysql->tls_ciphers)
mysql_ssl_set(host->db,
@@ -593,7 +609,6 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
mysql_options(host->db, DICT_MYSQL_SSL_VERIFY_SERVER_CERT,
&dict_mysql->tls_verify_cert);
#endif
-#endif
if (mysql_real_connect(host->db,
(host->type == TYPEINET ? host->name : 0),
dict_mysql->username,
@@ -602,6 +617,12 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
host->port,
(host->type == TYPEUNIX ? host->name : 0),
CLIENT_MULTI_RESULTS)) {
+ if (mysql_set_character_set(host->db, dict_mysql->charset) != 0) {
+ msg_warn("dict_mysql: mysql_set_character_set '%s' failed: %s",
+ dict_mysql->charset, mysql_error(host->db));
+ plmysql_down_host(host, dict_mysql->retry_interval);
+ return;
+ }
if (msg_verbose)
msg_info("dict_mysql: successful connection to host %s",
host->hostname);
@@ -609,7 +630,7 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
} else {
msg_warn("connect to mysql server %s: %s",
host->hostname, mysql_error(host->db));
- plmysql_down_host(host);
+ plmysql_down_host(host, dict_mysql->retry_interval);
}
}
@@ -625,11 +646,11 @@ static void plmysql_close_host(HOST *host)
* plmysql_down_host - close a failed connection AND set a "stay away from
* this host" timer
*/
-static void plmysql_down_host(HOST *host)
+static void plmysql_down_host(HOST *host, int retry_interval)
{
mysql_close(host->db);
host->db = 0;
- host->ts = time((time_t *) 0) + RETRY_CONN_INTV;
+ host->ts = time((time_t *) 0) + retry_interval;
host->stat = STATFAIL;
event_cancel_timer(dict_mysql_event, (void *) host);
}
@@ -646,10 +667,14 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
dict_mysql->username = cfg_get_str(p, "user", "", 0, 0);
dict_mysql->password = cfg_get_str(p, "password", "", 0, 0);
dict_mysql->dbname = cfg_get_str(p, "dbname", "", 1, 0);
+ dict_mysql->charset = cfg_get_str(p, "charset", "utf8mb4", 1, 0);
+ dict_mysql->retry_interval = cfg_get_int(p, "retry_interval",
+ DEF_RETRY_INTV, 1, 0);
+ dict_mysql->idle_interval = cfg_get_int(p, "idle_interval",
+ DEF_IDLE_INTV, 1, 0);
dict_mysql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0);
dict_mysql->option_file = cfg_get_str(p, "option_file", NULL, 0, 0);
dict_mysql->option_group = cfg_get_str(p, "option_group", "client", 0, 0);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
dict_mysql->tls_key_file = cfg_get_str(p, "tls_key_file", NULL, 0, 0);
dict_mysql->tls_cert_file = cfg_get_str(p, "tls_cert_file", NULL, 0, 0);
dict_mysql->tls_CAfile = cfg_get_str(p, "tls_CAfile", NULL, 0, 0);
@@ -658,7 +683,6 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
dict_mysql->tls_verify_cert = cfg_get_bool(p, "tls_verify_cert", -1);
#endif
-#endif
dict_mysql->require_result_set = cfg_get_bool(p, "require_result_set", 1);
/*
@@ -741,9 +765,7 @@ DICT *dict_mysql_open(const char *name, int open_flags, int dict_flags)
dict_mysql->dict.flags = dict_flags;
dict_mysql->parser = parser;
mysql_parse_config(dict_mysql, name);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
dict_mysql->active_host = 0;
-#endif
dict_mysql->pldb = plmysql_init(dict_mysql->hosts);
if (dict_mysql->pldb == NULL)
msg_fatal("couldn't initialize pldb!\n");
@@ -826,13 +848,13 @@ static void dict_mysql_close(DICT *dict)
myfree(dict_mysql->username);
myfree(dict_mysql->password);
myfree(dict_mysql->dbname);
+ myfree(dict_mysql->charset);
myfree(dict_mysql->query);
myfree(dict_mysql->result_format);
if (dict_mysql->option_file)
myfree(dict_mysql->option_file);
if (dict_mysql->option_group)
myfree(dict_mysql->option_group);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
if (dict_mysql->tls_key_file)
myfree(dict_mysql->tls_key_file);
if (dict_mysql->tls_cert_file)
@@ -843,7 +865,6 @@ static void dict_mysql_close(DICT *dict)
myfree(dict_mysql->tls_CApath);
if (dict_mysql->tls_ciphers)
myfree(dict_mysql->tls_ciphers);
-#endif
if (dict_mysql->hosts)
argv_free(dict_mysql->hosts);
if (dict_mysql->ctx)
diff --git a/src/global/dict_pgsql.c b/src/global/dict_pgsql.c
index 5992135..c626854 100644
--- a/src/global/dict_pgsql.c
+++ b/src/global/dict_pgsql.c
@@ -108,18 +108,18 @@
#define TYPEUNIX (1<<0)
#define TYPEINET (1<<1)
-#define TYPECONNSTRING (1<<2)
+#define TYPECONNSTR (1<<2)
#define RETRY_CONN_MAX 100
-#define RETRY_CONN_INTV 60 /* 1 minute */
-#define IDLE_CONN_INTV 60 /* 1 minute */
+#define DEF_RETRY_INTV 60 /* 1 minute */
+#define DEF_IDLE_INTV 60 /* 1 minute */
typedef struct {
PGconn *db;
char *hostname;
char *name;
char *port;
- unsigned type; /* TYPEUNIX | TYPEINET | TYPECONNSTRING */
+ unsigned type; /* TYPEUNIX | TYPEINET | TYPECONNSTR */
unsigned stat; /* STATUNTRIED | STATFAIL | STATCUR */
time_t ts; /* used for attempting reconnection */
} HOST;
@@ -140,6 +140,8 @@ typedef struct {
char *password;
char *dbname;
char *encoding;
+ int retry_interval;
+ int idle_interval;
char *table;
ARGV *hosts;
PLPGSQL *pldb;
@@ -152,12 +154,11 @@ typedef struct {
/* internal function declarations */
static PLPGSQL *plpgsql_init(ARGV *);
-static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *, char *,
- char *, char *, char *);
+static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *);
static void plpgsql_dealloc(PLPGSQL *);
static void plpgsql_close_host(HOST *);
-static void plpgsql_down_host(HOST *);
-static void plpgsql_connect_single(HOST *, char *, char *, char *, char *);
+static void plpgsql_down_host(HOST *, int);
+static void plpgsql_connect_single(DICT_PGSQL *, HOST *);
static const char *dict_pgsql_lookup(DICT *, const char *);
DICT *dict_pgsql_open(const char *, int, int);
static void dict_pgsql_close(DICT *);
@@ -280,7 +281,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name)
*/
#ifdef SNAPSHOT
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
- && !valid_utf8_string(name, strlen(name))) {
+ && !valid_utf8_stringz(name)) {
if (msg_verbose)
msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
myname, dict_pgsql->parser->name, name);
@@ -324,11 +325,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name)
return (0);
/* do the query - set dict->error & cleanup if there's an error */
- if ((query_res = plpgsql_query(dict_pgsql, name, query,
- dict_pgsql->dbname,
- dict_pgsql->encoding,
- dict_pgsql->username,
- dict_pgsql->password)) == 0) {
+ if ((query_res = plpgsql_query(dict_pgsql, name, query)) == 0) {
dict->error = DICT_ERR_RETRY;
return 0;
}
@@ -404,8 +401,7 @@ static HOST *dict_pgsql_find_host(PLPGSQL *PLDB, unsigned stat, unsigned type)
/* dict_pgsql_get_active - get an active connection */
-static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding,
- char *username, char *password)
+static HOST *dict_pgsql_get_active(DICT_PGSQL *dict_pgsql, PLPGSQL *PLDB)
{
const char *myname = "dict_pgsql_get_active";
HOST *host;
@@ -414,7 +410,7 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding,
/* try the active connections first; prefer the ones to UNIX sockets */
if ((host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPEUNIX)) != NULL ||
(host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPEINET)) != NULL ||
- (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTRING)) != NULL) {
+ (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTR)) != NULL) {
if (msg_verbose)
msg_info("%s: found active connection to host %s", myname,
host->hostname);
@@ -432,11 +428,11 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding,
(host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL,
TYPEINET)) != NULL ||
(host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL,
- TYPECONNSTRING)) != NULL)) {
+ TYPECONNSTR)) != NULL)) {
if (msg_verbose)
msg_info("%s: attempting to connect to host %s", myname,
host->hostname);
- plpgsql_connect_single(host, dbname, encoding, username, password);
+ plpgsql_connect_single(dict_pgsql, host);
if (host->stat == STATACTIVE)
return host;
}
@@ -464,18 +460,14 @@ static void dict_pgsql_event(int unused_event, void *context)
static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
const char *name,
- VSTRING *query,
- char *dbname,
- char *encoding,
- char *username,
- char *password)
+ VSTRING *query)
{
PLPGSQL *PLDB = dict_pgsql->pldb;
HOST *host;
PGSQL_RES *res = 0;
ExecStatusType status;
- while ((host = dict_pgsql_get_active(PLDB, dbname, encoding, username, password)) != NULL) {
+ while ((host = dict_pgsql_get_active(dict_pgsql, PLDB)) != NULL) {
/*
* The active host is used to escape strings in the context of the
@@ -490,7 +482,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
/* Check for potential dict_pgsql_quote() failure. */
if (host->stat == STATFAIL) {
- plpgsql_down_host(host);
+ plpgsql_down_host(host, dict_pgsql->retry_interval);
continue;
}
@@ -528,7 +520,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
msg_info("dict_pgsql: successful query from host %s",
host->hostname);
event_request_timer(dict_pgsql_event, (void *) host,
- IDLE_CONN_INTV);
+ dict_pgsql->idle_interval);
return (res);
case PGRES_FATAL_ERROR:
msg_warn("pgsql query failed: fatal error from host %s: %s",
@@ -559,7 +551,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
*/
if (res != 0)
PQclear(res);
- plpgsql_down_host(host);
+ plpgsql_down_host(host, dict_pgsql->retry_interval);
}
return (0);
@@ -570,24 +562,25 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
* used to reconnect to a single database when one is down or none is
* connected yet. Log all errors and set the stat field of host accordingly
*/
-static void plpgsql_connect_single(HOST *host, char *dbname, char *encoding, char *username, char *password)
+static void plpgsql_connect_single(DICT_PGSQL *dict_pgsql, HOST *host)
{
- if (host->type == TYPECONNSTRING) {
+ if (host->type == TYPECONNSTR) {
host->db = PQconnectdb(host->name);
} else {
host->db = PQsetdbLogin(host->name, host->port, NULL, NULL,
- dbname, username, password);
+ dict_pgsql->dbname, dict_pgsql->username,
+ dict_pgsql->password);
}
if (host->db == NULL || PQstatus(host->db) != CONNECTION_OK) {
msg_warn("connect to pgsql server %s: %s",
host->hostname, PQerrorMessage(host->db));
- plpgsql_down_host(host);
+ plpgsql_down_host(host, dict_pgsql->retry_interval);
return;
}
- if (PQsetClientEncoding(host->db, encoding) != 0) {
+ if (PQsetClientEncoding(host->db, dict_pgsql->encoding) != 0) {
msg_warn("dict_pgsql: cannot set the encoding to %s, skipping %s",
- encoding, host->hostname);
- plpgsql_down_host(host);
+ dict_pgsql->encoding, host->hostname);
+ plpgsql_down_host(host, dict_pgsql->retry_interval);
return;
}
if (msg_verbose)
@@ -611,12 +604,12 @@ static void plpgsql_close_host(HOST *host)
* plpgsql_down_host - close a failed connection AND set a "stay away from
* this host" timer.
*/
-static void plpgsql_down_host(HOST *host)
+static void plpgsql_down_host(HOST *host, int retry_interval)
{
if (host->db)
PQfinish(host->db);
host->db = 0;
- host->ts = time((time_t *) 0) + RETRY_CONN_INTV;
+ host->ts = time((time_t *) 0) + retry_interval;
host->stat = STATFAIL;
event_cancel_timer(dict_pgsql_event, (void *) host);
}
@@ -635,6 +628,10 @@ static void pgsql_parse_config(DICT_PGSQL *dict_pgsql, const char *pgsqlcf)
dict_pgsql->password = cfg_get_str(p, "password", "", 0, 0);
dict_pgsql->dbname = cfg_get_str(p, "dbname", "", 1, 0);
dict_pgsql->encoding = cfg_get_str(p, "encoding", "UTF8", 1, 0);
+ dict_pgsql->retry_interval = cfg_get_int(p, "retry_interval",
+ DEF_RETRY_INTV, 1, 0);
+ dict_pgsql->idle_interval = cfg_get_int(p, "idle_interval",
+ DEF_IDLE_INTV, 1, 0);
dict_pgsql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0);
/*
@@ -764,7 +761,7 @@ static HOST *host_init(const char *hostname)
* Modern syntax: "postgresql://connection-info".
*/
if (strncmp(d, "postgresql:", 11) == 0) {
- host->type = TYPECONNSTRING;
+ host->type = TYPECONNSTR;
host->name = mystrdup(d);
host->port = 0;
}
diff --git a/src/global/dict_sqlite.c b/src/global/dict_sqlite.c
index 677d05a..7d6608a 100644
--- a/src/global/dict_sqlite.c
+++ b/src/global/dict_sqlite.c
@@ -149,7 +149,7 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name)
* Don't frustrate future attempts to make Postfix UTF-8 transparent.
*/
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0
- && !valid_utf8_string(name, strlen(name))) {
+ && !valid_utf8_stringz(name)) {
if (msg_verbose)
msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'",
myname, dict_sqlite->parser->name, name);
diff --git a/src/global/mail_addr_find.c b/src/global/mail_addr_find.c
index afbccd5..c7e5545 100644
--- a/src/global/mail_addr_find.c
+++ b/src/global/mail_addr_find.c
@@ -442,8 +442,8 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
/*
* Try localpart@ even if the domain is not local.
*/
- if ((strategy & MA_FIND_LOCALPART_AT) != 0 \
- &&result == 0 && path->error == 0)
+ if ((strategy & MA_FIND_LOCALPART_AT) != 0
+ && result == 0 && path->error == 0)
result = find_local(path, ratsign, 1, int_full_key,
int_bare_key, query_form, extp, &saved_ext,
ext_addr_buf);
diff --git a/src/global/mail_date.c b/src/global/mail_date.c
index 55d8907..439a0ea 100644
--- a/src/global/mail_date.c
+++ b/src/global/mail_date.c
@@ -10,7 +10,7 @@
/* time_t when;
/* DESCRIPTION
/* mail_date() converts the time specified in \fIwhen\fR to the
-/* form: "Mon, 9 Dec 1996 05:38:26 -0500 (EST)" and returns
+/* form: "Mon, 09 Dec 1996 05:38:26 -0500 (EST)" and returns
/* a pointer to the result. The result is overwritten upon
/* each call.
/* DIAGNOSTICS
@@ -98,8 +98,13 @@ const char *mail_date(time_t when)
* First, format the date and wall-clock time. XXX The %e format (day of
* month, leading zero replaced by blank) isn't in my POSIX book, but
* many vendors seem to support it.
+ *
+ * The RFC 5322 Date and Time Specification recommends (i.e., should) "that
+ * a single space be used in each place that FWS appears". To avoid a
+ * potentially breaking change, we prefer the %d (two-digit day) format,
+ * i.e. days 1-9 now have a leading zero instead of a leading space.
*/
-#ifdef MISSING_STRFTIME_E
+#if defined(MISSING_STRFTIME_E) || defined(TWO_DIGIT_DAY_IN_DATE_TIME)
#define STRFTIME_FMT "%a, %d %b %Y %H:%M:%S "
#else
#define STRFTIME_FMT "%a, %e %b %Y %H:%M:%S "
diff --git a/src/global/mail_dict.c b/src/global/mail_dict.c
index c640a80..55ac5dc 100644
--- a/src/global/mail_dict.c
+++ b/src/global/mail_dict.c
@@ -52,6 +52,7 @@
#include <dict_pgsql.h>
#include <dict_sqlite.h>
#include <dict_memcache.h>
+#include <dict_mongodb.h>
#include <mail_dict.h>
#include <mail_params.h>
#include <mail_dict.h>
@@ -71,6 +72,9 @@ static const DICT_OPEN_INFO dict_open_info[] = {
#ifdef HAS_SQLITE
DICT_TYPE_SQLITE, dict_sqlite_open, 0,
#endif
+#ifdef HAS_MONGODB
+ DICT_TYPE_MONGODB, dict_mongodb_open, 0,
+#endif
#endif /* !USE_DYNAMIC_MAPS */
DICT_TYPE_MEMCACHE, dict_memcache_open, 0,
0,
diff --git a/src/global/mail_params.c b/src/global/mail_params.c
index 81aee73..2a7f84c 100644
--- a/src/global/mail_params.c
+++ b/src/global/mail_params.c
@@ -159,6 +159,7 @@
/* char *var_maillog_file_pfxs;
/* char *var_maillog_file_comp;
/* char *var_maillog_file_stamp;
+/* char *var_maillog_file_perms;
/* char *var_postlog_service;
/*
/* char *var_dnssec_probe;
@@ -226,6 +227,7 @@
#include <vstring_vstream.h>
#include <iostuff.h>
#include <midna_domain.h>
+#include <logwriter.h>
/* Global library. */
@@ -375,6 +377,7 @@ char *var_maillog_file;
char *var_maillog_file_pfxs;
char *var_maillog_file_comp;
char *var_maillog_file_stamp;
+char *var_maillog_file_perms;
char *var_postlog_service;
char *var_dnssec_probe;
@@ -515,9 +518,11 @@ static void check_mail_owner(void)
*/
if ((pwd = getpwuid(var_owner_uid)) != 0
&& strcmp(pwd->pw_name, var_mail_owner) != 0)
- msg_fatal("file %s/%s: parameter %s: user %s has same user ID as %s",
+ msg_fatal("file %s/%s: parameter %s: user %s has the same"
+ " user ID %ld as user %s",
var_config_dir, MAIN_CONF_FILE,
- VAR_MAIL_OWNER, var_mail_owner, pwd->pw_name);
+ VAR_MAIL_OWNER, var_mail_owner,
+ (long) var_owner_uid, pwd->pw_name);
}
/* check_sgid_group - lookup setgid group attributes and validate */
@@ -542,9 +547,11 @@ static void check_sgid_group(void)
*/
if ((grp = getgrgid(var_sgid_gid)) != 0
&& strcmp(grp->gr_name, var_sgid_group) != 0)
- msg_fatal("file %s/%s: parameter %s: group %s has same group ID as %s",
+ msg_fatal("file %s/%s: parameter %s: group %s has the same"
+ " group ID %ld as group %s",
var_config_dir, MAIN_CONF_FILE,
- VAR_SGID_GROUP, var_sgid_group, grp->gr_name);
+ VAR_SGID_GROUP, var_sgid_group,
+ (long) var_sgid_gid, grp->gr_name);
}
/* check_overlap - disallow UID or GID sharing */
@@ -729,6 +736,7 @@ void mail_params_init()
VAR_MAILLOG_FILE_PFXS, DEF_MAILLOG_FILE_PFXS, &var_maillog_file_pfxs, 1, 0,
VAR_MAILLOG_FILE_COMP, DEF_MAILLOG_FILE_COMP, &var_maillog_file_comp, 1, 0,
VAR_MAILLOG_FILE_STAMP, DEF_MAILLOG_FILE_STAMP, &var_maillog_file_stamp, 1, 0,
+ VAR_MAILLOG_FILE_PERMS, DEF_MAILLOG_FILE_PERMS, &var_maillog_file_perms, 1, 0,
VAR_POSTLOG_SERVICE, DEF_POSTLOG_SERVICE, &var_postlog_service, 1, 0,
VAR_DNSSEC_PROBE, DEF_DNSSEC_PROBE, &var_dnssec_probe, 0, 0,
VAR_KNOWN_TCP_PORTS, DEF_KNOWN_TCP_PORTS, &var_known_tcp_ports, 0, 0,
@@ -979,6 +987,9 @@ void mail_params_init()
dict_db_cache_size = var_db_read_buf;
dict_lmdb_map_size = var_lmdb_map_size;
inet_windowsize = var_inet_windowsize;
+ if (set_logwriter_create_perms(var_maillog_file_perms) < 0)
+ msg_warn("ignoring bad permissions: %s = %s",
+ VAR_MAILLOG_FILE_PERMS, var_maillog_file_perms);
/*
* Variables whose defaults are determined at runtime, after other
diff --git a/src/global/mail_params.h b/src/global/mail_params.h
index 3064b01..1f03b0b 100644
--- a/src/global/mail_params.h
+++ b/src/global/mail_params.h
@@ -1321,6 +1321,10 @@ extern bool var_smtpd_tls_ask_ccert;
#define DEF_SMTPD_TLS_RCERT 0
extern bool var_smtpd_tls_req_ccert;
+#define VAR_SMTPD_TLS_ENABLE_RPK "smtpd_tls_enable_rpk"
+#define DEF_SMTPD_TLS_ENABLE_RPK 0
+extern bool var_smtpd_tls_enable_rpk;
+
#define VAR_SMTPD_TLS_CCERT_VD "smtpd_tls_ccert_verifydepth"
#define DEF_SMTPD_TLS_CCERT_VD 9
extern int var_smtpd_tls_ccert_vd;
@@ -1555,6 +1559,12 @@ extern char *var_smtp_tls_mand_excl;
"{md5} : {sha256}}"
extern char *var_smtp_tls_fpt_dgst;
+#define VAR_SMTP_TLS_ENABLE_RPK "smtp_tls_enable_rpk"
+#define DEF_SMTP_TLS_ENABLE_RPK 0
+#define VAR_LMTP_TLS_ENABLE_RPK "lmtp_tls_enable_rpk"
+#define DEF_LMTP_TLS_ENABLE_RPK 0
+extern bool var_smtp_tls_enable_rpk;
+
#define VAR_SMTP_TLS_TAFILE "smtp_tls_trust_anchor_file"
#define DEF_SMTP_TLS_TAFILE ""
#define VAR_LMTP_TLS_TAFILE "lmtp_tls_trust_anchor_file"
@@ -1745,6 +1755,12 @@ extern bool var_smtp_sasl_enable;
#define DEF_SMTP_SASL_PASSWD ""
extern char *var_smtp_sasl_passwd;
+#define VAR_SMTP_SASL_PASSWD_RES_DELIM "smtp_sasl_password_result_delimiter"
+#define DEF_SMTP_SASL_PASSWD_RES_DELIM ":"
+#define VAR_LMTP_SASL_PASSWD_RES_DELIM "lmtp_sasl_password_result_delimiter"
+#define DEF_LMTP_SASL_PASSWD_RES_DELIM DEF_SMTP_SASL_PASSWD_RES_DELIM
+extern char *var_smtp_sasl_passwd_res_delim;
+
#define VAR_SMTP_SASL_OPTS "smtp_sasl_security_options"
#define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous"
extern char *var_smtp_sasl_opts;
@@ -2437,7 +2453,7 @@ extern char *var_smtpd_exp_filter;
extern bool var_smtpd_peername_lookup;
#define VAR_SMTPD_FORBID_UNAUTH_PIPE "smtpd_forbid_unauth_pipelining"
-#define DEF_SMTPD_FORBID_UNAUTH_PIPE 0
+#define DEF_SMTPD_FORBID_UNAUTH_PIPE 1
extern bool var_smtpd_forbid_unauth_pipe;
/*
@@ -3072,6 +3088,10 @@ extern bool var_disable_mime_input;
#define DEF_DISABLE_MIME_OCONV 0
extern bool var_disable_mime_oconv;
+#define VAR_FORCE_MIME_ICONV "force_mime_input_conversion"
+#define DEF_FORCE_MIME_ICONV 0
+extern bool var_force_mime_iconv;
+
#define VAR_STRICT_8BITMIME "strict_8bitmime"
#define DEF_STRICT_8BITMIME 0
extern bool var_strict_8bitmime;
@@ -3982,6 +4002,10 @@ extern bool var_tlsp_tls_ask_ccert;
#define DEF_TLSP_TLS_RCERT "$" VAR_SMTPD_TLS_RCERT
extern bool var_tlsp_tls_req_ccert;
+#define VAR_TLSP_TLS_ENABLE_RPK "tlsproxy_tls_enable_rpk"
+#define DEF_TLSP_TLS_ENABLE_RPK "$" VAR_SMTPD_TLS_ENABLE_RPK
+extern bool var_tlsp_tls_enable_rpk;
+
#define VAR_TLSP_TLS_CCERT_VD "tlsproxy_tls_ccert_verifydepth"
#define DEF_TLSP_TLS_CCERT_VD "$" VAR_SMTPD_TLS_CCERT_VD
extern int var_tlsp_tls_ccert_vd;
@@ -4282,7 +4306,7 @@ extern char *var_smtpd_dns_re_filter;
* Backwards compatibility.
*/
#define VAR_SMTPD_FORBID_BARE_LF "smtpd_forbid_bare_newline"
-#define DEF_SMTPD_FORBID_BARE_LF "no"
+#define DEF_SMTPD_FORBID_BARE_LF "normalize"
#define VAR_SMTPD_FORBID_BARE_LF_EXCL "smtpd_forbid_bare_newline_exclusions"
#define DEF_SMTPD_FORBID_BARE_LF_EXCL "$" VAR_MYNETWORKS
@@ -4379,6 +4403,10 @@ extern char *var_maillog_file_comp;
#define DEF_MAILLOG_FILE_STAMP "%Y%m%d-%H%M%S"
extern char *var_maillog_file_stamp;
+#define VAR_MAILLOG_FILE_PERMS "maillog_file_permissions"
+#define DEF_MAILLOG_FILE_PERMS "0600"
+extern char *var_maillog_file_perms;
+
#define VAR_POSTLOG_SERVICE "postlog_service_name"
#define DEF_POSTLOG_SERVICE MAIL_SERVICE_POSTLOG
extern char *var_postlog_service;
diff --git a/src/global/mail_proto.h b/src/global/mail_proto.h
index 315a2e1..bea0886 100644
--- a/src/global/mail_proto.h
+++ b/src/global/mail_proto.h
@@ -63,6 +63,13 @@
#define MAIL_SERVICE_POSTLOG "postlog"
/*
+ * Process names: convention is to use the basename of an executable file,
+ * but there is nothing to enforce that.
+ */
+#define MAIL_PROC_NAME_SMTP "smtp"
+#define MAIL_PROC_NAME_LMTP "lmtp"
+
+ /*
* Mail source classes. Used to specify policy decisions for content
* inspection and SMTPUTF8 detection.
*/
diff --git a/src/global/mail_version.h b/src/global/mail_version.h
index 9eda667..9e08896 100644
--- a/src/global/mail_version.h
+++ b/src/global/mail_version.h
@@ -20,8 +20,8 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20240304"
-#define MAIL_VERSION_NUMBER "3.8.6"
+#define MAIL_RELEASE_DATE "20240306"
+#define MAIL_VERSION_NUMBER "3.9"
#ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
diff --git a/src/global/maillog_client.c b/src/global/maillog_client.c
index 7f79a1f..34952ef 100644
--- a/src/global/maillog_client.c
+++ b/src/global/maillog_client.c
@@ -58,7 +58,7 @@
/* unitialized and the process environment does not specify
/* POSTLOG_SERVICE, the program will log to the syslog service
/* instead.
-/* .IP "myhostname (default: see postconf -d output)"
+/* .IP "myhostname (default: see 'postconf -d' output)"
/* The internet hostname of this mail system.
/* .IP "postlog_service_name (postlog)"
/* The name of the internal postlog logging service.
diff --git a/src/global/maps.c b/src/global/maps.c
index 790396b..d237002 100644
--- a/src/global/maps.c
+++ b/src/global/maps.c
@@ -195,8 +195,12 @@ const char *maps_find(MAPS *maps, const char *name, int flags)
for (map_name = maps->argv->argv; *map_name; map_name++) {
if ((dict = dict_handle(*map_name)) == 0)
msg_panic("%s: dictionary not found: %s", myname, *map_name);
- if (flags != 0 && (dict->flags & flags) == 0)
+ if (flags != 0 && (dict->flags & flags) == 0) {
+ if (msg_verbose)
+ msg_info("%s: %s: skipping %s lookup for %s",
+ myname, maps->title, *map_name, name);
continue;
+ }
if ((expansion = dict_get(dict, name)) != 0) {
if (*expansion == 0) {
msg_warn("%s lookup of %s returns an empty string result",
@@ -252,8 +256,12 @@ const char *maps_file_find(MAPS *maps, const char *name, int flags)
if ((dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) == 0)
msg_panic("%s: %s: opened without DICT_FLAG_SRC_RHS_IS_FILE",
myname, maps->title);
- if (flags != 0 && (dict->flags & flags) == 0)
+ if (flags != 0 && (dict->flags & flags) == 0) {
+ if (msg_verbose)
+ msg_info("%s: %s: skipping %s lookup for %s",
+ myname, maps->title, *map_name, name);
continue;
+ }
if ((expansion = dict_get(dict, name)) != 0) {
if (*expansion == 0) {
msg_warn("%s lookup of %s returns an empty string result",
diff --git a/src/global/wildcard_inet_addr.c b/src/global/wildcard_inet_addr.c
index 97f6c46..0a3c37a 100644
--- a/src/global/wildcard_inet_addr.c
+++ b/src/global/wildcard_inet_addr.c
@@ -11,7 +11,7 @@
/* wildcard_inet_addr() determines all wild-card addresses
/* for all supported address families.
/* DIAGNOSTICS
-/* Fatal errors: out of memory.
+/* Fatal errors: out of memory; no wildcard addresses.
/* SEE ALSO
/* inet_addr_list(3) address list management
/* LICENSE
diff --git a/src/local/command.c b/src/local/command.c
index 4781daf..368307d 100644
--- a/src/local/command.c
+++ b/src/local/command.c
@@ -17,7 +17,8 @@
/* Duplicate commands for the same recipient are suppressed.
/* A limited amount of information is exported via the environment:
/* HOME, SHELL, LOGNAME, USER, EXTENSION, DOMAIN, RECIPIENT (entire
-/* address) LOCAL (just the local part) and SENDER. The exported
+/* address) LOCAL (just the local part), SENDER, and ENVID
+/* (see RFC 3461). The exported
/* information is censored with var_cmd_filter.
/*
/* Arguments:
@@ -169,6 +170,8 @@ int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, const char *comma
if (state.msg_attr.rcpt.orig_addr && state.msg_attr.rcpt.orig_addr[0])
argv_add(env, "ORIGINAL_RECIPIENT", state.msg_attr.rcpt.orig_addr,
ARGV_END);
+ if (state.request->dsn_envid[0])
+ argv_add(env, "ENVID", state.request->dsn_envid, ARGV_END);
#define EXPORT_REQUEST(name, value) \
if ((value)[0]) argv_add(env, (name), (value), ARGV_END);
diff --git a/src/local/local.c b/src/local/local.c
index 32bdea7..10b8082 100644
--- a/src/local/local.c
+++ b/src/local/local.c
@@ -207,27 +207,30 @@
/* is specified with the \fBcommand_expansion_filter\fR configuration
/* parameter.
/* .IP \fBSHELL\fR
-/* The recipient user's login shell.
+/* The envelope recipient user's login shell.
/* .IP \fBHOME\fR
-/* The recipient user's home directory.
+/* The envelope recipient user's home directory.
/* .IP \fBUSER\fR
-/* The bare recipient name.
+/* The bare envelope recipient name.
/* .IP \fBEXTENSION\fR
-/* The optional recipient address extension.
+/* The optional envelope recipient address extension.
/* .IP \fBDOMAIN\fR
-/* The recipient address domain part.
+/* The envelope recipient address domain part.
/* .IP \fBLOGNAME\fR
-/* The bare recipient name.
+/* The bare envelope recipient name.
/* .IP \fBLOCAL\fR
-/* The entire recipient address localpart (text to the left of the
-/* rightmost @ character).
+/* The entire envelope recipient address localpart (text to
+/* the left of the rightmost @ character).
/* .IP \fBORIGINAL_RECIPIENT\fR
-/* The entire recipient address, before any address rewriting
-/* or aliasing (Postfix 2.5 and later).
+/* The entire envelope recipient address, before any address
+/* rewriting or aliasing (Postfix 2.5 and later).
/* .IP \fBRECIPIENT\fR
-/* The entire recipient address.
+/* The entire envelope recipient address.
/* .IP \fBSENDER\fR
-/* The entire sender address.
+/* The entire envelope sender address.
+/* .IP \fBENVID\fR
+/* The optional RFC 3461 envelope ID. Available as of Postfix
+/* 3.9.
/* .PP
/* Additional remote client information is made available via
/* the following environment variables:
@@ -413,7 +416,9 @@
/* home_mailbox, mail_spool_directory, fallback_transport_maps,
/* fallback_transport, and luser_relay.
/* .IP "\fBalias_maps (see 'postconf -d' output)\fR"
-/* The alias databases that are used for \fBlocal\fR(8) delivery.
+/* Optional lookup tables with aliases that apply only to \fBlocal\fR(8)
+/* recipients; this is unlike virtual_alias_maps that apply to all
+/* recipients: \fBlocal\fR(8), virtual, and remote.
/* .IP "\fBforward_path (see 'postconf -d' output)\fR"
/* The \fBlocal\fR(8) delivery agent search list for finding a .forward
/* file with user-specified delivery methods.
diff --git a/src/master/master.c b/src/master/master.c
index 1fc3fe9..b6afe3f 100644
--- a/src/master/master.c
+++ b/src/master/master.c
@@ -135,13 +135,13 @@
/* The external command to execute when a Postfix daemon program is
/* invoked with the -D option.
/* .IP "\fBinet_interfaces (all)\fR"
-/* The network interface addresses that this mail system receives
-/* mail on.
-/* .IP "\fBinet_protocols (see 'postconf -d output')\fR"
+/* The local network interface addresses that this mail system
+/* receives mail on.
+/* .IP "\fBinet_protocols (see 'postconf -d' output)\fR"
/* The Internet protocols Postfix will attempt to use when making
/* or accepting connections.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a privileged Postfix
+/* The list of environment variables that a privileged Postfix
/* process will import from a non-Postfix parent process, or name=value
/* environment overrides.
/* .IP "\fBmail_owner (postfix)\fR"
@@ -495,7 +495,7 @@ int main(int argc, char **argv)
vstring_sprintf(lock_path, "%s/%s.pid", DEF_PID_DIR, var_procname);
if (test_lock && access(vstring_str(lock_path), F_OK) < 0)
exit(0);
- lock_fp = open_lock(vstring_str(lock_path), O_RDWR | O_CREAT, 0644, why);
+ lock_fp = open_lock(vstring_str(lock_path), O_RDWR | O_CREAT, 0600, why);
if (test_lock)
exit(lock_fp ? 0 : 1);
if (lock_fp == 0)
@@ -513,7 +513,7 @@ int main(int argc, char **argv)
vstring_sprintf(data_lock_path, "%s/%s.lock", var_data_dir, var_procname);
set_eugid(var_owner_uid, var_owner_gid);
data_lock_fp =
- open_lock(vstring_str(data_lock_path), O_RDWR | O_CREAT, 0644, why);
+ open_lock(vstring_str(data_lock_path), O_RDWR | O_CREAT, 0600, why);
set_ugid(getuid(), getgid());
if (data_lock_fp == 0)
msg_fatal("open lock file %s: %s",
diff --git a/src/master/master_ent.c b/src/master/master_ent.c
index 5edc308..98f8404 100644
--- a/src/master/master_ent.c
+++ b/src/master/master_ent.c
@@ -369,8 +369,12 @@ MASTER_SERV *get_master_ent()
} else {
MASTER_INET_ADDRLIST(serv) =
strcasecmp(saved_interfaces, INET_INTERFACES_ALL) ?
- own_inet_addr_list() : /* virtual */
- wildcard_inet_addr_list(); /* wild-card */
+ own_inet_addr_list() : /* result can be empty */
+ wildcard_inet_addr_list(); /* result can't be empty */
+ if (MASTER_INET_ADDRLIST(serv)->used == 0)
+ fatal_with_context("service definition requires valid"
+ " host name or address, or non-empty"
+ " %s setting", VAR_INET_INTERFACES);
inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
}
diff --git a/src/oqmgr/qmgr_deliver.c b/src/oqmgr/qmgr_deliver.c
index 03e0340..6c09350 100644
--- a/src/oqmgr/qmgr_deliver.c
+++ b/src/oqmgr/qmgr_deliver.c
@@ -155,7 +155,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
*/
for (recipient = list.info; recipient < list.info + list.len; recipient++)
if (var_smtputf8_enable && (addr = recipient->address)[0]
- && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) {
+ && !allascii(addr) && valid_utf8_stringz(addr)) {
smtputf8 |= SMTPUTF8_FLAG_RECIPIENT;
if (message->verp_delims)
smtputf8 |= SMTPUTF8_FLAG_SENDER;
@@ -334,7 +334,7 @@ static void qmgr_deliver_update(int unused_event, void *context)
#define SUSPENDED "delivery temporarily suspended: "
if (status == DELIVER_STAT_CRASH)
- DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error");
+ (void) DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error");
if (status == DELIVER_STAT_CRASH || status == DELIVER_STAT_DEFER) {
message->flags |= DELIVER_STAT_DEFER;
if (VSTRING_LEN(dsb->status)) {
diff --git a/src/pipe/pipe.c b/src/pipe/pipe.c
index 8a99430..3017937 100644
--- a/src/pipe/pipe.c
+++ b/src/pipe/pipe.c
@@ -230,6 +230,11 @@
/* This information is modified by the \fBh\fR flag for case folding.
/* .sp
/* This feature is available as of Postfix 2.5.
+/* .IP \fB${envid}\fR
+/* This macro expands to the RFC 3461 envelope ID if available,
+/* otherwise the empty string.
+/* .sp
+/* This feature is available as of Postfix 3.9.
/* .IP \fB${extension}\fR
/* This macro expands to the extension part of a recipient address.
/* For example, with an address \fIuser+foo@domain\fR the extension is
@@ -544,6 +549,7 @@
#define PIPE_DICT_SASL_USERNAME "sasl_username" /* key */
#define PIPE_DICT_SASL_SENDER "sasl_sender" /* key */
#define PIPE_DICT_QUEUE_ID "queue_id" /* key */
+#define PIPE_DICT_ENVID "envid" /* key */
/*
* Flags used to pass back the type of special parameter found by
@@ -649,6 +655,7 @@ static int parse_callback(int type, VSTRING *buf, void *context)
PIPE_DICT_SASL_USERNAME, 0,
PIPE_DICT_SASL_SENDER, 0,
PIPE_DICT_QUEUE_ID, 0,
+ PIPE_DICT_ENVID, 0,
0, 0,
};
struct cmd_flags *p;
@@ -1278,6 +1285,8 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
request->sasl_sender);
dict_update(PIPE_DICT_TABLE, PIPE_DICT_QUEUE_ID,
request->queue_id);
+ dict_update(PIPE_DICT_TABLE, PIPE_DICT_ENVID,
+ request->dsn_envid);
vstring_free(buf);
if ((expanded_argv = expand_argv(service, attr.command,
diff --git a/src/postalias/postalias.c b/src/postalias/postalias.c
index d17e397..72ca729 100644
--- a/src/postalias/postalias.c
+++ b/src/postalias/postalias.c
@@ -393,7 +393,7 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
*/
if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE)
&& !allascii(STR(line_buffer))
- && !valid_utf8_string(STR(line_buffer), LEN(line_buffer))) {
+ && !valid_utf8_stringz(STR(line_buffer))) {
msg_warn("%s, line %d: non-UTF-8 input \"%s\""
" -- ignoring this line",
VSTREAM_PATH(source_fp), lineno, STR(line_buffer));
diff --git a/src/postcat/postcat.c b/src/postcat/postcat.c
index 36f2740..26b46a9 100644
--- a/src/postcat/postcat.c
+++ b/src/postcat/postcat.c
@@ -76,7 +76,7 @@
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a privileged Postfix
+/* The list of environment variables that a privileged Postfix
/* process will import from a non-Postfix parent process, or name=value
/* environment overrides.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
@@ -274,7 +274,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
break;
/* Optimization: skip to extracted segment marker. */
if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV)
- && data_offset >= 0 && data_size >= 0
+ && data_offset > 0 && data_size >= 0
&& vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
msg_fatal("seek error: %m");
}
@@ -289,7 +289,7 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
PRINT_MARKER(flags, fp, offset, rec_type, "MESSAGE CONTENTS");
/* Optimization: skip to extracted segment marker. */
if ((flags & PC_MASK_PRINT_TEXT) == 0
- && data_offset >= 0 && data_size >= 0
+ && data_offset > 0 && data_size >= 0
&& vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
msg_fatal("seek error: %m");
/* Update the state machine, even when skipping. */
diff --git a/src/postconf/Makefile.in b/src/postconf/Makefile.in
index 6aff794..6df6dfa 100644
--- a/src/postconf/Makefile.in
+++ b/src/postconf/Makefile.in
@@ -17,7 +17,7 @@ MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
nint_table.h nint_vars.h nbool_table.h nbool_vars.h long_table.h \
long_vars.h str_fn_table.h str_fn_vars.h
DB_MAKES= pcf_ldap_suffixes.h pcf_memcache_suffixes.h pcf_mysql_suffixes.h \
- pcf_pgsql_suffixes.h pcf_sqlite_suffixes.h
+ pcf_pgsql_suffixes.h pcf_sqlite_suffixes.h pcf_mongodb_suffixes.h
TEST_TMP= main.cf master.cf test*.tmp
DUMMIES = makes_dummy # for "make -j"
PROG = postconf
@@ -55,7 +55,8 @@ tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \
test31 test32 test33 test34 test35 test36 test37 test39 test40 test41 \
test42 test43 test44 test45 test46 test47 test48 test49 test50 test51 \
test52 test53 test54 test55 test56 test57 test58 test59 test60 test61 \
- test62 test63 test64 test65 test66 test67 test68 test69 test70 test71
+ test62 test63 test64 test65 test66 test67 test68 test69 test70 test71 \
+ test72 test73 test74 test75 test76
root_tests:
@@ -78,6 +79,9 @@ pcf_ldap_suffixes.h: ../global/dict_ldap.c
pcf_memcache_suffixes.h: ../global/dict_memcache.c
sh extract_cfg.sh -d ../global/dict_memcache.c > $@
+pcf_mongodb_suffixes.h: ../global/dict_mongodb.c
+ sh extract_cfg.sh -d ../global/dict_mongodb.c > $@
+
pcf_mysql_suffixes.h: ../global/dict_mysql.c
sh extract_cfg.sh -d -s ../global/dict_mysql.c > $@
@@ -465,6 +469,9 @@ test29: $(PROG) test29.ref
echo 'memcachexx = proxy:memcache:memcachefoo' >> main.cf
echo 'memcachefoo_domain = bar' >> main.cf
echo 'memcachefoo_domainx = bar' >> main.cf
+ echo 'mongodbxx = proxy:mongodb:mongodbfoo' >> main.cf
+ echo 'mongodbfoo_domain = bar' >> main.cf
+ echo 'mongodbfoo_domainx = bar' >> main.cf
touch -t 197101010000 main.cf
$(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test29.tmp 2>&1
diff test29.ref test29.tmp
@@ -807,7 +814,7 @@ test58: $(PROG) test58.ref
echo 'yy_backup = bbb' >> main.cf
echo 'yy_bogus = bbb' >> main.cf
touch -t 197101010000 main.cf
- $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./postconf -nc. >test58.tmp 2>&1 || true
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc. >test58.tmp 2>&1 || true
diff test58.ref test58.tmp
rm -f main.cf master.cf test58.tmp
@@ -989,6 +996,75 @@ test71: $(PROG) test71.ref
diff test71.ref test71.tmp
rm -f main.cf master.cf test71.tmp
+# Different requests to add lines to master.cf.
+test72: $(PROG) test72.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/unix='smtp unix - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp fifo - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp inet - n n - 0 other'
+ touch -t 197201010000 main.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. >test72.tmp 2>&1
+ diff test72.ref test72.tmp
+ rm -f main.cf master.cf test72.tmp
+
+# Replace one entry based on the name+type in the request's service entry.
+test73: $(PROG) test73.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/unix='smtp unix - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp fifo - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp inet - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp unix - n n - 0 otherx'
+ touch -t 197301010000 main.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. >test73.tmp 2>&1
+ diff test73.ref test73.tmp
+ rm -f main.cf master.cf test73.tmp
+
+# Replace one entry based on the name+type in the request's service pattern.
+test74: $(PROG) test74.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/unix='smtp unix - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp fifo - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/abcd='smtp inet - n n - 0 other'
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. smtp/fifo='lmtp unix - n n - 0 otherx'
+ touch -t 197401010000 main.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -Mc. >test74.tmp 2>&1
+ diff test74.ref test74.tmp
+ rm -f main.cf master.cf test74.tmp
+
+# Warn about skipping redundant name=value update.
+test75: $(PROG) test75.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. mail_version=x mail_version=y >test75.tmp 2>&1
+ touch -t 197501010000 main.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc. >>test75.tmp 2>&1
+ diff test75.ref test75.tmp
+ rm -f main.cf master.cf test75.tmp
+
+# Warn about unused, deprecated, or deleted parameters.
+test76: $(PROG) test76.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c. \
+ config_directory=. \
+ deleted-test-only=whatever \
+ disable_dns_lookups=no \
+ lmtp_use_tls=no \
+ smtpd_tls_dh1024_param_file=auto >test76.tmp 2>&1
+ touch -t 197601010000 main.cf
+ echo foo unix - n n - 0 other >> master.cf
+ echo ' -o alias_maps=foo' >> master.cf
+ echo ' -o smtp_enforce_tls=yes' >> master.cf
+ touch -t 197601010000 master.cf
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc. >>test76.tmp 2>&1
+ diff test76.ref test76.tmp
+ $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -qnc. >/dev/null 2>test76.tmp
+ diff /dev/null test76.tmp
+ rm -f main.cf master.cf test76.tmp
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@@ -1094,6 +1170,7 @@ postconf_dbms.o: ../../include/dict.h
postconf_dbms.o: ../../include/dict_ht.h
postconf_dbms.o: ../../include/dict_ldap.h
postconf_dbms.o: ../../include/dict_memcache.h
+postconf_dbms.o: ../../include/dict_mongodb.h
postconf_dbms.o: ../../include/dict_mysql.h
postconf_dbms.o: ../../include/dict_pcre.h
postconf_dbms.o: ../../include/dict_pgsql.h
@@ -1118,6 +1195,7 @@ postconf_dbms.o: ../../include/vstream.h
postconf_dbms.o: ../../include/vstring.h
postconf_dbms.o: pcf_ldap_suffixes.h
postconf_dbms.o: pcf_memcache_suffixes.h
+postconf_dbms.o: pcf_mongodb_suffixes.h
postconf_dbms.o: pcf_mysql_suffixes.h
postconf_dbms.o: pcf_pgsql_suffixes.h
postconf_dbms.o: pcf_sqlite_suffixes.h
@@ -1184,6 +1262,7 @@ postconf_main.o: postconf_main.c
postconf_master.o: ../../include/argv.h
postconf_master.o: ../../include/check_arg.h
postconf_master.o: ../../include/dict.h
+postconf_master.o: ../../include/dict_ht.h
postconf_master.o: ../../include/htable.h
postconf_master.o: ../../include/mail_params.h
postconf_master.o: ../../include/master_proto.h
diff --git a/src/postconf/postconf.c b/src/postconf/postconf.c
index f598a5b..74f13b2 100644
--- a/src/postconf/postconf.c
+++ b/src/postconf/postconf.c
@@ -8,7 +8,7 @@
/* .ti -4
/* \fBManaging main.cf:\fR
/*
-/* \fBpostconf\fR [\fB-dfhHnopvx\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostconf\fR [\fB-dfhHnopqvx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-C \fIclass,...\fR] [\fIparameter ...\fR]
/*
/* \fBpostconf\fR [\fB-epv\fR] [\fB-c \fIconfig_dir\fR]
@@ -23,7 +23,7 @@
/* .ti -4
/* \fBManaging master.cf service entries:\fR
/*
-/* \fBpostconf\fR \fB-M\fR [\fB-fovx\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostconf\fR \fB-M\fR [\fB-foqvx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIservice\fR[\fB/\fItype\fR]\fI ...\fR]
/*
/* \fBpostconf\fR \fB-M\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
@@ -38,7 +38,7 @@
/* .ti -4
/* \fBManaging master.cf service fields:\fR
/*
-/* \fBpostconf\fR \fB-F\fR [\fB-fhHovx\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostconf\fR \fB-F\fR [\fB-fhHoqvx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIservice\fR[\fB/\fItype\fR[\fB/\fIfield\fR]]\fI ...\fR]
/*
/* \fBpostconf\fR \fB-F\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
@@ -47,7 +47,7 @@
/* .ti -4
/* \fBManaging master.cf service parameters:\fR
/*
-/* \fBpostconf\fR \fB-P\fR [\fB-fhHovx\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostconf\fR \fB-P\fR [\fB-fhHoqvx\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIservice\fR[\fB/\fItype\fR[\fB/\fIparameter\fR]]\fI ...\fR]
/*
/* \fBpostconf\fR \fB-P\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
@@ -293,6 +293,11 @@
/* \fBmemcache_table\fR(5).
/*
/* This feature is available with Postfix 2.9 and later.
+/* .IP "\fBmongodb\fR"
+/* MongoDB database client. This is described in
+/* \fBmongodb_table\fR(5).
+/*
+/* This feature is available with Postfix 3.9 and later.
/* .IP "\fBmysql\fR (read-only)"
/* MySQL database client. Available on systems with support
/* for MySQL databases. This is described in \fBmysql_table\fR(5).
@@ -452,6 +457,10 @@
/* wildcard fields.
/*
/* This feature is available with Postfix 2.11 and later.
+/* .IP \fB-q\fR
+/* Do not log warnings for deprecated or unused parameters.
+/*
+/* This feature is available with Postfix 3.9 and later.
/* .IP "\fB-t\fR [\fItemplate_file\fR]"
/* Display the templates for text that appears at the beginning
/* of delivery status notification (DSN) messages, without
@@ -779,6 +788,8 @@ static void pcf_check_compat_options(int optval)
const int (*op)[2];
int excess;
+ optval &= ~PCF_DEF_MODE;
+
for (op = pcf_compat_options; op[0][0] != 0; op++) {
if ((optval & *op[0]) != 0
&& (excess = (optval & ~((*op)[0] | (*op)[1]))) != 0)
@@ -844,7 +855,7 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "aAbc:C:deEfFhHlmMno:pPtT:vxX#")) > 0) {
+ while ((ch = GETOPT(argc, argv, "aAbc:C:deEfFhHlmMno:pPqtT:vxX#")) > 0) {
switch (ch) {
case 'a':
pcf_cmd_mode |= PCF_SHOW_SASL_SERV;
@@ -912,6 +923,9 @@ int main(int argc, char **argv)
case 'P':
pcf_cmd_mode |= PCF_MASTER_PARAM;
break;
+ case 'q':
+ pcf_cmd_mode &= ~(PCF_WARN_UNUSED_DEPRECATED);
+ break;
case 't':
pcf_cmd_mode |= PCF_DUMP_DSN_TEMPL;
if (ext_argv)
@@ -1028,7 +1042,7 @@ int main(int argc, char **argv)
pcf_set_parameters(override_params->argv);
pcf_register_builtin_parameters(basename(argv[0]), getpid());
pcf_register_service_parameters();
- pcf_register_user_parameters();
+ pcf_register_user_parameters(pcf_cmd_mode);
if (pcf_cmd_mode & PCF_MASTER_FLD)
pcf_show_master_fields(VSTREAM_OUT, pcf_cmd_mode, argc - optind,
argv + optind);
@@ -1038,7 +1052,8 @@ int main(int argc, char **argv)
else
pcf_show_master_entries(VSTREAM_OUT, pcf_cmd_mode, argc - optind,
argv + optind);
- pcf_flag_unused_master_parameters();
+ if (pcf_cmd_mode & PCF_WARN_UNUSED_DEPRECATED)
+ pcf_flag_unused_master_parameters();
}
/*
@@ -1090,7 +1105,7 @@ int main(int argc, char **argv)
pcf_read_master(PCF_WARN_ON_OPEN_ERROR);
pcf_register_service_parameters();
if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0)
- pcf_register_user_parameters();
+ pcf_register_user_parameters(pcf_cmd_mode);
/*
* Show the requested values.
@@ -1099,11 +1114,12 @@ int main(int argc, char **argv)
argv + optind);
/*
- * Flag unused parameters. This makes no sense with "postconf -d",
- * because that ignores all the user-specified parameters and
- * user-specified macro expansions in main.cf.
+ * Flag unused or deprecated parameters. This makes no sense with
+ * "postconf -d", because that ignores all the user-specified
+ * parameters and user-specified macro expansions in main.cf.
*/
- if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0) {
+ if ((pcf_cmd_mode & PCF_SHOW_DEFS) == 0
+ && (pcf_cmd_mode & PCF_WARN_UNUSED_DEPRECATED) != 0) {
pcf_flag_unused_main_parameters();
pcf_flag_unused_master_parameters();
}
diff --git a/src/postconf/postconf.h b/src/postconf/postconf.h
index 24a1ed7..b42245c 100644
--- a/src/postconf/postconf.h
+++ b/src/postconf/postconf.h
@@ -46,8 +46,9 @@
#define PCF_MASTER_PARAM (1<<19) /* manage master.cf -o name=value */
#define PCF_HIDE_VALUE (1<<20) /* hide main.cf/master.cf =value */
#define PCF_SHOW_TLS (1<<21) /* TLS support introspection */
+#define PCF_WARN_UNUSED_DEPRECATED (1<<22) /* As the name says */
-#define PCF_DEF_MODE 0
+#define PCF_DEF_MODE (PCF_WARN_UNUSED_DEPRECATED)
/*
* Structure for one "valid parameter" (built-in, service-defined or valid
@@ -274,12 +275,12 @@ typedef struct {
/*
* postconf_user.c.
*/
-extern void pcf_register_user_parameters(void);
+extern void pcf_register_user_parameters(int);
/*
* postconf_dbms.c
*/
-extern void pcf_register_dbms_parameters(const char *,
+extern void pcf_register_dbms_parameters(int, const char *,
const char *(*) (const char *, int, PCF_MASTER_ENT *),
PCF_MASTER_ENT *);
diff --git a/src/postconf/postconf_dbms.c b/src/postconf/postconf_dbms.c
index 0ed5b53..105ae85 100644
--- a/src/postconf/postconf_dbms.c
+++ b/src/postconf/postconf_dbms.c
@@ -6,8 +6,9 @@
/* SYNOPSIS
/* #include <postconf.h>
/*
-/* void pcf_register_dbms_parameters(param_value, flag_parameter,
+/* void pcf_register_dbms_parameters(mode, param_value, flag_parameter,
/* local_scope)
+/* int mode;
/* const char *param_value;
/* const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *);
/* PCF_MASTER_ENT *local_scope;
@@ -17,6 +18,9 @@
/* the database name to a database-defined suffix.
/*
/* Arguments:
+/* .IP mode
+/* If PCF_WARN_UNUSED_DEPRECATED is set, warn about unused
+/* database settings.
/* .IP param_value
/* A parameter value to be searched for "type:table" strings.
/* When a database type is found that supports legacy-style
@@ -77,6 +81,7 @@
#include <dict_pgsql.h>
#include <dict_sqlite.h>
#include <dict_memcache.h>
+#include <dict_mongodb.h>
#include <dict_regexp.h>
#include <dict_pcre.h>
@@ -131,6 +136,13 @@ static const char *pcf_memcache_suffixes[] = {
0,
};
+/* See mongodb_table(5). */
+
+static const char *pcf_mongodb_suffixes[] = {
+#include "pcf_mongodb_suffixes.h"
+ 0,
+};
+
/*
* Bundle up the database types and their suffix lists.
*/
@@ -149,6 +161,7 @@ static const PCF_DBMS_INFO pcf_dbms_info[] = {
{DICT_TYPE_PGSQL, PCF_DBMS_CLASS_CLIENT, pcf_pgsql_suffixes},
{DICT_TYPE_SQLITE, PCF_DBMS_CLASS_CLIENT, pcf_sqlite_suffixes},
{DICT_TYPE_MEMCACHE, PCF_DBMS_CLASS_CLIENT, pcf_memcache_suffixes},
+ {DICT_TYPE_MONGODB, PCF_DBMS_CLASS_CLIENT, pcf_mongodb_suffixes},
{DICT_TYPE_REGEXP, PCF_DBMS_CLASS_REGEX},
{DICT_TYPE_PCRE, PCF_DBMS_CLASS_REGEX},
{0},
@@ -163,7 +176,8 @@ static const PCF_DBMS_INFO pcf_dbms_info[] = {
/* pcf_check_dbms_client - look for unused names in client configuration */
-static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file)
+static void pcf_check_dbms_client(int mode, const PCF_DBMS_INFO *dp,
+ const char *cf_file)
{
DICT *dict;
VSTREAM *fp;
@@ -217,19 +231,21 @@ static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file)
* code, because a database client parameter namespace is unlike the
* parameter namespaces in main.cf or master.cf.
*/
- for (cpp = dp->db_suffixes; *cpp; cpp++)
- (void) dict_del(dict, *cpp);
- for (dir = DICT_SEQ_FUN_FIRST;
- dict->sequence(dict, dir, &name, &value) == DICT_STAT_SUCCESS;
- dir = DICT_SEQ_FUN_NEXT)
- msg_warn("%s: unused parameter: %s=%s", dict_spec, name, value);
+ if (mode & PCF_WARN_UNUSED_DEPRECATED) {
+ for (cpp = dp->db_suffixes; *cpp; cpp++)
+ (void) dict_del(dict, *cpp);
+ for (dir = DICT_SEQ_FUN_FIRST;
+ dict->sequence(dict, dir, &name, &value) == DICT_STAT_SUCCESS;
+ dir = DICT_SEQ_FUN_NEXT)
+ msg_warn("%s: unused parameter: %s=%s", dict_spec, name, value);
+ }
}
myfree(dict_spec);
}
/* pcf_register_dbms_helper - parse one possible database type:name */
-static void pcf_register_dbms_helper(char *str_value,
+static void pcf_register_dbms_helper(int mode, char *str_value,
const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *),
PCF_MASTER_ENT *local_scope,
int recurse)
@@ -258,8 +274,8 @@ static void pcf_register_dbms_helper(char *str_value,
myfree(err);
}
if (recurse)
- pcf_register_dbms_helper(db_type, flag_parameter, local_scope,
- recurse);
+ pcf_register_dbms_helper(mode, db_type, flag_parameter,
+ local_scope, recurse);
continue;
}
@@ -287,7 +303,7 @@ static void pcf_register_dbms_helper(char *str_value,
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
if (strcmp(db_type, dp->db_type) == 0) {
if (dp->db_class == PCF_DBMS_CLASS_CLIENT)
- pcf_check_dbms_client(dp, prefix);
+ pcf_check_dbms_client(mode, dp, prefix);
break;
}
}
@@ -321,8 +337,8 @@ static void pcf_register_dbms_helper(char *str_value,
break;
}
}
- pcf_register_dbms_helper(prefix, flag_parameter, local_scope,
- next_recurse);
+ pcf_register_dbms_helper(mode, prefix, flag_parameter,
+ local_scope, next_recurse);
continue;
} else {
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
@@ -347,7 +363,7 @@ static void pcf_register_dbms_helper(char *str_value,
/* pcf_register_dbms_parameters - look for database_type:prefix_name */
-void pcf_register_dbms_parameters(const char *param_value,
+void pcf_register_dbms_parameters(int mode, const char *param_value,
const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *),
PCF_MASTER_ENT *local_scope)
{
@@ -363,7 +379,8 @@ void pcf_register_dbms_parameters(const char *param_value,
buffer = vstring_alloc(100);
bufp = pcf_expand_parameter_value(buffer, PCF_SHOW_EVAL, param_value,
local_scope);
- pcf_register_dbms_helper(bufp, flag_parameter, local_scope, PCF_DBMS_RECURSE);
+ pcf_register_dbms_helper(mode, bufp, flag_parameter, local_scope,
+ PCF_DBMS_RECURSE);
}
#endif
diff --git a/src/postconf/postconf_unused.c b/src/postconf/postconf_unused.c
index d4416f8..717d1a5 100644
--- a/src/postconf/postconf_unused.c
+++ b/src/postconf/postconf_unused.c
@@ -2,7 +2,7 @@
/* NAME
/* postconf_unused 3
/* SUMMARY
-/* report unused parameters
+/* report unused or deprecated parameters
/* SYNOPSIS
/* #include <postconf.h>
/*
@@ -15,11 +15,11 @@
/* In other words, don't call these functions with "postconf
/* -d" which ignores user-defined main.cf settings.
/*
-/* pcf_flag_unused_main_parameters() reports unused "name=value"
-/* entries in main.cf.
+/* pcf_flag_unused_main_parameters() reports unused or deprecated
+/* "name=value" entries in main.cf.
/*
-/* pcf_flag_unused_master_parameters() reports unused "-o
-/* name=value" entries in master.cf.
+/* pcf_flag_unused_master_parameters() reports unused or
+/* deprecated "-o name=value" entries in master.cf.
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* LICENSE
@@ -31,6 +31,10 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
/*--*/
/* System library. */
@@ -52,12 +56,66 @@
#include <postconf.h>
+ /*
+ * Deprecated parameter names and suggested alternatives. If we keep deleted
+ * parameter names in the table, a warning can still suggest alternatives.
+ * The downside of keeping deleted names in the table is that we may falsely
+ * warn about a user-defined parameter whose name matches that of a deleted
+ * parameter.
+ */
+typedef struct {
+ char *name;
+ char *alternative;
+} PCF_DEPR_PARAM_INFO;
+
+static const PCF_DEPR_PARAM_INFO pcf_depr_param_info[] = {
+
+ /*
+ * Parameters with deprecation warnings as of Postfix 3.9. The
+ * disable_dns_lookups parameter was documented as deprecated since
+ * Postfix 2.11 but nothing was logged.
+ */
+ "disable_dns_lookups", "specify \"smtp_dns_support_level\"",
+ "lmtp_use_tls", "specify \"lmtp_tls_security_level\"",
+ "postscreen_use_tls", "specify \"postscreen_tls_security_level\"",
+ "smtp_use_tls", "specify \"smtp_tls_security_level\"",
+ "smtpd_use_tls", "specify \"smtpd_tls_security_level\"",
+ "tlsproxy_client_use_tls", "specify \"tlsproxy_client_security_level\"",
+ "tlsproxy_use_tls", "specify \"tlsproxy_tls_security_level\"",
+ "lmtp_enforce_tls", "lmtp_tls_security_level",
+ "postscreen_enforce_tls", "specify \"postscreen_tls_security_level\"",
+ "smtp_enforce_tls", "specify \"smtp_tls_security_level\"",
+ "smtpd_enforce_tls", "specify \"smtpd_tls_security_level\"",
+ "tlsproxy_client_enforce_tls", "specify \"tlsproxy_client_security_level\"",
+ "tlsproxy_enforce_tls", "specify \"tlsproxy_tls_security_level\"",
+ "lmtp_tls_per_site", "specify \"lmtp_tls_policy_maps\"",
+ "smtp_tls_per_site", "specify \"smtp_tls_policy_maps\"",
+ "tlsproxy_client_per_site", "specify \"tlsproxy_client_policy_maps\"",
+ "smtpd_tls_dh1024_param_file", "do not specify (leave at default)",
+ "smtpd_tls_eecdh_grade", "do not specify (leave at default)",
+ "deleted-test-only", "do not specify", /* For testing */
+ 0,
+};
+static HTABLE *pcf_depr_param_table;
+
+/* pcf_init_depr_params - initialize lookup table */
+
+static void pcf_init_depr_params(void)
+{
+ const PCF_DEPR_PARAM_INFO *dp;
+
+ pcf_depr_param_table = htable_create(30);
+ for (dp = pcf_depr_param_info; dp->name; dp++)
+ (void) htable_enter(pcf_depr_param_table, dp->name, (void *) dp);
+}
+
/* pcf_flag_unused_parameters - warn about unused parameters */
static void pcf_flag_unused_parameters(DICT *dict, const char *conf_name,
PCF_MASTER_ENT *local_scope)
{
const char *myname = "pcf_flag_unused_parameters";
+ const PCF_DEPR_PARAM_INFO *dp;
const char *param_name;
const char *param_value;
int how;
@@ -67,23 +125,55 @@ static void pcf_flag_unused_parameters(DICT *dict, const char *conf_name,
*/
if (pcf_param_table == 0)
msg_panic("%s: global parameter table is not initialized", myname);
+ if (dict->sequence == 0)
+ msg_panic("%s: parameter dictionary %s has no iterator",
+ myname, conf_name);
+
+ /*
+ * One-time initialization.
+ */
+ if (pcf_depr_param_table == 0)
+ pcf_init_depr_params();
/*
* Iterate over all entries, and flag parameter names that aren't used
- * anywhere. Show the warning message at the end of the output.
+ * anywhere, or that are deprecated. Show the warning message(s) after
+ * the end of the stdout output.
*/
- if (dict->sequence == 0)
- msg_panic("%s: parameter dictionary %s has no iterator",
- myname, conf_name);
for (how = DICT_SEQ_FUN_FIRST;
dict->sequence(dict, how, &param_name, &param_value) == 0;
how = DICT_SEQ_FUN_NEXT) {
+
+ /*
+ * Flag a parameter that is not used (deleted name, or incorrect
+ * name).
+ */
if (PCF_PARAM_TABLE_LOCATE(pcf_param_table, param_name) == 0
&& (local_scope == 0
|| PCF_PARAM_TABLE_LOCATE(local_scope->valid_names, param_name) == 0)) {
vstream_fflush(VSTREAM_OUT);
- msg_warn("%s/%s: unused parameter: %s=%s",
- var_config_dir, conf_name, param_name, param_value);
+ if ((dp = (const PCF_DEPR_PARAM_INFO *)
+ htable_find(pcf_depr_param_table, param_name)) != 0) {
+ msg_warn("%s/%s: support for parameter %s has been removed;"
+ " instead, %s", var_config_dir, conf_name,
+ param_name, dp->alternative);
+ } else {
+ msg_warn("%s/%s: unused parameter: %s=%s",
+ var_config_dir, conf_name, param_name, param_value);
+ }
+ }
+
+ /*
+ * Flag a parameter that is used but deprecated. Note that this may
+ * falsely complain about a user-defined parameter whose name matches
+ * that of a deleted parameter.
+ */
+ else if ((dp = (const PCF_DEPR_PARAM_INFO *)
+ htable_find(pcf_depr_param_table, param_name)) != 0) {
+ vstream_fflush(VSTREAM_OUT);
+ msg_warn("%s/%s: support for parameter \"%s\" will be removed;"
+ " instead, %s", var_config_dir, conf_name,
+ param_name, dp->alternative);
}
}
}
diff --git a/src/postconf/postconf_user.c b/src/postconf/postconf_user.c
index 5942ec0..46f4d61 100644
--- a/src/postconf/postconf_user.c
+++ b/src/postconf/postconf_user.c
@@ -6,7 +6,7 @@
/* SYNOPSIS
/* #include <postconf.h>
/*
-/* void pcf_register_user_parameters()
+/* void pcf_register_user_parameters(int mode)
/* DESCRIPTION
/* Postfix has multiple parameter name spaces: the global
/* main.cf parameter name space, and the local parameter name
@@ -40,6 +40,10 @@
/* to instantiate legacy per-dbms parameters, and to examine
/* per-dbms configuration files. This is limited to the content
/* of global and local, built-in and per-service, parameters.
+/*
+/* Arguments:
+/* .IP mode
+/* Passed on to pcf_register_dbms_parameters().
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
/* LICENSE
@@ -224,7 +228,7 @@ static const char *pcf_lookup_eval(const char *dict_name, const char *name)
/* pcf_scan_user_parameter_namespace - scan parameters in name space */
-static void pcf_scan_user_parameter_namespace(const char *dict_name,
+static void pcf_scan_user_parameter_namespace(int mode, const char *dict_name,
PCF_MASTER_ENT *local_scope)
{
const char *myname = "pcf_scan_user_parameter_namespace";
@@ -308,7 +312,7 @@ static void pcf_scan_user_parameter_namespace(const char *dict_name,
*/
if (node != 0
&& (PCF_BUILTIN_PARAMETER(node) || PCF_SERVICE_PARAMETER(node)))
- pcf_register_dbms_parameters(cparam_value, pcf_flag_user_parameter,
+ pcf_register_dbms_parameters(mode, cparam_value, pcf_flag_user_parameter,
local_scope);
#endif
}
@@ -345,7 +349,7 @@ static void pcf_scan_default_parameter_values(HTABLE *valid_params,
/* pcf_register_user_parameters - add parameters with user-defined names */
-void pcf_register_user_parameters(void)
+void pcf_register_user_parameters(int mode)
{
const char *myname = "pcf_register_user_parameters";
PCF_MASTER_ENT *masterp;
@@ -403,7 +407,7 @@ void pcf_register_user_parameters(void)
*/
for (masterp = pcf_master_table; masterp->argv != 0; masterp++)
if (masterp->all_params != 0)
- pcf_scan_user_parameter_namespace(masterp->name_space, masterp);
+ pcf_scan_user_parameter_namespace(mode, masterp->name_space, masterp);
/*
* Scan parameter values that are left at their defaults in the global
@@ -418,5 +422,5 @@ void pcf_register_user_parameters(void)
/*
* Scan the explicit name=value entries in the global name space.
*/
- pcf_scan_user_parameter_namespace(CONFIG_DICT, (PCF_MASTER_ENT *) 0);
+ pcf_scan_user_parameter_namespace(mode, CONFIG_DICT, (PCF_MASTER_ENT *) 0);
}
diff --git a/src/postconf/test29.ref b/src/postconf/test29.ref
index 646890a..c3bbaec 100644
--- a/src/postconf/test29.ref
+++ b/src/postconf/test29.ref
@@ -2,15 +2,18 @@ config_directory = .
./postconf: warning: ./main.cf: unused parameter: pgsqlfoo_domain=bar
./postconf: warning: ./main.cf: unused parameter: sqlitefoo_domain=bar
./postconf: warning: ./main.cf: unused parameter: ldapxx=proxy:ldap:ldapfoo
+./postconf: warning: ./main.cf: unused parameter: mongodbfoo_domain=bar
./postconf: warning: ./main.cf: unused parameter: sqlitexx=proxy:sqlite:sqlitefoo
./postconf: warning: ./main.cf: unused parameter: mysqlfoo_domain=bar
./postconf: warning: ./main.cf: unused parameter: sqlitefoo_domainx=bar
./postconf: warning: ./main.cf: unused parameter: memcachefoo_domain=bar
./postconf: warning: ./main.cf: unused parameter: pgsqlfoo_domainx=bar
+./postconf: warning: ./main.cf: unused parameter: mongodbfoo_domainx=bar
./postconf: warning: ./main.cf: unused parameter: ldapfoo_domainx=bar
./postconf: warning: ./main.cf: unused parameter: ldapfoo_domain=bar
./postconf: warning: ./main.cf: unused parameter: memcachexx=proxy:memcache:memcachefoo
./postconf: warning: ./main.cf: unused parameter: memcachefoo_domainx=bar
./postconf: warning: ./main.cf: unused parameter: mysqlfoo_domainx=bar
./postconf: warning: ./main.cf: unused parameter: mysqlxx=proxy:mysql:mysqlfoo
+./postconf: warning: ./main.cf: unused parameter: mongodbxx=proxy:mongodb:mongodbfoo
./postconf: warning: ./main.cf: unused parameter: pgsqlxx=proxy:pgsql:pgsqlfoo
diff --git a/src/postconf/test72.ref b/src/postconf/test72.ref
new file mode 100644
index 0000000..6b13cdc
--- /dev/null
+++ b/src/postconf/test72.ref
@@ -0,0 +1,3 @@
+smtp unix - n n - 0 other
+smtp fifo - n n - 0 other
+smtp inet - n n - 0 other
diff --git a/src/postconf/test73.ref b/src/postconf/test73.ref
new file mode 100644
index 0000000..9554cc0
--- /dev/null
+++ b/src/postconf/test73.ref
@@ -0,0 +1,3 @@
+smtp unix - n n - 0 otherx
+smtp fifo - n n - 0 other
+smtp inet - n n - 0 other
diff --git a/src/postconf/test74.ref b/src/postconf/test74.ref
new file mode 100644
index 0000000..2886334
--- /dev/null
+++ b/src/postconf/test74.ref
@@ -0,0 +1,3 @@
+smtp unix - n n - 0 other
+lmtp unix - n n - 0 otherx
+smtp inet - n n - 0 other
diff --git a/src/postconf/test75.ref b/src/postconf/test75.ref
new file mode 100644
index 0000000..b8c54ab
--- /dev/null
+++ b/src/postconf/test75.ref
@@ -0,0 +1,3 @@
+./postconf: warning: ignoring earlier request: 'mail_version = x'
+config_directory = .
+mail_version = y
diff --git a/src/postconf/test76.ref b/src/postconf/test76.ref
new file mode 100644
index 0000000..3e4cd26
--- /dev/null
+++ b/src/postconf/test76.ref
@@ -0,0 +1,9 @@
+config_directory = .
+disable_dns_lookups = no
+lmtp_use_tls = no
+smtpd_tls_dh1024_param_file = auto
+./postconf: warning: ./main.cf: support for parameter "disable_dns_lookups" will be removed; instead, specify "smtp_dns_support_level"
+./postconf: warning: ./main.cf: support for parameter "lmtp_use_tls" will be removed; instead, specify "lmtp_tls_security_level"
+./postconf: warning: ./main.cf: support for parameter "smtpd_tls_dh1024_param_file" will be removed; instead, do not specify (leave at default)
+./postconf: warning: ./main.cf: support for parameter deleted-test-only has been removed; instead, do not specify
+./postconf: warning: ./master.cf: support for parameter "smtp_enforce_tls" will be removed; instead, specify "smtp_tls_security_level"
diff --git a/src/postdrop/postdrop.c b/src/postdrop/postdrop.c
index e9335e9..66c9ea5 100644
--- a/src/postdrop/postdrop.c
+++ b/src/postdrop/postdrop.c
@@ -64,7 +64,7 @@
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a privileged Postfix
+/* The list of environment variables that a privileged Postfix
/* process will import from a non-Postfix parent process, or name=value
/* environment overrides.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/src/postfix/postfix.c b/src/postfix/postfix.c
index c7f8b40..93bcecc 100644
--- a/src/postfix/postfix.c
+++ b/src/postfix/postfix.c
@@ -303,7 +303,7 @@
/*
/* Table-driven mechanisms:
/* access(5), Postfix SMTP access control table
-/* aliases(5), Postfix alias database
+/* aliases(5), Postfix local aliasing
/* canonical(5), Postfix input address rewriting
/* generic(5), Postfix output address rewriting
/* header_checks(5), body_checks(5), Postfix content inspection
@@ -316,6 +316,7 @@
/* ldap_table(5), Postfix LDAP client
/* lmdb_table(5), Postfix LMDB database driver
/* memcache_table(5), Postfix memcache client
+/* mongodb_table(5), Postfix MongoDB client
/* mysql_table(5), Postfix MYSQL client
/* nisplus_table(5), Postfix NIS+ client
/* pcre_table(5), Associate PCRE pattern with value
diff --git a/src/postkick/postkick.c b/src/postkick/postkick.c
index 6bf9245..a1ce55c 100644
--- a/src/postkick/postkick.c
+++ b/src/postkick/postkick.c
@@ -54,7 +54,7 @@
/* How long the \fBpostkick\fR(1) command waits for a request to enter the
/* Postfix daemon process input buffer before giving up.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a privileged Postfix
+/* The list of environment variables that a privileged Postfix
/* process will import from a non-Postfix parent process, or name=value
/* environment overrides.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/src/postlock/postlock.c b/src/postlock/postlock.c
index a05d11e..972577b 100644
--- a/src/postlock/postlock.c
+++ b/src/postlock/postlock.c
@@ -79,7 +79,7 @@
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a privileged Postfix
+/* The list of environment variables that a privileged Postfix
/* process will import from a non-Postfix parent process, or name=value
/* environment overrides.
/* SEE ALSO
diff --git a/src/postlog/postlog.c b/src/postlog/postlog.c
index 7175f42..195ebd9 100644
--- a/src/postlog/postlog.c
+++ b/src/postlog/postlog.c
@@ -82,6 +82,12 @@
/* \fBpostlogd\fR(8) service.
/* .IP "\fBpostlog_service_name (postlog)\fR"
/* The name of the \fBpostlogd\fR(8) service entry in master.cf.
+/* .PP
+/* Available in Postfix 3.9 and later:
+/* .IP "\fBmaillog_file_permissions (0600)\fR"
+/* The file access permissions that will be set when the file
+/* $maillog_file is created for the first time, or when the file is
+/* created after an existing file is rotated.
/* SEE ALSO
/* postconf(5), configuration parameters
/* postlogd(8), Postfix logging
diff --git a/src/postlogd/postlogd.c b/src/postlogd/postlogd.c
index 902cbe5..13f996f 100644
--- a/src/postlogd/postlogd.c
+++ b/src/postlogd/postlogd.c
@@ -31,10 +31,10 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
-/* Changes to \fBmain.cf\fR are picked up automatically, as
-/* \fBpostlogd\fR(8) processes run for only a limited amount
-/* of time. Use the command "\fBpostfix reload\fR" to speed
-/* up a change.
+/* Changes to \fBmain.cf\fR are not picked up automatically,
+/* because \fBpostlogd\fR(8) terminates only after reaching
+/* the \fBmax_idle\fR time limit.
+/* Use the command "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
@@ -56,6 +56,12 @@
/* .IP "\fBpostlogd_watchdog_timeout (10s)\fR"
/* How much time a \fBpostlogd\fR(8) process may take to process a request
/* before it is terminated by a built-in watchdog timer.
+/* .PP
+/* Available in Postfix 3.9 and later:
+/* .IP "\fBmaillog_file_permissions (0600)\fR"
+/* The file access permissions that will be set when the file
+/* $maillog_file is created for the first time, or when the file is
+/* created after an existing file is rotated.
/* SEE ALSO
/* postconf(5), configuration parameters
/* syslogd(8), system logging
diff --git a/src/postmap/postmap.c b/src/postmap/postmap.c
index 2826fc6..7390450 100644
--- a/src/postmap/postmap.c
+++ b/src/postmap/postmap.c
@@ -489,7 +489,7 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
*/
if ((mkmap->dict->flags & DICT_FLAG_UTF8_ACTIVE)
&& !allascii(STR(line_buffer))
- && !valid_utf8_string(STR(line_buffer), LEN(line_buffer))) {
+ && !valid_utf8_stringz(STR(line_buffer))) {
msg_warn("%s, line %d: non-UTF-8 input \"%s\""
" -- ignoring this line",
VSTREAM_PATH(source_fp), lineno, STR(line_buffer));
diff --git a/src/postqueue/showq_json.c b/src/postqueue/showq_json.c
index db79404..a2820dd 100644
--- a/src/postqueue/showq_json.c
+++ b/src/postqueue/showq_json.c
@@ -58,69 +58,6 @@
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
-/* json_quote - quote JSON string */
-
-static char *json_quote(VSTRING *result, const char *text)
-{
- unsigned char *cp;
- int ch;
-
- /*
- * We use short escape sequences for common control characters. Note that
- * RFC 4627 allows "/" (0x2F) to be sent without quoting. Differences
- * with RFC 4627: we send DEL (0x7f) as \u007F; the result remains RFC
- * 4627 complaint.
- */
- VSTRING_RESET(result);
- for (cp = (unsigned char *) text; (ch = *cp) != 0; cp++) {
- if (UNEXPECTED(ISCNTRL(ch))) {
- switch (ch) {
- case '\b':
- VSTRING_ADDCH(result, '\\');
- VSTRING_ADDCH(result, 'b');
- break;
- case '\f':
- VSTRING_ADDCH(result, '\\');
- VSTRING_ADDCH(result, 'f');
- break;
- case '\n':
- VSTRING_ADDCH(result, '\\');
- VSTRING_ADDCH(result, 'n');
- break;
- case '\r':
- VSTRING_ADDCH(result, '\\');
- VSTRING_ADDCH(result, 'r');
- break;
- case '\t':
- VSTRING_ADDCH(result, '\\');
- VSTRING_ADDCH(result, 't');
- break;
- default:
- vstring_sprintf_append(result, "\\u%04X", ch);
- break;
- }
- } else {
- switch (ch) {
- case '\\':
- case '"':
- VSTRING_ADDCH(result, '\\');
- /* FALLTHROUGH */
- default:
- VSTRING_ADDCH(result, ch);
- break;
- }
- }
- }
- VSTRING_TERMINATE(result);
-
- /*
- * Force the result to be UTF-8 (with SMTPUTF8 enabled) or ASCII (with
- * SMTPUTF8 disabled).
- */
- printable(STR(result), '?');
- return (STR(result));
-}
-
/* json_message - report status for one message */
static void format_json(VSTREAM *showq_stream)
@@ -148,6 +85,12 @@ static void format_json(VSTREAM *showq_stream)
}
/*
+ * Force JSON values to UTF-8 (with SMTPUTF8 enabled) or ASCII (with
+ * SMTPUTF8 disabled).
+ */
+#define QUOTE_JSON(res, src) printable(quote_for_json((res), (src), -1), '?')
+
+ /*
* Read the message properties and sender address.
*/
if (attr_scan(showq_stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT
@@ -162,14 +105,14 @@ static void format_json(VSTREAM *showq_stream)
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
vstream_printf("{");
vstream_printf("\"queue_name\": \"%s\", ",
- json_quote(quote_buf, STR(queue_name)));
+ QUOTE_JSON(quote_buf, STR(queue_name)));
vstream_printf("\"queue_id\": \"%s\", ",
- json_quote(quote_buf, STR(queue_id)));
+ QUOTE_JSON(quote_buf, STR(queue_id)));
vstream_printf("\"arrival_time\": %ld, ", arrival_time);
vstream_printf("\"message_size\": %ld, ", message_size);
vstream_printf("\"forced_expire\": %s, ", forced_expire ? "true" : "false");
vstream_printf("\"sender\": \"%s\", ",
- json_quote(quote_buf, STR(addr)));
+ QUOTE_JSON(quote_buf, STR(addr)));
/*
* Read zero or more (recipient, reason) pair(s) until attr_scan_more()
@@ -188,10 +131,10 @@ static void format_json(VSTREAM *showq_stream)
ATTR_TYPE_END) != 2)
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
vstream_printf("\"address\": \"%s\"",
- json_quote(quote_buf, STR(addr)));
+ QUOTE_JSON(quote_buf, STR(addr)));
if (LEN(why) > 0)
vstream_printf(", \"delay_reason\": \"%s\"",
- json_quote(quote_buf, STR(why)));
+ QUOTE_JSON(quote_buf, STR(why)));
vstream_printf("}");
}
vstream_printf("]");
diff --git a/src/postscreen/postscreen.c b/src/postscreen/postscreen.c
index 192c2e9..ebb680c 100644
--- a/src/postscreen/postscreen.c
+++ b/src/postscreen/postscreen.c
@@ -291,25 +291,29 @@
/* The amount of time that \fBpostscreen\fR(8) will cache an expired
/* temporary allowlist entry before it is removed.
/* .IP "\fBpostscreen_bare_newline_ttl (30d)\fR"
-/* The amount of time that \fBpostscreen\fR(8) will use the result from
-/* a successful "bare newline" SMTP protocol test.
+/* The amount of time that \fBpostscreen\fR(8) remembers that a client
+/* IP address passed a "bare newline" SMTP protocol test, before it
+/* address is required to pass that test again.
/* .IP "\fBpostscreen_dnsbl_max_ttl (${postscreen_dnsbl_ttl?{$postscreen_dnsbl_ttl}:{1}}h)\fR"
-/* The maximum amount of time that \fBpostscreen\fR(8) will use the
-/* result from a successful DNS-based reputation test before a
-/* client IP address is required to pass that test again.
+/* The maximum amount of time that \fBpostscreen\fR(8) remembers that a
+/* client IP address passed a DNS-based reputation test, before it is
+/* required to pass that test again.
/* .IP "\fBpostscreen_dnsbl_min_ttl (60s)\fR"
-/* The minimum amount of time that \fBpostscreen\fR(8) will use the
-/* result from a successful DNS-based reputation test before a
-/* client IP address is required to pass that test again.
+/* The minimum amount of time that \fBpostscreen\fR(8) remembers that a
+/* client IP address passed a DNS-based reputation test, before it
+/* is required to pass that test again.
/* .IP "\fBpostscreen_greet_ttl (1d)\fR"
-/* The amount of time that \fBpostscreen\fR(8) will use the result from
-/* a successful PREGREET test.
+/* The amount of time that \fBpostscreen\fR(8) remembers that a client
+/* IP address passed a PREGREET test, before it is required to pass
+/* that test again.
/* .IP "\fBpostscreen_non_smtp_command_ttl (30d)\fR"
-/* The amount of time that \fBpostscreen\fR(8) will use the result from
-/* a successful "non_smtp_command" SMTP protocol test.
+/* The amount of time that \fBpostscreen\fR(8) remembers that a client
+/* IP address passed a "non_smtp_command" SMTP protocol test, before
+/* it is required to pass that test again.
/* .IP "\fBpostscreen_pipelining_ttl (30d)\fR"
-/* The amount of time that \fBpostscreen\fR(8) will use the result from
-/* a successful "pipelining" SMTP protocol test.
+/* The amount of time that \fBpostscreen\fR(8) remembers that a client
+/* IP address passed a "pipelining" SMTP protocol test, before it is
+/* required to pass that test again.
/* RESOURCE CONTROLS
/* .ad
/* .fi
diff --git a/src/postscreen/postscreen_smtpd.c b/src/postscreen/postscreen_smtpd.c
index dfc5d54..6b72626 100644
--- a/src/postscreen/postscreen_smtpd.c
+++ b/src/postscreen/postscreen_smtpd.c
@@ -874,7 +874,8 @@ static void psc_smtpd_read_event(int event, void *context)
}
/*
- * Bare newline test.
+ * Bare newline test. Note: at this point, state->cmd_buffer is
+ * not null-terminated and may contain embedded null bytes.
*/
if (ch == '\n') {
if ((state->flags & PSC_STATE_MASK_BARLF_TODO_SKIP)
@@ -929,18 +930,19 @@ static void psc_smtpd_read_event(int event, void *context)
}
/*
- * Avoid complaints from Postfix maps about malformed content.
+ * Avoid complaints from Postfix maps about malformed content. Note:
+ * this will stop at the first null byte, just like the code that
+ * parses the command name or command arguments.
*/
-#define PSC_BAD_UTF8(str, len) \
- (var_smtputf8_enable && !valid_utf8_string((str), (len)))
+#define PSC_BAD_UTF8(str) \
+ (var_smtputf8_enable && !valid_utf8_stringz(str))
/*
* Terminate the command buffer, and apply the last-resort command
* editing workaround.
*/
VSTRING_TERMINATE(state->cmd_buffer);
- if (psc_cmd_filter != 0 && !PSC_BAD_UTF8(STR(state->cmd_buffer),
- LEN(state->cmd_buffer))) {
+ if (psc_cmd_filter != 0 && !PSC_BAD_UTF8(STR(state->cmd_buffer))) {
const char *cp;
for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++)
@@ -1007,7 +1009,7 @@ static void psc_smtpd_read_event(int event, void *context)
if ((state->flags & PSC_STATE_MASK_NSMTP_TODO_SKIP)
== PSC_STATE_FLAG_NSMTP_TODO && cmdp->name == 0
&& (is_header(command)
- || PSC_BAD_UTF8(command, strlen(command))
+ || PSC_BAD_UTF8(command)
/* Ignore forbid_cmds lookup errors. Non-critical feature. */
|| (*var_psc_forbid_cmds
&& string_list_match(psc_forbid_cmds, command)))) {
diff --git a/src/postsuper/postsuper.c b/src/postsuper/postsuper.c
index d3f2d5b..c9b8e38 100644
--- a/src/postsuper/postsuper.c
+++ b/src/postsuper/postsuper.c
@@ -288,7 +288,7 @@
/* The names of queue directories that are split across multiple
/* subdirectory levels.
/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
-/* The list of environment parameters that a privileged Postfix
+/* The list of environment variables that a privileged Postfix
/* process will import from a non-Postfix parent process, or name=value
/* environment overrides.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
diff --git a/src/posttls-finger/posttls-finger.c b/src/posttls-finger/posttls-finger.c
index d64c355..b474a40 100644
--- a/src/posttls-finger/posttls-finger.c
+++ b/src/posttls-finger/posttls-finger.c
@@ -103,7 +103,7 @@
/* in the DNS). In Postfix versions prior to 3.6, the default value
/* was "md5".
/* .IP "\fB-f\fR"
-/* Lookup the associated DANE TLSA RRset even when a hostname is not an
+/* Look up the associated DANE TLSA RRset even when a hostname is not an
/* alias and its address records lie in an unsigned zone. See
/* smtp_tls_force_insecure_host_tlsa_lookup for details.
/* .IP "\fB-F \fICAfile.pem\fR (default: none)"
@@ -264,6 +264,15 @@
/* the SMTP-in-SSL protocol, rather than the STARTTLS protocol.
/* The destination \fIdomain\fR:\fIport\fR must of course provide such
/* a service.
+/* .IP "\fB-x\fR"
+/* Prefer RFC7250 non-X.509 raw public key (RPK) server credentials. By
+/* default only X.509 certificates are accepted. This is analogous to
+/* setting \fBsmtp_tls_enable_rpk = yes\fR in the smtp(8) client. At the
+/* fingerprint security level, when raw public keys are enabled, only
+/* public key (and not certificate) fingerprints will be compared against
+/* the specified list of \fImatch\fR arguments. Certificate fingerprints
+/* are fragile when raw public keys are solicited, the server may at some
+/* point in time start returning only the public key.
/* .IP "\fB-X\fR"
/* Enable \fBtlsproxy\fR(8) mode. This is an unsupported mode,
/* for program development only.
@@ -441,6 +450,9 @@ typedef struct OPTIONS {
ARGV *tas;
char *host_lookup;
char *addr_pref;
+#ifdef USE_TLS
+ int enable_rpk;
+#endif
} OPTIONS;
/*
@@ -696,7 +708,7 @@ static void print_stack(STATE *state, x509_stack_t *sk, int trustout)
BIO_printf(state->tls_bio, " cert digest=%s\n", digest);
myfree(digest);
- digest = tls_pkey_fprint(cert, state->mdalg);
+ digest = tls_pkey_fprint(X509_get0_pubkey(cert), state->mdalg);
BIO_printf(state->tls_bio, " pkey digest=%s\n", digest);
myfree(digest);
@@ -809,6 +821,7 @@ static int starttls(STATE *state)
mdalg = state->mdalg);
TLS_PROXY_CLIENT_START_PROPS(&start_props,
timeout = smtp_tmout,
+ enable_rpk = state->options.enable_rpk,
tls_level = state->level,
nexthop = state->nexthop,
host = state->hostname,
@@ -826,7 +839,7 @@ static int starttls(STATE *state)
state->ddane : state->dane);
#define PROXY_OPEN_FLAGS \
- (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT)
+ (TLS_PROXY_FLAG_ROLE_CLIENT | TLS_PROXY_FLAG_SEND_CONTEXT)
#define var_tlsproxy_service
if ((cwd_fd = open(".", O_RDONLY)) < 0)
@@ -886,13 +899,19 @@ static int starttls(STATE *state)
state->tls_context = tls_proxy_context_receive(state->stream);
if (state->tls_context) {
if (state->log_mask &
- (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
- msg_info("%s: subject_CN=%s, issuer_CN=%s, "
- "fingerprint=%s, pkey_fingerprint=%s",
- state->namaddrport, state->tls_context->peer_CN,
- state->tls_context->issuer_CN,
- state->tls_context->peer_cert_fprint,
- state->tls_context->peer_pkey_fprint);
+ (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) {
+ if (state->tls_context->stoc_rpk)
+ msg_info("%s: pkey_fingerprint=%s", state->namaddrport,
+ state->tls_context->peer_pkey_fprint);
+ else
+ msg_info("%s: subject_CN=%s, issuer_CN=%s, "
+ "fingerprint=%s, pkey_fingerprint=%s",
+ state->namaddrport,
+ state->tls_context->peer_CN,
+ state->tls_context->issuer_CN,
+ state->tls_context->peer_cert_fprint,
+ state->tls_context->peer_pkey_fprint);
+ }
tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW,
state->tls_context);
} else {
@@ -906,6 +925,7 @@ static int starttls(STATE *state)
stream = stream,
fd = -1,
timeout = smtp_tmout,
+ enable_rpk = state->options.enable_rpk,
tls_level = state->level,
nexthop = state->nexthop,
host = state->hostname,
@@ -938,7 +958,7 @@ static int starttls(STATE *state)
if (state->pass == 1) {
ehlo(state);
- if (!TLS_CERT_IS_PRESENT(state->tls_context))
+ if (!TLS_CRED_IS_PRESENT(state->tls_context))
msg_info("Server is anonymous");
else if (state->tlsproxy_mode == 0) {
if (state->print_trust)
@@ -1232,7 +1252,7 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
* should not clobber a soft error text and status code.
*/
#define RETRY_AI_ERROR(e) \
- ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
+ ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
#ifdef EAI_NODATA
#define DSN_NOHOST(e) \
((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME)
@@ -1833,14 +1853,14 @@ static void usage(void)
#ifdef USE_TLS
fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s \\\n\t%s"
" destination [match ...]\n", var_procname,
- "[-acCfSvw] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
+ "[-acCfRSvwx] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
"[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]",
"[-A tafile] [-F CAfile.pem] [-P CApath/] [-s servername]",
"[ [-H chainfiles] | [-k certfile [-K keyfile]] ]",
"[-m count] [-r delay] [-o name=value]");
#else
- fprintf(stderr, "usage: %s [-acStTv] [-h host_lookup] [-o name=value] destination\n",
- var_procname);
+ fprintf(stderr, "usage: %s [-acRStTv] [-h host_lookup] [-o name=value]"
+ " destination\n", var_procname);
#endif
exit(1);
}
@@ -1910,7 +1930,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
#define OPTS "a:ch:o:RSt:T:v"
#ifdef USE_TLS
-#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wX"
+#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wxX"
state->mdalg = 0;
state->CApath = mystrdup("");
@@ -1921,6 +1941,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
state->sni = mystrdup("");
state->options.tas = argv_alloc(1);
state->options.logopts = 0;
+ state->options.enable_rpk = 0;
state->level = TLS_LEV_DANE;
state->mxinsec_level = TLS_LEV_DANE;
state->tlsproxy_mode = 0;
@@ -2054,6 +2075,9 @@ static void parse_options(STATE *state, int argc, char *argv[])
case 'w':
state->wrapper_mode = 1;
break;
+ case 'x':
+ state->options.enable_rpk = 1;
+ break;
case 'X':
state->tlsproxy_mode = 1;
break;
@@ -2119,8 +2143,8 @@ static void parse_match(STATE *state, int argc, char *argv[])
int smtp_mode = 1;
/*
- * DANE match names are configured late, once the TLSA records are in
- * hand. For now, prepare to fall back to "secure".
+ * DANE match names are configured late, once the TLSA records are in hand.
+ * For now, prepare to fall back to "secure".
*/
switch (state->level) {
default:
@@ -2148,8 +2172,8 @@ static void parse_match(STATE *state, int argc, char *argv[])
case TLS_LEV_FPRINT:
state->dane = tls_dane_alloc();
while (*argv)
- tls_dane_add_fpt_digests((TLS_DANE *) state->dane, *argv++, "",
- smtp_mode);
+ tls_dane_add_fpt_digests(state->dane, state->options.enable_rpk,
+ *argv++, "", smtp_mode);
break;
}
#endif
diff --git a/src/proxymap/proxymap.c b/src/proxymap/proxymap.c
index abdcf3a..c0af411 100644
--- a/src/proxymap/proxymap.c
+++ b/src/proxymap/proxymap.c
@@ -37,7 +37,7 @@
/* .IP \(bu
/* To provide single-updater functionality for lookup tables
/* that do not reliably support multiple writers (i.e. all
-/* file-based tables).
+/* file-based tables that are not based on \fBlmdb\fR).
/* .PP
/* The \fBproxymap\fR(8) server implements the following requests:
/* .IP "\fBopen\fR \fImaptype:mapname flags\fR"
@@ -752,8 +752,10 @@ static void post_jail_init(char *service_name, char **unused_argv)
if (strcmp(service_name, MAIL_SERVICE_PROXYWRITE) == 0)
proxy_writer = 1;
else if (strcmp(service_name, MAIL_SERVICE_PROXYMAP) != 0)
- msg_fatal("service name must be one of %s or %s",
- MAIL_SERVICE_PROXYMAP, MAIL_SERVICE_PROXYMAP);
+ msg_fatal("invalid service name: \"%s\" - "
+ "service name must be \"%s\" or \"%s\"",
+ service_name, MAIL_SERVICE_PROXYWRITE,
+ MAIL_SERVICE_PROXYMAP);
/*
* Pre-allocate buffers.
@@ -841,6 +843,36 @@ int main(int argc, char **argv)
*/
MAIL_VERSION_STAMP_ALLOCATE;
+ /*
+ * XXX When invoked with the master.cf service name "proxywrite", the
+ * proxymap daemon will allow update requests. To update a table that is
+ * not multi-writer safe (for example, some versions of Berkeley DB), the
+ * "proxywrite" service should run as a single updater (i.e. a process
+ * limit of 1, which could be enforced below by requesting
+ * CA_MAIL_SERVER_SOLITARY).
+ *
+ * In the default master.cf file, the "proxywrite" service has a process
+ * limit of 1. Assuming that updates will be rare, this process limit
+ * will suffice. Latency-sensitive services such as postscreen must not
+ * use the proxywrite service (in fact, postscreen has a latency check
+ * built-in).
+ *
+ * Optimizing for multi-writer operation would suffer from all kinds of
+ * complexity that would make it hard to use:
+ *
+ * - The master daemon specifies the "proxywrite" service name with the -n
+ * command-line option. This information is not known here, before the
+ * multi_server_main() call. The multi_server_main() function could
+ * reveal process limit information to its call-back functions, and leave
+ * single-updater enforcement to its call-back functions.
+ *
+ * - If we really want multi-writer update support, the "proxywrite" service
+ * would have to parse the $proxy_write_maps value, and permit
+ * multi-writer operation only if all tables are multi-writer safe. That
+ * would require a new dict(3) method, to query each lookup table
+ * implementation if it is multi-writer safe, without instantiating a
+ * lookup table client.
+ */
multi_server_main(argc, argv, proxymap_service,
CA_MAIL_SERVER_STR_TABLE(str_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
diff --git a/src/qmgr/qmgr.c b/src/qmgr/qmgr.c
index 9d90a6e..25168e4 100644
--- a/src/qmgr/qmgr.c
+++ b/src/qmgr/qmgr.c
@@ -206,7 +206,7 @@
/* parameter value, where \fItransport\fR is the master.cf name of
/* the message delivery transport.
/* .IP "\fBdefault_recipient_refill_delay (5s)\fR"
-/* The default per-transport maximum delay between recipients refills.
+/* The default per-transport maximum delay between refilling recipients.
/* .IP "\fBtransport_recipient_refill_delay ($default_recipient_refill_delay)\fR"
/* A transport-specific override for the default_recipient_refill_delay
/* parameter value, where \fItransport\fR is the master.cf name of
diff --git a/src/qmgr/qmgr_deliver.c b/src/qmgr/qmgr_deliver.c
index 577bb98..6c880ce 100644
--- a/src/qmgr/qmgr_deliver.c
+++ b/src/qmgr/qmgr_deliver.c
@@ -160,7 +160,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
*/
for (recipient = list.info; recipient < list.info + list.len; recipient++)
if (var_smtputf8_enable && (addr = recipient->address)[0]
- && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) {
+ && !allascii(addr) && valid_utf8_stringz(addr)) {
smtputf8 |= SMTPUTF8_FLAG_RECIPIENT;
if (message->verp_delims)
smtputf8 |= SMTPUTF8_FLAG_SENDER;
@@ -339,7 +339,7 @@ static void qmgr_deliver_update(int unused_event, void *context)
#define SUSPENDED "delivery temporarily suspended: "
if (status == DELIVER_STAT_CRASH)
- DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error");
+ (void) DSN_SIMPLE(&dsb->dsn, "4.3.0", "unknown mail transport error");
if (status == DELIVER_STAT_CRASH || status == DELIVER_STAT_DEFER) {
message->flags |= DELIVER_STAT_DEFER;
if (VSTRING_LEN(dsb->status)) {
diff --git a/src/qmqpd/qmqpd.c b/src/qmqpd/qmqpd.c
index d94d33d..138ac64 100644
--- a/src/qmqpd/qmqpd.c
+++ b/src/qmqpd/qmqpd.c
@@ -57,7 +57,7 @@
/* Preliminary SMTPUTF8 support is introduced with Postfix 3.0.
/* .IP "\fBsmtputf8_enable (yes)\fR"
/* Enable preliminary SMTPUTF8 support for the protocols described
-/* in RFC 6531..6533.
+/* in RFC 6531, RFC 6532, and RFC 6533.
/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR"
/* Detect that a message requires SMTPUTF8 support for the specified
/* mail origin classes.
diff --git a/src/sendmail/sendmail.c b/src/sendmail/sendmail.c
index 27b3543..df052c5 100644
--- a/src/sendmail/sendmail.c
+++ b/src/sendmail/sendmail.c
@@ -412,9 +412,10 @@
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/* The location of the Postfix top-level queue directory.
/* .IP "\fBremote_header_rewrite_domain (empty)\fR"
-/* Don't rewrite message headers from remote clients at all when
-/* this parameter is empty; otherwise, rewrite message headers and
-/* append the specified domain name to incomplete addresses.
+/* Rewrite or add message headers in mail from remote clients if
+/* the remote_header_rewrite_domain parameter value is non-empty,
+/* updating incomplete addresses with the domain specified in the
+/* remote_header_rewrite_domain parameter, and adding missing headers.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
diff --git a/src/smtp/lmtp_params.c b/src/smtp/lmtp_params.c
index bca7cd4..385c81f 100644
--- a/src/smtp/lmtp_params.c
+++ b/src/smtp/lmtp_params.c
@@ -4,6 +4,7 @@
VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
+ VAR_LMTP_SASL_PASSWD_RES_DELIM, DEF_LMTP_SASL_PASSWD_RES_DELIM, &var_smtp_sasl_passwd_res_delim, 1, 1,
VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
VAR_LMTP_SASL_PATH, DEF_LMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0,
#ifdef USE_TLS
@@ -120,6 +121,7 @@
VAR_LMTP_TLS_NOTEOFFER, DEF_LMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
VAR_LMTP_TLS_BLK_EARLY_MAIL_REPLY, DEF_LMTP_TLS_BLK_EARLY_MAIL_REPLY, &var_smtp_tls_blk_early_mail_reply,
VAR_LMTP_TLS_FORCE_TLSA, DEF_LMTP_TLS_FORCE_TLSA, &var_smtp_tls_force_tlsa,
+ VAR_LMTP_TLS_ENABLE_RPK, DEF_LMTP_TLS_ENABLE_RPK, &var_smtp_tls_enable_rpk,
#endif
VAR_LMTP_TLS_WRAPPER, DEF_LMTP_TLS_WRAPPER, &var_smtp_tls_wrappermode,
VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth,
diff --git a/src/smtp/smtp.c b/src/smtp/smtp.c
index f7f2fc1..51b2e6d 100644
--- a/src/smtp/smtp.c
+++ b/src/smtp/smtp.c
@@ -1,17 +1,21 @@
/*++
/* NAME
-/* smtp 8
+/* smtp, lmtp 8
/* SUMMARY
/* Postfix SMTP+LMTP client
/* SYNOPSIS
/* \fBsmtp\fR [generic Postfix daemon options] [flags=DORX]
+/*
+/* \fBlmtp\fR [generic Postfix daemon options] [flags=DORX]
/* DESCRIPTION
/* The Postfix SMTP+LMTP client implements the SMTP and LMTP mail
/* delivery protocols. It processes message delivery requests from
/* the queue manager. Each request specifies a queue file, a sender
/* address, a domain or host to deliver to, and recipient information.
/* This program expects to be run from the \fBmaster\fR(8) process
-/* manager.
+/* manager. The process name, \fBsmtp\fR or \fBlmtp\fR, controls
+/* the protocol, and the names of the configuration parameters
+/* that will be used.
/*
/* The SMTP+LMTP client updates the queue file and marks recipients
/* as finished, or it informs the queue manager that delivery should
@@ -19,13 +23,9 @@
/* to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as
/* appropriate.
/*
-/* The SMTP+LMTP client looks up a list of mail exchanger addresses for
-/* the destination host, sorts the list by preference, and connects
-/* to each listed address until it finds a server that responds.
-/*
-/* When a server is not reachable, or when mail delivery fails due
-/* to a recoverable error condition, the SMTP+LMTP client will try to
-/* deliver the mail to an alternate host.
+/* The server lookup strategy is different for SMTP and LMTP,
+/* as described in the sections "SMTP SERVER LOOKUP" and "LMTP
+/* SERVER LOOKUP".
/*
/* After a successful mail transaction, a connection may be saved
/* to the \fBscache\fR(8) connection cache server, so that it
@@ -35,44 +35,58 @@
/* destinations that have a high volume of mail in the active
/* queue. Connection caching can be enabled permanently for
/* specific destinations.
-/* SMTP DESTINATION SYNTAX
+/* SMTP SERVER LOOKUP
/* .ad
/* .fi
-/* The Postfix SMTP+LMTP client supports multiple destinations
+/* The Postfix SMTP client supports multiple destinations
/* separated by comma or whitespace (Postfix 3.5 and later).
+/* Each destination is tried in the specified order.
+/*
/* SMTP destinations have the following form:
/* .IP \fIdomainname\fR
-/* .IP \fIdomainname\fR:\fIport\fR
+/* .IP \fIdomainname\fR:\fIservice\fR
/* Look up the mail exchangers for the specified domain, and
-/* connect to the specified port (default: \fBsmtp\fR).
+/* connect to the specified service (default: \fBsmtp\fR).
+/* Optionally, mail exchangers may be looked up with SRV queries
+/* instead of MX; this requires that \fIservice\fR is given
+/* in symbolic form.
/* .IP [\fIhostname\fR]
-/* .IP [\fIhostname\fR]:\fIport\fR
-/* Look up the address(es) of the specified host, and connect to
-/* the specified port (default: \fBsmtp\fR).
+/* .IP [\fIhostname\fR]:\fIservice\fR
+/* Look up the address(es) for the specified host, and connect to
+/* the specified service (default: \fBsmtp\fR).
/* .IP [\fIaddress\fR]
-/* .IP [\fIaddress\fR]:\fIport\fR
+/* .IP [\fIaddress\fR]:\fIservice\fR
/* Connect to the host at the specified address, and connect
-/* to the specified port (default: \fBsmtp\fR). An IPv6 address
+/* to the specified service (default: \fBsmtp\fR). An IPv6 address
/* must be formatted as [\fBipv6\fR:\fIaddress\fR].
-/* LMTP DESTINATION SYNTAX
+/* LMTP SERVER LOOKUP
/* .ad
/* .fi
-/* The Postfix SMTP+LMTP client supports multiple destinations
+/* The Postfix LMTP client supports multiple destinations
/* separated by comma or whitespace (Postfix 3.5 and later).
+/* Each destination is tried in the specified order.
+/*
/* LMTP destinations have the following form:
/* .IP \fBunix\fR:\fIpathname\fR
/* Connect to the local UNIX-domain server that is bound to the specified
/* \fIpathname\fR. If the process runs chrooted, an absolute pathname
/* is interpreted relative to the Postfix queue directory.
+/* .IP \fBinet\fR:\fIdomainname\fR
+/* .IP \fBinet\fR:\fIdomainname\fR:\fIservice\fR
+/* Look up the LMTP servers for the specified domain and service
+/* (default: \fBlmtp\fR).
+/* This form is supported when SRV lookups are enabled, and
+/* requires that \fIservice\fR is in symbolic form.
/* .IP \fBinet\fR:\fIhostname\fR
-/* .IP \fBinet\fR:\fIhostname\fR:\fIport\fR
+/* .IP \fBinet\fR:\fIhostname\fR:\fIservice\fR
+/* Look up the address(es) for the specified host, and connect to
+/* the specified service (default: \fBlmtp\fR). When SRV lookups
+/* are enabled, use the form \fB[\fIhostname\fB]\fR to force
+/* address lookups.
/* .IP \fBinet\fR:[\fIaddress\fR]
-/* .IP \fBinet\fR:[\fIaddress\fR]:\fIport\fR
-/* Connect to the specified TCP port on the specified local or
-/* remote host. If no port is specified, connect to the port defined as
-/* \fBlmtp\fR in \fBservices\fR(4).
-/* If no such service is found, the \fBlmtp_tcp_port\fR configuration
-/* parameter (default value of 24) will be used.
+/* .IP \fBinet\fR:[\fIaddress\fR]:\fIservice\fR
+/* Connect to the specified local or remote host and service
+/* (default: \fBlmtp\fR).
/* An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR].
/* SINGLE-RECIPIENT DELIVERY
/* .ad
@@ -130,6 +144,8 @@
/* This feature is available as of Postfix 3.5.
/* .RE
/* SECURITY
+/* .ad
+/* .fi
/* The SMTP+LMTP client is moderately security-sensitive. It
/* talks to SMTP or LMTP servers and to DNS servers on the
/* network. The SMTP+LMTP client can be run chrooted at fixed
@@ -175,11 +191,10 @@
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
-/* Before Postfix version 2.3, the LMTP client is a separate
-/* program that implements only a subset of the functionality
-/* available with SMTP: there is no support for TLS, and
-/* connections are cached in-process, making it ineffective
-/* when the client is used for multiple domains.
+/* Postfix versions 2.3 and later implement the SMTP and LMTP
+/* client with the same program, and choose the protocol and
+/* configuration parameters based on the process name, \fBsmtp\fR
+/* or \fBlmtp\fR.
/*
/* Most smtp_\fIxxx\fR configuration parameters have an
/* lmtp_\fIxxx\fR "mirror" parameter for the equivalent LMTP
@@ -432,6 +447,11 @@
/* .IP "\fBsmtp_send_dummy_mail_auth (no)\fR"
/* Whether or not to append the "AUTH=<>" option to the MAIL
/* FROM command in SASL-authenticated SMTP sessions.
+/* .PP
+/* Available in Postfix version 3.9 and later:
+/* .IP "\fBsmtp_sasl_password_result_delimiter (:)\fR"
+/* The delimiter between username and password in sasl_passwd_maps lookup
+/* results.
/* STARTTLS SUPPORT CONTROLS
/* .ad
/* .fi
@@ -532,7 +552,7 @@
/* certificate fingerprints.
/* .PP
/* Available in Postfix version 2.6 and later:
-/* .IP "\fBsmtp_tls_protocols (see postconf -d output)\fR"
+/* .IP "\fBsmtp_tls_protocols (see 'postconf -d' output)\fR"
/* TLS protocols that the Postfix SMTP client will use with
/* opportunistic TLS encryption.
/* .IP "\fBsmtp_tls_ciphers (medium)\fR"
@@ -613,6 +633,11 @@
/* .IP "\fBtls_config_name (empty)\fR"
/* The application name passed by Postfix to OpenSSL library
/* initialization functions.
+/* .PP
+/* Available in Postfix version 3.9 and later:
+/* .IP "\fBsmtp_tls_enable_rpk (no)\fR"
+/* Request that remote SMTP servers send an RFC7250 raw public key
+/* instead of an X.509 certificate.
/* OBSOLETE STARTTLS CONTROLS
/* .ad
/* .fi
@@ -799,9 +824,9 @@
/* .IP "\fBdisable_dns_lookups (no)\fR"
/* Disable DNS lookups in the Postfix SMTP and LMTP clients.
/* .IP "\fBinet_interfaces (all)\fR"
-/* The local network interface addresses that this mail system receives
-/* mail on.
-/* .IP "\fBinet_protocols (see 'postconf -d output')\fR"
+/* The local network interface addresses that this mail system
+/* receives mail on.
+/* .IP "\fBinet_protocols (see 'postconf -d' output)\fR"
/* The Internet protocols Postfix will attempt to use when making
/* or accepting connections.
/* .IP "\fBipc_timeout (3600s)\fR"
@@ -1020,6 +1045,7 @@ int var_smtp_never_ehlo;
char *var_smtp_sasl_opts;
char *var_smtp_sasl_path;
char *var_smtp_sasl_passwd;
+char *var_smtp_sasl_passwd_res_delim;
bool var_smtp_sasl_enable;
char *var_smtp_sasl_mechs;
char *var_smtp_sasl_type;
@@ -1090,6 +1116,7 @@ char *var_smtp_tls_sni;
bool var_smtp_tls_blk_early_mail_reply;
bool var_smtp_tls_force_tlsa;
char *var_smtp_tls_insecure_mx_policy;
+bool var_smtp_tls_enable_rpk;
#endif
@@ -1117,8 +1144,8 @@ bool var_smtp_balance_inet_proto;
bool var_smtp_req_deadline;
int var_smtp_min_data_rate;
char *var_use_srv_lookup;
-bool var_ign_srv_lookup_err;
-bool var_allow_srv_fallback;
+bool var_ign_srv_lookup_err;
+bool var_allow_srv_fallback;
/* Special handling of 535 AUTH errors. */
char *var_smtp_sasl_auth_cache_name;
@@ -1126,7 +1153,7 @@ int var_smtp_sasl_auth_cache_time;
bool var_smtp_sasl_auth_soft_bounce;
char *var_hfrom_format;
-bool var_smtp_bind_addr_enforce;
+bool var_smtp_bind_addr_enforce;
/*
* Global variables.
@@ -1459,6 +1486,19 @@ static void pre_init(char *unused_name, char **unused_argv)
};
/*
+ * The process name, "smtp" or "lmtp", determines the configuration
+ * parameters to use, protocol, DSN server reply type, SASL service
+ * information lookup, and more. We peeked at the name in the main()
+ * function before logging was initialized. Here, we detect and report an
+ * invalid process name.
+ */
+ if (strcmp(var_procname, MAIL_PROC_NAME_SMTP) != 0
+ && strcmp(var_procname, MAIL_PROC_NAME_LMTP) != 0)
+ msg_fatal("unexpected process name \"%s\" - "
+ "specify \"%s\" or \"%s\"", var_procname,
+ MAIL_PROC_NAME_SMTP, MAIL_PROC_NAME_LMTP);
+
+ /*
* Turn on per-peer debugging.
*/
debug_peer_init();
@@ -1649,21 +1689,15 @@ int main(int argc, char **argv)
MAIL_VERSION_STAMP_ALLOCATE;
/*
- * XXX At this point, var_procname etc. are not initialized.
- *
- * The process name, "smtp" or "lmtp", determines the protocol, the DSN
- * server reply type, SASL service information lookup, and more. Prepare
- * for the possibility there may be another personality.
+ * XXX The process name, "smtp" or "lmtp", determines what configuration
+ * parameter settings to use, and more. However, at this point, logging
+ * and var_procname are not initialized. Here, we peek at the process
+ * name to determine what configuration parameter settings to use. Later,
+ * we detect and report an invalid process name.
*/
sane_procname = sane_basename((VSTRING *) 0, argv[0]);
- if (strcmp(sane_procname, "smtp") == 0)
+ if (strcmp(sane_procname, MAIL_PROC_NAME_SMTP) == 0)
smtp_mode = 1;
- else if (strcmp(sane_procname, "lmtp") == 0)
- smtp_mode = 0;
- else
- /* TODO: logging is not initialized. */
- msg_fatal("unexpected process name \"%s\" - "
- "specify \"smtp\" or \"lmtp\"", var_procname);
/*
* Initialize with the LMTP or SMTP parameter name space.
diff --git a/src/smtp/smtp.h b/src/smtp/smtp.h
index f8c8f58..60c68f8 100644
--- a/src/smtp/smtp.h
+++ b/src/smtp/smtp.h
@@ -107,6 +107,7 @@ typedef struct SMTP_TLS_POLICY {
TLS_DANE *dane; /* DANE TLSA digests */
char *sni; /* Optional SNI name when not DANE */
int conn_reuse; /* enable connection reuse */
+ int enable_rpk; /* Enable server->client RPK */
} SMTP_TLS_POLICY;
/*
@@ -142,6 +143,7 @@ extern void smtp_tls_policy_cache_flush(void);
_tls_policy_init_tmp->dane = 0; \
_tls_policy_init_tmp->sni = 0; \
_tls_policy_init_tmp->conn_reuse = 0; \
+ _tls_policy_init_tmp->enable_rpk = 0; \
} while (0)
#endif
diff --git a/src/smtp/smtp_addr.c b/src/smtp/smtp_addr.c
index f30ce73..8c384fc 100644
--- a/src/smtp/smtp_addr.c
+++ b/src/smtp/smtp_addr.c
@@ -262,7 +262,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
msg_fatal("host %s: conversion error for address family "
"%d: %m", host, res0->ai_addr->sa_family);
addr_list = dns_rr_append(addr_list, addr);
- if (DNS_RR_IS_TRUNCATED(addr_list))
+ if (DNS_RR_IS_TRUNCATED(addr_list))
break;
if (msg_verbose) {
MAI_HOSTADDR_STR hostaddr_str;
diff --git a/src/smtp/smtp_params.c b/src/smtp/smtp_params.c
index 22f4709..cebff93 100644
--- a/src/smtp/smtp_params.c
+++ b/src/smtp/smtp_params.c
@@ -4,6 +4,7 @@
VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
+ VAR_SMTP_SASL_PASSWD_RES_DELIM, DEF_SMTP_SASL_PASSWD_RES_DELIM, &var_smtp_sasl_passwd_res_delim, 1, 1,
VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
VAR_SMTP_SASL_PATH, DEF_SMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0,
#ifdef USE_TLS
@@ -124,6 +125,7 @@
VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
VAR_SMTP_TLS_BLK_EARLY_MAIL_REPLY, DEF_SMTP_TLS_BLK_EARLY_MAIL_REPLY, &var_smtp_tls_blk_early_mail_reply,
VAR_SMTP_TLS_FORCE_TLSA, DEF_SMTP_TLS_FORCE_TLSA, &var_smtp_tls_force_tlsa,
+ VAR_SMTP_TLS_ENABLE_RPK, DEF_SMTP_TLS_ENABLE_RPK, &var_smtp_tls_enable_rpk,
#endif
VAR_SMTP_TLS_WRAPPER, DEF_SMTP_TLS_WRAPPER, &var_smtp_tls_wrappermode,
VAR_SMTP_SENDER_AUTH, DEF_SMTP_SENDER_AUTH, &var_smtp_sender_auth,
diff --git a/src/smtp/smtp_proto.c b/src/smtp/smtp_proto.c
index 097d518..e022bc2 100644
--- a/src/smtp/smtp_proto.c
+++ b/src/smtp/smtp_proto.c
@@ -929,6 +929,7 @@ static int smtp_start_tls(SMTP_STATE *state)
TLS_PROXY_CLIENT_START_PROPS(&start_props,
timeout = var_smtp_starttls_tmout,
tls_level = state->tls->level,
+ enable_rpk = state->tls->enable_rpk,
nexthop = session->tls_nexthop,
host = STR(iter->host),
namaddr = session->namaddrport,
@@ -1051,6 +1052,7 @@ static int smtp_start_tls(SMTP_STATE *state)
fd = -1,
timeout = var_smtp_starttls_tmout,
tls_level = state->tls->level,
+ enable_rpk = state->tls->enable_rpk,
nexthop = session->tls_nexthop,
host = STR(iter->host),
namaddr = session->namaddrport,
diff --git a/src/smtp/smtp_sasl_glue.c b/src/smtp/smtp_sasl_glue.c
index ef8e8c4..cce5ef7 100644
--- a/src/smtp/smtp_sasl_glue.c
+++ b/src/smtp/smtp_sasl_glue.c
@@ -200,7 +200,9 @@ int smtp_sasl_passwd_lookup(SMTP_SESSION *session)
if (session->sasl_username)
myfree(session->sasl_username);
session->sasl_username = mystrdup(value);
- passwd = split_at(session->sasl_username, ':');
+ /* Historically, the delimiter may appear in the password. */
+ passwd = split_at(session->sasl_username,
+ *var_smtp_sasl_passwd_res_delim);
if (session->sasl_passwd)
myfree(session->sasl_passwd);
session->sasl_passwd = mystrdup(passwd ? passwd : "");
diff --git a/src/smtp/smtp_tls_policy.c b/src/smtp/smtp_tls_policy.c
index 92a231d..f407d65 100644
--- a/src/smtp/smtp_tls_policy.c
+++ b/src/smtp/smtp_tls_policy.c
@@ -334,9 +334,10 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level,
INVALID_RETURN(tls->why, site_level);
break;
case TLS_LEV_FPRINT:
- if (!tls->dane)
- tls->dane = tls_dane_alloc();
- tls_dane_add_fpt_digests(tls->dane, val, "|", smtp_mode);
+ if (tls->matchargv == 0)
+ tls->matchargv = argv_split(val, "|");
+ else
+ argv_split_append(tls->matchargv, val, "|");
break;
case TLS_LEV_VERIFY:
case TLS_LEV_SECURE:
@@ -390,6 +391,19 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level,
}
continue;
}
+ if (!strcasecmp(name, "enable_rpk")) {
+ /* Ultimately ignored at some security levels */
+ if (strcasecmp(val, "yes") == 0) {
+ tls->enable_rpk = 1;
+ } else if (strcasecmp(val, "no") == 0) {
+ tls->enable_rpk = 0;
+ } else {
+ msg_warn("%s: attribute \"%s\" has bad value: \"%s\"",
+ WHERE, name, val);
+ INVALID_RETURN(tls->why, site_level);
+ }
+ continue;
+ }
msg_warn("%s: invalid attribute name: \"%s\"", WHERE, name);
INVALID_RETURN(tls->why, site_level);
}
@@ -518,6 +532,7 @@ static void *policy_create(const char *unused_key, void *context)
smtp_tls_policy_init(tls, dsb_create());
tls->conn_reuse = var_smtp_tls_conn_reuse;
+ tls->enable_rpk = var_smtp_tls_enable_rpk;
/*
* Compute the per-site TLS enforcement level. For compatibility with the
@@ -602,6 +617,13 @@ static void *policy_create(const char *unused_key, void *context)
*/
set_cipher_grade(tls);
+/*
+ * Even when soliciting raw public keys, synthesize TLSA RRs that also match
+ * certificates. Though this is fragile, it maintains compatibility with
+ * servers that never return RPKs.
+ */
+#define DONT_SUPPRESS_CERT_MATCH 0
+
/*
* Use main.cf cert_match setting if not set in per-destination table.
*/
@@ -617,16 +639,26 @@ static void *policy_create(const char *unused_key, void *context)
case TLS_LEV_FPRINT:
if (tls->dane == 0)
tls->dane = tls_dane_alloc();
- if (tls->dane->tlsa == 0) {
- tls_dane_add_fpt_digests(tls->dane, var_smtp_tls_fpt_cmatch,
- CHARS_COMMA_SP, smtp_mode);
- if (tls->dane->tlsa == 0) {
- msg_warn("nexthop domain %s: configured at fingerprint "
- "security level, but with no fingerprints to match.",
- dest);
- MARK_INVALID(tls->why, &tls->level);
- return ((void *) tls);
+ /* Process the specified fingerprint match patterns */
+ if (tls->matchargv) {
+ int i;
+
+ for (i = 0; i < tls->matchargv->argc; ++i) {
+ tls_dane_add_fpt_digests(tls->dane, DONT_SUPPRESS_CERT_MATCH,
+ tls->matchargv->argv[i], "",
+ smtp_mode);
}
+ } else {
+ tls_dane_add_fpt_digests(tls->dane, DONT_SUPPRESS_CERT_MATCH,
+ var_smtp_tls_fpt_cmatch, CHARS_COMMA_SP,
+ smtp_mode);
+ }
+ if (tls->dane->tlsa == 0) {
+ msg_warn("nexthop domain %s: configured at fingerprint "
+ "security level, but with no fingerprints to match.",
+ dest);
+ MARK_INVALID(tls->why, &tls->level);
+ return ((void *) tls);
}
break;
case TLS_LEV_VERIFY:
diff --git a/src/smtpd/Makefile.in b/src/smtpd/Makefile.in
index 7fdfe12..c8837fe 100644
--- a/src/smtpd/Makefile.in
+++ b/src/smtpd/Makefile.in
@@ -75,7 +75,8 @@ broken-tests: smtpd_check_test smtpd_check_test2
tests: smtpd_acl_test smtpd_addr_valid_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_nullmx_test smtpd_dns_filter_test
+ smtpd_server_test smtpd_nullmx_test smtpd_dns_filter_test \
+ smtpd_deprecated_test
root_tests:
@@ -114,7 +115,8 @@ smtpd_addr_valid_test: smtpd_check smtpd_addr_valid.in smtpd_addr_valid.ref
# This requires that the DNS server can query porcupine.org.
-ADDRINFO_FIX = sed 's/No address associated with hostname/hostname nor servname provided, or not known/'
+ADDRINFO_FIX = sed -e 's/No address associated with hostname/hostname nor servname provided, or not known/' \
+ -e 's/Name or service not known/hostname nor servname provided, or not known/'
smtpd_exp_test: smtpd_check smtpd_exp.in smtpd_exp.ref
$(SHLIB_ENV) $(VALGRIND) ../postmap/postmap hash:smtpd_check_access
@@ -170,6 +172,11 @@ smtpd_error_test: smtpd_check smtpd_error.in smtpd_error.ref
diff smtpd_error.ref smtpd_check.tmp
rm -f smtpd_check.tmp
+smtpd_deprecated_test: smtpd_check smtpd_deprecated.in smtpd_deprecated.ref
+ $(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_deprecated.in >smtpd_check.tmp 2>&1
+ diff smtpd_deprecated.ref smtpd_check.tmp
+ rm -f smtpd_check.tmp
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
diff --git a/src/smtpd/smtpd.c b/src/smtpd/smtpd.c
index 6a2cf01..bce0d43 100644
--- a/src/smtpd/smtpd.c
+++ b/src/smtpd/smtpd.c
@@ -468,7 +468,7 @@
/* \fBcheck_ccert_access\fR and \fBpermit_tls_clientcerts\fR.
/* .PP
/* Available in Postfix version 2.6 and later:
-/* .IP "\fBsmtpd_tls_protocols (see postconf -d output)\fR"
+/* .IP "\fBsmtpd_tls_protocols (see 'postconf -d' output)\fR"
/* TLS protocols accepted by the Postfix SMTP server with opportunistic
/* TLS encryption.
/* .IP "\fBsmtpd_tls_ciphers (medium)\fR"
@@ -537,6 +537,12 @@
/* .IP "\fBtls_config_name (empty)\fR"
/* The application name passed by Postfix to OpenSSL library
/* initialization functions.
+/* .PP
+/* Available in Postfix version 3.9 and later:
+/* .IP "\fBsmtpd_tls_enable_rpk (no)\fR"
+/* Request that remote SMTP clients send an RFC7250 raw public key
+/* instead of an X.509 certificate, when asking for or requiring client
+/* authentication.
/* OBSOLETE STARTTLS CONTROLS
/* .ad
/* .fi
@@ -662,12 +668,12 @@
/* The list of domains that are delivered via the $local_transport
/* mail delivery transport.
/* .IP "\fBinet_interfaces (all)\fR"
-/* The local network interface addresses that this mail system receives
-/* mail on.
+/* The local network interface addresses that this mail system
+/* receives mail on.
/* .IP "\fBproxy_interfaces (empty)\fR"
/* The remote network interface addresses that this mail system receives mail
/* on by way of a proxy or network address translation unit.
-/* .IP "\fBinet_protocols (see 'postconf -d output')\fR"
+/* .IP "\fBinet_protocols (see 'postconf -d' output)\fR"
/* The Internet protocols Postfix will attempt to use when making
/* or accepting connections.
/* .IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR"
@@ -698,8 +704,9 @@
/* alias domains, that is, domains for which all addresses are aliased
/* to addresses in other local or remote domains.
/* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
-/* Optional lookup tables that alias specific mail addresses or domains
-/* to other local or remote addresses.
+/* Optional lookup tables with aliases that apply to all recipients:
+/* \fBlocal\fR(8), virtual, and remote; this is unlike alias_maps that apply
+/* only to \fBlocal\fR(8) recipients.
/* .IP "\fBunknown_virtual_alias_reject_code (550)\fR"
/* The Postfix SMTP server reply code when a recipient address matches
/* $virtual_alias_domains, and $virtual_alias_maps specifies a list
@@ -817,7 +824,7 @@
/* command pipelining constraints.
/* .PP
/* Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later:
-/* .IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR"
+/* .IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: normalize)\fR"
/* Reject or restrict input lines from an SMTP client that end in
/* <LF> instead of the standard <CR><LF>.
/* .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR"
@@ -1492,6 +1499,7 @@ char *var_smtpd_tls_eecdh;
char *var_smtpd_tls_eccert_file;
char *var_smtpd_tls_eckey_file;
char *var_smtpd_tls_chain_files;
+int var_smtpd_tls_enable_rpk;
#endif
@@ -1664,13 +1672,16 @@ int smtpd_hfrom_format;
*/
#define BARE_LF_FLAG_WANT_STD_EOD (1<<0) /* Require CRLF.CRLF */
#define BARE_LF_FLAG_REPLY_REJECT (1<<1) /* Reject bare newline */
+#define BARE_LF_FLAG_NOTE_LOG (1<<2) /* Note bare newline */
#define IS_BARE_LF_WANT_STD_EOD(m) ((m) & BARE_LF_FLAG_WANT_STD_EOD)
#define IS_BARE_LF_REPLY_REJECT(m) ((m) & BARE_LF_FLAG_REPLY_REJECT)
+#define IS_BARE_LF_NOTE_LOG(m) ((m) & BARE_LF_FLAG_NOTE_LOG)
static const NAME_CODE bare_lf_mask_table[] = {
"normalize", BARE_LF_FLAG_WANT_STD_EOD, /* Default */
"yes", BARE_LF_FLAG_WANT_STD_EOD, /* Migration aid */
+ "note", BARE_LF_FLAG_WANT_STD_EOD | BARE_LF_FLAG_NOTE_LOG,
"reject", BARE_LF_FLAG_WANT_STD_EOD | BARE_LF_FLAG_REPLY_REJECT,
"no", 0,
0, -1, /* error */
@@ -3504,11 +3515,15 @@ static void common_pre_message_handling(SMTPD_STATE *state,
}
if (state->tls_context->srvr_sig_curve
&& *state->tls_context->srvr_sig_curve)
- vstring_sprintf_append(state->buffer, " (%s)",
- state->tls_context->srvr_sig_curve);
+ vstring_sprintf_append(state->buffer, " (%s%s)",
+ state->tls_context->srvr_sig_curve,
+ state->tls_context->stoc_rpk ?
+ " raw public key" : "");
else if (state->tls_context->srvr_sig_bits > 0)
- vstring_sprintf_append(state->buffer, " (%d bits)",
- state->tls_context->srvr_sig_bits);
+ vstring_sprintf_append(state->buffer, " (%d bit%s)",
+ state->tls_context->srvr_sig_bits,
+ state->tls_context->stoc_rpk ?
+ " raw public key" : "s");
if (state->tls_context->srvr_sig_dgst
&& *state->tls_context->srvr_sig_dgst)
vstring_sprintf_append(state->buffer, " server-digest %s",
@@ -3522,11 +3537,15 @@ static void common_pre_message_handling(SMTPD_STATE *state,
state->tls_context->clnt_sig_name);
if (state->tls_context->clnt_sig_curve
&& *state->tls_context->clnt_sig_curve)
- vstring_sprintf_append(state->buffer, " (%s)",
- state->tls_context->clnt_sig_curve);
+ vstring_sprintf_append(state->buffer, " (%s%s)",
+ state->tls_context->clnt_sig_curve,
+ state->tls_context->ctos_rpk ?
+ " raw public key" : "");
else if (state->tls_context->clnt_sig_bits > 0)
- vstring_sprintf_append(state->buffer, " (%d bits)",
- state->tls_context->clnt_sig_bits);
+ vstring_sprintf_append(state->buffer, " (%d bit%s)",
+ state->tls_context->clnt_sig_bits,
+ state->tls_context->ctos_rpk ?
+ " raw public key" : "s");
if (state->tls_context->clnt_sig_dgst
&& *state->tls_context->clnt_sig_dgst)
vstring_sprintf_append(state->buffer, " client-digest %s",
@@ -3546,6 +3565,11 @@ static void common_pre_message_handling(SMTPD_STATE *state,
"verified OK" : "not verified");
vstring_free(issuer_CN);
vstring_free(peer_CN);
+ } else if (TLS_RPK_IS_PRESENT(state->tls_context)) {
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "\t(Client RPK %s digest %s)",
+ var_smtpd_tls_fpt_dgst,
+ state->tls_context->peer_pkey_fprint);
} else if (var_smtpd_tls_ask_ccert)
out_fprintf(out_stream, REC_TYPE_NORM,
"\t(Client did not present a certificate)");
@@ -3648,6 +3672,8 @@ static void receive_data_message(SMTPD_STATE *state,
curr_rec_type = REC_TYPE_CONT;
if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf))
state->err |= CLEANUP_STAT_BARE_LF;
+ else if (IS_BARE_LF_NOTE_LOG(smtp_got_bare_lf))
+ state->notes |= SMTPD_NOTE_BARE_LF;
start = vstring_str(state->buffer);
len = VSTRING_LEN(state->buffer);
if (first) {
@@ -4168,6 +4194,8 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
}
if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf))
state->err |= CLEANUP_STAT_BARE_LF;
+ else if (IS_BARE_LF_NOTE_LOG(smtp_got_bare_lf))
+ state->notes |= SMTPD_NOTE_BARE_LF;
start = vstring_str(state->bdat_get_buffer);
len = VSTRING_LEN(state->bdat_get_buffer);
if (state->err == CLEANUP_STAT_OK) {
@@ -5231,6 +5259,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
stream = state->client,
fd = -1,
timeout = var_smtpd_starttls_tmout,
+ enable_rpk = var_smtpd_tls_enable_rpk,
requirecert = requirecert,
serverid = state->service,
namaddr = state->namaddr,
@@ -5469,8 +5498,6 @@ static void tls_reset(SMTPD_STATE *state)
#endif
-#if !defined(USE_TLS) || !defined(USE_SASL_AUTH)
-
/* unimpl_cmd - dummy for functionality that is not compiled in */
static int unimpl_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
@@ -5487,8 +5514,6 @@ static int unimpl_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
return (-1);
}
-#endif
-
/*
* The table of all SMTP commands that we know. Set the junk limit flag on
* any command that can be repeated an arbitrary number of times without
@@ -5513,6 +5538,8 @@ typedef struct SMTPD_CMD {
#define SMTPD_CMD_FLAG_PRE_TLS (1<<1) /* allow before STARTTLS */
#define SMTPD_CMD_FLAG_LAST (1<<2) /* last in PIPELINING command group */
+static int help_cmd(SMTPD_STATE *, int, SMTPD_TOKEN *);
+
static SMTPD_CMD smtpd_cmd_table[] = {
{SMTPD_CMD_HELO, helo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS | SMTPD_CMD_FLAG_LAST,},
{SMTPD_CMD_EHLO, ehlo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS | SMTPD_CMD_FLAG_LAST,},
@@ -5537,12 +5564,44 @@ static SMTPD_CMD smtpd_cmd_table[] = {
{SMTPD_CMD_VRFY, vrfy_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_LAST,},
{SMTPD_CMD_ETRN, etrn_cmd, SMTPD_CMD_FLAG_LIMIT,},
{SMTPD_CMD_QUIT, quit_cmd, SMTPD_CMD_FLAG_PRE_TLS,},
+ {SMTPD_CMD_HELP, help_cmd, SMTPD_CMD_FLAG_PRE_TLS,},
{0,},
};
static STRING_LIST *smtpd_noop_cmds;
static STRING_LIST *smtpd_forbid_cmds;
+/* help_cmd - process HELP command */
+
+static int help_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_argv)
+{
+ ARGV *argv = argv_alloc(sizeof(smtpd_cmd_table)
+ / sizeof(*smtpd_cmd_table));
+ VSTRING *buf = vstring_alloc(100);
+ SMTPD_CMD *cmdp;
+
+ /*
+ * Return a list of implemented commands.
+ *
+ * The HELP command does not suppress commands that can be dynamically
+ * disabled in the EHLO response or through access control. That would
+ * require refactoring the EHLO feature-suppression and per-feature
+ * access control, so that they can be reused (not duplicated) here.
+ *
+ * The HELP command does not provide information that makes Postfix easier
+ * to fingerprint, such as software name, version, or build information.
+ */
+ for (cmdp = smtpd_cmd_table; cmdp->name != 0; cmdp++)
+ if (cmdp->action != unimpl_cmd)
+ argv_add(argv, cmdp->name, ARGV_END);
+ argv_sort(argv);
+ smtpd_chat_reply(state, "214 2.0.0 Commands: %s",
+ argv_join(buf, argv, ' '));
+ vstring_free(buf);
+ argv_free(argv);
+ return (0);
+}
+
/* smtpd_flag_ill_pipelining - flag pipelining protocol violation */
static int smtpd_flag_ill_pipelining(SMTPD_STATE *state)
@@ -5869,9 +5928,11 @@ static void smtpd_proto(SMTPD_STATE *state)
var_smtpd_forbid_bare_lf_code, var_myhostname);
break;
}
+ if (IS_BARE_LF_NOTE_LOG(smtp_got_bare_lf))
+ state->notes |= SMTPD_NOTE_BARE_LF;
/* Safety: protect internal interfaces against malformed UTF-8. */
- if (var_smtputf8_enable && valid_utf8_string(STR(state->buffer),
- LEN(state->buffer)) == 0) {
+ if (var_smtputf8_enable
+ && valid_utf8_stringz(STR(state->buffer)) == 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "500 5.5.2 Error: bad UTF-8 syntax");
state->error_count++;
@@ -6055,11 +6116,12 @@ static void smtpd_proto(SMTPD_STATE *state)
/* smtpd_format_cmd_stats - format per-command statistics */
-static char *smtpd_format_cmd_stats(VSTRING *buf)
+static char *smtpd_format_cmd_stats(SMTPD_STATE *state)
{
SMTPD_CMD *cmdp;
int all_success = 0;
int all_total = 0;
+ VSTRING *buf = state->buffer;
/*
* Log the statistics. Note that this loop produces no output when no
@@ -6103,6 +6165,13 @@ static char *smtpd_format_cmd_stats(VSTRING *buf)
vstring_sprintf_append(buf, " commands=%d", all_success);
if (all_success != all_total || all_total == 0)
vstring_sprintf_append(buf, "/%d", all_total);
+
+ /*
+ * Log aggregated warnings.
+ */
+ if (state->notes & SMTPD_NOTE_BARE_LF)
+ vstring_sprintf_append(buf, " notes=bare_lf");
+
return (lowercase(STR(buf)));
}
@@ -6244,7 +6313,7 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
* connection time.
*/
msg_info("disconnect from %s%s", state.namaddr,
- smtpd_format_cmd_stats(state.buffer));
+ smtpd_format_cmd_stats(&state));
teardown_milters(&state); /* duplicates xclient_cmd */
smtpd_state_reset(&state);
debug_peer_restore();
@@ -6403,7 +6472,6 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
no_server_cert_ok = 0;
cert_file = var_smtpd_tls_cert_file;
}
-
have_server_cert = *cert_file != 0;
have_server_cert |= *var_smtpd_tls_eccert_file != 0;
have_server_cert |= *var_smtpd_tls_dcert_file != 0;
@@ -6653,6 +6721,7 @@ int main(int argc, char **argv)
#ifdef USE_TLS
VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
+ VAR_SMTPD_TLS_ENABLE_RPK, DEF_SMTPD_TLS_ENABLE_RPK, &var_smtpd_tls_enable_rpk,
VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header,
VAR_SMTPD_TLS_SET_SESSID, DEF_SMTPD_TLS_SET_SESSID, &var_smtpd_tls_set_sessid,
#endif
diff --git a/src/smtpd/smtpd.h b/src/smtpd/smtpd.h
index 56ebc07..c049194 100644
--- a/src/smtpd/smtpd.h
+++ b/src/smtpd/smtpd.h
@@ -114,6 +114,7 @@ typedef struct {
int junk_cmds; /* counter */
int rcpt_overshoot; /* counter */
char *rewrite_context; /* address rewriting context */
+ int notes; /* notes aggregator */
/*
* SASL specific.
@@ -209,6 +210,8 @@ typedef struct {
#define SMTPD_FLAG_SMTPUTF8 (1<<3) /* RFC 6531/2 transaction */
#define SMTPD_FLAG_NEED_MILTER_ABORT (1<<4) /* undo milter_mail_event() */
+#define SMTPD_NOTE_BARE_LF (1<<0) /* saw at least one bare LF */
+
/* Security: don't reset SMTPD_FLAG_AUTH_USED. */
#define SMTPD_MASK_MAIL_KEEP \
~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */
@@ -260,6 +263,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
#define SMTPD_CMD_XCLIENT "XCLIENT"
#define SMTPD_CMD_XFORWARD "XFORWARD"
#define SMTPD_CMD_UNKNOWN "UNKNOWN"
+#define SMTPD_CMD_HELP "HELP"
/*
* Representation of unknown and non-existent client information. Throughout
diff --git a/src/smtpd/smtpd_check.c b/src/smtpd/smtpd_check.c
index 093aa06..6aeda74 100644
--- a/src/smtpd/smtpd_check.c
+++ b/src/smtpd/smtpd_check.c
@@ -1598,6 +1598,7 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
{
#ifdef USE_TLS
+ const char *myname = "permit_tls_clientcerts";
const char *found = 0;
if (!state->tls_context)
@@ -1612,9 +1613,9 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
/*
* When directly checking the fingerprint, it is OK if the issuing CA is
- * not trusted.
+ * not trusted. Raw public keys are also acceptable.
*/
- if (TLS_CERT_IS_PRESENT(state->tls_context)) {
+ if (TLS_CRED_IS_PRESENT(state->tls_context)) {
int i;
char *prints[2];
@@ -1623,12 +1624,24 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
VAR_SMTPD_TLS_FPT_DGST "=md5 to compute certificate "
"fingerprints");
- prints[0] = state->tls_context->peer_cert_fprint;
- prints[1] = state->tls_context->peer_pkey_fprint;
+ prints[0] = state->tls_context->peer_pkey_fprint;
+ prints[1] = state->tls_context->peer_cert_fprint;
/* After lookup error, leave relay_ccerts->error at non-zero value. */
for (i = 0; i < 2; ++i) {
+ /* With RFC7250 RPK, no certificate may be available */
+ if (!*prints[i])
+ continue;
found = maps_find(relay_ccerts, prints[i], DICT_FLAG_NONE);
+ if (var_smtpd_tls_enable_rpk && i > 0 && found) {
+ msg_warn("%s: %s: %s: Fragile access policy: %s=yes, but"
+ " public key fingerprint \"%s\" not matched, while"
+ " certificate fingerprint \"%s\" matched",
+ myname, state->namaddr, relay_ccerts->title,
+ VAR_SMTPD_TLS_ENABLE_RPK,
+ state->tls_context->peer_cert_fprint,
+ state->tls_context->peer_pkey_fprint);
+ }
if (found != 0) {
if (msg_verbose)
msg_info("Relaying allowed for certified client: %s", found);
@@ -1659,44 +1672,16 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
{
const char *myname = "check_relay_domains";
-#if 1
- static int once;
-
- if (once == 0) {
- once = 1;
- msg_warn("support for restriction \"%s\" will be removed from %s; "
- "use \"%s\" instead",
- CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST);
- }
-#endif
-
- if (msg_verbose)
- msg_info("%s: %s", myname, recipient);
-
/*
- * Permit if the client matches the relay_domains list.
+ * Restriction check_relay_domains is deprecated as of Postfix 2.2.
*/
- if (domain_list_match(relay_domains, state->name)) {
- if (warn_compat_break_relay_domains)
- msg_info("using backwards-compatible default setting "
- VAR_RELAY_DOMAINS "=$mydestination to permit "
- "request from client \"%s\"", state->name);
- return (SMTPD_CHECK_OK);
- }
-
- /*
- * Permit authorized destinations.
- */
- if (permit_auth_destination(state, recipient) == SMTPD_CHECK_OK)
- return (SMTPD_CHECK_OK);
+ if (msg_verbose)
+ msg_info("%s: %s", myname, recipient);
- /*
- * Deny relaying between sites that both are not in relay_domains.
- */
- return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
- var_relay_code, "5.7.1",
- "<%s>: %s rejected: Relay access denied",
- reply_name, reply_class));
+ msg_warn("support for restriction \"%s\" has been removed in %s 3.9; "
+ "instead, specify \"%s\"",
+ CHECK_RELAY_DOMAINS, var_mail_name, REJECT_UNAUTH_DEST);
+ reject_server_error(state);
}
/* permit_auth_destination - OK for message relaying */
@@ -2002,11 +1987,22 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient,
DNS_RR *middle;
DNS_RR *rest;
int dns_status;
+ static int once;
if (msg_verbose)
msg_info("%s: %s", myname, recipient);
/*
+ * Restriction permit_mx_backup is deprecated as of Postfix 3.9.
+ */
+ if (once == 0) {
+ once = 1;
+ msg_warn("support for restriction \"%s\" will be removed from %s; "
+ "instead, specify \"%s\"",
+ PERMIT_MX_BACKUP, var_mail_name, VAR_RELAY_DOMAINS);
+ }
+
+ /*
* Resolve the address.
*/
reply = smtpd_resolve_addr(state->sender, recipient);
@@ -3185,6 +3181,9 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
#ifdef USE_TLS
const char *myname = "check_ccert_access";
+ int cert_result = SMTPD_CHECK_DUNNO;
+ int pkey_result = SMTPD_CHECK_DUNNO;
+ int *respt;
int found;
const MAP_SEARCH *acl;
const char default_search[] = {
@@ -3211,9 +3210,9 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
/*
* When directly checking the fingerprint, it is OK if the issuing CA is
- * not trusted.
+ * not trusted. Raw public keys are also acceptable.
*/
- if (TLS_CERT_IS_PRESENT(state->tls_context)) {
+ if (TLS_CRED_IS_PRESENT(state->tls_context)) {
const char *action;
const char *match_this;
const char *known_action;
@@ -3222,17 +3221,19 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
switch (*action) {
case SMTPD_ACL_SEARCH_CODE_CERT_FPRINT:
match_this = state->tls_context->peer_cert_fprint;
- if (warn_compat_break_smtpd_tls_fpt_dgst)
+ if (*match_this && warn_compat_break_smtpd_tls_fpt_dgst)
msg_info("using backwards-compatible default setting "
VAR_SMTPD_TLS_FPT_DGST "=md5 to compute "
"certificate fingerprints");
+ respt = &cert_result;
break;
case SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT:
match_this = state->tls_context->peer_pkey_fprint;
- if (warn_compat_break_smtpd_tls_fpt_dgst)
+ if (*match_this && warn_compat_break_smtpd_tls_fpt_dgst)
msg_info("using backwards-compatible default setting "
VAR_SMTPD_TLS_FPT_DGST "=md5 to compute "
- "certificate fingerprints");
+ "public key fingerprints");
+ respt = &pkey_result;
break;
default:
known_action = str_name_code(search_actions, *action);
@@ -3245,6 +3246,9 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
451, "4.3.5",
"Server configuration error"));
}
+ /* With RFC7250 RPK, no certificate may be available */
+ if (!*match_this)
+ continue;
if (msg_verbose)
msg_info("%s: look up %s %s",
myname, str_name_code(search_actions, *action),
@@ -3257,11 +3261,16 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
* "reject" event. XXX Should log the thing that is rejected
* (fingerprint etc.) or would that give away too much?
*/
- result = check_access(state, acl->map_type_name, match_this,
+ *respt = check_access(state, acl->map_type_name, match_this,
DICT_FLAG_NONE, &found,
state->tls_context->peer_CN,
SMTPD_NAME_CCERT, def_acl);
- if (result != SMTPD_CHECK_DUNNO)
+ if (*respt == SMTPD_CHECK_DUNNO)
+ continue;
+ if (result == SMTPD_CHECK_DUNNO)
+ result = *respt;
+ if (!var_smtpd_tls_enable_rpk
+ || *action == SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT)
break;
}
} else if (!var_smtpd_tls_ask_ccert) {
@@ -3271,6 +3280,17 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
if (msg_verbose)
msg_info("%s: no client certificate", myname);
}
+ if (var_smtpd_tls_enable_rpk
+ && cert_result != SMTPD_CHECK_DUNNO
+ && cert_result != pkey_result) {
+ msg_warn("%s: %s: %s: Fragile access policy: %s=yes, but"
+ " the action for certificate fingerprint \"%s\" !="
+ " the action for public key fingerprint \"%s\"",
+ myname, state->namaddr, acl->map_type_name,
+ VAR_SMTPD_TLS_ENABLE_RPK,
+ state->tls_context->peer_cert_fprint,
+ state->tls_context->peer_pkey_fprint);
+ }
#endif
return (result);
}
@@ -3877,34 +3897,18 @@ static int permit_dnswl_domain(SMTPD_STATE *state, const char *dnswl_domain,
static int reject_maps_rbl(SMTPD_STATE *state)
{
const char *myname = "reject_maps_rbl";
- char *saved_domains = mystrdup(var_maps_rbl_domains);
- char *bp = saved_domains;
- char *rbl_domain;
- int result = SMTPD_CHECK_DUNNO;
- static int warned;
if (msg_verbose)
msg_info("%s: %s", myname, state->addr);
- if (warned == 0) {
- warned++;
- msg_warn("support for restriction \"%s\" will be removed from %s; "
- "use \"%s domain-name\" instead",
- REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
- }
- while ((rbl_domain = mystrtok(&bp, CHARS_COMMA_SP)) != 0) {
- result = reject_rbl_addr(state, rbl_domain, state->addr,
- SMTPD_NAME_CLIENT);
- if (result != SMTPD_CHECK_DUNNO)
- break;
- }
-
/*
- * Clean up.
+ * Restriction reject_maps_rbl is deprecated as of Postfix 2.1.
*/
- myfree(saved_domains);
+ msg_warn("support for restriction \"%s\" has been removed in %s 3.9; "
+ "instead, specify \"%s domain-name\"",
+ REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
- return (result);
+ reject_server_error(state);
}
#ifdef USE_SASL_AUTH
@@ -3980,7 +3984,7 @@ static int valid_utf8_action(const char *server, const char *action)
{
int retval;
- if ((retval = valid_utf8_string(action, strlen(action))) == 0)
+ if ((retval = valid_utf8_stringz(action)) == 0)
msg_warn("malformed UTF-8 in policy server %s response: \"%s\"",
server, action);
return (retval);
@@ -4035,6 +4039,8 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
ENCODE_CN(subject, subject_buf, state->tls_context->peer_CN);
ENCODE_CN(issuer, issuer_buf, state->tls_context->issuer_CN);
+#define NONEMPTY(x) ((x) != 0 && (*x) != 0)
+
/*
* XXX: Too noisy to warn for each policy lookup, especially because we
* don't even know whether the policy server will use the fingerprint. So
@@ -4044,12 +4050,12 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
if (!warned
&& warn_compat_break_smtpd_tls_fpt_dgst
&& state->tls_context
- && state->tls_context->peer_cert_fprint
- && *state->tls_context->peer_cert_fprint) {
+ && (NONEMPTY(state->tls_context->peer_cert_fprint)
+ || NONEMPTY(state->tls_context->peer_pkey_fprint))) {
warned = 1;
msg_info("using backwards-compatible default setting "
VAR_SMTPD_TLS_FPT_DGST "=md5 to compute certificate "
- "fingerprints");
+ "and public key fingerprints");
}
#endif
@@ -4480,15 +4486,12 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
state->helo_name, SMTPD_NAME_HELO);
}
} else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
- msg_warn("restriction %s is deprecated. Use %s or %s instead",
- PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS, PERMIT_SASL_AUTH);
- if (state->helo_name) {
- if (state->helo_name[strspn(state->helo_name, "0123456789.:")] == 0
- && (status = reject_invalid_hostaddr(state, state->helo_name,
- state->helo_name, SMTPD_NAME_HELO)) == 0)
- status = smtpd_acl_permit(state, name, SMTPD_NAME_HELO,
- state->helo_name, NO_PRINT_ARGS);
- }
+ /* permit_naked_ip_addr is deprecated as of Postfix 2.0. */
+ msg_warn("support for restriction \"%s\" has been removed in %s"
+ " 3.9; instead, specify \"%s\" or \"%s\"",
+ PERMIT_NAKED_IP_ADDR, var_mail_name,
+ PERMIT_MYNETWORKS, PERMIT_SASL_AUTH);
+ reject_server_error(state);
} else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
if (state->helo_name) {
status = check_server_access(state, *cpp, state->helo_name,
@@ -5255,8 +5258,9 @@ static int check_recipient_rcpt_maps(SMTPD_STATE *state, const char *recipient)
{
/*
- * Duplicate suppression. There's an implicit check_recipient_maps
- * restriction at the end of all recipient restrictions.
+ * Duplicate suppression. With "smtpd_reject_unlisted_recipient = yes",
+ * there's an implicit reject_unlisted_recipient restriction at the end
+ * of all recipient restrictions.
*/
if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT)
return (0);
@@ -5275,8 +5279,9 @@ static int check_sender_rcpt_maps(SMTPD_STATE *state, const char *sender)
{
/*
- * Duplicate suppression. There's an implicit check_sender_maps
- * restriction at the end of all sender restrictions.
+ * Duplicate suppression. With "smtpd_reject_unlisted_sender = yes",
+ * there's an implicit reject_unlisted_sender restriction at the end of
+ * all sender restrictions.
*/
if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT)
return (0);
@@ -5832,6 +5837,7 @@ char *var_smtpd_dns_re_filter;
bool var_smtpd_tls_ask_ccert;
int var_smtpd_cipv4_prefix;
int var_smtpd_cipv6_prefix;
+bool var_smtpd_tls_enable_rpk;
#define int_table test_int_table
@@ -5869,6 +5875,7 @@ static const INT_TABLE int_table[] = {
VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
VAR_SMTPD_CIPV4_PREFIX, DEF_SMTPD_CIPV4_PREFIX, &var_smtpd_cipv4_prefix,
VAR_SMTPD_CIPV6_PREFIX, DEF_SMTPD_CIPV6_PREFIX, &var_smtpd_cipv6_prefix,
+ VAR_SMTPD_TLS_ENABLE_RPK, DEF_SMTPD_TLS_ENABLE_RPK, &var_smtpd_tls_enable_rpk,
0,
};
@@ -6406,7 +6413,7 @@ int main(int argc, char **argv)
state.tls_context->peer_cert_fprint =
state.tls_context->peer_pkey_fprint = 0;
}
- state.tls_context->peer_status |= TLS_CERT_FLAG_PRESENT;
+ state.tls_context->peer_status |= TLS_CRED_FLAG_CERT;
UPDATE_STRING(state.tls_context->peer_cert_fprint,
args->argv[1]);
state.tls_context->peer_pkey_fprint =
diff --git a/src/smtpd/smtpd_check_backup.ref b/src/smtpd/smtpd_check_backup.ref
index 8f4a0f2..c15be35 100644
--- a/src/smtpd/smtpd_check_backup.ref
+++ b/src/smtpd/smtpd_check_backup.ref
@@ -17,6 +17,7 @@ OK
>>> recipient_restrictions permit_mx_backup,reject
OK
>>> rcpt wietse@wzv.porcupine.org
+./smtpd_check: warning: support for restriction "permit_mx_backup" will be removed from Postfix; instead, use "relay_domains"
OK
>>> rcpt wietse@backup.porcupine.org
OK
diff --git a/src/smtpd/smtpd_deprecated.in b/src/smtpd/smtpd_deprecated.in
new file mode 100644
index 0000000..345ee71
--- /dev/null
+++ b/src/smtpd/smtpd_deprecated.in
@@ -0,0 +1,20 @@
+#
+# permit_naked_ip_address
+#
+client foo 127.0.0.2
+recipient_restrictions permit_naked_ip_address
+helo 127.0.0.2
+mail sname@sdomain.example
+rcpt rname@rdomain.example
+#
+# check_relay_domains
+#
+client foo 127.0.0.2
+recipient_restrictions check_relay_domains
+relay_domains foo
+helo 127.0.0.2
+mail sname@sdomain.example
+rcpt rname@rdomain.example
+#
+# reject_maps_rbl is already covered elsewhere.
+#
diff --git a/src/smtpd/smtpd_deprecated.ref b/src/smtpd/smtpd_deprecated.ref
new file mode 100644
index 0000000..d64f1b3
--- /dev/null
+++ b/src/smtpd/smtpd_deprecated.ref
@@ -0,0 +1,35 @@
+>>> #
+>>> # permit_naked_ip_address
+>>> #
+>>> client foo 127.0.0.2
+OK
+>>> recipient_restrictions permit_naked_ip_address
+OK
+>>> helo 127.0.0.2
+OK
+>>> mail sname@sdomain.example
+OK
+>>> rcpt rname@rdomain.example
+./smtpd_check: warning: restriction permit_naked_ip_address has been removed in Postfix 3.9; use permit_mynetworks or permit_sasl_authenticated instead
+./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 451 4.3.5 Server configuration error; from=<sname@sdomain.example> to=<rname@rdomain.example> proto=SMTP helo=<127.0.0.2>
+451 4.3.5 Server configuration error
+>>> #
+>>> # check_relay_domains
+>>> #
+>>> client foo 127.0.0.2
+OK
+>>> recipient_restrictions check_relay_domains
+OK
+>>> relay_domains foo
+OK
+>>> helo 127.0.0.2
+OK
+>>> mail sname@sdomain.example
+OK
+>>> rcpt rname@rdomain.example
+./smtpd_check: warning: support for restriction "check_relay_domains" has been removed in Postfix 3.9; use "reject_unauth_destination" instead
+./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 451 4.3.5 Server configuration error; from=<sname@sdomain.example> to=<rname@rdomain.example> proto=SMTP helo=<127.0.0.2>
+451 4.3.5 Server configuration error
+>>> #
+>>> # reject_maps_rbl is already covered elsewhere.
+>>> #
diff --git a/src/smtpd/smtpd_exp.ref b/src/smtpd/smtpd_exp.ref
index 22c027e..00848a5 100644
--- a/src/smtpd/smtpd_exp.ref
+++ b/src/smtpd/smtpd_exp.ref
@@ -25,13 +25,15 @@ OK
>>> client spike.porcupine.org 168.100.3.2
OK
>>> rcpt rname@rdomain
-./smtpd_check: warning: support for restriction "reject_maps_rbl" will be removed from Postfix; use "reject_rbl_client domain-name" instead
-OK
+./smtpd_check: warning: support for restriction "reject_maps_rbl" has been removed in Postfix 3.9; use "reject_rbl_client domain-name" instead
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.3.2]: 451 4.3.5 Server configuration error; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<foobar>
+451 4.3.5 Server configuration error
>>> client foo 127.0.0.2
OK
>>> rcpt rname@rdomain
-./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 554 5.7.1 Service unavailable; Client host [127.0.0.2] blocked using dnsbltest.porcupine.org; DNS blocklist test; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<foobar>
-554 5.7.1 Service unavailable; Client host [127.0.0.2] blocked using dnsbltest.porcupine.org; DNS blocklist test
+./smtpd_check: warning: support for restriction "reject_maps_rbl" has been removed in Postfix 3.9; use "reject_rbl_client domain-name" instead
+./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 451 4.3.5 Server configuration error; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<foobar>
+451 4.3.5 Server configuration error
>>> #
>>> recipient_restrictions reject_rbl_client,dnsbltest.porcupine.org
OK
diff --git a/src/smtpd/smtpd_sasl_glue.c b/src/smtpd/smtpd_sasl_glue.c
index d9db7b0..1163366 100644
--- a/src/smtpd/smtpd_sasl_glue.c
+++ b/src/smtpd/smtpd_sasl_glue.c
@@ -120,6 +120,10 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
/*--*/
/* System library. */
diff --git a/src/smtpd/smtpd_state.c b/src/smtpd/smtpd_state.c
index f2f5f89..fefc543 100644
--- a/src/smtpd/smtpd_state.c
+++ b/src/smtpd/smtpd_state.c
@@ -135,6 +135,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
state->instance = vstring_alloc(10);
state->seqno = 0;
state->rewrite_context = 0;
+ state->notes = 0;
#if 0
state->ehlo_discard_mask = ~0;
#else
diff --git a/src/smtpstone/smtp-source.c b/src/smtpstone/smtp-source.c
index be388d6..f9fa64f 100644
--- a/src/smtpstone/smtp-source.c
+++ b/src/smtpstone/smtp-source.c
@@ -42,7 +42,7 @@
/* Don't disconnect after sending a message; send the next
/* message over the same connection.
/* .IP "\fB-f \fIfrom\fR"
-/* Use the specified sender address (default: <foo@myhostname>).
+/* Use the specified sender address (default: <foo@my-hostname>).
/* .IP "\fB-F \fIfile\fR"
/* Send the pre-formatted message header and body in the
/* specified \fIfile\fR, while prepending '.' before lines that
@@ -54,31 +54,49 @@
/* Speak LMTP rather than SMTP.
/* .IP "\fB-m \fImessage_count\fR"
/* Send the specified number of messages (default: 1).
-/* .IP "\fB-M \fImyhostname\fR"
+/* .IP "\fB-M \fImy-hostname\fR"
/* Use the specified hostname or [address] in the HELO command
/* and in the default sender and recipient addresses, instead
/* of the machine hostname.
/* .IP "\fB-N\fR"
-/* Prepend a non-repeating sequence number to each recipient
-/* address. This avoids the artificial 100% hit rate in the
-/* resolve and rewrite client caches and exercises the
-/* trivial-rewrite daemon, better approximating Postfix
-/* performance under real-life work-loads.
+/* Generate each recipient address by appending a number (a
+/* per-process recipient counter) to the recipient address
+/* localpart specified with the \fB-t\fR option.
+/*
+/* Note: to use the number as an address extension, specify
+/* an explicit address delimiter at the end of the recipient
+/* localpart, as in "\fB-t localpart+@domain\fR" or "\fB-t
+/* localpart+\fR", where "\fB+\fR" is a Postfix recipient
+/* address delimiter.
+/*
+/* Benefits:
+/* .RS
+/* .IP \(bu
+/* A non-constant recipient address avoids an unrealistic 100%
+/* cache hit rate in clients of the Postfix trivial-rewrite
+/* service, better approximating performance under real-life
+/* work-loads.
+/* .IP \(bu
+/* A fixed recipient address local-part with a non-constant
+/* address extension avoids the need to configure a large
+/* number of valid recipient addresses in the receiving Postfix
+/* server.
+/* .RE
/* .IP \fB-o\fR
/* Old mode: don't send HELO, and don't send message headers.
/* .IP "\fB-r \fIrecipient_count\fR"
-/* Send the specified number of recipients per transaction (default: 1).
-/* Recipient names are generated by prepending a number to the
-/* recipient address.
+/* Send the specified number of recipients per transaction
+/* (default: 1), and generate recipient addresses as described
+/* under the \fB-N\fR option.
/* .IP "\fB-R \fIinterval\fR"
-/* Wait for a random period of time 0 <= n <= interval between messages.
+/* Wait a random time (0 <= n <= \fIinterval\fR) between messages.
/* Suspending one thread does not affect other delivery threads.
/* .IP "\fB-s \fIsession_count\fR"
/* Run the specified number of SMTP sessions in parallel (default: 1).
/* .IP "\fB-S \fIsubject\fR"
/* Send mail with the named subject line (default: none).
/* .IP "\fB-t \fIto\fR"
-/* Use the specified recipient address (default: <foo@myhostname>).
+/* Use the specified recipient address (default: <foo@my-hostname>).
/* .IP "\fB-T \fIwindowsize\fR"
/* Override the default TCP window size. To work around
/* broken TCP window scaling implementations, specify a
@@ -172,6 +190,7 @@ typedef struct SESSION {
int rcpt_done; /* # of recipients done */
int rcpt_count; /* # of recipients to go */
int rcpt_accepted; /* # of recipients accepted */
+ int rcpt_sample; /* Sample recipient # for To: header */
VSTREAM *stream; /* open connection */
int connect_count; /* # of connect()s to retry */
struct SESSION *next; /* connect() queue linkage */
@@ -202,7 +221,11 @@ static struct sockaddr *sa;
static int sa_length;
static int recipients = 1;
static char *defaddr;
-static char *recipient;
+typedef struct {
+ char *local;
+ char *at_domain;
+} RECIPIENT;
+static RECIPIENT *recipient;
static char *sender;
static char *message_data;
static int message_length;
@@ -216,7 +239,8 @@ static int random_delay = 0;
static int fixed_delay = 0;
static int talk_lmtp = 0;
static char *subject = 0;
-static int number_rcpts = 0;
+static int global_rcpt_suffix = 0;
+static int global_rcpt_done = 0;
static int allow_reject = 0;
static void enqueue_connect(SESSION *);
@@ -238,6 +262,20 @@ static void send_quit(SESSION *);
static void quit_done(int, void *);
static void close_session(SESSION *);
+/* make_recipient - parse recipient into localpart and at_domain */
+
+static RECIPIENT *make_recipient(const char *address)
+{
+ RECIPIENT *rp = (RECIPIENT *) mymalloc(sizeof(*rp));
+ const char *at;
+
+ if ((at = strrchr(address, '@')) == 0)
+ at = address + strlen(address);
+ rp->local = mystrndup(address, at - address);
+ rp->at_domain = mystrdup(at);
+ return (rp);
+}
+
/* random_interval - generate a random value in 0 .. (small) interval */
static int random_interval(int interval)
@@ -655,12 +693,13 @@ static void send_rcpt(int unused_event, void *context)
if ((except = vstream_setjmp(session->stream)) != 0)
msg_fatal("%s while sending recipient", exception_text(except));
- if (session->rcpt_count > 1 || number_rcpts > 0)
- command(session->stream, "RCPT TO:<%d%s>",
- number_rcpts ? number_rcpts++ : session->rcpt_count,
- recipient);
+ if (global_rcpt_suffix)
+ command(session->stream, "RCPT TO:<%s%d%s>",
+ recipient->local, session->rcpt_sample = global_rcpt_done++,
+ recipient->at_domain);
else
- command(session->stream, "RCPT TO:<%s>", recipient);
+ command(session->stream, "RCPT TO:<%s%s>",
+ recipient->local, recipient->at_domain);
session->rcpt_count--;
session->rcpt_done++;
@@ -765,10 +804,16 @@ static void data_done(int unused, void *context)
mypid = getpid();
}
smtp_printf(session->stream, "From: <%s>", sender);
- smtp_printf(session->stream, "To: <%s>", recipient);
+ if (global_rcpt_suffix)
+ smtp_printf(session->stream, "To: <%s%d%s>", recipient->local,
+ session->rcpt_sample, recipient->at_domain);
+ else
+ smtp_printf(session->stream, "To: <%s%s>",
+ recipient->local, recipient->at_domain);
smtp_printf(session->stream, "Date: %s", mydate);
smtp_printf(session->stream, "Message-Id: <%04x.%04x.%04x@%s>",
- mypid, vstream_fileno(session->stream), message_count, var_myhostname);
+ mypid, vstream_fileno(session->stream), message_count,
+ var_myhostname);
if (subject)
smtp_printf(session->stream, "Subject: %s", subject);
smtp_fputs("", 0, session->stream);
@@ -1021,7 +1066,7 @@ int main(int argc, char **argv)
var_myhostname = optarg;
break;
case 'N':
- number_rcpts = 1;
+ global_rcpt_suffix = 1;
break;
case 'o':
send_helo_first = 0;
@@ -1030,6 +1075,7 @@ int main(int argc, char **argv)
case 'r':
if ((recipients = atoi(optarg)) <= 0)
msg_fatal("bad recipient count: %s", optarg);
+ global_rcpt_suffix = 1;
break;
case 'R':
if (fixed_delay > 0)
@@ -1045,7 +1091,7 @@ int main(int argc, char **argv)
subject = optarg;
break;
case 't':
- recipient = optarg;
+ recipient = make_recipient(optarg);
break;
case 'T':
if ((inet_windowsize = atoi(optarg)) <= 0)
@@ -1160,7 +1206,7 @@ int main(int argc, char **argv)
if (sender == 0)
sender = defaddr;
if (recipient == 0)
- recipient = defaddr;
+ recipient = make_recipient(defaddr);
}
/*
diff --git a/src/tls/tls.h b/src/tls/tls.h
index 73eebae..3ec41ba 100644
--- a/src/tls/tls.h
+++ b/src/tls/tls.h
@@ -78,6 +78,7 @@ extern const char *str_tls_level(int);
#include <openssl/opensslv.h> /* OPENSSL_VERSION_NUMBER */
#include <openssl/ssl.h>
#include <openssl/conf.h>
+#include <openssl/tls1.h> /* TLS extensions */
/* Appease indent(1) */
#define x509_stack_t STACK_OF(X509)
@@ -203,8 +204,8 @@ extern void tls_dane_flush(void);
extern TLS_DANE *tls_dane_alloc(void);
extern void tls_tlsa_free(TLS_TLSA *);
extern void tls_dane_free(TLS_DANE *);
-extern void tls_dane_add_fpt_digests(TLS_DANE *, const char *, const char *,
- int);
+extern void tls_dane_add_fpt_digests(TLS_DANE *, int, const char *,
+ const char *, int);
extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int);
extern int tls_dane_load_trustfile(TLS_DANE *, const char *);
@@ -232,6 +233,8 @@ typedef struct {
const char *kex_name; /* shared key-exchange algorithm */
const char *kex_curve; /* shared key-exchange ECDHE curve */
int kex_bits; /* shared FFDHE key exchange bits */
+ int ctos_rpk; /* Did the client send an RPK? */
+ int stoc_rpk; /* Did the server send an RPK? */
const char *clnt_sig_name; /* client's signature key algorithm */
const char *clnt_sig_curve; /* client's ECDSA curve name */
int clnt_sig_bits; /* client's RSA signature key bits */
@@ -264,13 +267,17 @@ typedef struct {
* Peer status bits. TLS_CERT_FLAG_MATCHED implies TLS_CERT_FLAG_TRUSTED
* only in the case of a hostname match.
*/
-#define TLS_CERT_FLAG_PRESENT (1<<0)
+#define TLS_CRED_FLAG_CERT (1<<0)
#define TLS_CERT_FLAG_ALTNAME (1<<1)
#define TLS_CERT_FLAG_TRUSTED (1<<2)
#define TLS_CERT_FLAG_MATCHED (1<<3)
#define TLS_CERT_FLAG_SECURED (1<<4)
+#define TLS_CRED_FLAG_RPK (1<<5)
+#define TLS_CRED_FLAG_ANY (TLS_CRED_FLAG_CERT|TLS_CRED_FLAG_RPK)
-#define TLS_CERT_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_PRESENT))
+#define TLS_CRED_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CRED_FLAG_ANY))
+#define TLS_CERT_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CRED_FLAG_CERT))
+#define TLS_RPK_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CRED_FLAG_RPK))
#define TLS_CERT_IS_ALTNAME(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_ALTNAME))
#define TLS_CERT_IS_TRUSTED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_TRUSTED))
#define TLS_CERT_IS_MATCHED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_MATCHED))
@@ -472,6 +479,7 @@ typedef struct {
VSTREAM *stream;
int fd; /* Event-driven file descriptor */
int timeout;
+ int enable_rpk; /* Solicit server raw public keys */
int tls_level; /* Security level */
const char *nexthop; /* destination domain */
const char *host; /* MX hostname */
@@ -508,12 +516,12 @@ extern TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *,
a6, a7, a8, a9, a10, a11, a12, a13, a14))
#define TLS_CLIENT_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \
- a10, a11, a12, a13, a14, a15, a16, a17) \
+ a10, a11, a12, a13, a14, a15, a16, a17, a18) \
tls_client_start((((props)->a1), ((props)->a2), ((props)->a3), \
((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15), \
- ((props)->a16), ((props)->a17), (props)))
+ ((props)->a16), ((props)->a17), ((props)->a18), (props)))
/*
* tls_server.c
@@ -546,6 +554,7 @@ typedef struct {
VSTREAM *stream; /* Client stream */
int fd; /* Event-driven file descriptor */
int timeout; /* TLS handshake timeout */
+ int enable_rpk; /* Solicit client raw public keys */
int requirecert; /* Insist on client cert? */
const char *serverid; /* Server instance (salt cache key) */
const char *namaddr; /* Client nam[addr] for logging */
@@ -570,10 +579,12 @@ extern TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *);
((props)->a16), ((props)->a17), ((props)->a18), ((props)->a19), \
((props)->a20), (props)))
-#define TLS_SERVER_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+#define TLS_SERVER_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \
+ a10, a11) \
tls_server_start((((props)->a1), ((props)->a2), ((props)->a3), \
((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
- ((props)->a8), ((props)->a9), ((props)->a10), (props)))
+ ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
+ (props)))
/*
* tls_session.c
@@ -660,7 +671,7 @@ extern TLS_TLSA *tlsa_prepend(TLS_TLSA *, uint8_t, uint8_t, uint8_t,
extern const EVP_MD *tls_digest_byname(const char *, EVP_MD_CTX **);
extern char *tls_digest_encode(const unsigned char *, int);
extern char *tls_cert_fprint(X509 *, const char *);
-extern char *tls_pkey_fprint(X509 *, const char *);
+extern char *tls_pkey_fprint(EVP_PKEY *, const char *);
extern char *tls_serverid_digest(TLS_SESS_STATE *,
const TLS_CLIENT_START_PROPS *, const char *);
@@ -696,6 +707,8 @@ extern long tls_bio_dump_cb(BIO *, int, const char *, int, long, long);
#endif
extern const EVP_MD *tls_validate_digest(const char *);
+extern void tls_enable_client_rpk(SSL_CTX *, SSL *);
+extern void tls_enable_server_rpk(SSL_CTX *, SSL *);
/*
* tls_seed.c
diff --git a/src/tls/tls_client.c b/src/tls/tls_client.c
index e0dfe15..3eda859 100644
--- a/src/tls/tls_client.c
+++ b/src/tls/tls_client.c
@@ -86,8 +86,9 @@
/* available as:
/* .IP TLScontext->peer_status
/* A bitmask field that records the status of the peer certificate
-/* verification. This consists of one or more of TLS_CERT_FLAG_PRESENT,
-/* TLS_CERT_FLAG_TRUSTED, TLS_CERT_FLAG_MATCHED and TLS_CERT_FLAG_SECURED.
+/* verification. This consists of one or more of TLS_CRED_FLAG_CERT,
+/* TLS_CRED_FLAG_RPK, TLS_CERT_FLAG_TRUSTED, TLS_CERT_FLAG_MATCHED and
+/* TLS_CERT_FLAG_SECURED.
/* .IP TLScontext->peer_CN
/* Extracted CommonName of the peer, or zero-length string if the
/* information could not be extracted.
@@ -303,15 +304,11 @@ static void uncache_session(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext)
tls_mgr_delete(TLScontext->cache_type, TLScontext->serverid);
}
-/* verify_extract_name - verify peer name and extract peer information */
+/* verify_x509 - process X.509 certificate verification status */
-static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
- const TLS_CLIENT_START_PROPS *props)
+static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
+ const TLS_CLIENT_START_PROPS *props)
{
- int verbose;
-
- verbose = TLScontext->log_mask &
- (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT);
/*
* On exit both peer_CN and issuer_CN should be set.
@@ -345,7 +342,8 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
TLScontext->peer_status |= TLS_CERT_FLAG_MATCHED;
- if (verbose) {
+ if (TLScontext->log_mask &
+ (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) {
const char *peername = SSL_get0_peername(TLScontext->con);
if (peername)
@@ -367,6 +365,50 @@ static void verify_extract_name(TLS_SESS_STATE *TLScontext, X509 *peercert,
if (TLScontext->session_reused == 0)
tls_log_verify_error(TLScontext);
else
+ msg_info("%s: re-using session with untrusted peer credential, "
+ "look for details earlier in the log", props->namaddr);
+ }
+}
+
+/* verify_rpk - process RFC7250 raw public key verification status */
+
+static void verify_rpk(TLS_SESS_STATE *TLScontext, EVP_PKEY *peerpkey,
+ const TLS_CLIENT_START_PROPS *props)
+{
+ /* Was the raw public key (type of cert) matched? */
+ if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) {
+ TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
+ if (TLScontext->must_fail) {
+ msg_panic("%s: raw public key valid despite trust init failure",
+ TLScontext->namaddr);
+ } else if (TLS_MUST_MATCH(TLScontext->level)) {
+
+ /*
+ * Fully secured only if not insecure like half-dane. We use
+ * TLS_CERT_FLAG_MATCHED to satisfy policy, but
+ * TLS_CERT_FLAG_SECURED to log the effective security.
+ */
+ if (!TLS_NEVER_SECURED(TLScontext->level))
+ TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
+ TLScontext->peer_status |= TLS_CERT_FLAG_MATCHED;
+
+ if (TLScontext->log_mask &
+ (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
+ tls_dane_log(TLScontext);
+ }
+ }
+
+ /*
+ * Give them a clue. Problems with trust chain verification are logged
+ * when the session is first negotiated, before the session is stored
+ * into the cache. We don't want mystery failures, so log the fact the
+ * real problem is to be found in the past.
+ */
+ if (!TLS_CERT_IS_MATCHED(TLScontext)
+ && (TLScontext->log_mask & TLS_LOG_UNTRUSTED)) {
+ if (TLScontext->session_reused == 0)
+ tls_log_verify_error(TLScontext);
+ else
msg_info("%s: re-using session with untrusted certificate, "
"look for details earlier in the log", props->namaddr);
}
@@ -793,6 +835,30 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
}
/*
+ * Enable support for client->server raw public keys, provided we actually
+ * have keys to send. They'll only be used if the server also enables
+ * client RPKs.
+ *
+ * XXX: When the server requests client auth, the TLS 1.2 protocol does not
+ * provide an unambiguous mechanism for the client to not send an RPK (as
+ * it can with client X.509 certs or TLS 1.3). This is why we don't just
+ * enable client RPK also with no keys in hand.
+ *
+ * A very unlikely scenario is that the server allows clients to not send
+ * keys, but only accepts keys for a set of algorithms we don't have. Then
+ * we still can't send a key, but have agreed to RPK. OpenSSL will attempt
+ * to send an empty RPK even with TLS 1.2 (and will accept such a message),
+ * but other implementations may be more strict.
+ *
+ * We could limit client RPK support to connections that support only TLS
+ * 1.3 and up, but that's practical only decades in the future, and the
+ * risk scenario is contrived and very unlikely.
+ */
+ if (SSL_CTX_get0_certificate(client_ctx) != NULL &&
+ SSL_CTX_get0_privatekey(client_ctx) != NULL)
+ tls_enable_client_rpk(client_ctx, NULL);
+
+ /*
* With OpenSSL 1.0.2 and later the client EECDH curve list becomes
* configurable with the preferred curve negotiated via the supported
* curves extension. With OpenSSL 3.0 and TLS 1.3, the same applies
@@ -1008,6 +1074,24 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
}
/*
+ * Possibly enable RFC7250 raw public keys in non-DANE/non-PKI levels
+ * when the fingerprint mask includes only public keys. For "may" and
+ * "encrypt" this is a heuristic, since we don't use the fingerprints
+ * beyond reporting them in verbose logging. If you always want certs
+ * with "may" and "encrypt" you'll have to tolerate them with
+ * "fingerprint", or use a separate transport.
+ */
+ switch (props->tls_level) {
+ case TLS_LEV_MAY:
+ case TLS_LEV_ENCRYPT:
+ case TLS_LEV_FPRINT:
+ if (props->enable_rpk)
+ tls_enable_server_rpk(NULL, TLScontext->con);
+ default:
+ break;
+ }
+
+ /*
* Try to convey the configured TLSA records for this connection to the
* OpenSSL library. If none are "usable", we'll fall back to "encrypt"
* when authentication is not mandatory, otherwise we must arrange to
@@ -1175,6 +1259,7 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext,
{
const SSL_CIPHER *cipher;
X509 *peercert;
+ EVP_PKEY *peerpkey = 0;
/* Turn off packet dump if only dumping the handshake */
if ((TLScontext->log_mask & TLS_LOG_ALLPKTS) == 0)
@@ -1192,31 +1277,61 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext,
* Do peername verification if requested and extract useful information
* from the certificate for later use.
*/
- if ((peercert = TLS_PEEK_PEER_CERT(TLScontext->con)) != 0) {
- TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT;
+ peercert = TLS_PEEK_PEER_CERT(TLScontext->con);
+ if (peercert != 0) {
+ peerpkey = X509_get0_pubkey(peercert);
+ }
+#if OPENSSL_VERSION_PREREQ(3,2)
+ else {
+ peerpkey = SSL_get0_peer_rpk(TLScontext->con);
+ }
+#endif
+
+ if (peercert != 0) {
+ TLScontext->peer_status |= TLS_CRED_FLAG_CERT;
/*
* Peer name or fingerprint verification as requested.
* Unconditionally set peer_CN, issuer_CN and peer_cert_fprint. Check
* fingerprint first, and avoid logging verified as untrusted in the
- * call to verify_extract_name().
+ * call to verify_x509().
*/
- TLScontext->peer_cert_fprint = tls_cert_fprint(peercert, props->mdalg);
- TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->mdalg);
- verify_extract_name(TLScontext, peercert, props);
+ TLScontext->peer_cert_fprint =
+ tls_cert_fprint(peercert, props->mdalg);
+ TLScontext->peer_pkey_fprint =
+ tls_pkey_fprint(peerpkey, props->mdalg);
+ verify_x509(TLScontext, peercert, props);
if (TLScontext->log_mask &
(TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
- msg_info("%s: subject_CN=%s, issuer_CN=%s, "
- "fingerprint=%s, pkey_fingerprint=%s", props->namaddr,
+ msg_info("%s: subject_CN=%s, issuer=%s%s%s%s%s",
+ TLScontext->namaddr,
TLScontext->peer_CN, TLScontext->issuer_CN,
- TLScontext->peer_cert_fprint,
- TLScontext->peer_pkey_fprint);
+ *TLScontext->peer_cert_fprint ?
+ ", cert fingerprint=" : "",
+ *TLScontext->peer_cert_fprint ?
+ TLScontext->peer_cert_fprint : "",
+ *TLScontext->peer_pkey_fprint ?
+ ", pkey fingerprint=" : "",
+ *TLScontext->peer_pkey_fprint ?
+ TLScontext->peer_pkey_fprint : "");
} else {
TLScontext->issuer_CN = mystrdup("");
TLScontext->peer_CN = mystrdup("");
TLScontext->peer_cert_fprint = mystrdup("");
- TLScontext->peer_pkey_fprint = mystrdup("");
+
+ if (!peerpkey) {
+ TLScontext->peer_pkey_fprint = mystrdup("");
+ } else {
+ TLScontext->peer_status |= TLS_CRED_FLAG_RPK;
+ TLScontext->peer_pkey_fprint =
+ tls_pkey_fprint(peerpkey, props->mdalg);
+ if (TLScontext->log_mask &
+ (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
+ msg_info("%s: raw public key fingerprint=%s", props->namaddr,
+ TLScontext->peer_pkey_fprint);
+ verify_rpk(TLScontext, peerpkey, props);
+ }
}
/*
diff --git a/src/tls/tls_dane.c b/src/tls/tls_dane.c
index a2b9b80..ac7f05f 100644
--- a/src/tls/tls_dane.c
+++ b/src/tls/tls_dane.c
@@ -22,8 +22,9 @@
/* void tls_dane_free(dane)
/* TLS_DANE *dane;
/*
-/* void tls_dane_add_fpt_digests(dane, digest, delim, smtp_mode)
+/* void tls_dane_add_fpt_digests(dane, pkey_only, digest, delim, smtp_mode)
/* TLS_DANE *dane;
+/* int pkey_only;
/* const char *digest;
/* const char *delim;
/* int smtp_mode;
@@ -130,6 +131,9 @@
/* SSL context to be configured with the chosen digest algorithms.
/* .IP fpt_alg
/* The OpenSSL EVP digest algorithm handle for the fingerprint digest.
+/* .IP pkey_only
+/* When true, generate "fingerprint" TLSA records for just the public
+/* keys. Otherwise, for both certificates and public keys.
/* .IP tlsa
/* TLSA record linked list head, initially NULL.
/* .IP usage
@@ -415,8 +419,9 @@ static void dane_free(void *dane, void *unused_context)
/* tls_dane_add_fpt_digests - map fingerprint list to DANE TLSA RRset */
-void tls_dane_add_fpt_digests(TLS_DANE *dane, const char *digest,
- const char *delim, int smtp_mode)
+void tls_dane_add_fpt_digests(TLS_DANE *dane, int pkey_only,
+ const char *digest, const char *delim,
+ int smtp_mode)
{
ARGV *values = argv_split(digest, delim);
ssize_t i;
@@ -455,31 +460,41 @@ void tls_dane_add_fpt_digests(TLS_DANE *dane, const char *digest,
continue;
}
+#define USTR_LEN(raw) (unsigned char *) STR(raw), VSTRING_LEN(raw)
+
/*
* At the "fingerprint" security level certificate digests and public
- * key digests are interchangeable. Each leaf certificate is matched
- * via either the public key digest or full certificate digest. The
- * DER encoding of a certificate is not a valid public key, and
- * conversely, the DER encoding of a public key is not a valid
- * certificate. An attacker would need a 2nd-preimage that is
+ * key digests are by default interchangeable. Each leaf certificate
+ * is matched via either the public key digest or full certificate
+ * digest. The DER encoding of a certificate is not a valid public
+ * key, and conversely, the DER encoding of a public key is not a
+ * valid certificate. An attacker would need a 2nd-preimage that is
* feasible across types (given cert digest == some pkey digest) and
* yet presumably difficult within a type (e.g. given cert digest ==
* some other cert digest). No such attacks are known at this time,
* and it is expected that if any are found they would work within as
* well as across the cert/pkey data types.
+ *
+ * That said, when `pkey_only` is true, we match only public keys.
*
* The private-use matching type "255" is mapped to the configured
* fingerprint digest, which may (harmlessly) coincide with one of
* the standard DANE digest algorithms. The private code point is
* however unconditionally enabled.
*/
+ if (!pkey_only) {
+ dane->tlsa = tlsa_prepend(dane->tlsa, 3, 0, 255, USTR_LEN(raw));
+ if (log_mask & (TLS_LOG_VERBOSE | TLS_LOG_DANE))
+ tlsa_info("fingerprint", "digest as private-use TLSA record",
+ 3, 0, 255, USTR_LEN(raw));
+ }
+
+ /* The public key match is unconditional */
+ dane->tlsa = tlsa_prepend(dane->tlsa, 3, 1, 255, USTR_LEN(raw));
if (log_mask & (TLS_LOG_VERBOSE | TLS_LOG_DANE))
tlsa_info("fingerprint", "digest as private-use TLSA record",
- 3, 0, 255, (unsigned char *) STR(raw), VSTRING_LEN(raw));
- dane->tlsa = tlsa_prepend(dane->tlsa, 3, 0, 255,
- (unsigned char *) STR(raw), VSTRING_LEN(raw));
- dane->tlsa = tlsa_prepend(dane->tlsa, 3, 1, 255,
- (unsigned char *) STR(raw), VSTRING_LEN(raw));
+ 3, 1, 255, USTR_LEN(raw));
+
vstring_free(raw);
}
argv_free(values);
@@ -798,12 +813,21 @@ int tls_dane_enable(TLS_SESS_STATE *TLScontext)
SSL *ssl = TLScontext->con;
int usable = 0;
int ret;
+ int rpk_compat = 1;
for (tp = dane->tlsa; tp != 0; tp = tp->next) {
ret = SSL_dane_tlsa_add(ssl, tp->usage, tp->selector,
tp->mtype, tp->data, tp->length);
if (ret > 0) {
++usable;
+ /*
+ * Disable use of RFC7250 raw public keys if any TLSA record
+ * depends on X.509 certificates. Only DANE-EE(3) SPKI(1) records
+ * can get by with just a public key.
+ */
+ if (tp->usage != DNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE
+ || tp->selector != DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO)
+ rpk_compat = 0;
continue;
}
if (ret == 0) {
@@ -818,6 +842,9 @@ int tls_dane_enable(TLS_SESS_STATE *TLScontext)
tls_print_errors();
return (-1);
}
+ if (rpk_compat)
+ tls_enable_server_rpk(NULL, ssl);
+
return (usable);
}
@@ -964,8 +991,9 @@ void tls_dane_log(TLS_SESS_STATE *TLScontext)
{
static VSTRING *top;
static VSTRING *bot;
+ X509 *mcert = 0;
EVP_PKEY *mspki = 0;
- int depth = SSL_get0_dane_authority(TLScontext->con, NULL, &mspki);
+ int depth = SSL_get0_dane_authority(TLScontext->con, &mcert, &mspki);
uint8_t u, s, m;
unsigned const char *data;
size_t dlen;
@@ -994,22 +1022,27 @@ void tls_dane_log(TLS_SESS_STATE *TLScontext)
hex_encode(top, (char *) data, dlen);
}
- switch (TLScontext->level) {
- case TLS_LEV_FPRINT:
+ if (TLScontext->level == TLS_LEV_FPRINT) {
msg_info("%s: Matched fingerprint: %s%s%s", TLScontext->namaddr,
STR(top), dlen > MAX_DUMP_BYTES ? "..." : "",
dlen > MAX_DUMP_BYTES ? STR(bot) : "");
return;
-
- default:
- msg_info("%s: Matched DANE %s at depth %d: %u %u %u %s%s%s",
- TLScontext->namaddr, mspki ?
- "TA public key verified certificate" : depth ?
- "TA certificate" : "EE certificate", depth, u, s, m,
+ }
+#if OPENSSL_VERSION_PREREQ(3,2)
+ if (SSL_get0_peer_rpk(TLScontext->con) != NULL) {
+ msg_info("%s: Matched DANE raw public key: %u %u %u %s%s%s",
+ TLScontext->namaddr, u, s, m,
STR(top), dlen > MAX_DUMP_BYTES ? "..." : "",
dlen > MAX_DUMP_BYTES ? STR(bot) : "");
return;
}
+#endif
+ msg_info("%s: Matched DANE %s at depth %d: %u %u %u %s%s%s",
+ TLScontext->namaddr, mspki ?
+ "TA public key verified certificate" : depth ?
+ "TA certificate" : "EE certificate", depth, u, s, m,
+ STR(top), dlen > MAX_DUMP_BYTES ? "..." : "",
+ dlen > MAX_DUMP_BYTES ? STR(bot) : "");
}
#ifdef TEST
diff --git a/src/tls/tls_fprint.c b/src/tls/tls_fprint.c
index 39b5a52..dc3f99e 100644
--- a/src/tls/tls_fprint.c
+++ b/src/tls/tls_fprint.c
@@ -24,7 +24,7 @@
/* const char *mdalg;
/*
/* char *tls_pkey_fprint(peercert, mdalg)
-/* X509 *peercert;
+/* EVP_PKEY *peerpkey;
/* const char *mdalg;
/* DESCRIPTION
/* tls_digest_byname() constructs, and optionally returns, an EVP_MD_CTX
@@ -48,8 +48,6 @@
/*
/* tls_pkey_fprint() returns a public-key fingerprint; in all
/* other respects the function behaves as tls_cert_fprint().
-/* The var_tls_bc_pkey_fprint variable enables an incorrect
-/* algorithm that was used in Postfix versions 2.9.[0-5].
/* The return value is dynamically allocated with mymalloc(),
/* and the caller must eventually free it with myfree().
/*
@@ -274,6 +272,9 @@ char *tls_serverid_digest(TLS_SESS_STATE *TLScontext,
CHECK_OK_AND_DIGEST_CHARS(mdctx, props->protocols);
CHECK_OK_AND_DIGEST_CHARS(mdctx, ciphers);
+ /* Just in case we make this destination-policy specific */
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &props->enable_rpk);
+
/*
* Ensure separation of caches for sessions where DANE trust
* configuration succeeded from those where it did not. The latter
@@ -398,38 +399,24 @@ char *tls_cert_fprint(X509 *peercert, const char *mdalg)
return (result);
}
-/* tls_pkey_fprint - extract public key fingerprint from certificate */
+/* tls_pkey_fprint - extract public key fingerprint */
-char *tls_pkey_fprint(X509 *peercert, const char *mdalg)
+char *tls_pkey_fprint(EVP_PKEY *peerpkey, const char *mdalg)
{
- if (var_tls_bc_pkey_fprint) {
- const char *myname = "tls_pkey_fprint";
- ASN1_BIT_STRING *key;
- char *result;
-
- key = X509_get0_pubkey_bitstr(peercert);
- if (key == 0)
- msg_fatal("%s: error extracting legacy public-key fingerprint: %m",
- myname);
-
- result = tls_data_fprint(key->data, key->length, mdalg);
- return (result);
- } else {
- int len;
- unsigned char *buf;
- unsigned char *buf2;
- char *result;
-
- len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), NULL);
- buf2 = buf = mymalloc(len);
- i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), &buf2);
- if (buf2 - buf != len)
- msg_panic("i2d_X509_PUBKEY invalid result length");
-
- result = tls_data_fprint(buf, len, mdalg);
- myfree(buf);
- return (result);
- }
+ int len;
+ unsigned char *buf;
+ unsigned char *buf2;
+ char *result;
+
+ len = i2d_PUBKEY(peerpkey, NULL);
+ buf2 = buf = mymalloc(len);
+ i2d_PUBKEY(peerpkey, &buf2);
+ if (buf2 - buf != len)
+ msg_panic("i2d_PUBKEY invalid result length");
+
+ result = tls_data_fprint(buf, len, mdalg);
+ myfree(buf);
+ return (result);
}
#endif
diff --git a/src/tls/tls_misc.c b/src/tls/tls_misc.c
index b7acd1d..cf8f6fa 100644
--- a/src/tls/tls_misc.c
+++ b/src/tls/tls_misc.c
@@ -118,6 +118,14 @@
/*
/* const EVP_MD *tls_validate_digest(dgst)
/* const char *dgst;
+/*
+/* void tls_enable_client_rpk(ctx, ssl)
+/* SSL_CTX *ctx;
+/* SSL *ssl;
+/*
+/* void tls_enable_server_rpk(ctx, ssl)
+/* SSL_CTX *ctx;
+/* SSL *ssl;
/* DESCRIPTION
/* This module implements public and internal routines that
/* support the TLS client and server.
@@ -215,6 +223,12 @@
/*
/* tls_validate_digest() returns a static handle for the named
/* digest algorithm, or NULL on error.
+/*
+/* tls_enable_client_rpk() enables the use of raw public keys in the
+/* client to server direction, if supported by the OpenSSL library.
+/*
+/* tls_enable_server_rpk() enables the use of raw public keys in the
+/* server to client direction, if supported by the OpenSSL library.
/* LICENSE
/* .ad
/* .fi
@@ -762,7 +776,7 @@ int tls_library_init(void)
/*
* The default global config file is optional. With "default"
- * initialisation we don't insist on a match for the requested
+ * initialization we don't insist on a match for the requested
* application name, allowing fallback to the default application
* name, even when a non-default application name is specified.
* Errors in loading the default configuration are ignored.
@@ -1028,7 +1042,6 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
SSL *ssl = TLScontext->con;
int srvr = SSL_is_server(ssl);
EVP_PKEY *dh_pkey = 0;
- X509 *local_cert;
EVP_PKEY *local_pkey = 0;
X509 *peer_cert;
EVP_PKEY *peer_pkey = 0;
@@ -1060,18 +1073,23 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
}
/*
- * On the client end, the certificate may be preset, but not used, so we
+ * On the client end, the certificate may be present, but not used, so we
* check via SSL_get_signature_nid(). This means that local signature
* data on clients requires at least 1.1.1a.
*/
- if (srvr || SSL_get_signature_nid(ssl, &nid))
- local_cert = SSL_get_certificate(ssl);
- else
- local_cert = 0;
-
+ if (srvr || SSL_get_signature_nid(ssl, &nid)) {
+ local_pkey = SSL_get_privatekey(ssl);
+ }
/* Signature algorithms for the local end of the connection */
- if (local_cert) {
- local_pkey = X509_get0_pubkey(local_cert);
+ if (local_pkey) {
+#if OPENSSL_VERSION_PREREQ(3,2)
+ if (srvr)
+ TLScontext->stoc_rpk = TLSEXT_cert_type_rpk ==
+ SSL_get_negotiated_server_cert_type(ssl);
+ else
+ TLScontext->ctos_rpk = TLSEXT_cert_type_rpk ==
+ SSL_get_negotiated_client_cert_type(ssl);
+#endif
/*
* Override the built-in name for the "ECDSA" algorithms OID, with
@@ -1097,7 +1115,6 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
break;
#endif
}
- /* No X509_free(local_cert) */
}
/*
@@ -1107,9 +1124,26 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
if (SSL_get_signature_nid(ssl, &nid) && nid != NID_undef)
locl_sig_dgst = OBJ_nid2sn(nid);
}
- /* Signature algorithms for the peer end of the connection */
- if ((peer_cert = TLS_PEEK_PEER_CERT(ssl)) != 0) {
+ peer_cert = TLS_PEEK_PEER_CERT(ssl);
+ if (peer_cert != 0) {
peer_pkey = X509_get0_pubkey(peer_cert);
+ }
+#if OPENSSL_VERSION_PREREQ(3,2)
+ else {
+ peer_pkey = SSL_get0_peer_rpk(ssl);
+ }
+#endif
+
+ /* Signature algorithms for the peer end of the connection */
+ if (peer_pkey != 0) {
+#if OPENSSL_VERSION_PREREQ(3,2)
+ if (srvr)
+ TLScontext->ctos_rpk = TLSEXT_cert_type_rpk ==
+ SSL_get_negotiated_client_cert_type(ssl);
+ else
+ TLScontext->stoc_rpk = TLSEXT_cert_type_rpk ==
+ SSL_get_negotiated_server_cert_type(ssl);
+#endif
/*
* Override the built-in name for the "ECDSA" algorithms OID, with
@@ -1144,8 +1178,9 @@ void tls_get_signature_params(TLS_SESS_STATE *TLScontext)
if (SSL_get_peer_signature_nid(ssl, &nid) && nid != NID_undef)
peer_sig_dgst = OBJ_nid2sn(nid);
- TLS_FREE_PEER_CERT(peer_cert);
}
+ TLS_FREE_PEER_CERT(peer_cert);
+
if (kex_name) {
TLScontext->kex_name = mystrdup(kex_name);
TLScontext->kex_curve = kex_curve;
@@ -1180,7 +1215,7 @@ void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx)
*/
vstring_sprintf(msg, "%s TLS connection %s %s %s%s%s: %s"
" with cipher %s (%d/%d bits)",
- !TLS_CERT_IS_PRESENT(ctx) ? "Anonymous" :
+ !TLS_CRED_IS_PRESENT(ctx) ? "Anonymous" :
TLS_CERT_IS_SECURED(ctx) ? "Verified" :
TLS_CERT_IS_TRUSTED(ctx) ? "Trusted" : "Untrusted",
usage == TLS_USAGE_NEW ? "established" : "reused",
@@ -1199,9 +1234,13 @@ void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx)
vstring_sprintf_append(msg, " server-signature %s",
ctx->srvr_sig_name);
if (ctx->srvr_sig_curve && *ctx->srvr_sig_curve)
- vstring_sprintf_append(msg, " (%s)", ctx->srvr_sig_curve);
+ vstring_sprintf_append(msg, " (%s%s)", ctx->srvr_sig_curve,
+ ctx->stoc_rpk ? " raw public key" : "");
else if (ctx->srvr_sig_bits > 0)
- vstring_sprintf_append(msg, " (%d bits)", ctx->srvr_sig_bits);
+ vstring_sprintf_append(msg, " (%d bit%s)", ctx->srvr_sig_bits,
+ ctx->stoc_rpk ? " raw public key" : "s");
+ else if (ctx->stoc_rpk)
+ vstring_sprintf_append(msg, " (raw public key)");
if (ctx->srvr_sig_dgst && *ctx->srvr_sig_dgst)
vstring_sprintf_append(msg, " server-digest %s",
ctx->srvr_sig_dgst);
@@ -1210,9 +1249,13 @@ void tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx)
vstring_sprintf_append(msg, " client-signature %s",
ctx->clnt_sig_name);
if (ctx->clnt_sig_curve && *ctx->clnt_sig_curve)
- vstring_sprintf_append(msg, " (%s)", ctx->clnt_sig_curve);
+ vstring_sprintf_append(msg, " (%s%s)", ctx->clnt_sig_curve,
+ ctx->ctos_rpk ? " raw public key" : "");
else if (ctx->clnt_sig_bits > 0)
- vstring_sprintf_append(msg, " (%d bits)", ctx->clnt_sig_bits);
+ vstring_sprintf_append(msg, " (%d bit%s)", ctx->clnt_sig_bits,
+ ctx->ctos_rpk ? " raw public key" : "s");
+ else if (ctx->ctos_rpk)
+ vstring_sprintf_append(msg, " (raw public key)");
if (ctx->clnt_sig_dgst && *ctx->clnt_sig_dgst)
vstring_sprintf_append(msg, " client-digest %s",
ctx->clnt_sig_dgst);
@@ -1288,6 +1331,8 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr)
TLScontext->cipher_name = 0;
TLScontext->kex_name = 0;
TLScontext->kex_curve = 0;
+ TLScontext->ctos_rpk = 0;
+ TLScontext->stoc_rpk = 0;
TLScontext->clnt_sig_name = 0;
TLScontext->clnt_sig_curve = 0;
TLScontext->clnt_sig_dgst = 0;
@@ -1702,6 +1747,52 @@ const EVP_MD *tls_validate_digest(const char *dgst)
return md_alg;
}
+void tls_enable_client_rpk(SSL_CTX *ctx, SSL *ssl)
+{
+#if OPENSSL_VERSION_PREREQ(3,2)
+ static int warned = 0;
+ static const unsigned char cert_types_rpk[] = {
+ TLSEXT_cert_type_rpk,
+ TLSEXT_cert_type_x509
+ };
+
+ if ((ctx && !SSL_CTX_set1_client_cert_type(ctx, cert_types_rpk,
+ sizeof(cert_types_rpk))) ||
+ (ssl && !SSL_set1_client_cert_type(ssl, cert_types_rpk,
+ sizeof(cert_types_rpk)))) {
+ if (warned++) {
+ ERR_clear_error();
+ return;
+ }
+ msg_warn("Failed to enable client to server raw public key support");
+ tls_print_errors();
+ }
+#endif
+}
+
+void tls_enable_server_rpk(SSL_CTX *ctx, SSL *ssl)
+{
+#if OPENSSL_VERSION_PREREQ(3,2)
+ static int warned = 0;
+ static const unsigned char cert_types_rpk[] = {
+ TLSEXT_cert_type_rpk,
+ TLSEXT_cert_type_x509
+ };
+
+ if ((ctx && !SSL_CTX_set1_server_cert_type(ctx, cert_types_rpk,
+ sizeof(cert_types_rpk))) ||
+ (ssl && !SSL_set1_server_cert_type(ssl, cert_types_rpk,
+ sizeof(cert_types_rpk)))) {
+ if (warned++) {
+ ERR_clear_error();
+ return;
+ }
+ msg_warn("Failed to enable server to client raw public key support");
+ tls_print_errors();
+ }
+#endif
+}
+
#else
/*
diff --git a/src/tls/tls_proxy.h b/src/tls/tls_proxy.h
index ca664c6..6528639 100644
--- a/src/tls/tls_proxy.h
+++ b/src/tls/tls_proxy.h
@@ -32,8 +32,10 @@
#ifdef USE_TLS
/*
- * TLS_CLIENT_PARAMS structure. If this changes, update all
- * TLS_CLIENT_PARAMS related functions in tls_proxy_client_*.c.
+ * TLS_CLIENT_PARAMS structure, to communicate global TLS library settings
+ * that are the same for all TLS client contexts. This information is used
+ * in tlsproxy(8) to detect inconsistencies. If this structure is changed,
+ * update all TLS_CLIENT_PARAMS related functions in tls_proxy_client_*.c.
*
* In the serialization these attributes are identified by their configuration
* parameter names.
@@ -106,11 +108,11 @@ extern VSTREAM *tls_proxy_open(const char *, int, VSTREAM *, const char *,
((props)->a12), ((props)->a13), ((props)->a14))
#define TLS_PROXY_CLIENT_START_PROPS(props, a1, a2, a3, a4, a5, a6, a7, a8, \
- a9, a10, a11, a12, a13, a14) \
+ a9, a10, a11, a12, a13, a14, a15) \
(((props)->a1), ((props)->a2), ((props)->a3), \
((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
- ((props)->a12), ((props)->a13), ((props)->a14))
+ ((props)->a12), ((props)->a13), ((props)->a14), ((props)->a15))
extern TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *);
extern void tls_proxy_context_free(TLS_SESS_STATE *);
@@ -168,6 +170,8 @@ extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *);
#define TLS_ATTR_KEX_NAME "key_exchange"
#define TLS_ATTR_KEX_CURVE "key_exchange_curve"
#define TLS_ATTR_KEX_BITS "key_exchange_bits"
+#define TLS_ATTR_CTOS_RPK "ctos_rpk"
+#define TLS_ATTR_STOC_RPK "stoc_rpk"
#define TLS_ATTR_CLNT_SIG_NAME "clnt_signature"
#define TLS_ATTR_CLNT_SIG_CURVE "clnt_signature_curve"
#define TLS_ATTR_CLNT_SIG_BITS "clnt_signature_bits"
@@ -237,6 +241,7 @@ extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *);
* TLS_CLIENT_START_PROPS attributes.
*/
#define TLS_ATTR_TIMEOUT "timeout"
+#define TLS_ATTR_ENABLE_RPK "enable_rpk"
#define TLS_ATTR_TLS_LEVEL "tls_level"
#define TLS_ATTR_NEXTHOP "nexthop"
#define TLS_ATTR_HOST "host"
diff --git a/src/tls/tls_proxy_client_print.c b/src/tls/tls_proxy_client_print.c
index 1cc5778..81e50b9 100644
--- a/src/tls/tls_proxy_client_print.c
+++ b/src/tls/tls_proxy_client_print.c
@@ -257,6 +257,7 @@ int tls_proxy_client_start_print(ATTR_PRINT_COMMON_FN print_fn,
ret = print_fn(fp, flags | ATTR_FLAG_MORE,
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, props->timeout),
+ SEND_ATTR_INT(TLS_ATTR_ENABLE_RPK, props->enable_rpk),
SEND_ATTR_INT(TLS_ATTR_TLS_LEVEL, props->tls_level),
SEND_ATTR_STR(TLS_ATTR_NEXTHOP,
STRING_OR_EMPTY(props->nexthop)),
diff --git a/src/tls/tls_proxy_client_scan.c b/src/tls/tls_proxy_client_scan.c
index a69388c..d36cf4d 100644
--- a/src/tls/tls_proxy_client_scan.c
+++ b/src/tls/tls_proxy_client_scan.c
@@ -451,6 +451,7 @@ int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
props->dane = 0; /* scan_fn may return early */
ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout),
+ RECV_ATTR_INT(TLS_ATTR_ENABLE_RPK, &props->enable_rpk),
RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level),
RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop),
RECV_ATTR_STR(TLS_ATTR_HOST, host),
@@ -478,7 +479,7 @@ int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
props->cipher_grade = vstring_export(cipher_grade);
props->cipher_exclusions = vstring_export(cipher_exclusions);
props->mdalg = vstring_export(mdalg);
- ret = (ret == 14 ? 1 : -1);
+ ret = (ret == 15 ? 1 : -1);
if (ret != 1) {
tls_proxy_client_start_free(props);
props = 0;
diff --git a/src/tls/tls_proxy_context_print.c b/src/tls/tls_proxy_context_print.c
index 04123cb..930410a 100644
--- a/src/tls/tls_proxy_context_print.c
+++ b/src/tls/tls_proxy_context_print.c
@@ -88,6 +88,10 @@ int tls_proxy_context_print(ATTR_PRINT_COMMON_FN print_fn, VSTREAM *fp,
STRING_OR_EMPTY(tp->kex_curve)),
SEND_ATTR_INT(TLS_ATTR_KEX_BITS,
tp->kex_bits),
+ SEND_ATTR_INT(TLS_ATTR_CTOS_RPK,
+ tp->ctos_rpk),
+ SEND_ATTR_INT(TLS_ATTR_STOC_RPK,
+ tp->stoc_rpk),
SEND_ATTR_STR(TLS_ATTR_CLNT_SIG_NAME,
STRING_OR_EMPTY(tp->clnt_sig_name)),
SEND_ATTR_STR(TLS_ATTR_CLNT_SIG_CURVE,
diff --git a/src/tls/tls_proxy_context_scan.c b/src/tls/tls_proxy_context_scan.c
index 1d463ad..48aaff6 100644
--- a/src/tls/tls_proxy_context_scan.c
+++ b/src/tls/tls_proxy_context_scan.c
@@ -113,6 +113,8 @@ int tls_proxy_context_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
RECV_ATTR_STR(TLS_ATTR_KEX_NAME, kex_name),
RECV_ATTR_STR(TLS_ATTR_KEX_CURVE, kex_curve),
RECV_ATTR_INT(TLS_ATTR_KEX_BITS, &tls_context->kex_bits),
+ RECV_ATTR_INT(TLS_ATTR_CTOS_RPK, &tls_context->ctos_rpk),
+ RECV_ATTR_INT(TLS_ATTR_STOC_RPK, &tls_context->stoc_rpk),
RECV_ATTR_STR(TLS_ATTR_CLNT_SIG_NAME, clnt_sig_name),
RECV_ATTR_STR(TLS_ATTR_CLNT_SIG_CURVE, clnt_sig_curve),
RECV_ATTR_INT(TLS_ATTR_CLNT_SIG_BITS, &tls_context->clnt_sig_bits),
@@ -139,7 +141,7 @@ int tls_proxy_context_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
tls_context->srvr_sig_curve = vstring_export(srvr_sig_curve);
tls_context->srvr_sig_dgst = vstring_export(srvr_sig_dgst);
tls_context->namaddr = vstring_export(namaddr);
- ret = (ret == 22 ? 1 : -1);
+ ret = (ret == 24 ? 1 : -1);
if (ret != 1) {
tls_proxy_context_free(tls_context);
tls_context = 0;
diff --git a/src/tls/tls_server.c b/src/tls/tls_server.c
index 262cda9..88b3326 100644
--- a/src/tls/tls_server.c
+++ b/src/tls/tls_server.c
@@ -62,8 +62,8 @@
/* available as:
/* .IP TLScontext->peer_status
/* A bitmask field that records the status of the peer certificate
-/* verification. One or more of TLS_CERT_FLAG_PRESENT and
-/* TLS_CERT_FLAG_TRUSTED.
+/* verification. One or more of TLS_CRED_FLAG_CERT, TLS_CRED_FLAG_RPK
+/* and TLS_CERT_FLAG_TRUSTED.
/* .IP TLScontext->peer_CN
/* Extracted CommonName of the peer, or zero-length string
/* when information could not be extracted.
@@ -637,6 +637,13 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
}
/*
+ * Always support server->client raw public keys, if they're good enough
+ * for the client, they're good enough for us.
+ */
+ tls_enable_server_rpk(server_ctx, NULL);
+ tls_enable_server_rpk(sni_ctx, NULL);
+
+ /*
* Upref and share the cert store. Sadly we can't yet use
* SSL_CTX_set1_cert_store(3) which was added in OpenSSL 1.1.0.
*/
@@ -865,11 +872,19 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
tls_free_context(TLScontext);
return (0);
}
-#ifdef SSL_SECOP_PEER
- /* When authenticating the peer, use 80-bit plus OpenSSL security level */
+
+ /*
+ * When encryption is mandatory use the 80-bit plus OpenSSL security level.
+ */
if (props->requirecert)
SSL_set_security_level(TLScontext->con, 1);
-#endif
+
+ /*
+ * Also enable client->server raw public keys, provided we're not
+ * interested in client certificate fingerprints.
+ */
+ if (props->enable_rpk)
+ tls_enable_client_rpk(NULL, TLScontext->con);
/*
* Before really starting anything, try to seed the PRNG a little bit
@@ -946,6 +961,7 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
{
const SSL_CIPHER *cipher;
X509 *peer;
+ EVP_PKEY *pkey = 0;
char buf[CCERT_BUFSIZ];
/* Turn off packet dump if only dumping the handshake */
@@ -966,8 +982,17 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
* actual information. We want to save it for later use.
*/
peer = TLS_PEEK_PEER_CERT(TLScontext->con);
+ if (peer) {
+ pkey = X509_get0_pubkey(peer);
+ }
+#if OPENSSL_VERSION_PREREQ(3,2)
+ else {
+ pkey = SSL_get0_peer_rpk(TLScontext->con);
+ }
+#endif
+
if (peer != NULL) {
- TLScontext->peer_status |= TLS_CERT_FLAG_PRESENT;
+ TLScontext->peer_status |= TLS_CRED_FLAG_CERT;
if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
@@ -981,16 +1006,23 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
}
TLScontext->peer_CN = tls_peer_CN(peer, TLScontext);
TLScontext->issuer_CN = tls_issuer_CN(peer, TLScontext);
- TLScontext->peer_cert_fprint = tls_cert_fprint(peer, TLScontext->mdalg);
- TLScontext->peer_pkey_fprint = tls_pkey_fprint(peer, TLScontext->mdalg);
+ TLScontext->peer_cert_fprint =
+ tls_cert_fprint(peer, TLScontext->mdalg);
+ TLScontext->peer_pkey_fprint =
+ tls_pkey_fprint(pkey, TLScontext->mdalg);
if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) {
- msg_info("%s: subject_CN=%s, issuer=%s, fingerprint=%s"
- ", pkey_fingerprint=%s",
+ msg_info("%s: subject_CN=%s, issuer=%s%s%s%s%s",
TLScontext->namaddr,
TLScontext->peer_CN, TLScontext->issuer_CN,
- TLScontext->peer_cert_fprint,
- TLScontext->peer_pkey_fprint);
+ *TLScontext->peer_cert_fprint ?
+ ", cert fingerprint=" : "",
+ *TLScontext->peer_cert_fprint ?
+ TLScontext->peer_cert_fprint : "",
+ *TLScontext->peer_pkey_fprint ?
+ ", pkey fingerprint=" : "",
+ *TLScontext->peer_pkey_fprint ?
+ TLScontext->peer_pkey_fprint : "");
}
TLS_FREE_PEER_CERT(peer);
@@ -1013,7 +1045,22 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
TLScontext->peer_CN = mystrdup("");
TLScontext->issuer_CN = mystrdup("");
TLScontext->peer_cert_fprint = mystrdup("");
- TLScontext->peer_pkey_fprint = mystrdup("");
+ if (!pkey) {
+ TLScontext->peer_pkey_fprint = mystrdup("");
+ } else {
+
+ /*
+ * Raw public keys don't involve CA trust, and we don't have a
+ * way to associate DANE TLSA RRs with clients just yet, we just
+ * make the fingerprint available to the access(5) layer.
+ */
+ TLScontext->peer_status |= TLS_CRED_FLAG_RPK;
+ TLScontext->peer_pkey_fprint =
+ tls_pkey_fprint(pkey, TLScontext->mdalg);
+ if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT))
+ msg_info("%s: raw public key fingerprint=%s",
+ TLScontext->namaddr, TLScontext->peer_pkey_fprint);
+ }
}
/*
diff --git a/src/tls/tls_verify.c b/src/tls/tls_verify.c
index f32f32b..c643f18 100644
--- a/src/tls/tls_verify.c
+++ b/src/tls/tls_verify.c
@@ -144,6 +144,7 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
int depth;
SSL *con;
TLS_SESS_STATE *TLScontext;
+ EVP_PKEY *rpk = 0;
/* May be NULL as of OpenSSL 1.0, thanks for the API change! */
cert = X509_STORE_CTX_get_current_cert(ctx);
@@ -151,6 +152,10 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
TLScontext = SSL_get_ex_data(con, TLScontext_index);
depth = X509_STORE_CTX_get_error_depth(ctx);
+#if OPENSSL_VERSION_PREREQ(3,2)
+ if (cert == 0)
+ rpk = X509_STORE_CTX_get0_rpk(ctx);
+#endif
/*
* Transient failures to load the (DNS or synthetic TLSA) trust settings
@@ -174,12 +179,15 @@ int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
update_error_state(TLScontext, depth, cert, err);
if (TLScontext->log_mask & TLS_LOG_VERBOSE) {
- if (cert)
+ if (cert) {
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
- else
- strcpy(buf, "<unknown>");
- msg_info("%s: depth=%d verify=%d subject=%s",
- TLScontext->namaddr, depth, ok, printable(buf, '?'));
+ msg_info("%s: depth=%d verify=%d subject=%s",
+ TLScontext->namaddr, depth, ok, printable(buf, '?'));
+ } else if (rpk) {
+ msg_info("%s: verify=%d raw public key", TLScontext->namaddr, ok);
+ } else {
+ msg_info("%s: depth=%d verify=%d", TLScontext->namaddr, depth, ok);
+ }
}
return (1);
}
diff --git a/src/tlsproxy/tlsproxy.c b/src/tlsproxy/tlsproxy.c
index 7c0d814..0ebf52c 100644
--- a/src/tlsproxy/tlsproxy.c
+++ b/src/tlsproxy/tlsproxy.c
@@ -237,6 +237,12 @@
/* .IP "\fBtlsproxy_tls_chain_files ($smtpd_tls_chain_files)\fR"
/* Files with the Postfix \fBtlsproxy\fR(8) server keys and certificate
/* chains in PEM format.
+/* .PP
+/* Available in Postfix version 3.9 and later:
+/* .IP "\fBtlsproxy_tls_enable_rpk ($smtpd_tls_enable_rpk)\fR"
+/* Request that remote SMTP clients send an RFC7250 raw public key
+/* instead of an X.509 certificate, when asking or requiring client
+/* authentication.
/* STARTTLS CLIENT CONTROLS
/* .ad
/* .fi
@@ -436,6 +442,7 @@ bool var_smtpd_use_tls;
bool var_smtpd_enforce_tls;
bool var_smtpd_tls_ask_ccert;
bool var_smtpd_tls_req_ccert;
+bool var_smtpd_tls_enable_rpk;
bool var_smtpd_tls_set_sessid;
char *var_smtpd_relay_ccerts;
char *var_smtpd_tls_chain_files;
@@ -465,6 +472,7 @@ bool var_tlsp_use_tls;
bool var_tlsp_enforce_tls;
bool var_tlsp_tls_ask_ccert;
bool var_tlsp_tls_req_ccert;
+bool var_tlsp_tls_enable_rpk;
bool var_tlsp_tls_set_sessid;
char *var_tlsp_tls_chain_files;
char *var_tlsp_tls_cert_file;
@@ -1081,6 +1089,7 @@ static int tlsp_server_start_pre_handshake(TLSP_STATE *state)
timeout = 0, /* unused */
requirecert = (var_tlsp_tls_req_ccert
&& var_tlsp_enforce_tls),
+ enable_rpk = var_tlsp_tls_enable_rpk,
serverid = state->server_id,
namaddr = state->remote_endpt,
cipher_grade = cipher_grade,
@@ -1827,6 +1836,7 @@ int main(int argc, char **argv)
VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
+ VAR_SMTPD_TLS_ENABLE_RPK, DEF_SMTPD_TLS_ENABLE_RPK, &var_smtpd_tls_enable_rpk,
VAR_SMTPD_TLS_SET_SESSID, DEF_SMTPD_TLS_SET_SESSID, &var_smtpd_tls_set_sessid,
VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls,
VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_tls,
@@ -1837,6 +1847,7 @@ int main(int argc, char **argv)
VAR_TLSP_ENFORCE_TLS, DEF_TLSP_ENFORCE_TLS, &var_tlsp_enforce_tls,
VAR_TLSP_TLS_ACERT, DEF_TLSP_TLS_ACERT, &var_tlsp_tls_ask_ccert,
VAR_TLSP_TLS_RCERT, DEF_TLSP_TLS_RCERT, &var_tlsp_tls_req_ccert,
+ VAR_TLSP_TLS_ENABLE_RPK, DEF_TLSP_TLS_ENABLE_RPK, &var_tlsp_tls_enable_rpk,
VAR_TLSP_TLS_SET_SESSID, DEF_TLSP_TLS_SET_SESSID, &var_tlsp_tls_set_sessid,
VAR_TLSP_CLNT_USE_TLS, DEF_TLSP_CLNT_USE_TLS, &var_tlsp_clnt_use_tls,
VAR_TLSP_CLNT_ENFORCE_TLS, DEF_TLSP_CLNT_ENFORCE_TLS, &var_tlsp_clnt_enforce_tls,
diff --git a/src/trivial-rewrite/resolve.c b/src/trivial-rewrite/resolve.c
index 40e6aa5..df761e7 100644
--- a/src/trivial-rewrite/resolve.c
+++ b/src/trivial-rewrite/resolve.c
@@ -427,7 +427,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
if (!valid_mailhost_literal(rcpt_domain, DONT_GRIPE))
*flags |= RESOLVE_FLAG_ERROR;
} else if (var_smtputf8_enable
- && valid_utf8_string(STR(nextrcpt), LEN(nextrcpt)) == 0) {
+ && valid_utf8_stringz(STR(nextrcpt)) == 0) {
*flags |= RESOLVE_FLAG_ERROR;
} else if (!valid_utf8_hostname(var_smtputf8_enable, rcpt_domain,
DONT_GRIPE)) {
diff --git a/src/trivial-rewrite/trivial-rewrite.c b/src/trivial-rewrite/trivial-rewrite.c
index 675af80..bb8da09 100644
--- a/src/trivial-rewrite/trivial-rewrite.c
+++ b/src/trivial-rewrite/trivial-rewrite.c
@@ -122,9 +122,10 @@
/* .PP
/* Available in Postfix 2.2 and later:
/* .IP "\fBremote_header_rewrite_domain (empty)\fR"
-/* Don't rewrite message headers from remote clients at all when
-/* this parameter is empty; otherwise, rewrite message headers and
-/* append the specified domain name to incomplete addresses.
+/* Rewrite or add message headers in mail from remote clients if
+/* the remote_header_rewrite_domain parameter value is non-empty,
+/* updating incomplete addresses with the domain specified in the
+/* remote_header_rewrite_domain parameter, and adding missing headers.
/* ROUTING CONTROLS
/* .ad
/* .fi
@@ -141,10 +142,12 @@
/* final delivery to domains listed with $virtual_mailbox_domains.
/* .IP "\fBrelay_transport (relay)\fR"
/* The default mail delivery transport and next-hop destination for
-/* remote delivery to domains listed with $relay_domains.
+/* the relay domain address class: recipient domains that match
+/* $relay_domains.
/* .IP "\fBdefault_transport (smtp)\fR"
/* The default mail delivery transport and next-hop destination for
-/* destinations that do not match $mydestination, $inet_interfaces,
+/* the default domain class: recipient domains that do not match
+/* $mydestination, $inet_interfaces,
/* $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
/* or $relay_domains.
/* .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR"
@@ -152,8 +155,8 @@
/* matches subdomains of example.com,
/* instead of requiring an explicit ".example.com" pattern.
/* .IP "\fBrelayhost (empty)\fR"
-/* The next-hop destination(s) for non-local mail; overrides non-local
-/* domains in recipient addresses.
+/* The next-hop destination(s) for non-local mail; takes precedence
+/* over non-local domains in recipient addresses.
/* .IP "\fBtransport_maps (empty)\fR"
/* Optional lookup tables with mappings from recipient address to
/* (message delivery transport, next-hop destination).
diff --git a/src/util/Makefile.in b/src/util/Makefile.in
index f69dec5..01211fb 100644
--- a/src/util/Makefile.in
+++ b/src/util/Makefile.in
@@ -45,7 +45,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
byte_mask.c known_tcp_ports.c argv_split_at.c dict_stream.c \
sane_strtol.c hash_fnv.c ldseed.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c \
mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c inet_prefix_top.c \
- inet_addr_sizes.c
+ inet_addr_sizes.c quote_for_json.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 \
@@ -91,7 +91,8 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o \
byte_mask.o known_tcp_ports.o argv_split_at.o dict_stream.o \
sane_strtol.o hash_fnv.o ldseed.o mkmap_db.o mkmap_dbm.o \
- mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o
+ mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o \
+ quote_for_json.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.
@@ -145,7 +146,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \
vbuf_print split_qnameval vstream msg_logger byte_mask \
known_tcp_ports dict_stream find_inet binhash hash_fnv argv \
- clean_env inet_prefix_top
+ clean_env inet_prefix_top printable readlline quote_for_json
PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) $(LIB_PREFIX)lmdb$(LIB_SUFFIX) \
$(LIB_PREFIX)cdb$(LIB_SUFFIX) $(LIB_PREFIX)sdbm$(LIB_SUFFIX)
HTABLE_FIX = NORANDOMIZE=1
@@ -365,6 +366,16 @@ unescape: $(LIB)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+printable: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
+readlline: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
hex_quote: $(LIB)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
@@ -609,6 +620,11 @@ inet_prefix_top: $(LIB)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+quote_for_json: $(LIB)
+ mv $@.o junk
+ $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+ mv junk $@.o
+
tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
attr_scan64_test attr_scan0_test host_port_test dict_tests \
@@ -618,7 +634,8 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
strcasecmp_utf8_test vbuf_print_test miss_endif_cidr_test \
miss_endif_regexp_test split_qnameval_test vstring_test \
vstream_test byte_mask_tests mystrtok_test known_tcp_ports_test \
- binhash_test argv_test inet_prefix_top_test
+ binhash_test argv_test inet_prefix_top_test printable_test \
+ valid_utf8_string_test readlline_test quote_for_json_test
dict_tests: all dict_test \
dict_pcre_tests dict_cidr_test dict_thash_test dict_static_test \
@@ -650,6 +667,15 @@ unescape_test: unescape unescape.in unescape.ref
# diff unescape.in unescape.tmp
rm -f unescape.tmp
+printable_test: printable
+ $(SHLIB_ENV) ${VALGRIND} ./printable
+
+readlline_test: readlline
+ $(SHLIB_ENV) ${VALGRIND} ./readlline
+
+valid_utf8_string_test: valid_utf8_string
+ $(SHLIB_ENV) ${VALGRIND} ./valid_utf8_string
+
hex_quote_test: hex_quote
$(SHLIB_ENV) ${VALGRIND} ./hex_quote <hex_quote.c | od -cb >hex_quote.tmp
od -cb <hex_quote.c >hex_quote.ref
@@ -1083,6 +1109,9 @@ argv_test: argv
inet_prefix_top_test: inet_prefix_top
$(SHLIB_ENV) ${VALGRIND} ./inet_prefix_top
+quote_for_json_test: quote_for_json
+ $(SHLIB_ENV) ${VALGRIND} ./quote_for_json
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -1119,9 +1148,12 @@ allspace.o: vbuf.h
allspace.o: vstring.h
argv.o: argv.c
argv.o: argv.h
+argv.o: check_arg.h
argv.o: msg.h
argv.o: mymalloc.h
argv.o: sys_defs.h
+argv.o: vbuf.h
+argv.o: vstring.h
argv_attr_print.o: argv.h
argv_attr_print.o: argv_attr.h
argv_attr_print.o: argv_attr_print.c
@@ -2157,6 +2189,7 @@ logwriter.o: logwriter.c
logwriter.o: logwriter.h
logwriter.o: msg.h
logwriter.o: mymalloc.h
+logwriter.o: name_code.h
logwriter.o: safe_open.h
logwriter.o: sys_defs.h
logwriter.o: vbuf.h
@@ -2525,11 +2558,16 @@ posix_signals.o: posix_signals.c
posix_signals.o: posix_signals.h
posix_signals.o: sys_defs.h
printable.o: check_arg.h
+printable.o: parse_utf8_char.h
printable.o: printable.c
printable.o: stringops.h
printable.o: sys_defs.h
printable.o: vbuf.h
printable.o: vstring.h
+quote_for_json.o: quote_for_json.c
+quote_for_json.o: stringops.h
+quote_for_json.o: sys_defs.h
+quote_for_json.o: vstring.h
rand_sleep.o: iostuff.h
rand_sleep.o: msg.h
rand_sleep.o: myrand.h
@@ -2848,6 +2886,7 @@ valid_utf8_hostname.o: valid_utf8_hostname.h
valid_utf8_hostname.o: vbuf.h
valid_utf8_hostname.o: vstring.h
valid_utf8_string.o: check_arg.h
+valid_utf8_string.o: parse_utf8_char.h
valid_utf8_string.o: stringops.h
valid_utf8_string.o: sys_defs.h
valid_utf8_string.o: valid_utf8_string.c
diff --git a/src/util/argv.c b/src/util/argv.c
index 4e05fd0..332426e 100644
--- a/src/util/argv.c
+++ b/src/util/argv.c
@@ -53,6 +53,11 @@
/* ssize_t pos;
/* ssize_t how_many;
/*
+/* char *argv_join(buf, argvp, delim)
+/* VSTRING *buf;
+/* ARGV *argvp;
+/* int delim;
+/*
/* void ARGV_FAKE_BEGIN(argv, arg)
/* const char *arg;
/*
@@ -109,6 +114,10 @@
/* starting at the specified array position. The result is
/* null-terminated.
/*
+/* argv_join() joins all elements in an array using the
+/* specified delimiter value, and appends the result to the
+/* specified buffer.
+/*
/* ARGV_FAKE_BEGIN/END are an optimization for the case where
/* a single string needs to be passed into an ARGV-based
/* interface. ARGV_FAKE_BEGIN() opens a statement block and
@@ -148,6 +157,7 @@
#include "mymalloc.h"
#include "msg.h"
+#include "vstring.h"
#include "argv.h"
#ifdef TEST
@@ -379,6 +389,20 @@ void argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many)
argvp->argc -= how_many;
}
+/* argv_join - concatenate array elements with delimiter */
+
+char *argv_join(VSTRING *buf, ARGV *argv, int delim)
+{
+ char **cpp;
+
+ for (cpp = argv->argv; *cpp; cpp++) {
+ vstring_strcat(buf, *cpp);
+ if (cpp[1])
+ VSTRING_ADDCH(buf, delim);
+ }
+ return (vstring_str(buf));
+}
+
#ifdef TEST
/*
@@ -402,6 +426,7 @@ typedef struct TEST_CASE {
const char *exp_panic_msg; /* expected panic */
int exp_argc; /* expected array length */
const char *exp_argv[ARRAY_LEN]; /* expected array content */
+ int join_delim; /* argv_join() delimiter */
} TEST_CASE;
#define TERMINATE_ARRAY (1)
@@ -559,6 +584,24 @@ static ARGV *test_argv_bad_delete3(const TEST_CASE *tp, ARGV *argvp)
return (argvp);
}
+/* test_argv_join - populate, join, and overwrite */
+
+static ARGV *test_argv_join(const TEST_CASE *tp, ARGV *argvp)
+{
+ VSTRING *buf = vstring_alloc(100);
+
+ /*
+ * Impedance mismatch: argv_join() produces output to VSTRING, but the
+ * test fixture wants output to ARGV.
+ */
+ test_argv_populate(tp, argvp);
+ argv_join(buf, argvp, tp->join_delim);
+ argv_delete(argvp, 0, argvp->argc);
+ argv_add(argvp, vstring_str(buf), ARGV_END);
+ vstring_free(buf);
+ return (argvp);
+}
+
/* test_argv_verify - verify result */
static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp)
@@ -573,7 +616,7 @@ static int test_argv_verify(const TEST_CASE *tp, ARGV *argvp)
}
if (strcmp(vstring_str(test_panic_str), tp->exp_panic_msg) != 0) {
msg_warn("test case '%s': got '%s', want: '%s'",
- tp->label, vstring_str(test_panic_str), tp->exp_panic_msg);
+ tp->label, vstring_str(test_panic_str), tp->exp_panic_msg);
return (FAIL);
}
return (PASS);
@@ -682,6 +725,18 @@ static const TEST_CASE test_cases[] = {
{"foo", "baz", "bar", 0}, 0, test_argv_bad_delete3,
"argv_delete bad range: (start=100 count=1)"
},
+ {"argv_join, multiple strings",
+ {"foo", "baz", "bar", 0}, 0, test_argv_join,
+ 0, 1, {"foo:baz:bar", 0}, ':'
+ },
+ {"argv_join, one string",
+ {"foo", 0}, 0, test_argv_join,
+ 0, 1, {"foo", 0}, ':'
+ },
+ {"argv_join, empty",
+ {0}, 0, test_argv_join,
+ 0, 1, {"", 0}, ':'
+ },
0,
};
diff --git a/src/util/argv.h b/src/util/argv.h
index b0098ce..f1e746a 100644
--- a/src/util/argv.h
+++ b/src/util/argv.h
@@ -33,6 +33,8 @@ extern void argv_truncate(ARGV *, ssize_t);
extern void argv_insert_one(ARGV *, ssize_t, const char *);
extern void argv_replace_one(ARGV *, ssize_t, const char *);
extern void argv_delete(ARGV *, ssize_t, ssize_t);
+struct VSTRING;
+extern char *argv_join(struct VSTRING *buf, ARGV *, int);
extern ARGV *argv_free(ARGV *);
extern ARGV *argv_split(const char *, const char *);
diff --git a/src/util/casefold.c b/src/util/casefold.c
index d3ebd4b..94860b8 100644
--- a/src/util/casefold.c
+++ b/src/util/casefold.c
@@ -300,7 +300,7 @@ int main(int argc, char **argv)
encode_utf8(buffer, codepoint);
if (msg_verbose)
vstream_printf("U+%X -> %s\n", codepoint, STR(buffer));
- if (valid_utf8_string(STR(buffer), LEN(buffer)) == 0)
+ if (valid_utf8_stringz(STR(buffer)) == 0)
msg_fatal("bad utf-8 encoding for U+%X\n", codepoint);
casefold(dest, STR(buffer));
}
diff --git a/src/util/dict_inline.c b/src/util/dict_inline.c
index 72339b2..d7f9344 100644
--- a/src/util/dict_inline.c
+++ b/src/util/dict_inline.c
@@ -87,7 +87,7 @@ DICT *dict_inline_open(const char *name, int open_flags, int dict_flags)
*/
if (DICT_NEED_UTF8_ACTIVATION(util_utf8_enable, dict_flags)
&& allascii(name) == 0
- && valid_utf8_string(name, strlen(name)) == 0)
+ && valid_utf8_stringz(name) == 0)
DICT_INLINE_RETURN(dict_surrogate(DICT_TYPE_INLINE, name,
open_flags, dict_flags,
"bad UTF-8 syntax: \"%s:%s\"; "
diff --git a/src/util/dict_thash.c b/src/util/dict_thash.c
index 69eb17b..bae4a63 100644
--- a/src/util/dict_thash.c
+++ b/src/util/dict_thash.c
@@ -127,7 +127,7 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
*/
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE)
&& allascii(STR(line_buffer)) == 0
- && valid_utf8_string(STR(line_buffer), LEN(line_buffer)) == 0) {
+ && valid_utf8_stringz(STR(line_buffer)) == 0) {
msg_warn("%s, line %d: non-UTF-8 input \"%s\""
" -- ignoring this line",
VSTREAM_PATH(fp), lineno, STR(line_buffer));
@@ -181,8 +181,8 @@ DICT *dict_thash_open(const char *path, int open_flags, int dict_flags)
" is this an alias file?", path, lineno);
/*
- * Optionally treat the value as a filename, and replace the value
- * with the BASE64-encoded content of the named file.
+ * Optionally treat the value as a filename, and replace the
+ * value with the BASE64-encoded content of the named file.
*/
if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
VSTRING *base64_buf;
diff --git a/src/util/dict_utf8.c b/src/util/dict_utf8.c
index f1fc65a..9bb6b7b 100644
--- a/src/util/dict_utf8.c
+++ b/src/util/dict_utf8.c
@@ -100,7 +100,7 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string,
/*
* Validate UTF-8 without casefolding.
*/
- if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) {
+ if (!allascii(string) && valid_utf8_stringz(string) == 0) {
if (err)
*err = "malformed UTF-8 or invalid codepoint";
return (0);
@@ -123,7 +123,7 @@ static char *dict_utf8_check_fold(DICT *dict, const char *string,
static int dict_utf8_check(const char *string, CONST_CHAR_STAR *err)
{
- if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) {
+ if (!allascii(string) && valid_utf8_stringz(string) == 0) {
if (err)
*err = "malformed UTF-8 or invalid codepoint";
return (0);
diff --git a/src/util/inet_prefix_top.c b/src/util/inet_prefix_top.c
index 8d5af00..f35d5f0 100644
--- a/src/util/inet_prefix_top.c
+++ b/src/util/inet_prefix_top.c
@@ -164,6 +164,7 @@ int main(int argc, char **argv)
msg_info("PASS %s/%d", str_name_code(af_map, tp->in_af),
tp->in_prefix_len);
}
+ myfree(act_prefix);
}
msg_info("PASS=%d FAIL=%d", pass, fail);
return (fail > 0);
diff --git a/src/util/logwriter.c b/src/util/logwriter.c
index aea2767..4a18be3 100644
--- a/src/util/logwriter.c
+++ b/src/util/logwriter.c
@@ -21,6 +21,9 @@
/* const char *path,
/* const char *buffer,
/* ssize_t buflen)
+/*
+/* int set_logwriter_create_perms(
+/* const char *mode)
/* DESCRIPTION
/* This module manages a logfile writer.
/*
@@ -38,6 +41,15 @@
/* logwriter_one_shot() combines all the above operations. The
/* result is zero if successful, VSTREAM_EOF if any operation
/* failed.
+/*
+/* set_logwriter_create_perms() sets the file permissions that
+/* will be used when creating a logfile. Valid inputs are
+/* "644", "640", and "600". Leading zeros are allowed and
+/* ignored.
+/* DIAGNOSTICS
+/* Fatal error: logfile create error; warning: logfile permission
+/* change error. set_logwriter_create_perms() returns the file
+/* create permission if the request is valid, -1 otherwise.
/* LICENSE
/* .ad
/* .fi
@@ -66,10 +78,12 @@
#include <mymalloc.h>
#include <safe_open.h>
#include <vstream.h>
+#include <name_code.h>
/*
* Application-specific.
*/
+static int logwriter_perms = 0600;
/* logwriter_open_or_die - open logfile */
@@ -82,7 +96,7 @@ VSTREAM *logwriter_open_or_die(const char *path)
#define NO_CHOWN (-1)
#define NO_CHGRP (-1)
- fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, 0644,
+ fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, logwriter_perms,
NO_STATP, NO_CHOWN, NO_CHGRP, why);
if (fp == 0)
msg_fatal("open logfile '%s': %s", path, vstring_str(why));
@@ -122,3 +136,21 @@ int logwriter_one_shot(const char *path, const char *buf, ssize_t len)
err |= logwriter_close(fp);
return (err ? VSTREAM_EOF : 0);
}
+
+/* set_logwriter_create_perms - logfile permission control */
+
+int set_logwriter_create_perms(const char *mode_str)
+{
+ static const NAME_CODE sane_perms[] = {
+ "644", 0644,
+ "640", 0640,
+ "600", 0600,
+ 0, -1,
+ };
+ int perms;
+
+ if ((perms = name_code(sane_perms, NAME_CODE_FLAG_NONE,
+ mode_str + strspn(mode_str, "0"))) != -1)
+ logwriter_perms = perms;
+ return (perms);
+}
diff --git a/src/util/logwriter.h b/src/util/logwriter.h
index f5266e4..c827d25 100644
--- a/src/util/logwriter.h
+++ b/src/util/logwriter.h
@@ -23,6 +23,7 @@ extern VSTREAM *logwriter_open_or_die(const char *);
extern int logwriter_write(VSTREAM *, const char *, ssize_t);
extern int logwriter_close(VSTREAM *);
extern int logwriter_one_shot(const char *, const char *, ssize_t);
+extern int set_logwriter_create_perms(const char *);
/* LICENSE
/* .ad
diff --git a/src/util/midna_domain.c b/src/util/midna_domain.c
index 333a5c9..bc016b6 100644
--- a/src/util/midna_domain.c
+++ b/src/util/midna_domain.c
@@ -178,7 +178,7 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context
/*
* Paranoia: do not expose uidna_*() to unfiltered network data.
*/
- if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) {
+ if (allascii(name) == 0 && valid_utf8_stringz(name) == 0) {
msg_warn("%s: Problem translating domain \"%.100s\" to ASCII form: %s",
myname, name, "malformed UTF-8");
return (0);
@@ -232,7 +232,7 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context)
/*
* Paranoia: do not expose uidna_*() to unfiltered network data.
*/
- if (allascii(name) == 0 && valid_utf8_string(name, strlen(name)) == 0) {
+ if (allascii(name) == 0 && valid_utf8_stringz(name) == 0) {
msg_warn("%s: Problem translating domain \"%.100s\" to UTF-8 form: %s",
myname, name, "malformed UTF-8");
return (0);
diff --git a/src/util/parse_utf8_char.h b/src/util/parse_utf8_char.h
new file mode 100644
index 0000000..b00a1c2
--- /dev/null
+++ b/src/util/parse_utf8_char.h
@@ -0,0 +1,122 @@
+/*++
+/* NAME
+/* parse_utf8_char 3h
+/* SUMMARY
+/* parse one UTF-8 multibyte character
+/* SYNOPSIS
+/* #include <parse_utf8_char.h>
+/*
+/* char *parse_utf8_char(str, end)
+/* const char *str;
+/* const char *end;
+/* DESCRIPTION
+/* parse_utf8_char() determines if the byte sequence starting
+/* at \fBstr\fR begins with a complete UTF-8 character as
+/* defined in RFC 3629. That is, a proper encoding of code
+/* points U+0000..U+10FFFF, excluding over-long encodings and
+/* excluding U+D800..U+DFFF surrogates.
+/*
+/* When the byte sequence starting at \fBstr\fR begins with a
+/* complete UTF-8 character, this function returns a pointer
+/* to the last byte in that character. Otherwise, it returns
+/* a null pointer.
+/*
+/* The \fBend\fR argument is either null (the byte sequence
+/* starting at \fBstr\fR must be null terminated), or \fBend
+/* - str\fR specifies the length of the byte sequence.
+/* BUGS
+/* Code points in the range U+FDD0..U+FDEF and ending in FFFE
+/* or FFFF are non-characters in UNICODE. This function does
+/* not reject these.
+/* 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
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+#ifdef NO_INLINE
+#define inline /* */
+#endif
+
+/* parse_utf8_char - parse and validate one UTF8 multibyte sequence */
+
+static inline char *parse_utf8_char(const char *str, const char *end)
+{
+ const unsigned char *cp = (const unsigned char *) str;
+ const unsigned char *ep = (const unsigned char *) end;
+ unsigned char c0, ch;
+
+ /*
+ * Optimized for correct input, time, space, and for CPUs that have a
+ * decent number of registers. Other implementation considerations:
+ *
+ * - In the UTF-8 encoding, a non-leading byte is never null. Therefore,
+ * this function will correctly reject a partial UTF-8 character at the
+ * end of a null-terminated string.
+ *
+ * - If the "end" argument is a null constant, and if this function is
+ * inlined, then an optimizing compiler should propagate the constant
+ * through the "ep" variable, and eliminate any code branches that
+ * require ep != 0.
+ */
+ /* Single-byte encodings. */
+ if (EXPECTED((c0 = *cp) <= 0x7f) /* we know that c0 >= 0x0 */ ) {
+ return ((char *) cp);
+ }
+ /* Two-byte encodings. */
+ else if (EXPECTED(c0 <= 0xdf) /* we know that c0 >= 0x80 */ ) {
+ /* Exclude over-long encodings. */
+ if (UNEXPECTED(c0 < 0xc2)
+ || UNEXPECTED(ep && cp + 1 >= ep)
+ /* Require UTF-8 tail byte. */
+ || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80))
+ return (0);
+ return ((char *) cp);
+ }
+ /* Three-byte encodings. */
+ else if (EXPECTED(c0 <= 0xef) /* we know that c0 >= 0xe0 */ ) {
+ if (UNEXPECTED(ep && cp + 2 >= ep)
+ /* Exclude over-long encodings. */
+ || UNEXPECTED((ch = *++cp) < (c0 == 0xe0 ? 0xa0 : 0x80))
+ /* Exclude U+D800..U+DFFF. */
+ || UNEXPECTED(ch > (c0 == 0xed ? 0x9f : 0xbf))
+ /* Require UTF-8 tail byte. */
+ || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80))
+ return (0);
+ return ((char *) cp);
+ }
+ /* Four-byte encodings. */
+ else if (EXPECTED(c0 <= 0xf4) /* we know that c0 >= 0xf0 */ ) {
+ if (UNEXPECTED(ep && cp + 3 >= ep)
+ /* Exclude over-long encodings. */
+ || UNEXPECTED((ch = *++cp) < (c0 == 0xf0 ? 0x90 : 0x80))
+ /* Exclude code points above U+10FFFF. */
+ || UNEXPECTED(ch > (c0 == 0xf4 ? 0x8f : 0xbf))
+ /* Require UTF-8 tail byte. */
+ || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)
+ /* Require UTF-8 tail byte. */
+ || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80))
+ return (0);
+ return ((char *) cp);
+ }
+ /* Invalid: c0 >= 0xf5 */
+ else {
+ return (0);
+ }
+}
+
+#undef inline
diff --git a/src/util/printable.c b/src/util/printable.c
index 6c148fd..0e1ae19 100644
--- a/src/util/printable.c
+++ b/src/util/printable.c
@@ -45,6 +45,10 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
/*--*/
/* System library. */
@@ -56,8 +60,9 @@
/* Utility library. */
#include "stringops.h"
+#include "parse_utf8_char.h"
-int util_utf8_enable = 0;
+int util_utf8_enable = 0;
/* printable - binary compatibility */
@@ -74,27 +79,150 @@ char *printable(char *string, int replacement)
char *printable_except(char *string, int replacement, const char *except)
{
- unsigned char *cp;
+ char *cp;
+ char *last;
int ch;
/*
- * XXX Replace invalid UTF8 sequences (too short, over-long encodings,
- * out-of-range code points, etc). See valid_utf8_string.c.
+ * In case of a non-UTF8 sequence (bad leader byte, bad non-leader byte,
+ * over-long encodings, out-of-range code points, etc), replace the first
+ * byte, and try to resynchronize at the next byte.
*/
- cp = (unsigned char *) string;
- while ((ch = *cp) != 0) {
- if (ISASCII(ch) && (ISPRINT(ch) || (except && strchr(except, ch)))) {
- /* ok */
- } else if (util_utf8_enable && ch >= 194 && ch <= 254
- && cp[1] >= 128 && cp[1] < 192) {
- /* UTF8; skip the rest of the bytes in the character. */
- while (cp[1] >= 128 && cp[1] < 192)
- cp++;
- } else {
- /* Not ASCII and not UTF8. */
- *cp = replacement;
+#define PRINT_OR_EXCEPT(ch) (ISPRINT(ch) || (except && strchr(except, ch)))
+
+ for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++) {
+ if (util_utf8_enable == 0) {
+ if (ISASCII(ch) && PRINT_OR_EXCEPT(ch))
+ continue;
+ } else if ((last = parse_utf8_char(cp, 0)) == cp) { /* ASCII */
+ if (PRINT_OR_EXCEPT(ch))
+ continue;
+ } else if (last != 0) { /* Other UTF8 */
+ cp = last;
+ continue;
}
- cp++;
+ *cp = replacement;
}
return (string);
}
+
+#ifdef TEST
+
+#include <stdlib.h>
+#include <string.h>
+#include <msg.h>
+#include <msg_vstream.h>
+#include <mymalloc.h>
+#include <vstream.h>
+
+ /*
+ * Test cases for 1-, 2-, and 3-byte encodings. Originally contributed by
+ * Viktor Dukhovni, and annotated using translate.google.com.
+ *
+ * See valid_utf8_string.c for single-error tests.
+ *
+ * XXX Need a test for 4-byte encodings, preferably with strings that can be
+ * displayed.
+ */
+struct testcase {
+ const char *name;
+ const char *input;
+ const char *expected;;
+};
+static const struct testcase testcases[] = {
+ {"Printable ASCII",
+ "printable", "printable"
+ },
+ {"ASCII with control character",
+ "non\bn-printable", "non?n-printable"
+ },
+ {"Latin accented text, no error",
+ "na\303\257ve", "na\303\257ve"
+ },
+ {"Latin text, with error",
+ "na\303ve", "na?ve"
+ },
+ {"Viktor, Cyrillic, no error",
+ "\320\262\320\270\320\272\321\202\320\276\321\200",
+ "\320\262\320\270\320\272\321\202\320\276\321\200"
+ },
+ {"Viktor, Cyrillic, two errors",
+ "\320\262\320\320\272\272\321\202\320\276\321\200",
+ "\320\262?\320\272?\321\202\320\276\321\200"
+ },
+ {"Viktor, Hebrew, no error",
+ "\327\225\327\231\327\247\327\230\327\225\326\274\327\250",
+ "\327\225\327\231\327\247\327\230\327\225\326\274\327\250"
+ },
+ {"Viktor, Hebrew, with error",
+ "\327\225\231\327\247\327\230\327\225\326\274\327\250",
+ "\327\225?\327\247\327\230\327\225\326\274\327\250"
+ },
+ {"Chinese (Simplified), no error",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345\221\212",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345\221\212"
+ },
+ {"Chinese (Simplified), with errors",
+ "\344\270\255\345\344\272\222\350\224\347\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345",
+ "\344\270\255?\344\272\222??\347\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245?"
+ },
+};
+
+int main(int argc, char **argv)
+{
+ const struct testcase *tp;
+ int pass;
+ int fail;
+
+#define NUM_TESTS sizeof(testcases)/sizeof(testcases[0])
+
+ msg_vstream_init(basename(argv[0]), VSTREAM_ERR);
+ util_utf8_enable = 1;
+
+ for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) {
+ char *input;
+ char *actual;
+ int ok = 0;
+
+ /*
+ * Notes:
+ *
+ * - The input is modified, therefore it must be copied.
+ *
+ * - The msg(3) functions use printable() which interferes when logging
+ * inputs and outputs. Use vstream_fprintf() instead.
+ */
+ vstream_fprintf(VSTREAM_ERR, "RUN %s\n", tp->name);
+ input = mystrdup(tp->input);
+ actual = printable(input, '?');
+
+ if (strcmp(actual, tp->expected) != 0) {
+ vstream_fprintf(VSTREAM_ERR, "input: >%s<, got: >%s<, want: >%s<\n",
+ tp->input, actual, tp->expected);
+ } else {
+ vstream_fprintf(VSTREAM_ERR, "input: >%s<, got and want: >%s<\n",
+ tp->input, actual);
+ ok = 1;
+ }
+ if (ok) {
+ vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name);
+ pass++;
+ } else {
+ vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
+ fail++;
+ }
+ myfree(input);
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ return (fail > 0);
+}
+
+#endif
diff --git a/src/util/quote_for_json.c b/src/util/quote_for_json.c
new file mode 100644
index 0000000..f54af3f
--- /dev/null
+++ b/src/util/quote_for_json.c
@@ -0,0 +1,218 @@
+/*++
+/* NAME
+/* quote_for_json 3
+/* SUMMARY
+/* quote UTF-8 string value for JSON
+/* SYNOPSIS
+/* #include <quote_for_json.h>
+/*
+/* char *quote_for_json(
+/* VSTRING *result,
+/* const char *in,
+/* ssize_t len)
+/*
+/* char *quote_for_json_append(
+/* VSTRING *result,
+/* const char *in,
+/* ssize_t len)
+/* DESCRIPTION
+/* quote_for_json() takes well-formed UTF-8 encoded text,
+/* quotes that text compliant with RFC 4627, and returns a
+/* pointer to the resulting text. The input may contain null
+/* bytes, but the output will not.
+/*
+/* quote_for_json() produces short (two-letter) escape sequences
+/* for common control characters, double quote and backslash.
+/* It will not quote "/" (0x2F), and will quote DEL (0x7f) as
+/* \u007F to make it printable. The input byte sequence "\uXXXX"
+/* is quoted like any other text (the "\" is escaped as "\\").
+/*
+/* quote_for_json() does not perform UTF-8 validation. The caller
+/* should use valid_utf8_string() or printable() as appropriate.
+/*
+/* quote_for_json_append() appends the output to the result buffer.
+/*
+/* Arguments:
+/* .IP result
+/* Storage for the result, resized automatically.
+/* .IP in
+/* Pointer to the input byte sequence.
+/* .IP len
+/* The length of the input byte sequence, or a negative number
+/* when the byte sequence is null-terminated.
+/* DIAGNOSTICS
+/* Fatal error: memory allocation error.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <ctype.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <stringops.h>
+#include <vstring.h>
+
+#define STR(x) vstring_str(x)
+
+/* quote_for_json_append - quote JSON string, append result */
+
+char *quote_for_json_append(VSTRING *result, const char *text, ssize_t len)
+{
+ const char *cp;
+ int ch;
+
+ if (len < 0)
+ len = strlen(text);
+
+ for (cp = text; len > 0; len--, cp++) {
+ ch = *(const unsigned char *) cp;
+ if (UNEXPECTED(ISCNTRL(ch))) {
+ switch (ch) {
+ case '\b':
+ VSTRING_ADDCH(result, '\\');
+ VSTRING_ADDCH(result, 'b');
+ break;
+ case '\f':
+ VSTRING_ADDCH(result, '\\');
+ VSTRING_ADDCH(result, 'f');
+ break;
+ case '\n':
+ VSTRING_ADDCH(result, '\\');
+ VSTRING_ADDCH(result, 'n');
+ break;
+ case '\r':
+ VSTRING_ADDCH(result, '\\');
+ VSTRING_ADDCH(result, 'r');
+ break;
+ case '\t':
+ VSTRING_ADDCH(result, '\\');
+ VSTRING_ADDCH(result, 't');
+ break;
+ default:
+ /* All other controls including DEL and NUL. */
+ vstring_sprintf_append(result, "\\u%04X", ch);
+ break;
+ }
+ } else {
+ switch (ch) {
+ case '\\':
+ case '"':
+ VSTRING_ADDCH(result, '\\');
+ /* FALLTHROUGH */
+ default:
+ /* Includes malformed UTF-8. */
+ VSTRING_ADDCH(result, ch);
+ break;
+ }
+ }
+ }
+ VSTRING_TERMINATE(result);
+ return (STR(result));
+}
+
+/* quote_for_json - quote JSON string */
+
+char *quote_for_json(VSTRING *result, const char *text, ssize_t len)
+{
+ VSTRING_RESET(result);
+ return (quote_for_json_append(result, text, len));
+}
+
+#ifdef TEST
+
+ /*
+ * System library.
+ */
+#include <stdlib.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <msg_vstream.h>
+
+typedef struct TEST_CASE {
+ const char *label; /* identifies test case */
+ char *(*fn) (VSTRING *, const char *, ssize_t);
+ const char *input; /* input string */
+ ssize_t input_len; /* -1 or input length */
+ const char *exp_res; /* expected result */
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+ /*
+ * The test cases.
+ */
+static const TEST_CASE test_cases[] = {
+ {"ordinary ASCII text", quote_for_json,
+ " abcABC012.,[]{}/", -1, " abcABC012.,[]{}/",
+ },
+ {"quote_for_json_append", quote_for_json_append,
+ "foo", -1, " abcABC012.,[]{}/foo",
+ },
+ {"common control characters", quote_for_json,
+ "\b\f\r\n\t", -1, "\\b\\f\\r\\n\\t",
+ },
+ {"uncommon control characters and DEL", quote_for_json,
+ "\0\01\037\040\176\177", 6, "\\u0000\\u0001\\u001F ~\\u007F",
+ },
+ {"malformed UTF-8", quote_for_json,
+ "\\*\\uasd\\u007F\x80", -1, "\\\\*\\\\uasd\\\\u007F\x80",
+ },
+ 0,
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+ VSTRING *res_buf = vstring_alloc(100);
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_fail = 0;
+ char *res;
+
+ msg_info("RUN %s", tp->label);
+ res = tp->fn(res_buf, tp->input, tp->input_len);
+ if (strcmp(res, tp->exp_res) != 0) {
+ msg_warn("test case '%s': got '%s', want '%s'",
+ tp->label, res, tp->exp_res);
+ test_fail = 1;
+ }
+ if (test_fail) {
+ fail++;
+ msg_info("FAIL %s", tp->label);
+ test_fail = 1;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ vstring_free(res_buf);
+ exit(fail != 0);
+}
+
+#endif
diff --git a/src/util/readlline.c b/src/util/readlline.c
index 015877a..721b75f 100644
--- a/src/util/readlline.c
+++ b/src/util/readlline.c
@@ -85,9 +85,15 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
int next;
ssize_t start;
char *cp;
+ int my_lineno = 0, my_first_line, got_null = 0;
VSTRING_RESET(buf);
+ if (lineno == 0)
+ lineno = &my_lineno;
+ if (first_line == 0)
+ first_line = &my_first_line;
+
/*
* Ignore comment lines, all whitespace lines, and empty lines. Terminate
* at EOF or at the beginning of the next logical line.
@@ -95,16 +101,19 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
for (;;) {
/* Read one line, possibly not newline terminated. */
start = LEN(buf);
- while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
+ while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n') {
VSTRING_ADDCH(buf, ch);
- if (lineno != 0 && (ch == '\n' || LEN(buf) > start))
+ if (ch == 0)
+ got_null = 1;
+ }
+ if (ch == '\n' || LEN(buf) > start)
*lineno += 1;
/* Ignore comment line, all whitespace line, or empty line. */
for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++)
/* void */ ;
if (cp == END(buf) || *cp == '#')
vstring_truncate(buf, start);
- else if (start == 0 && lineno != 0 && first_line != 0)
+ if (start == 0)
*first_line = *lineno;
/* Terminate at EOF or at the beginning of the next logical line. */
if (ch == VSTREAM_EOF)
@@ -119,6 +128,20 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
VSTRING_TERMINATE(buf);
/*
+ * This code does not care about embedded null bytes, but callers do.
+ */
+ if (got_null) {
+ const char *why = "text after null byte may be ignored";
+
+ if (*first_line == *lineno)
+ msg_warn("%s, line %d: %s",
+ VSTREAM_PATH(fp), *lineno, why);
+ else
+ msg_warn("%s, line %d-%d: %s",
+ VSTREAM_PATH(fp), *first_line, *lineno, why);
+ }
+
+ /*
* Invalid input: continuing text without preceding text. Allowing this
* would complicate "postconf -e", which implements its own multi-line
* parsing routine. Do not abort, just warn, so that critical programs
@@ -136,3 +159,205 @@ VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
*/
return (LEN(buf) > 0 ? buf : 0);
}
+
+ /*
+ * Stand-alone test program.
+ */
+#ifdef TEST
+#include <stdlib.h>
+#include <string.h>
+#include <msg.h>
+#include <msg_vstream.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Test cases. Note: the input and exp_output fields are converted with
+ * unescape(). Embedded null bytes must be specified as \\0.
+ */
+struct testcase {
+ const char *name;
+ const char *input;
+ const char *exp_output;
+ int exp_first_line;
+ int exp_last_line;
+};
+
+static const struct testcase testcases[] = {
+ {"leading space before non-comment",
+ " abcde\nfghij\n",
+ "fghij",
+ 2, 2
+ /* Expect "logical line must not start with whitespace" */
+ },
+ {"leading space before leading comment",
+ " #abcde\nfghij\n",
+ "fghij",
+ 2, 2
+ },
+ {"leading #comment at beginning of line",
+ "#abc\ndef",
+ "def",
+ 2, 2,
+ },
+ {"empty line before non-comment",
+ "\nabc\n",
+ "abc",
+ 2, 2,
+ },
+ {"whitespace line before non-comment",
+ " \nabc\n",
+ "abc",
+ 2, 2,
+ },
+ {"missing newline at end of non-comment",
+ "abc def",
+ "abc def",
+ 1, 1,
+ },
+ {"missing newline at end of comment",
+ "#abc def",
+ "",
+ 1, 1,
+ },
+ {"embedded null, single-line",
+ "abc\\0def",
+ "abc\\0def",
+ 1, 1,
+ /* Expect "line 1: text after null byte may be ignored" */
+ },
+ {"embedded null, multiline",
+ "abc\\0\n def",
+ "abc\\0 def",
+ 1, 2,
+ /* Expect "line 1-2: text after null byte may be ignored" */
+ },
+ {"embedded null in comment",
+ "#abc\\0\ndef",
+ "def",
+ 2, 2,
+ /* Expect "line 2: text after null byte may be ignored" */
+ },
+ {"multiline input",
+ "abc\n def\n",
+ "abc def",
+ 1, 2,
+ },
+ {"multiline input with embedded #comment after space",
+ "abc\n #def\n ghi",
+ "abc ghi",
+ 1, 3,
+ },
+ {"multiline input with embedded #comment flush left",
+ "abc\n#def\n ghi",
+ "abc ghi",
+ 1, 3,
+ },
+ {"multiline input with embedded whitespace line",
+ "abc\n \n ghi",
+ "abc ghi",
+ 1, 3,
+ },
+ {"multiline input with embedded empty line",
+ "abc\n\n ghi",
+ "abc ghi",
+ 1, 3,
+ },
+ {"multiline input with embedded #comment after space",
+ "abc\n #def\n",
+ "abc",
+ 1, 2,
+ },
+ {"multiline input with embedded #comment flush left",
+ "abc\n#def\n",
+ "abc",
+ 1, 2,
+ },
+ {"empty line at end of file",
+ "\n",
+ "",
+ 1, 1,
+ },
+ {"whitespace line at end of file",
+ "\n \n",
+ "",
+ 2, 2,
+ },
+ {"whitespace at end of file",
+ "abc\n ",
+ "abc",
+ 1, 2,
+ },
+};
+
+int main(int argc, char **argv)
+{
+ const struct testcase *tp;
+ VSTRING *inp_buf = vstring_alloc(100);
+ VSTRING *exp_buf = vstring_alloc(100);
+ VSTRING *out_buf = vstring_alloc(100);
+ VSTRING *esc_buf = vstring_alloc(100);
+ VSTREAM *fp;
+ int last_line;
+ int first_line;
+ int pass;
+ int fail;
+
+#define NUM_TESTS sizeof(testcases)/sizeof(testcases[0])
+
+ msg_vstream_init(basename(argv[0]), VSTREAM_ERR);
+ util_utf8_enable = 1;
+
+ for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) {
+ int ok = 0;
+
+ vstream_fprintf(VSTREAM_ERR, "RUN %s\n", tp->name);
+ unescape(inp_buf, tp->input);
+ unescape(exp_buf, tp->exp_output);
+ if ((fp = vstream_memopen(inp_buf, O_RDONLY)) == 0)
+ msg_panic("open memory stream for reading: %m");
+ vstream_control(fp, CA_VSTREAM_CTL_PATH("memory buffer"),
+ CA_VSTREAM_CTL_END);
+ last_line = 0;
+ if (readllines(out_buf, fp, &last_line, &first_line) == 0) {
+ VSTRING_RESET(out_buf);
+ VSTRING_TERMINATE(out_buf);
+ }
+ if (LEN(out_buf) != LEN(exp_buf)) {
+ msg_warn("unexpected output length, got: %ld, want: %ld",
+ (long) LEN(out_buf), (long) LEN(exp_buf));
+ } else if (memcmp(STR(out_buf), STR(exp_buf), LEN(out_buf)) != 0) {
+ msg_warn("unexpected output: got: >%s<, want: >%s<",
+ STR(escape(esc_buf, STR(out_buf), LEN(out_buf))),
+ tp->exp_output);
+ } else if (first_line != tp->exp_first_line) {
+ msg_warn("unexpected first_line: got: %d, want: %d",
+ first_line, tp->exp_first_line);
+ } else if (last_line != tp->exp_last_line) {
+ msg_warn("unexpected last_line: got: %d, want: %d",
+ last_line, tp->exp_last_line);
+ } else {
+ vstream_fprintf(VSTREAM_ERR, "got and want: >%s<\n",
+ tp->exp_output);
+ ok = 1;
+ }
+ if (ok) {
+ vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name);
+ pass++;
+ } else {
+ vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
+ fail++;
+ }
+ vstream_fclose(fp);
+ }
+ vstring_free(inp_buf);
+ vstring_free(exp_buf);
+ vstring_free(out_buf);
+ vstring_free(esc_buf);
+
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ return (fail > 0);
+}
+
+#endif
diff --git a/src/util/stringops.h b/src/util/stringops.h
index 97aa597..db56f23 100644
--- a/src/util/stringops.h
+++ b/src/util/stringops.h
@@ -60,10 +60,13 @@ extern int allascii_len(const char *, ssize_t);
extern const char *WARN_UNUSED_RESULT split_nameval(char *, char **, char **);
extern const char *WARN_UNUSED_RESULT split_qnameval(char *, char **, char **);
extern int valid_utf8_string(const char *, ssize_t);
+extern int valid_utf8_stringz(const char *);
extern size_t balpar(const char *, const char *);
extern char *WARN_UNUSED_RESULT extpar(char **, const char *, int);
extern int strcasecmp_utf8x(int, const char *, const char *);
extern int strncasecmp_utf8x(int, const char *, const char *, ssize_t);
+extern char *quote_for_json(VSTRING *, const char *, ssize_t);
+extern char *quote_for_json_append(VSTRING *, const char *, ssize_t);
#define EXTPAR_FLAG_NONE (0)
#define EXTPAR_FLAG_STRIP (1<<0) /* "{ text }" -> "text" */
diff --git a/src/util/sys_defs.h b/src/util/sys_defs.h
index 9247185..62749ab 100644
--- a/src/util/sys_defs.h
+++ b/src/util/sys_defs.h
@@ -1332,6 +1332,13 @@ extern int dup2_pass_on_exec(int oldd, int newd);
#endif
/*
+ * The RFC 5322 Date and Time Specification recommends single space between
+ * date-time tokens. To avoid breaking change, format all numerical days as
+ * two-digit days (i.e. days 1-9 now have a leading zero instead of space).
+ */
+#define TWO_DIGIT_DAY_IN_DATE_TIME
+
+ /*
* Check for required but missing definitions.
*/
#if !defined(HAS_FCNTL_LOCK) && !defined(HAS_FLOCK_LOCK)
diff --git a/src/util/valid_hostname.c b/src/util/valid_hostname.c
index 8b234c4..457d1f1 100644
--- a/src/util/valid_hostname.c
+++ b/src/util/valid_hostname.c
@@ -6,9 +6,9 @@
/* SYNOPSIS
/* #include <valid_hostname.h>
/*
-/* int valid_hostname(name, gripe)
+/* int valid_hostname(name, flags)
/* const char *name;
-/* int gripe;
+/* int flags;
/*
/* int valid_hostaddr(addr, gripe)
/* const char *addr;
@@ -32,6 +32,10 @@
/* dots, no leading or trailing dots or hyphens, no labels
/* longer than VALID_LABEL_LEN characters, and it should not
/* be all numeric.
+/* The flags argument is the bit-wise or of zero or more of
+/* DO_GRIPE or DO_WILDCARD (the latter allows the "*." name
+/* prefix, which is rare but valid in some DNS responses and
+/* queries).
/*
/* valid_hostaddr() requires that the input is a valid string
/* representation of an IPv4 or IPv6 network address as
@@ -403,8 +407,9 @@ int main(int unused_argc, char **argv)
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
msg_info("testing: \"%s\"", vstring_str(buffer));
- valid_hostname(vstring_str(buffer), DO_GRIPE);
- valid_hostaddr(vstring_str(buffer), DO_GRIPE);
+ valid_hostname(vstring_str(buffer), DO_GRIPE | DO_WILDCARD);
+ if (strchr(vstring_str(buffer), '*') == 0)
+ valid_hostaddr(vstring_str(buffer), DO_GRIPE);
}
exit(0);
}
diff --git a/src/util/valid_hostname.in b/src/util/valid_hostname.in
index 608c0d1..4cdf019 100644
--- a/src/util/valid_hostname.in
+++ b/src/util/valid_hostname.in
@@ -53,3 +53,9 @@ g:a:a:a:a:a:a:a
a::b
:a::b
a::b:
+*.foo.bar
+*foo.bar
+foo.*.bar
+foo*bar
+foo.bar*
+*
diff --git a/src/util/valid_hostname.ref b/src/util/valid_hostname.ref
index 08b23b8..eccc558 100644
--- a/src/util/valid_hostname.ref
+++ b/src/util/valid_hostname.ref
@@ -141,3 +141,13 @@
./valid_hostname: testing: "a::b:"
./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a::b:
./valid_hostname: warning: valid_ipv6_hostaddr: bad null last field in IPv6 address: a::b:
+./valid_hostname: testing: "*.foo.bar"
+./valid_hostname: testing: "*foo.bar"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: *foo.bar
+./valid_hostname: testing: "foo.*.bar"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo.*.bar
+./valid_hostname: testing: "foo*bar"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo*bar
+./valid_hostname: testing: "foo.bar*"
+./valid_hostname: warning: valid_hostname: '*' can be the first label only: foo.bar*
+./valid_hostname: testing: "*"
diff --git a/src/util/valid_utf8_string.c b/src/util/valid_utf8_string.c
index 96b5b4d..f5b4ff4 100644
--- a/src/util/valid_utf8_string.c
+++ b/src/util/valid_utf8_string.c
@@ -9,24 +9,24 @@
/* int valid_utf8_string(str, len)
/* const char *str;
/* ssize_t len;
+/*
+/* int valid_utf8_stringz(str)
+/* const char *str;
+/* ssize_t len;
/* DESCRIPTION
-/* valid_utf8_string() determines if a string satisfies the UTF-8
-/* definition in RFC 3629. That is, it contains proper encodings
-/* of code points U+0000..U+10FFFF, excluding over-long encodings
-/* and excluding U+D800..U+DFFF surrogates.
+/* valid_utf8_string() determines if all bytes in a string
+/* satisfy parse_utf8_char(3h) checks. See there for any
+/* implementation limitations.
+/*
+/* valid_utf8_stringz() determines the same for zero-terminated
+/* strings.
/*
/* A zero-length string is considered valid.
/* DIAGNOSTICS
/* The result value is zero when the caller specifies a negative
-/* length, or a string that violates RFC 3629, for example a
-/* string that is truncated in the middle of a multi-byte
-/* sequence.
-/* BUGS
-/* But wait, there is more. Code points in the range U+FDD0..U+FDEF
-/* and ending in FFFE or FFFF are non-characters in UNICODE. This
-/* function does not block these.
+/* length, or a string that does not pass parse_utf8_char(3h) checks.
/* SEE ALSO
-/* RFC 3629
+/* parse_utf8_char(3h), parse one UTF-8 multibyte character
/* LICENSE
/* .ad
/* .fi
@@ -36,6 +36,10 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
/*--*/
/* System library. */
@@ -45,66 +49,50 @@
/* Utility library. */
#include <stringops.h>
+#include <parse_utf8_char.h>
/* valid_utf8_string - validate string according to RFC 3629 */
int valid_utf8_string(const char *str, ssize_t len)
{
- const unsigned char *end = (const unsigned char *) str + len;
- const unsigned char *cp;
- unsigned char c0, ch;
+ const char *ep = str + len;
+ const char *cp;
+ const char *last;
if (len < 0)
return (0);
- if (len <= 0)
+ if (len == 0)
return (1);
/*
- * Optimized for correct input, time, space, and for CPUs that have a
- * decent number of registers.
+ * Ideally, the compiler will inline parse_utf8_char().
*/
- for (cp = (const unsigned char *) str; cp < end; cp++) {
- /* Single-byte encodings. */
- if (EXPECTED((c0 = *cp) <= 0x7f) /* we know that c0 >= 0x0 */ ) {
- /* void */ ;
- }
- /* Two-byte encodings. */
- else if (EXPECTED(c0 <= 0xdf) /* we know that c0 >= 0x80 */ ) {
- /* Exclude over-long encodings. */
- if (UNEXPECTED(c0 < 0xc2)
- || UNEXPECTED(cp + 1 >= end)
- /* Require UTF-8 tail byte. */
- || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80))
- return (0);
- }
- /* Three-byte encodings. */
- else if (EXPECTED(c0 <= 0xef) /* we know that c0 >= 0xe0 */ ) {
- if (UNEXPECTED(cp + 2 >= end)
- /* Exclude over-long encodings. */
- || UNEXPECTED((ch = *++cp) < (c0 == 0xe0 ? 0xa0 : 0x80))
- /* Exclude U+D800..U+DFFF. */
- || UNEXPECTED(ch > (c0 == 0xed ? 0x9f : 0xbf))
- /* Require UTF-8 tail byte. */
- || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80))
- return (0);
- }
- /* Four-byte encodings. */
- else if (EXPECTED(c0 <= 0xf4) /* we know that c0 >= 0xf0 */ ) {
- if (UNEXPECTED(cp + 3 >= end)
- /* Exclude over-long encodings. */
- || UNEXPECTED((ch = *++cp) < (c0 == 0xf0 ? 0x90 : 0x80))
- /* Exclude code points above U+10FFFF. */
- || UNEXPECTED(ch > (c0 == 0xf4 ? 0x8f : 0xbf))
- /* Require UTF-8 tail byte. */
- || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)
- /* Require UTF-8 tail byte. */
- || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80))
- return (0);
- }
- /* Invalid: c0 >= 0xf5 */
- else {
+ for (cp = str; cp < ep; cp++) {
+ if ((last = parse_utf8_char(cp, ep)) != 0)
+ cp = last;
+ else
+ return (0);
+ }
+ return (1);
+}
+
+/* valid_utf8_stringz - validate string according to RFC 3629 */
+
+int valid_utf8_stringz(const char *str)
+{
+ const char *cp;
+ const char *last;
+
+ /*
+ * Ideally, the compiler will inline parse_utf8_char(), propagate the
+ * null pointer constant value, and eliminate code branches that test
+ * whether 0 != 0.
+ */
+ for (cp = str; *cp; cp++) {
+ if ((last = parse_utf8_char(cp, 0)) != 0)
+ cp = last;
+ else
return (0);
- }
}
return (1);
}
@@ -114,26 +102,139 @@ int valid_utf8_string(const char *str, ssize_t len)
*/
#ifdef TEST
#include <stdlib.h>
+#include <string.h>
+#include <msg.h>
#include <vstream.h>
-#include <vstring.h>
-#include <vstring_vstream.h>
+#include <msg_vstream.h>
+
+ /*
+ * Test cases for 1-, 2-, and 3-byte encodings. See printable.c for UTF8
+ * parser resychronization tests.
+ *
+ * XXX Need a test for 4-byte encodings, preferably with strings that can be
+ * displayed.
+ *
+ * XXX Need tests with hand-crafted over-long encodings and surrogates.
+ */
+struct testcase {
+ const char *name;
+ const char *input;
+ int expected;
+};
-#define STR(x) vstring_str(x)
-#define LEN(x) VSTRING_LEN(x)
+#define T_VALID (1)
+#define T_INVALID (0)
+#define valid_to_str(v) ((v) ? "VALID" : "INVALID")
-int main(void)
+static const struct testcase testcases[] = {
+ {"Printable ASCII",
+ "printable", T_VALID,
+ },
+ {"Latin script, accented, no error",
+ "na\303\257ve", T_VALID,
+ },
+ {"Latin script, accented, missing non-leading byte",
+ "na\303ve", T_INVALID,
+ },
+ {"Latin script, accented, missing leading byte",
+ "na\257ve", T_INVALID,
+ },
+ {"Viktor, Cyrillic, no error",
+ "\320\262\320\270\320\272\321\202\320\276\321\200", T_VALID,
+ },
+ {"Viktor, Cyrillic, missing non-leading byte",
+ "\320\262\320\320\272\321\202\320\276\321\200", T_INVALID,
+ },
+ {"Viktor, Cyrillic, missing leading byte",
+ "\320\262\270\320\272\321\202\320\276\321\200", T_INVALID,
+ },
+ {"Viktor, Cyrillic, truncated",
+ "\320\262\320\270\320\272\321\202\320\276\321", T_INVALID,
+ },
+ {"Viktor, Hebrew, no error",
+ "\327\225\327\231\327\247\327\230\327\225\326\274\327\250", T_VALID,
+ },
+ {"Viktor, Hebrew, missing leading byte",
+ "\327\225\231\327\247\327\230\327\225\326\274\327\250", T_INVALID,
+ },
+ {"Chinese (Simplified), no error",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345\221\212", T_VALID,
+ },
+ {"Chinese (Simplified), missing leading byte",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345\221\212", T_INVALID,
+ },
+ {"Chinese (Simplified), missing first non-leading byte",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\347\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345\221\212", T_INVALID,
+ },
+ {"Chinese (Simplified), missing second non-leading byte",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345\221\212", T_INVALID,
+ },
+ {"Chinese (Simplified), truncated",
+ "\344\270\255\345\233\275\344\272\222\350\201\224\347\275\221\347"
+ "\273\234\345\217\221\345\261\225\347\212\266\345\206\265\347\273"
+ "\237\350\256\241\346\212\245\345", T_INVALID,
+ },
+};
+
+int main(int argc, char **argv)
{
- VSTRING *buf = vstring_alloc(1);
+ const struct testcase *tp;
+ int pass;
+ int fail;
+
+#define NUM_TESTS sizeof(testcases)/sizeof(testcases[0])
+
+ msg_vstream_init(basename(argv[0]), VSTREAM_ERR);
+ util_utf8_enable = 1;
+
+ for (pass = fail = 0, tp = testcases; tp < testcases + NUM_TESTS; tp++) {
+ int actual_l;
+ int actual_z;
+ int ok = 0;
- while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
- vstream_printf("%c", (LEN(buf) && !valid_utf8_string(STR(buf), LEN(buf))) ?
- '!' : ' ');
- vstream_fwrite(VSTREAM_OUT, STR(buf), LEN(buf));
- vstream_printf("\n");
+ /*
+ * Notes:
+ *
+ * - The msg(3) functions use printable() which interferes when logging
+ * inputs and outputs. Use vstream_fprintf() instead.
+ */
+ vstream_fprintf(VSTREAM_ERR, "RUN %s\n", tp->name);
+ actual_l = valid_utf8_string(tp->input, strlen(tp->input));
+ actual_z = valid_utf8_stringz(tp->input);
+
+ if (actual_l != tp->expected) {
+ vstream_fprintf(VSTREAM_ERR,
+ "input: >%s<, 'actual_l' got: >%s<, want: >%s<\n",
+ tp->input, valid_to_str(actual_l),
+ valid_to_str(tp->expected));
+ } else if (actual_z != tp->expected) {
+ vstream_fprintf(VSTREAM_ERR,
+ "input: >%s<, 'actual_z' got: >%s<, want: >%s<\n",
+ tp->input, valid_to_str(actual_z),
+ valid_to_str(tp->expected));
+ } else {
+ vstream_fprintf(VSTREAM_ERR, "input: >%s<, got and want: >%s<\n",
+ tp->input, valid_to_str(actual_l));
+ ok = 1;
+ }
+ if (ok) {
+ vstream_fprintf(VSTREAM_ERR, "PASS %s\n", tp->name);
+ pass++;
+ } else {
+ vstream_fprintf(VSTREAM_ERR, "FAIL %s\n", tp->name);
+ fail++;
+ }
}
- vstream_fflush(VSTREAM_OUT);
- vstring_free(buf);
- exit(0);
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ return (fail > 0);
}
#endif
diff --git a/src/util/vstream.c b/src/util/vstream.c
index b4f9fbb..affbcc0 100644
--- a/src/util/vstream.c
+++ b/src/util/vstream.c
@@ -522,6 +522,7 @@
/* System library. */
#include <sys_defs.h>
+#include <sys/stat.h>
#include <stdlib.h> /* 44BSD stdarg.h uses abort() */
#include <stdarg.h>
#include <stddef.h>
@@ -1386,7 +1387,38 @@ VSTREAM *vstream_fopen(const char *path, int flags, mode_t mode)
VSTREAM *stream;
int fd;
- if ((fd = open(path, flags, mode)) < 0) {
+ /*
+ * To set permissions on new files only, we need to distinguish between
+ * creating a new file and opening an existing one.
+ */
+#define open_create(path, flags, mode) \
+ open((path), (flags) | (O_CREAT | O_EXCL), (mode))
+#define open_exist(path, flags, mode) \
+ open((path), (flags) & ~(O_CREAT | O_EXCL), (mode))
+
+ switch (flags & (O_CREAT | O_EXCL)) {
+ case O_CREAT:
+ fd = open_exist(path, flags, mode);
+ if (fd < 0 && errno == ENOENT) {
+ fd = open_create(path, flags, mode);
+ if (fd >= 0) {
+ if (fchmod(fd, mode) < 0) /* can't uncreate */
+ msg_warn("fchmod %s 0%o: %m", path, (unsigned) mode);
+ } else if ( /* fd < 0 && */ errno == EEXIST)
+ fd = open_exist(path, flags, mode);
+ }
+ break;
+ case O_CREAT | O_EXCL:
+ fd = open(path, flags, mode);
+ if (fd >= 0)
+ if (fchmod(fd, mode) < 0) /* can't uncreate */
+ msg_warn("fchmod %s 0%o: %m", path, (unsigned) mode);
+ break;
+ default:
+ fd = open(path, flags, mode);
+ break;
+ }
+ if (fd < 0) {
return (0);
} else {
stream = vstream_fdopen(fd, flags);
diff --git a/src/xsasl/xsasl_cyrus_server.c b/src/xsasl/xsasl_cyrus_server.c
index 4bf2ed2..e903289 100644
--- a/src/xsasl/xsasl_cyrus_server.c
+++ b/src/xsasl/xsasl_cyrus_server.c
@@ -52,6 +52,10 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
/*--*/
/* System library. */
diff --git a/src/xsasl/xsasl_server.c b/src/xsasl/xsasl_server.c
index e8d7e16..c504864 100644
--- a/src/xsasl/xsasl_server.c
+++ b/src/xsasl/xsasl_server.c
@@ -123,7 +123,10 @@
/* reply.
/*
/* xsasl_server_get_username() returns the stored username
-/* after successful authentication.
+/* after successful authentication. The username may be null
+/* after authentication failure, depending on the kind of
+/* failure and on authentication backend implementation
+/* details. A non-null result is converted to printable text.
/*
/* Arguments:
/* .IP addr_family
@@ -207,6 +210,10 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
+/* Amawalk, NY 10501, USA
/*--*/
/* System library. */