-Tregmatch_t
-Tsasl_conn_t
-Tsasl_secret_t
+-Tsfsistat
-Tsize_t
-Tssize_t
-Ttls_client_init_props
Cleanup: replaced documentation references to xxgdb by ddd.
The xxgdb program hasn't been updated in more than 10 years.
Files: proto/postconf.proto, conf/main.cf.
+
+20071219-20
+
+ Feature: support for all new Sendmail 8.14 Milter features
+ except SMFIR_SKIP (skip further events of this type),
+ SMFIP_RCPT_REJ (report rejected recipients to the mail
+ filter), SMFIR_CHGFROM (replace sender, with optional ESMTP
+ command parameters), and SMFIR_ADDRCPT_PAR (add recipient,
+ with optional ESMTP command parameters). Files: milter/milters.c,
+ milter/milter8.c, milter/test-milter.c, cleanup/cleanup_milter.c.
+
+20071221
+
+ Feature: support for Sendmail 8.14 Milter SMFIR_SKIP (skip
+ further events of this type). Files: milter/milter8.c,
+ milter/test-milter.c.
+
+ Cleanup: don't try sending HELO after a 421 EHLO reply.
+ File: smtp/smtp_proto.c.
to receive mail as if the filter does not exist, and "reject" to reject mail
with a permanent status.
+ /etc/postfix/main.cf:
# What to do in case of errors? Specify accept, reject, or tempfail.
milter_default_action = tempfail
As Postfix is not built with the Sendmail libmilter library, you may need to
configure the Milter protocol version that Postfix should use. The default
-version is 2.
+version is 2. Other protocol versions are 3 and 4 (Postfix 2.3 and later), and
+6 (Postfix 2.5 an later).
- milter_protocol = 2
+ /etc/postfix/main.cf:
+ milter_protocol = 2
If the Postfix milter_protocol setting specifies a too low version, the
libmilter library will log an error message like this:
S\bSe\ben\bnd\bdm\bma\bai\bil\bl m\bma\bac\bcr\bro\bo e\bem\bmu\bul\bla\bat\bti\bio\bon\bn
Postfix emulates a limited number of Sendmail macros, as shown in the table.
-Different macros are available at different SMTP protocol stages (EOM = end-of-
-message); their availability is not always the same as in Sendmail. See the
-workarounds section below for solutions.
+Different macros are available at different SMTP protocol stages (EOH = end-of-
+header, EOM = end-of-message); their availability is not always the same as in
+Sendmail. See the workarounds section below for solutions.
_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b
|N\bNa\bam\bme\be |A\bAv\bva\bai\bil\bla\bab\bbi\bil\bli\bit\bty\by |D\bDe\bes\bsc\bcr\bri\bip\bpt\bti\bio\bon\bn |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |i |DATA, EOM |Queue ID |
+ |i |DATA, EOH, EOM |Queue ID |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|j |Always |value of myhostname |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|_ |Always |The validated client name |
| | |and address |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{auth_authen} |MAIL, DATA, EOM |SASL login name |
+ |{auth_authen} |MAIL, DATA, EOH, EOM |SASL login name |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{auth_author} |MAIL, DATA, EOM |SASL sender |
+ |{auth_author} |MAIL, DATA, EOH, EOM |SASL sender |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{auth_type} |MAIL, DATA, EOM |SASL login method |
+ |{auth_type} |MAIL, DATA, EOH, EOM |SASL login method |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|{client_addr} |Always |Client IP address |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|{client_ptr} |CONNECT, HELO, MAIL, DATA|lookup, "unknown" when |
| | |lookup fails |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{cert_issuer} |HELO, MAIL, DATA, EOM |TLS client certificate |
- | | |issuer |
+ |{cert_issuer} |HELO, MAIL, DATA, EOH, |TLS client certificate |
+ | |EOM |issuer |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{cert_subject} |HELO, MAIL, DATA, EOM |TLS client certificate |
- | | |subject |
+ |{cert_subject} |HELO, MAIL, DATA, EOH, |TLS client certificate |
+ | |EOM |subject |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{cipher_bits} |HELO, MAIL, DATA, EOM |TLS session key size |
+ |{cipher_bits} |HELO, MAIL, DATA, EOH, |TLS session key size |
+ | |EOM | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{cipher} |HELO, MAIL, DATA, EOM |TLS cipher |
+ |{cipher} |HELO, MAIL, DATA, EOH, |TLS cipher |
+ | |EOM | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|{daemon_name} |Always |value of |
| | |milter_macro_daemon_name |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|{rcpt_addr} |RCPT |Recipient address |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |{tls_version} |HELO, MAIL, DATA, EOM |TLS protocol version |
+ |{tls_version} |HELO, MAIL, DATA, EOH, |TLS protocol version |
+ | |EOM | |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|v |Always |value of milter_macro_v |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
Postfix sends specific sets of macros at different SMTP protocol stages. The
-sets are configured with the parameters as described in the table (EOM = end of
-message).
+sets are configured with the parameters as described in the table (EOH = end of
+headers; EOM = end of message).
_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b
|P\bPa\bar\bra\bam\bme\bet\bte\ber\br n\bna\bam\bme\be |P\bPr\bro\bot\bto\boc\bco\bol\bl v\bve\ber\brs\bsi\bio\bon\bn|P\bPr\bro\bot\bto\boc\bco\bol\bl s\bst\bta\bag\bge\be |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|milter_data_macros |4 or higher |DATA |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+ |milter_end_of_header_macros |6 or higher |EOH |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|milter_end_of_data_macros |2 or higher |EOM |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|milter_unknown_command_macros|3 or higher |unknown command|
course the usual limitations of before-queue filtering will always apply. See
the CONTENT_INSPECTION_README document for a discussion.
- * Postfix currently supports only applications that speak the Sendmail 8
- Milter protocol versions 2..4. Support for other protocol types or protocol
- versions may be added later.
+ * Postfix version 2.3 introduces support for Sendmail 8 milter protocol
+ versions 2, 3 and 4; Postfix version 2.5 adds support for protocol version
+ 6, which is available with Sendmail 8.14. Support for other protocol types
+ or protocol versions may be added later.
* For applications that are written in C, you need to use the Sendmail
libmilter library. A Postfix replacement may be provided in the future.
The solution is to use Postfix version 2.4 or later.
+ * Postfix version 2.5 implements the Sendmail 8.14 features except:
+ SMFIP_RCPT_REJ (report rejected recipients to the mail filter),
+ SMFIR_CHGFROM (replace sender, with optional ESMTP command parameters), and
+ SMFIR_ADDRCPT_PAR (add recipient, with optional ESMTP command parameters).
+
* Most Milter configuration options are global. Future Postfix versions may
support per-Milter timeouts, per-Milter error handling, etc.
The mail_release_date configuration parameter (format: yyyymmdd)
specifies the release date of a stable release or snapshot release.
+Major changes with Postfix snapshot 20071221
+============================================
+
+Support for most of the Sendmail 8.14 Milter protocol features.
+
+To enable the new features specify "milter_protocol = 6" and link
+the filter application with a libmilter library from Sendmail 8.14
+or later.
+
+Sendmail 8.14 Milter features supported at this time:
+
+- NR_CONN, NR_HELO, NR_MAIL, NR_RCPT, NR_DATA, NR_UNKN, NR_HDR,
+ NR_EOH, NR_BODY: The filter can tell Postfix that it won't reply
+ to some of the SMTP events that Postfix sends. This makes the
+ protocol less chatty and improves performance.
+
+- SKIP: The filter can tell Postfix to skip sending the rest of
+ the message body, which also improves performance.
+
+- HDR_LEADSPC: The filter can request that Postfix does not delete
+ the first space character between header name and header value
+ when sending a header to the filter, and that Postfix does not
+ insert a space character between header name and header value
+ when receiving a header from the filter. This fixes a limitation
+ in the old Milter protocol that can break DKIM and DK signatures.
+
+- SETSYMLIST: The filter can override one or more of the main.cf
+ milter_xxx_macros parameter settings.
+
+Sendmail 8.14 Milter features not supported at this time:
+
+- RCPT_REJ: report rejected recipients to the mail filter.
+
+- CHGFROM: replace sender, with optional ESMTP command parameters.
+
+- ADDRCPT_PAR: add recipient, with optional ESMTP command parameters.
+
+It is unclear when (if ever) the missing features will be implemented.
+SMFIP_RCPT_REJ requires invasive changes in the SMTP server recipient
+processing and error handling. SMFIR_CHGFROM and SMFIR_ADDRCPT_PAR
+require ESMTP command-line parsing in the cleanup server. Unfortunately,
+Sendmail's documentation does not specify what ESMTP options are
+supported, but only discusses examples of things that don't work.
+
Incompatibility with Postfix 2.3 and earlier
============================================
Wish list:
+ In the SMTP client, handle 421 replies in smtp_loop() by
+ having the input function raise a flag after detecting 421
+ (kill connection caching and be sure to do the right thing
+ with RSET probes), leave the smtp_loop() per-command reply
+ handlers unchanged, and have the smtp_loop() reader loop
+ bail out with smtp_site_fail("server disconnected after
+ %s", where), but only in the case that it isn't already in
+ the final state. Handle 421 replies in HELO/EHLO with custom
+ code to prevent EHLO->HELO fall-back.
+
Make event_drain() a proper event loop; update the zero mask,
and don't ignore a non-empty timer queue.
<blockquote>
<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
# What to do in case of errors? Specify accept, reject, or tempfail.
<a href="postconf.5.html#milter_default_action">milter_default_action</a> = tempfail
</pre>
<p> As Postfix is not built with the Sendmail libmilter library,
you may need to configure the Milter protocol version that Postfix
-should use. The default version is 2. </p>
+should use. The default version is 2. Other protocol versions are
+3 and 4 (Postfix 2.3 and later), and 6 (Postfix 2.5 an later). </p>
<blockquote>
<pre>
-<a href="postconf.5.html#milter_protocol">milter_protocol</a> = 2
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#milter_protocol">milter_protocol</a> = 2
</pre>
</blockquote>
<p> Postfix emulates a limited number of Sendmail macros, as shown
in the table. Different macros are available at different SMTP
-protocol stages (EOM = end-of-message); their availability is not
+protocol stages (EOH = end-of-header, EOM = end-of-message); their
+availability is not
always the same as in Sendmail. See the <a
href="#workarounds">workarounds</a> section below for solutions.
</p>
<tr> <th> Name </th> <th> Availability </th> <th> Description </th>
</tr>
-<tr> <td> i </td> <td> DATA, EOM </td> <td> Queue ID </td> </tr>
+<tr> <td> i </td> <td> DATA, EOH, EOM </td> <td> Queue ID </td> </tr>
<tr> <td> j </td> <td> Always </td> <td> value of <a href="postconf.5.html#myhostname">myhostname</a> </td>
</tr>
<tr> <td> _ </td> <td> Always </td> <td> The validated client name
and address </td> </tr>
-<tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOM </td> <td> SASL
+<tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL
login name </td> </tr>
-<tr> <td> {auth_author} </td> <td> MAIL, DATA, EOM </td> <td> SASL
+<tr> <td> {auth_author} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL
sender </td> </tr>
-<tr> <td> {auth_type} </td> <td> MAIL, DATA, EOM </td> <td> SASL
+<tr> <td> {auth_type} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL
login method </td> </tr>
<tr> <td> {client_addr} </td> <td> Always </td> <td> Client IP
<td> Client name from reverse lookup, "unknown" when lookup fails
</td> </tr>
-<tr> <td> {cert_issuer} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
+<tr> <td> {cert_issuer} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td>
TLS client certificate issuer </td> </tr>
-<tr> <td> {cert_subject} </td> <td> HELO, MAIL, DATA, EOM </td>
+<tr> <td> {cert_subject} </td> <td> HELO, MAIL, DATA, EOH, EOM </td>
<td> TLS client certificate subject </td> </tr>
-<tr> <td> {cipher_bits} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
+<tr> <td> {cipher_bits} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td>
TLS session key size </td> </tr>
-<tr> <td> {cipher} </td> <td> HELO, MAIL, DATA, EOM </td> <td> TLS
+<tr> <td> {cipher} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td> TLS
cipher </td> </tr>
<tr> <td> {daemon_name} </td> <td> Always </td> <td> value of
<tr> <td> {rcpt_addr} </td> <td> RCPT </td> <td> Recipient address
</td> </tr>
-<tr> <td> {tls_version} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
+<tr> <td> {tls_version} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td>
TLS protocol version </td> </tr>
<tr> <td> v </td> <td> Always </td> <td> value of <a href="postconf.5.html#milter_macro_v">milter_macro_v</a>
<p> Postfix sends specific sets of macros at different SMTP protocol
stages. The sets are configured with the parameters as described
-in the table (EOM = end of message). </p>
+in the table (EOH = end of headers; EOM = end of message). </p>
<blockquote>
<tr> <td> <a href="postconf.5.html#milter_data_macros">milter_data_macros</a> </td> <td> 4 or higher </td> <td> DATA
</td> </tr>
+<tr> <td> <a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> </td> <td> 6 or higher </td>
+<td> EOH </td> </tr>
+
<tr> <td> <a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> </td> <td> 2 or higher </td>
<td> EOM </td> </tr>
<ul>
-<li> <p> Postfix currently supports only applications that speak
-the Sendmail 8 Milter protocol versions 2..4. Support for other
-protocol types or protocol versions may be added later. </p>
+<li> <p> Postfix version 2.3 introduces support for Sendmail 8
+milter protocol versions 2, 3 and 4; Postfix version 2.5 adds support
+for protocol version 6, which is available with Sendmail 8.14.
+Support for other protocol types or protocol versions may be added
+later. </p>
<li> <p> For applications that are written in C, you need to use
the Sendmail libmilter library. A Postfix replacement may be
<p> The solution is to use Postfix version 2.4 or later. </p>
+<li> <p> Postfix version 2.5 implements the Sendmail 8.14 features
+except: SMFIP_RCPT_REJ (report rejected recipients to the mail
+filter), SMFIR_CHGFROM (replace sender, with optional ESMTP command
+parameters), and SMFIR_ADDRCPT_PAR (add recipient, with optional
+ESMTP command parameters).
+
<li> <p> Most Milter configuration options are global. Future Postfix
versions may support per-Milter timeouts, per-Milter error handling,
etc. </p>
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 -n output)</b>
+ The macros that are sent to Milter (mail filter)
+ applications after the end of the message header.
+
<b>MIME PROCESSING CONTROLS</b>
Available in Postfix version 2.0 and later:
will handle.
<b><a href="postconf.5.html#strict_8bitmime">strict_8bitmime</a> (no)</b>
- Enable both <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a> and strict_8bit-
+ Enable both <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a> and strict_8bit-
mime_body.
<b><a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a> (no)</b>
Reject mail with 8-bit text in message headers.
<b><a href="postconf.5.html#strict_8bitmime_body">strict_8bitmime_body</a> (no)</b>
- Reject 8-bit message body text without 8-bit MIME
+ Reject 8-bit message body text without 8-bit MIME
content encoding 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 for the message/* or multipart/* MIME
+ 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 look-
- ing at Content-Transfer-Encoding: message headers;
- historically, this behavior was hard-coded to be
+ ing at Content-Transfer-Encoding: message headers;
+ historically, this behavior was hard-coded to be
"always on".
<b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
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
+ Optional address that receives a "blind carbon
copy" of each message that is received by the Post-
fix 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
+ Optional BCC (blind carbon-copy) address lookup
tables, indexed by sender address.
<b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
- Optional BCC (blind carbon-copy) address lookup
+ Optional BCC (blind carbon-copy) address lookup
tables, indexed by 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 <a href="cleanup.8.html"><b>cleanup</b>(8)</a> server implements table driven
+ 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
+ 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
+ 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 sender addresses.
- <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender,</b>
+ <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender,</b>
<b>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
+ 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 address
+ Optional list of user names that are not subjected
+ to address masquerading, even when their address
matches $<a href="postconf.5.html#masquerade_domains">masquerade_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 exten-
+ What address lookup tables copy an address exten-
sion 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 domains, and b) addresses
- that are aliased to addresses in other local or
+ 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
+ Optional lookup tables that alias specific mail
+ addresses or domains to other local or remote
address.
Available in Postfix version 2.2 and later:
- <b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient,</b>
+ <b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient,</b>
<b>header_sender, header_recipient)</b>
- What addresses are subject to <a href="postconf.5.html#canonical_maps">canonical_maps</a>
+ What addresses are subject to <a href="postconf.5.html#canonical_maps">canonical_maps</a>
address mapping.
<b><a href="postconf.5.html#recipient_canonical_classes">recipient_canonical_classes</a> (envelope_recipient,</b>
<b>header_recipient)</b>
- What addresses are subject to <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
+ What addresses are subject to <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
<a href="postconf.5.html#recipient_canonical_maps">cal_maps</a> address mapping.
<b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b>
address mapping.
<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
+ Don't rewrite message headers from remote clients
at all when this parameter is empty; otherwise, re-
- write message headers and append the specified
+ write message headers and append the specified
domain name to incomplete addresses.
<b>RESOURCE AND RATE CONTROLS</b>
<b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
- The maximal number of addresses remembered by the
- address duplicate filter for <a href="aliases.5.html"><b>aliases</b>(5)</a> or <a href="virtual.5.html"><b>vir-</b></a>
+ The maximal number of addresses remembered by the
+ address duplicate filter for <a href="aliases.5.html"><b>aliases</b>(5)</a> or <a href="virtual.5.html"><b>vir-</b></a>
<a href="virtual.5.html"><b>tual</b>(5)</a> alias expansion, or for <a href="showq.8.html"><b>showq</b>(8)</a> queue dis-
plays.
message header.
<b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
- The maximal number of Received: message headers
+ The maximal number of Received: message headers
that is allowed in the primary message headers.
<b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
- Time to pause before accepting a new message, when
+ Time to pause before accepting a new message, when
the message arrival rate exceeds the message deliv-
ery rate.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
- The maximal size in bytes of a message, including
+ The maximal size in bytes of a message, including
envelope information.
Available in Postfix version 2.0 and later:
will handle.
<b><a href="postconf.5.html#queue_file_attribute_count_limit">queue_file_attribute_count_limit</a> (100)</b>
- The maximal number of (name=value) attributes that
+ The maximal number of (name=value) attributes that
may be stored in a Postfix queue file.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
- The maximal number of addresses that virtual alias
+ The maximal number of addresses that virtual alias
expansion produces from each original recipient.
<b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
- The maximal nesting depth of virtual alias expan-
+ The maximal nesting depth of virtual alias expan-
sion.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
- The maximal number of digits after the decimal
+ The maximal number of digits after the decimal
point when logging sub-second delay values.
<b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
- The time after which the sender receives the mes-
+ The time after which the sender receives the mes-
sage headers of mail that is still queued.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
over an internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of incoming connections that a
- Postfix daemon process will service before termi-
+ The maximal number of incoming connections that a
+ Postfix daemon process will service before termi-
nating voluntarily.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
- Enable support for the X-Original-To message
+ Enable support for the X-Original-To message
header.
<b>FILES</b>
<a href="CONTENT_INSPECTION_README.html">CONTENT_INSPECTION_README</a> content inspection
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<p> This feature is available in Postfix 2.3 and later. </p>
+</DD>
+
+<DT><b><a name="milter_end_of_header_macros">milter_end_of_header_macros</a>
+(default: see postconf -n output)</b></DT><DD>
+
+<p> The macros that are sent to Milter (mail filter) applications
+after the end of the message header. See <a href="MILTER_README.html">MILTER_README</a> for a list
+of available macro names and their meanings. </p>
+
+<p> This feature is available in Postfix 2.5 and later. </p>
+
+
</DD>
<DT><b><a name="milter_helo_macros">milter_helo_macros</a>
(default: 2)</b></DT><DD>
<p> The mail filter protocol version and optional protocol extensions
-for communication with a Milter (mail filter) application. This
-information should match the protocol that is expected by the actual
-mail filter application. </p>
+for communication with a Milter (mail filter) application. Postfix
+sends this version number during the initial protocol handshake.
+It should match the version number that is expected by the mail
+filter application (or by its Milter library). </p>
<p>Protocol versions: </p>
<dl compact>
-<dt>2</dt> <dd>Use Sendmail 8 mail filter protocol version 2.</dd>
+<dt>2</dt> <dd>Use Sendmail 8 mail filter protocol version 2 (default
+as of Sendmail version 8.11).</dd>
<dt>3</dt> <dd>Use Sendmail 8 mail filter protocol version 3.</dd>
<dt>4</dt> <dd>Use Sendmail 8 mail filter protocol version 4.</dd>
+<dt>6</dt> <dd>Use Sendmail 8 mail filter protocol version 6 (default
+as of Sendmail version 8.14).</dd>
+
</dl>
<p>Protocol extensions: </p>
<a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> parameter specifies the response code to
rejected requests (default: 504).</dd>
+<dt><b><a name="reject_rhsbl_helo">reject_rhsbl_helo <i>rbl_domain=d.d.d.d</i></a></b></dt>
+
+<dd>Reject the request when the HELO or EHLO hostname hostname is
+listed with the A record "<i>d.d.d.d</i>" under <i>rbl_domain</i>
+(Postfix version 2.1 and later only). If no "<i>=d.d.d.d</i>" is
+specified, reject the request when the HELO or EHLO hostname is
+listed with any A record under <i>rbl_domain</i>. See the
+<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> description for additional RBL related configuration
+parameters. This feature is available in Postfix 2.0 and later.
+</dd>
+
<dt><b><a name="reject_unknown_helo_hostname">reject_unknown_helo_hostname</a></b> (with Postfix < 2.3: reject_unknown_hostname)</dt>
<dd>Reject the request when the HELO or EHLO hostname has no DNS A
and use quotes to protect white space from the
shell. Command names are case-insensitive.
- <b>-r</b> <i>command,command,...</i>
- Reject the specified commands with a soft (4xx)
- error code. This option implies <b>-p</b>.
+ <b>-Q</b> <i>command,command,...</i>
+ Disconnect after sending a 431 reply after receiv-
+ ing one of the specified commands.
Examples of commands are CONNECT, HELO, EHLO, LHLO,
MAIL, RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT.
and use quotes to protect white space from the
shell. Command names are case-insensitive.
+ <b>-r</b> <i>command,command,...</i>
+ Reject the specified commands with a soft (4xx)
+ error code. This option implies <b>-p</b>.
+
+ Examples of commands are CONNECT, HELO, EHLO, LHLO,
+ MAIL, RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT.
+ Separate command names by white space or commas,
+ and use quotes to protect white space from the
+ shell. Command names are case-insensitive.
+
<b>-R</b> <i>root-directory</i>
- Change the process root directory to the specified
- location. This option requires super-user privi-
+ Change the process root directory to the specified
+ location. This option requires super-user privi-
leges. See also the <b>-u</b> option.
<b>-s</b> <i>command,command,...</i>
Log the named commands to syslogd.
Examples of commands are CONNECT, HELO, EHLO, LHLO,
- MAIL, RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT.
- Separate command names by white space or commas,
- and use quotes to protect white space from the
+ MAIL, RCPT, VRFY, DATA, ., RSET, NOOP, and QUIT.
+ Separate command names by white space or commas,
+ and use quotes to protect white space from the
shell. Command names are case-insensitive.
<b>-S start-string</b>
- An optional string that is prepended to each mes-
- sage that is written to a dump file (see the dump
- file format description below). The following C
+ An optional string that is prepended to each mes-
+ sage that is written to a dump file (see the dump
+ file format description below). The following C
escape sequences are supported: \a (bell), \b
- (backslace), \f (formfeed), \n (newline), \r (car-
- riage return), \t (horizontal tab), \v (vertical
- tab), \<i>ddd</i> (up to three octal digits) and \\ (the
+ (backslace), \f (formfeed), \n (newline), \r (car-
+ riage return), \t (horizontal tab), \v (vertical
+ tab), \<i>ddd</i> (up to three octal digits) and \\ (the
backslash character).
<b>-t</b> <i>timeout</i> (default: 100)
Limit the time for receiving a command or sending a
- response. The time limit is specified in seconds.
+ response. The time limit is specified in seconds.
<b>-u</b> <i>username</i>
Switch to the specified user privileges after open-
- ing the network socket and optionally changing the
- process root directory. This option is required
- when the process runs with super-user privileges.
+ ing the network socket and optionally changing the
+ process root directory. This option is required
+ when the process runs with super-user privileges.
See also the <b>-R</b> option.
<b>-v</b> Show the SMTP conversations.
mand.
<b>-W</b> <i>command:delay[:odds]</i>
- Wait <i>delay</i> seconds before responding to <i>command</i>.
- If <i>odds</i> is also specified (a number between 1-99
- inclusive), wait for a random multiple of <i>delay</i>.
- The random multiplier is equal to the number of
+ Wait <i>delay</i> seconds before responding to <i>command</i>.
+ If <i>odds</i> is also specified (a number between 1-99
+ inclusive), wait for a random multiple of <i>delay</i>.
+ The random multiplier is equal to the number of
times the program needs to roll a dice with a range
- of 0..99 inclusive, before the dice produces a
+ of 0..99 inclusive, before the dice produces a
result greater than or equal to <i>odds</i>.
[<b>inet:</b>][<i>host</i>]:<i>port</i>
- Listen on network interface <i>host</i> (default: any
+ Listen on network interface <i>host</i> (default: any
interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
specified in numeric or symbolic form.
Listen on the UNIX-domain socket at <i>pathname</i>.
<i>backlog</i>
- The maximum length the queue of pending connec-
+ The maximum length the queue of pending connec-
tions, as defined by the <b>listen</b>(2) system call.
<b>DUMP FILE FORMAT</b>
- Each dumped message contains a sequence of text lines,
- terminated with the newline character. The sequence of
+ Each dumped message contains a sequence of text lines,
+ terminated with the newline character. The sequence of
information is as follows:
<b>o</b> The optional string specified with the <b>-S</b> option.
- <b>o</b> The <b>smtp-sink</b> generated headers as documented
+ <b>o</b> The <b>smtp-sink</b> generated headers as documented
below.
- <b>o</b> The message header and body as received from the
+ <b>o</b> The message header and body as received from the
SMTP client.
<b>o</b> An empty line.
- The format of the <b>smtp-sink</b> generated headers is as fol-
+ The format of the <b>smtp-sink</b> generated headers is as fol-
lows:
<b>X-Client-Addr:</b> <i>text</i>
The client IP address without enclosing []. An IPv6
- address is prefixed with "ipv6:". This record is
+ address is prefixed with "ipv6:". This record is
always present.
<b>X-Client-Proto:</b> <i>text</i>
- The client protocol: SMTP, ESMTP or LMTP. This
+ The client protocol: SMTP, ESMTP or LMTP. This
record is always present.
<b>X-Helo-Args:</b> <i>text</i>
- The arguments of the last HELO or EHLO command
- before this mail delivery transaction. This record
- is present only if the client sent a recognizable
+ The arguments of the last HELO or EHLO command
+ before this mail delivery transaction. This record
+ is present only if the client sent a recognizable
HELO or EHLO command before the DATA command.
<b>X-Mail-Args:</b> <i>text</i>
The arguments of the MAIL command that started this
- mail delivery transaction. This record is present
+ mail delivery transaction. This record is present
exactly once.
<b>X-Rcpt-Args:</b> <i>text</i>
- The arguments of an RCPT command within this mail
- delivery transaction. There is one record for each
- RCPT command, and they are in the order as sent by
+ The arguments of an RCPT command within this mail
+ delivery transaction. There is one record for each
+ RCPT command, and they are in the order as sent by
the client.
<b>Received:</b> <i>text</i>
- A message header for compatibility with mail pro-
- cessing software. This three-line header marks the
- end of the headers provided by <b>smtp-sink</b>, and is
+ A message header for compatibility with mail pro-
+ cessing software. This three-line header marks the
+ end of the headers provided by <b>smtp-sink</b>, and is
formatted as follows:
<b>from</b> <i>helo</i> <b>([</b><i>addr</i><b>])</b>
The HELO or EHLO command argument and client
IP address. If the client did not send HELO
- or EHLO, the client IP address is used
+ or EHLO, the client IP address is used
instead.
<b>by</b> <i>host</i> <b>(smtp-sink) with</b> <i>proto</i> <b>id</b> <i>random</i><b>;</b>
- The hostname specified with the <b>-h</b> option,
- the client protocol (see <b>X-Client-Proto</b>
+ The hostname specified with the <b>-h</b> option,
+ the client protocol (see <b>X-Client-Proto</b>
above), and the pseudo-random portion of the
per-message capture file name.
<a href="smtp-source.1.html">smtp-source(1)</a>, SMTP/LMTP message generator
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
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 -n output)</b>
+ <b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see postconf -n output)</b>
The macros that are sent to Milter (mail filter)
+ applications after the message header.
+
+ <b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see postconf -n output)</b>
+ The macros that are sent to Milter (mail filter)
applications after the message end-of-data.
<b>GENERAL CONTENT INSPECTION CONTROLS</b>
- The following parameters are applicable for both built-in
+ The following parameters are applicable for both built-in
and external content filters.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
- Enable or disable recipient validation, built-in
+ Enable or disable recipient validation, built-in
content filtering, or address mapping.
<b>EXTERNAL CONTENT INSPECTION CONTROLS</b>
- The following parameters are applicable for both before-
+ The following parameters are applicable for both before-
queue and after-queue content filtering.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_xforward_hosts">smtpd_authorized_xforward_hosts</a> (empty)</b>
- What SMTP clients are allowed to use the XFORWARD
+ What SMTP clients are allowed to use the XFORWARD
feature.
<b>SASL AUTHENTICATION CONTROLS</b>
- Postfix SASL support (<a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a>) can be used to authenti-
- cate remote SMTP clients to the Postfix SMTP server, and
- to authenticate the Postfix SMTP client to a remote SMTP
+ Postfix SASL support (<a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a>) can be used to authenti-
+ cate remote SMTP clients to the Postfix SMTP server, and
+ to authenticate the Postfix SMTP client to a remote SMTP
server. See the <a href="SASL_README.html">SASL_README</a> document for details.
<b><a href="postconf.5.html#broken_sasl_auth_clients">broken_sasl_auth_clients</a> (no)</b>
- Enable inter-operability with SMTP clients that
- implement an obsolete version of the AUTH command
+ Enable inter-operability with SMTP clients that
+ implement an obsolete version of the AUTH command
(<a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a>).
<b><a href="postconf.5.html#smtpd_sasl_auth_enable">smtpd_sasl_auth_enable</a> (no)</b>
- Enable SASL authentication in the Postfix SMTP
+ Enable SASL authentication in the Postfix SMTP
server.
<b><a href="postconf.5.html#smtpd_sasl_local_domain">smtpd_sasl_local_domain</a> (empty)</b>
- The name of the Postfix SMTP server's local SASL
+ The name of the Postfix SMTP server's local SASL
authentication realm.
<b><a href="postconf.5.html#smtpd_sasl_security_options">smtpd_sasl_security_options</a> (noanonymous)</b>
- Postfix SMTP server SASL security options; as of
- Postfix 2.3 the list of available features depends
- on the SASL server implementation that is selected
+ Postfix SMTP server SASL security options; as of
+ Postfix 2.3 the list of available features depends
+ on the SASL server implementation that is selected
with <b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b>.
<b><a href="postconf.5.html#smtpd_sender_login_maps">smtpd_sender_login_maps</a> (empty)</b>
- Optional lookup table with the SASL login names
+ Optional lookup table with the SASL login names
that own sender (MAIL FROM) addresses.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_sasl_exceptions_networks">smtpd_sasl_exceptions_networks</a> (empty)</b>
- What remote SMTP clients the Postfix SMTP server
+ What remote SMTP clients the Postfix SMTP server
will not offer AUTH support to.
Available in Postfix version 2.1 and 2.2:
<b>smtpd_sasl_application_name (smtpd)</b>
- The application name that the Postfix SMTP server
+ The application name that the Postfix SMTP server
uses for SASL server initialization.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_sasl_authenticated_header">smtpd_sasl_authenticated_header</a> (no)</b>
- Report the SASL authenticated user name in the
+ Report the SASL authenticated user name in the
<a href="smtpd.8.html"><b>smtpd</b>(8)</a> Received message header.
<b><a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a> (smtpd)</b>
- Implementation-specific information that the Post-
- fix SMTP server passes through to the SASL plug-in
- implementation that is selected with
+ Implementation-specific information that the Post-
+ fix SMTP server passes through to the SASL plug-in
+ implementation that is selected with
<b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b>.
<b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a> (cyrus)</b>
- The SASL plug-in type that the Postfix SMTP server
+ The SASL plug-in type that the Postfix SMTP server
should use for authentication.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#cyrus_sasl_config_path">cyrus_sasl_config_path</a> (empty)</b>
- Search path for Cyrus SASL application configura-
- tion files, currently used only to locate the
+ Search path for Cyrus SASL application configura-
+ tion files, currently used only to locate the
$<a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a>.conf file.
<b>STARTTLS SUPPORT CONTROLS</b>
- Detailed information about STARTTLS configuration may be
+ Detailed information about STARTTLS configuration may be
found in the <a href="TLS_README.html">TLS_README</a> document.
<b><a href="postconf.5.html#smtpd_tls_security_level">smtpd_tls_security_level</a> (empty)</b>
- The SMTP TLS security level for the Postfix SMTP
- server; when a non-empty value is specified, this
+ The SMTP TLS security level for the Postfix SMTP
+ server; when a non-empty value is specified, this
overrides the obsolete parameters <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> and
<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a>.
<b><a href="postconf.5.html#smtpd_sasl_tls_security_options">smtpd_sasl_tls_security_options</a> ($<a href="postconf.5.html#smtpd_sasl_security_options">smtpd_sasl_secu</a>-</b>
<b><a href="postconf.5.html#smtpd_sasl_security_options">rity_options</a>)</b>
- The SASL authentication security options that the
- Postfix SMTP server uses for TLS encrypted SMTP
+ The SASL authentication security options that the
+ Postfix SMTP server uses for TLS encrypted SMTP
sessions.
<b><a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> (300s)</b>
- The time limit for Postfix SMTP server write and
- read operations during TLS startup and shutdown
+ The time limit for Postfix SMTP server write and
+ read operations during TLS startup and shutdown
handshake procedures.
<b><a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> (empty)</b>
- The file with the certificate of the certification
- authority (CA) that issued the Postfix SMTP server
+ The file with the certificate of the certification
+ authority (CA) that issued the Postfix SMTP server
certificate.
<b><a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> (empty)</b>
- The file with the certificate of the certification
- authority (CA) that issued the Postfix SMTP server
+ The file with the certificate of the certification
+ authority (CA) that issued the Postfix SMTP server
certificate.
<b><a href="postconf.5.html#smtpd_tls_always_issue_session_ids">smtpd_tls_always_issue_session_ids</a> (yes)</b>
- Force the Postfix SMTP server to issue a TLS ses-
- sion id, even when TLS session caching is turned
+ Force the Postfix SMTP server to issue a TLS ses-
+ sion id, even when TLS session caching is turned
off (<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> is empty).
<b><a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> (no)</b>
- Ask a remote SMTP client for a client certificate.
+ Ask a remote SMTP client for a client certificate.
<b><a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> (no)</b>
When TLS encryption is optional in the Postfix SMTP
- server, do not announce or accept SASL authentica-
+ server, do not announce or accept SASL authentica-
tion over unencrypted connections.
<b><a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a> (5)</b>
- The verification depth for remote SMTP client cer-
+ The verification depth for remote SMTP client cer-
tificates.
<b><a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> (empty)</b>
- File with the Postfix SMTP server RSA certificate
+ File with the Postfix SMTP server RSA certificate
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_exclude_ciphers">smtpd_tls_exclude_ciphers</a> (empty)</b>
SMTP server cipher list at all TLS security levels.
<b><a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> (empty)</b>
- File with the Postfix SMTP server DSA certificate
+ File with the Postfix SMTP server DSA certificate
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> (empty)</b>
- File with DH parameters that the Postfix SMTP
+ File with DH parameters that the Postfix SMTP
server should use with EDH ciphers.
<b><a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> (empty)</b>
- File with DH parameters that the Postfix SMTP
+ File with DH parameters that the Postfix SMTP
server should use with EDH ciphers.
<b><a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b>
- File with the Postfix SMTP server DSA private key
+ File with the Postfix SMTP server DSA private key
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> ($<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b>
- File with the Postfix SMTP server RSA private key
+ File with the Postfix SMTP server RSA private key
in PEM format.
<b><a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> (0)</b>
- Enable additional Postfix SMTP server logging of
+ Enable additional Postfix SMTP server logging of
TLS activity.
<b><a href="postconf.5.html#smtpd_tls_mandatory_ciphers">smtpd_tls_mandatory_ciphers</a> (medium)</b>
- The minimum TLS cipher grade that the Postfix SMTP
+ The minimum TLS cipher grade that the Postfix SMTP
server will use with mandatory TLS encryption.
<b><a href="postconf.5.html#smtpd_tls_mandatory_exclude_ciphers">smtpd_tls_mandatory_exclude_ciphers</a> (empty)</b>
- Additional list of ciphers or cipher types to
- exclude from the SMTP server cipher list at manda-
+ Additional list of ciphers or cipher types to
+ exclude from the SMTP server cipher list at manda-
tory TLS security levels.
<b><a href="postconf.5.html#smtpd_tls_mandatory_protocols">smtpd_tls_mandatory_protocols</a> (SSLv3, TLSv1)</b>
- The TLS protocols accepted by the Postfix SMTP
+ The TLS protocols accepted by the Postfix SMTP
server with mandatory TLS encryption.
<b><a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> (no)</b>
Request that the Postfix SMTP server produces
Received: message headers that include information
- about the protocol and cipher used, as well as the
- client CommonName and client certificate issuer
+ about the protocol and cipher used, as well as the
+ client CommonName and client certificate issuer
CommonName.
<b><a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a> (no)</b>
- With mandatory TLS encryption, require a remote
- SMTP client certificate in order to allow TLS con-
+ With mandatory TLS encryption, require a remote
+ SMTP client certificate in order to allow TLS con-
nections to proceed.
<b><a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> (empty)</b>
- Name of the file containing the optional Postfix
+ Name of the file containing the optional Postfix
SMTP server TLS session cache.
<b><a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> (3600s)</b>
sion cache information.
<b><a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a> (no)</b>
- Run the Postfix SMTP server in the non-standard
- "wrapper" mode, instead of using the STARTTLS com-
+ Run the Postfix SMTP server in the non-standard
+ "wrapper" mode, instead of using the STARTTLS com-
mand.
<b><a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> (32)</b>
- The number of pseudo-random bytes that an <a href="smtp.8.html"><b>smtp</b>(8)</a>
- or <a href="smtpd.8.html"><b>smtpd</b>(8)</a> process requests from the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a>
- server in order to seed its internal pseudo random
+ The number of pseudo-random bytes that an <a href="smtp.8.html"><b>smtp</b>(8)</a>
+ or <a href="smtpd.8.html"><b>smtpd</b>(8)</a> process requests from the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a>
+ server in order to seed its internal pseudo random
number generator (PRNG).
<b><a href="postconf.5.html#tls_high_cipherlist">tls_high_cipherlist</a></b>
ciphers.
<b><a href="postconf.5.html#tls_low_cipherlist">tls_low_cipherlist</a> (ALL:!EXPORT:+RC4:@STRENGTH)</b>
- The OpenSSL cipherlist for "LOW" or higher grade
+ The OpenSSL cipherlist for "LOW" or higher grade
ciphers.
<b><a href="postconf.5.html#tls_export_cipherlist">tls_export_cipherlist</a> (ALL:+RC4:@STRENGTH)</b>
ciphers.
<b><a href="postconf.5.html#tls_null_cipherlist">tls_null_cipherlist</a> (eNULL:!aNULL)</b>
- The OpenSSL cipherlist for "NULL" grade ciphers
+ The OpenSSL cipherlist for "NULL" grade ciphers
that provide authentication without encryption.
<b>OBSOLETE STARTTLS CONTROLS</b>
- The following configuration parameters exist for compati-
+ The following configuration parameters exist for compati-
bility with Postfix versions before 2.3. Support for these
will be removed in a future release.
<b><a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> (no)</b>
- Opportunistic TLS: announce STARTTLS support to
- SMTP clients, but do not require that clients use
+ Opportunistic TLS: announce STARTTLS support to
+ SMTP clients, but do not require that clients use
TLS encryption.
<b><a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> (no)</b>
- Mandatory TLS: announce STARTTLS support to SMTP
- clients, and require that clients use TLS encryp-
+ Mandatory TLS: announce STARTTLS support to SMTP
+ clients, and require that clients use TLS encryp-
tion.
<b><a href="postconf.5.html#smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> (empty)</b>
server TLS cipher list.
<b>VERP SUPPORT CONTROLS</b>
- With VERP style delivery, each recipient of a message
+ With VERP style delivery, each recipient of a message
receives a customized copy of the message with his/her own
- recipient address encoded in the envelope sender address.
+ recipient address encoded in the envelope sender address.
The <a href="VERP_README.html">VERP_README</a> file describes configuration and operation
- details of Postfix support for variable envelope return
+ details of Postfix support for variable envelope return
path addresses. VERP style delivery is requested with the
- SMTP XVERP command or with the "sendmail -V" command-line
- option and is available in Postfix version 1.1 and later.
+ SMTP XVERP command or with the "sendmail -V" command-line
+ option and is available in Postfix version 1.1 and later.
<b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a> (+=)</b>
The two default VERP delimiter characters.
<b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
- The characters Postfix accepts as VERP delimiter
- characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
+ The characters Postfix accepts as VERP delimiter
+ characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
and in SMTP commands.
Available in Postfix version 1.1 and 2.0:
<b><a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- What SMTP clients are allowed to specify the XVERP
+ What SMTP clients are allowed to specify the XVERP
command.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_verp_clients">smtpd_authorized_verp_clients</a> ($<a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a>)</b>
- What SMTP clients are allowed to specify the XVERP
+ What SMTP clients are allowed to specify the XVERP
command.
<b>TROUBLE SHOOTING CONTROLS</b>
- The <a href="DEBUG_README.html">DEBUG_README</a> document describes how to debug parts of
- the Postfix mail system. The methods vary from making the
- software log a lot of detail, to running some daemon pro-
+ The <a href="DEBUG_README.html">DEBUG_README</a> document describes how to debug parts of
+ the Postfix mail system. The methods vary from making the
+ software log a lot of detail, to running some daemon pro-
cesses under control of a call tracer or debugger.
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ The increment in verbose logging level when a
+ remote client or server matches a pattern in the
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
<b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
- Optional list of remote client or server hostname
- or network address patterns that cause the verbose
- logging level to increase by the amount specified
+ Optional list of remote client or server hostname
+ or network address patterns that cause the verbose
+ logging level to increase by the amount specified
in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
<b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
<b><a href="postconf.5.html#internal_mail_filter_classes">internal_mail_filter_classes</a> (empty)</b>
- What categories of Postfix-generated mail are sub-
- ject to before-queue content inspection by
+ What categories of Postfix-generated mail are sub-
+ ject to before-queue content inspection by
<a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a>, <a href="postconf.5.html#header_checks">header_checks</a> and <a href="postconf.5.html#body_checks">body_checks</a>.
<b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
<b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a> (empty)</b>
- What SMTP clients are allowed to use the XCLIENT
+ What SMTP clients are allowed to use the XCLIENT
feature.
<b>KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS</b>
- As of Postfix version 2.0, the SMTP server rejects mail
- for unknown recipients. This prevents the mail queue from
- clogging up with undeliverable MAILER-DAEMON messages.
- Additional information on this topic is in the
+ As of Postfix version 2.0, the SMTP server rejects mail
+ for unknown recipients. This prevents the mail queue from
+ clogging up with undeliverable MAILER-DAEMON messages.
+ Additional information on this topic is in the
<a href="LOCAL_RECIPIENT_README.html">LOCAL_RECIPIENT_README</a> and <a href="ADDRESS_CLASS_README.html">ADDRESS_CLASS_README</a> documents.
<b><a href="postconf.5.html#show_user_unknown_table_name">show_user_unknown_table_name</a> (yes)</b>
- Display the name of the recipient table in the
+ Display the name of the recipient table in the
"User unknown" responses.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for message
+ Optional address mapping lookup tables for message
headers and envelopes.
<b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, local-</b>
<b>host)</b>
- The list of domains that are delivered via the
+ The list of domains that are delivered via the
$<a href="postconf.5.html#local_transport">local_transport</a> mail delivery transport.
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
<b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
- The Internet protocols Postfix will attempt to use
+ The Internet protocols Postfix will attempt to use
when making or accepting connections.
<b><a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> (<a href="proxymap.8.html">proxy</a>:unix:passwd.byname</b>
<b>$<a href="postconf.5.html#alias_maps">alias_maps</a>)</b>
- Lookup tables with all names or addresses of local
- recipients: a recipient address is local when its
- domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
+ Lookup tables with all names or addresses of local
+ recipients: a recipient address is local when its
+ domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
$<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
<b><a href="postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
- when a recipient address is local, and
- $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a list of lookup
+ The numerical Postfix SMTP server response code
+ when a recipient address is local, and
+ $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a list of lookup
tables that does not match the recipient.
- Parameters concerning known/unknown recipients of relay
+ Parameters concerning known/unknown recipients of relay
destinations:
<b><a href="postconf.5.html#relay_domains">relay_domains</a> ($<a href="postconf.5.html#mydestination">mydestination</a>)</b>
- What destination domains (and subdomains thereof)
+ What destination domains (and subdomains thereof)
this system will relay mail to.
<b><a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> (empty)</b>
- Optional lookup tables with all valid addresses in
+ Optional lookup tables with all valid addresses in
the domains that match $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#unknown_relay_recipient_reject_code">unknown_relay_recipient_reject_code</a> (550)</b>
The numerical Postfix SMTP server reply code when a
- recipient address matches $<a href="postconf.5.html#relay_domains">relay_domains</a>, and
- <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies a list of lookup
+ recipient address matches $<a href="postconf.5.html#relay_domains">relay_domains</a>, and
+ <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies a list of lookup
tables that does not match the recipient address.
- Parameters concerning known/unknown recipients in virtual
+ Parameters concerning known/unknown recipients in virtual
alias domains:
<b><a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> ($<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>)</b>
Postfix is final destination for the specified list
- of virtual alias domains, that is, domains for
- which all addresses are aliased to addresses in
+ of virtual alias domains, that is, domains for
+ which all addresses are aliased to addresses in
other local or remote domains.
<b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
- Optional lookup tables that alias specific mail
- addresses or domains to other local or remote
+ Optional lookup tables that alias specific mail
+ addresses or domains to other local or remote
address.
<b><a href="postconf.5.html#unknown_virtual_alias_reject_code">unknown_virtual_alias_reject_code</a> (550)</b>
The SMTP server reply code when a recipient address
- matches $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, and $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
- <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of lookup tables
+ matches $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, and $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
+ <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of lookup tables
that does not match the recipient address.
- Parameters concerning known/unknown recipients in virtual
+ Parameters concerning known/unknown recipients in virtual
mailbox domains:
<b><a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> ($<a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a>)</b>
Postfix is final destination for the specified list
- of domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">vir</a>-
+ of domains; mail is delivered via the $<a href="postconf.5.html#virtual_transport">vir</a>-
<a href="postconf.5.html#virtual_transport">tual_transport</a> mail delivery transport.
<b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> (empty)</b>
- Optional lookup tables with all valid addresses in
+ Optional lookup tables with all valid addresses in
the domains that match $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
<b><a href="postconf.5.html#unknown_virtual_mailbox_reject_code">unknown_virtual_mailbox_reject_code</a> (550)</b>
The SMTP server reply code when a recipient address
- matches $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, and $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
+ matches $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>, and $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
<a href="postconf.5.html#virtual_mailbox_maps">tual_mailbox_maps</a> specifies a list of lookup tables
that does not match the recipient address.
<b>RESOURCE AND RATE CONTROLS</b>
- The following parameters limit resource usage by the SMTP
+ The following parameters limit resource usage by the SMTP
server and/or control client request rates.
<b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
- Upon input, long lines are chopped up into pieces
- of at most this length; upon delivery, long lines
+ Upon input, long lines are chopped up into pieces
+ of at most this length; upon delivery, long lines
are reconstructed.
<b><a href="postconf.5.html#queue_minfree">queue_minfree</a> (0)</b>
- The minimal amount of free space in bytes in the
+ The minimal amount of free space in bytes in the
queue file system that is needed to receive mail.
<b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
- The maximal size in bytes of a message, including
+ The maximal size in bytes of a message, including
envelope information.
<b><a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a> (1000)</b>
- The maximal number of recipients that the Postfix
+ The maximal number of recipients that the Postfix
SMTP server accepts per message delivery request.
<b><a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> (300s)</b>
- The time limit for sending a Postfix SMTP server
- response and for receiving a remote SMTP client
+ The time limit for sending a Postfix SMTP server
+ response and for receiving a remote SMTP client
request.
<b><a href="postconf.5.html#smtpd_history_flush_threshold">smtpd_history_flush_threshold</a> (100)</b>
- The maximal number of lines in the Postfix SMTP
- server command history before it is flushed upon
+ The maximal number of lines in the Postfix SMTP
+ server command history before it is flushed upon
receipt of EHLO, RSET, or end of DATA.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#smtpd_peername_lookup">smtpd_peername_lookup</a> (yes)</b>
Attempt to look up the remote SMTP client hostname,
- and verify that the name matches the client IP
+ and verify that the name matches the client IP
address.
The per SMTP client connection count and request rate lim-
its are implemented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> ser-
- vice, and are available in Postfix version 2.2 and later.
+ vice, and are available in Postfix version 2.2 and later.
<b><a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a> (50)</b>
- How many simultaneous connections any client is
+ How many simultaneous connections any client is
allowed to make to this service.
<b><a href="postconf.5.html#smtpd_client_connection_rate_limit">smtpd_client_connection_rate_limit</a> (0)</b>
The maximal number of connection attempts any
- client is allowed to make to this service per time
+ client is allowed to make to this service per time
unit.
<b><a href="postconf.5.html#smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a> (0)</b>
- The maximal number of message delivery requests
- that any client is allowed to make to this service
+ The maximal number of message delivery requests
+ that any client is allowed to make to this service
per time unit, regardless of whether or not Postfix
actually accepts those messages.
<b><a href="postconf.5.html#smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a> (0)</b>
- The maximal number of recipient addresses that any
- client is allowed to send to this service per time
+ The maximal number of recipient addresses that any
+ client is allowed to send to this service per time
unit, regardless of whether or not Postfix actually
accepts those recipients.
<b><a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
- Clients that are excluded from connection count,
+ Clients that are excluded from connection count,
connection rate, or SMTP request rate restrictions.
Available in Postfix version 2.3 and later:
tiate with this service per time unit.
<b>TARPIT CONTROLS</b>
- When a remote SMTP client makes errors, the Postfix SMTP
- server can insert delays before responding. This can help
- to slow down run-away software. The behavior is con-
- trolled by an error counter that counts the number of
- errors within an SMTP session that a client makes without
+ When a remote SMTP client makes errors, the Postfix SMTP
+ server can insert delays before responding. This can help
+ to slow down run-away software. The behavior is con-
+ trolled by an error counter that counts the number of
+ errors within an SMTP session that a client makes without
delivering mail.
<b><a href="postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time</a> (1s)</b>
With Postfix version 2.1 and later: the SMTP server
- response delay after a client has made more than
- $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> errors, and fewer than
- $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without delivering
+ response delay after a client has made more than
+ $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> errors, and fewer than
+ $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without delivering
mail.
<b><a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> (10)</b>
- The number of errors a remote SMTP client is
- allowed to make without delivering mail before the
+ The number of errors a remote SMTP client is
+ allowed to make without delivering mail before the
Postfix SMTP server slows down all its responses.
<b><a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> (20)</b>
- The maximal number of errors a remote SMTP client
+ The maximal number of errors a remote SMTP client
is allowed to make without delivering mail.
<b><a href="postconf.5.html#smtpd_junk_command_limit">smtpd_junk_command_limit</a> (100)</b>
- The number of junk commands (NOOP, VRFY, ETRN or
+ The number of junk commands (NOOP, VRFY, ETRN or
RSET) that a remote SMTP client can send before the
- Postfix SMTP server starts to increment the error
+ Postfix SMTP server starts to increment the error
counter with each junk command.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_recipient_overshoot_limit">smtpd_recipient_overshoot_limit</a> (1000)</b>
- The number of recipients that a remote SMTP client
- can send in excess of the limit specified with
+ The number of recipients that a remote SMTP client
+ can send in excess of the limit specified with
$<a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a>, before the Postfix SMTP
- server increments the per-session error count for
+ server increments the per-session error count for
each excess recipient.
<b>ACCESS POLICY DELEGATION CONTROLS</b>
- As of version 2.1, Postfix can be configured to delegate
- access policy decisions to an external server that runs
- outside Postfix. See the file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
+ As of version 2.1, Postfix can be configured to delegate
+ access policy decisions to an external server that runs
+ outside Postfix. See the file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
more information.
<b><a href="postconf.5.html#smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a> (300s)</b>
- The time after which an idle SMTPD policy service
+ The time after which an idle SMTPD policy service
connection is closed.
<b><a href="postconf.5.html#smtpd_policy_service_max_ttl">smtpd_policy_service_max_ttl</a> (1000s)</b>
connection is closed.
<b><a href="postconf.5.html#smtpd_policy_service_timeout">smtpd_policy_service_timeout</a> (100s)</b>
- The time limit for connecting to, writing to or
+ The time limit for connecting to, writing to or
receiving from a delegated SMTPD policy server.
<b>ACCESS CONTROLS</b>
- The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
+ The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
all the SMTP server access control features.
<b><a href="postconf.5.html#smtpd_delay_reject">smtpd_delay_reject</a> (yes)</b>
- Wait until the RCPT TO command before evaluating
+ Wait until the RCPT TO command before evaluating
$<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a>, $smtpd_helo_restric-
tions and $<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a>, or wait until
- the ETRN command before evaluating
+ the ETRN command before evaluating
$<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> and $smtpd_helo_restric-
tions.
- <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
+ <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
<b>put)</b>
What Postfix features match subdomains of
"domain.tld" automatically, instead of requiring an
explicit ".domain.tld" pattern.
<b><a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> (empty)</b>
- Optional SMTP server access restrictions in the
+ Optional SMTP server access restrictions in the
context of a client SMTP connection request.
<b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b>
Require that a remote SMTP client introduces itself
- at the beginning of an SMTP session with the HELO
+ at the beginning of an SMTP session with the HELO
or EHLO command.
<b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server
+ Optional restrictions that the Postfix SMTP server
applies in the context of the SMTP HELO command.
<b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
- Optional restrictions that the Postfix SMTP server
+ Optional restrictions that the Postfix SMTP server
applies in the context of the MAIL FROM command.
<b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b>
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b>
The access restrictions that the Postfix SMTP
- server applies in the context of the RCPT TO com-
+ server applies in the context of the RCPT TO com-
mand.
<b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
- Optional SMTP server access restrictions in the
+ Optional SMTP server access restrictions in the
context of a client ETRN request.
<b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b>
- Forward mail with sender-specified routing
- (user[@%!]remote[@%!]site) from untrusted clients
+ Forward mail with sender-specified routing
+ (user[@%!]remote[@%!]site) from untrusted clients
to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b>
- User-defined aliases for groups of access restric-
+ User-defined aliases for groups of access restric-
tions.
<b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b><><b>)</b>
- The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
+ The lookup key to be used in SMTP <a href="access.5.html"><b>access</b>(5)</a> tables
instead of the null sender address.
<b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b>
Restrict the use of the <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a> SMTP
- access feature to only domains whose primary MX
+ access feature to only domains whose primary MX
hosts match the listed networks.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b>
- Optional access restrictions that the Postfix SMTP
+ Optional access restrictions that the Postfix SMTP
server applies in the context of the SMTP DATA com-
mand.
<b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b>
- What characters are allowed in $name expansions of
+ What characters are allowed in $name expansions of
RBL reply templates.
Available in Postfix version 2.1 and later:
<b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
- Request that the Postfix SMTP server rejects mail
- from unknown sender addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
+ Request that the Postfix SMTP server rejects mail
+ from unknown sender addresses, even when no
+ explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
is specified.
<b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b>
- Request that the Postfix SMTP server rejects mail
+ Request that the Postfix SMTP server rejects mail
for unknown recipient addresses, even when no
- explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
+ explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
tion is specified.
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b>
- Optional access restrictions that the Postfix SMTP
- server applies in the context of the SMTP END-OF-
+ Optional access restrictions that the Postfix SMTP
+ server applies in the context of the SMTP END-OF-
DATA command.
<b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
- Postfix version 2.1 introduces sender and recipient
- address verification. This feature is implemented by
- sending probe email messages that are not actually deliv-
- ered. This feature is requested via the <a href="postconf.5.html#reject_unverified_sender">reject_unveri</a>-
- <a href="postconf.5.html#reject_unverified_sender">fied_sender</a> and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
- restrictions. The status of verification probes is main-
+ Postfix version 2.1 introduces sender and recipient
+ address verification. This feature is implemented by
+ sending probe email messages that are not actually deliv-
+ ered. This feature is requested via the <a href="postconf.5.html#reject_unverified_sender">reject_unveri</a>-
+ <a href="postconf.5.html#reject_unverified_sender">fied_sender</a> and <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> access
+ restrictions. The status of verification probes is main-
tained by the <a href="verify.8.html"><b>verify</b>(8)</a> server. See the file <a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VER</a>-
- <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
+ <a href="ADDRESS_VERIFICATION_README.html">IFICATION_README</a> for information about how to configure
and operate the Postfix sender/recipient address verifica-
tion service.
<b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (3)</b>
- How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
- the completion of an address verification request
+ How many times to query the <a href="verify.8.html"><b>verify</b>(8)</a> service for
+ the completion of an address verification request
in progress.
<b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b>
- The delay between queries for the completion of an
+ The delay between queries for the completion of an
address verification request in progress.
<b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> ($<a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a>)</b>
- The sender address to use in address verification
+ The sender address to use in address verification
probes; prior to Postfix 2.5 the default was "post-
master".
<b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a recipient address is rejected by the
+ The numerical Postfix SMTP server response code
+ when a recipient address is rejected by the
<a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction.
<b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response when a
+ The numerical Postfix SMTP server response when a
recipient address is rejected by the <a href="postconf.5.html#reject_unverified_recipient">reject_unveri</a>-
<a href="postconf.5.html#reject_unverified_recipient">fied_recipient</a> restriction.
<b>ACCESS CONTROL RESPONSES</b>
- The following parameters control numerical SMTP reply
+ The following parameters control numerical SMTP reply
codes and/or text responses.
<b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a client is rejected by an <a href="access.5.html"><b>access</b>(5)</a> map
+ The numerical Postfix SMTP server response code
+ when a client is rejected by an <a href="access.5.html"><b>access</b>(5)</a> map
restriction.
<b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "defer" restriction.
<b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
- The numerical Postfix SMTP server response code
- when the client HELO or EHLO command parameter is
- rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
+ The numerical Postfix SMTP server response code
+ when the client HELO or EHLO command parameter is
+ rejected by the <a href="postconf.5.html#reject_invalid_helo_hostname">reject_invalid_helo_hostname</a>
restriction.
<b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>, <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>,
<a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a> or <a href="postconf.5.html#reject_rhsbl_recipient">reject_rhsbl_recipient</a>
<b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
The numerical Postfix SMTP server reply code when a
- client request is rejected by the
+ client request is rejected by the
<a href="postconf.5.html#reject_non_fqdn_helo_hostname">reject_non_fqdn_helo_hostname</a>,
<a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a>
restriction.
<b><a href="postconf.5.html#plaintext_reject_code">plaintext_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a request is rejected by the <b>reject_plain-</b>
+ The numerical Postfix SMTP server response code
+ when a request is rejected by the <b>reject_plain-</b>
<b>text_session</b> restriction.
<b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a remote SMTP client request is rejected by
+ The numerical Postfix SMTP server response code
+ when a remote SMTP client request is rejected by
the "reject" restriction.
<b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
- The numerical Postfix SMTP server response code
- when a client request is rejected by the
+ The numerical Postfix SMTP server response code
+ when a client request is rejected by the
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
<b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a sender or recipient address is rejected by
+ The numerical Postfix SMTP server response code
+ when a sender or recipient address is rejected by
the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a> or
<a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
<b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when a client without valid address <=> name map-
+ The numerical Postfix SMTP server response code
+ when a client without valid address <=> name map-
ping is rejected by the reject_unknown_client_host-
name restriction.
<b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
- The numerical Postfix SMTP server response code
- when the hostname specified with the HELO or EHLO
- command is rejected by the
+ The numerical Postfix SMTP server response code
+ when the hostname specified with the HELO or EHLO
+ command is rejected by the
<a href="postconf.5.html#reject_unknown_helo_hostname">reject_unknown_helo_hostname</a> restriction.
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
- The default SMTP server response template for a
- request that is rejected by an RBL-based restric-
+ The default SMTP server response template for a
+ request that is rejected by an RBL-based restric-
tion.
<b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
- The numerical Postfix SMTP server response code
+ The numerical Postfix SMTP server response code
when a remote SMTP client request is blocked by the
<a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
- The location of all postfix administrative com-
+ The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
and most Postfix daemon processes.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for an incoming connection
+ The maximum amount of time that an idle Postfix
+ daemon process waits for an incoming connection
before terminating voluntarily.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of incoming connections that a
- Postfix daemon process will service before termi-
+ The maximal number of incoming connections that a
+ Postfix daemon process will service before termi-
nating voluntarily.
<b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
The internet hostname of this mail system.
<b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
- The list of "trusted" SMTP clients that have more
+ The list of "trusted" SMTP clients that have more
privileges than "strangers".
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
sions (user+foo).
<b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
- The text that follows the 220 status code in the
+ The text that follows the 220 status code in the
SMTP greeting banner.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
- List of commands that causes the Postfix SMTP
- server to immediately terminate the session with a
+ List of commands that causes the Postfix SMTP
+ server to immediately terminate the session with a
221 code.
Available in Postfix version 2.5 and later:
<b><a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> (no)</b>
- Enable logging of the remote SMTP client port in
+ Enable logging of the remote SMTP client port in
addition to the hostname and IP address.
<b>SEE ALSO</b>
<a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
DATA, ., RSET, NOOP, and QUIT. Separate command names by
white space or commas, and use quotes to protect white space
from the shell. Command names are case-insensitive.
+.IP "\fB-Q \fIcommand,command,...\fR"
+Disconnect after sending a 431 reply after receiving one
+of the specified commands.
+.sp
+Examples of commands are CONNECT, HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+DATA, ., RSET, NOOP, and QUIT. Separate command names by
+white space or commas, and use quotes to protect white space
+from the shell. Command names are case-insensitive.
.IP "\fB-r \fIcommand,command,...\fR"
Reject the specified commands with a soft (4xx) error code.
This option implies \fB-p\fR.
available macro names and their meanings.
.PP
This feature is available in Postfix 2.3 and later.
+.SH milter_end_of_header_macros (default: see postconf -n output)
+The macros that are sent to Milter (mail filter) applications
+after the end of the message header. See MILTER_README for a list
+of available macro names and their meanings.
+.PP
+This feature is available in Postfix 2.5 and later.
.SH milter_helo_macros (default: see postconf -n output)
The macros that are sent to Milter (mail filter) applications
after the SMTP HELO or EHLO command. See
This feature is available in Postfix 2.3 and later.
.SH milter_protocol (default: 2)
The mail filter protocol version and optional protocol extensions
-for communication with a Milter (mail filter) application. This
-information should match the protocol that is expected by the actual
-mail filter application.
+for communication with a Milter (mail filter) application. Postfix
+sends this version number during the initial protocol handshake.
+It should match the version number that is expected by the mail
+filter application (or by its Milter library).
.PP
Protocol versions:
.IP "2"
-Use Sendmail 8 mail filter protocol version 2.
+Use Sendmail 8 mail filter protocol version 2 (default
+as of Sendmail version 8.11).
.IP "3"
Use Sendmail 8 mail filter protocol version 3.
.IP "4"
Use Sendmail 8 mail filter protocol version 4.
+.IP "6"
+Use Sendmail 8 mail filter protocol version 6 (default
+as of Sendmail version 8.14).
.PP
Protocol extensions:
.IP "no_header_reply"
The
non_fqdn_reject_code parameter specifies the response code to
rejected requests (default: 504).
+.IP "\fBreject_rhsbl_helo \fIrbl_domain=d.d.d.d\fR\fR"
+Reject the request when the HELO or EHLO hostname hostname is
+listed with the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR
+(Postfix version 2.1 and later only). If no "\fI=d.d.d.d\fR" is
+specified, reject the request when the HELO or EHLO hostname is
+listed with any A record under \fIrbl_domain\fR. See the
+reject_rbl_client description for additional RBL related configuration
+parameters. This feature is available in Postfix 2.0 and later.
.IP "\fBreject_unknown_helo_hostname\fR (with Postfix < 2.3: reject_unknown_hostname)"
Reject the request when the HELO or EHLO hostname has no DNS A
or MX record.
.IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
+.PP
+Available in Postfix version 2.5 and later:
+.IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
+The macros that are sent to Milter (mail filter) applications
+after the end of the message header.
.SH "MIME PROCESSING CONTROLS"
.na
.nf
.IP "\fBmilter_unknown_command_macros (see postconf -n output)\fR"
The macros that are sent to version 3 or higher Milter (mail
filter) applications after an unknown SMTP command.
+.IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
+The macros that are sent to Milter (mail filter) applications
+after the message header.
.IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
s;\breject_invalid_hostname\b;<a href="postconf.5.html#reject_invalid_helo_hostname">$&</a>;g;
s;\breject_non_fqdn_helo_hostname\b;<a href="postconf.5.html#reject_non_fqdn_helo_hostname">$&</a>;g;
s;\breject_non_fqdn_hostname\b;<a href="postconf.5.html#reject_non_fqdn_helo_hostname">$&</a>;g;
+ s;\breject_rhsbl_helo\b;<a href="postconf.5.html#reject_rhsbl_helo">$&</a>;g;
s;\breject_unknown_helo_hostname\b;<a href="postconf.5.html#reject_unknown_helo_hostname">$&</a>;g;
s;\breject_unknown_hostname\b;<a href="postconf.5.html#reject_unknown_helo_hostname">$&</a>;g;
s;\bmilter_data_macros\b;<a href="postconf.5.html#milter_data_macros">$&</a>;g;
s;\bmilter_unknown_command_macros\b;<a href="postconf.5.html#milter_unknown_command_macros">$&</a>;g;
s;\bmilter_end_of_data_macros\b;<a href="postconf.5.html#milter_end_of_data_macros">$&</a>;g;
+ s;\bmilter_end_of_header_macros\b;<a href="postconf.5.html#milter_end_of_header_macros">$&</a>;g;
# Hyperlink URLs and RFC documents
<blockquote>
<pre>
+/etc/postfix/main.cf:
# What to do in case of errors? Specify accept, reject, or tempfail.
milter_default_action = tempfail
</pre>
<p> As Postfix is not built with the Sendmail libmilter library,
you may need to configure the Milter protocol version that Postfix
-should use. The default version is 2. </p>
+should use. The default version is 2. Other protocol versions are
+3 and 4 (Postfix 2.3 and later), and 6 (Postfix 2.5 an later). </p>
<blockquote>
<pre>
-milter_protocol = 2
+/etc/postfix/main.cf:
+ milter_protocol = 2
</pre>
</blockquote>
<p> Postfix emulates a limited number of Sendmail macros, as shown
in the table. Different macros are available at different SMTP
-protocol stages (EOM = end-of-message); their availability is not
+protocol stages (EOH = end-of-header, EOM = end-of-message); their
+availability is not
always the same as in Sendmail. See the <a
href="#workarounds">workarounds</a> section below for solutions.
</p>
<tr> <th> Name </th> <th> Availability </th> <th> Description </th>
</tr>
-<tr> <td> i </td> <td> DATA, EOM </td> <td> Queue ID </td> </tr>
+<tr> <td> i </td> <td> DATA, EOH, EOM </td> <td> Queue ID </td> </tr>
<tr> <td> j </td> <td> Always </td> <td> value of myhostname </td>
</tr>
<tr> <td> _ </td> <td> Always </td> <td> The validated client name
and address </td> </tr>
-<tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOM </td> <td> SASL
+<tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL
login name </td> </tr>
-<tr> <td> {auth_author} </td> <td> MAIL, DATA, EOM </td> <td> SASL
+<tr> <td> {auth_author} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL
sender </td> </tr>
-<tr> <td> {auth_type} </td> <td> MAIL, DATA, EOM </td> <td> SASL
+<tr> <td> {auth_type} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL
login method </td> </tr>
<tr> <td> {client_addr} </td> <td> Always </td> <td> Client IP
<td> Client name from reverse lookup, "unknown" when lookup fails
</td> </tr>
-<tr> <td> {cert_issuer} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
+<tr> <td> {cert_issuer} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td>
TLS client certificate issuer </td> </tr>
-<tr> <td> {cert_subject} </td> <td> HELO, MAIL, DATA, EOM </td>
+<tr> <td> {cert_subject} </td> <td> HELO, MAIL, DATA, EOH, EOM </td>
<td> TLS client certificate subject </td> </tr>
-<tr> <td> {cipher_bits} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
+<tr> <td> {cipher_bits} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td>
TLS session key size </td> </tr>
-<tr> <td> {cipher} </td> <td> HELO, MAIL, DATA, EOM </td> <td> TLS
+<tr> <td> {cipher} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td> TLS
cipher </td> </tr>
<tr> <td> {daemon_name} </td> <td> Always </td> <td> value of
<tr> <td> {rcpt_addr} </td> <td> RCPT </td> <td> Recipient address
</td> </tr>
-<tr> <td> {tls_version} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
+<tr> <td> {tls_version} </td> <td> HELO, MAIL, DATA, EOH, EOM </td> <td>
TLS protocol version </td> </tr>
<tr> <td> v </td> <td> Always </td> <td> value of milter_macro_v
<p> Postfix sends specific sets of macros at different SMTP protocol
stages. The sets are configured with the parameters as described
-in the table (EOM = end of message). </p>
+in the table (EOH = end of headers; EOM = end of message). </p>
<blockquote>
<tr> <td> milter_data_macros </td> <td> 4 or higher </td> <td> DATA
</td> </tr>
+<tr> <td> milter_end_of_header_macros </td> <td> 6 or higher </td>
+<td> EOH </td> </tr>
+
<tr> <td> milter_end_of_data_macros </td> <td> 2 or higher </td>
<td> EOM </td> </tr>
<ul>
-<li> <p> Postfix currently supports only applications that speak
-the Sendmail 8 Milter protocol versions 2..4. Support for other
-protocol types or protocol versions may be added later. </p>
+<li> <p> Postfix version 2.3 introduces support for Sendmail 8
+milter protocol versions 2, 3 and 4; Postfix version 2.5 adds support
+for protocol version 6, which is available with Sendmail 8.14.
+Support for other protocol types or protocol versions may be added
+later. </p>
<li> <p> For applications that are written in C, you need to use
the Sendmail libmilter library. A Postfix replacement may be
<p> The solution is to use Postfix version 2.4 or later. </p>
+<li> <p> Postfix version 2.5 implements the Sendmail 8.14 features
+except: SMFIP_RCPT_REJ (report rejected recipients to the mail
+filter), SMFIR_CHGFROM (replace sender, with optional ESMTP command
+parameters), and SMFIR_ADDRCPT_PAR (add recipient, with optional
+ESMTP command parameters).
+
<li> <p> Most Milter configuration options are global. Future Postfix
versions may support per-Milter timeouts, per-Milter error handling,
etc. </p>
non_fqdn_reject_code parameter specifies the response code to
rejected requests (default: 504).</dd>
+<dt><b><a name="reject_rhsbl_helo">reject_rhsbl_helo <i>rbl_domain=d.d.d.d</i></a></b></dt>
+
+<dd>Reject the request when the HELO or EHLO hostname hostname is
+listed with the A record "<i>d.d.d.d</i>" under <i>rbl_domain</i>
+(Postfix version 2.1 and later only). If no "<i>=d.d.d.d</i>" is
+specified, reject the request when the HELO or EHLO hostname is
+listed with any A record under <i>rbl_domain</i>. See the
+reject_rbl_client description for additional RBL related configuration
+parameters. This feature is available in Postfix 2.0 and later.
+</dd>
+
<dt><b><a name="reject_unknown_helo_hostname">reject_unknown_helo_hostname</a></b> (with Postfix < 2.3: reject_unknown_hostname)</dt>
<dd>Reject the request when the HELO or EHLO hostname has no DNS A
%PARAM milter_protocol 2
<p> The mail filter protocol version and optional protocol extensions
-for communication with a Milter (mail filter) application. This
-information should match the protocol that is expected by the actual
-mail filter application. </p>
+for communication with a Milter (mail filter) application. Postfix
+sends this version number during the initial protocol handshake.
+It should match the version number that is expected by the mail
+filter application (or by its Milter library). </p>
<p>Protocol versions: </p>
<dl compact>
-<dt>2</dt> <dd>Use Sendmail 8 mail filter protocol version 2.</dd>
+<dt>2</dt> <dd>Use Sendmail 8 mail filter protocol version 2 (default
+as of Sendmail version 8.11).</dd>
<dt>3</dt> <dd>Use Sendmail 8 mail filter protocol version 3.</dd>
<dt>4</dt> <dd>Use Sendmail 8 mail filter protocol version 4.</dd>
+<dt>6</dt> <dd>Use Sendmail 8 mail filter protocol version 6 (default
+as of Sendmail version 8.14).</dd>
+
</dl>
<p>Protocol extensions: </p>
<p> This feature is available in Postfix 2.3 and later. </p>
+%PARAM milter_end_of_header_macros see postconf -n output
+
+<p> The macros that are sent to Milter (mail filter) applications
+after the end of the message header. See MILTER_README for a list
+of available macro names and their meanings. </p>
+
+<p> This feature is available in Postfix 2.5 and later. </p>
+
%PARAM milter_end_of_data_macros see postconf -n output
<p> The macros that are sent to Milter (mail filter) applications
/* .IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
/* The macros that are sent to Milter (mail filter) applications
/* after the message end-of-data.
+/* .PP
+/* Available in Postfix version 2.5 and later:
+/* .IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
+/* The macros that are sent to Milter (mail filter) applications
+/* after the end of the message header.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
char *var_milt_mail_macros; /* MAIL FROM macros */
char *var_milt_rcpt_macros; /* RCPT TO macros */
char *var_milt_data_macros; /* DATA macros */
+char *var_milt_eoh_macros; /* end-of-header macros */
char *var_milt_eod_macros; /* end-of-data macros */
char *var_milt_unk_macros; /* unknown command macros */
char *var_cleanup_milters; /* non-SMTP mail */
VAR_MILT_MAIL_MACROS, DEF_MILT_MAIL_MACROS, &var_milt_mail_macros, 0, 0,
VAR_MILT_RCPT_MACROS, DEF_MILT_RCPT_MACROS, &var_milt_rcpt_macros, 0, 0,
VAR_MILT_DATA_MACROS, DEF_MILT_DATA_MACROS, &var_milt_data_macros, 0, 0,
+ VAR_MILT_EOH_MACROS, DEF_MILT_EOH_MACROS, &var_milt_eoh_macros, 0, 0,
VAR_MILT_EOD_MACROS, DEF_MILT_EOD_MACROS, &var_milt_eod_macros, 0, 0,
VAR_MILT_UNK_MACROS, DEF_MILT_UNK_MACROS, &var_milt_unk_macros, 0, 0,
VAR_CLEANUP_MILTERS, DEF_CLEANUP_MILTERS, &var_cleanup_milters, 0, 0,
var_milt_mail_macros,
var_milt_rcpt_macros,
var_milt_data_macros,
+ var_milt_eoh_macros,
var_milt_eod_macros,
var_milt_unk_macros);
/* cleanup_add_header - append message header */
-static const char *cleanup_add_header(void *context, char *name, char *value)
+static const char *cleanup_add_header(void *context, const char *name,
+ const char *space,
+ const char *value)
{
const char *myname = "cleanup_add_header";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
return (cleanup_milter_error(state, errno));
}
buf = vstring_alloc(100);
- vstring_sprintf(buf, "%s: %s", name, value);
+ vstring_sprintf(buf, "%s:%s%s", name, space, value);
cleanup_out_header(state, buf); /* Includes padding */
vstring_free(buf);
if ((reverse_ptr_offset = vstream_ftell(state->dst)) < 0) {
static const char *cleanup_patch_header(CLEANUP_STATE *state,
const char *new_hdr_name,
+ const char *hdr_space,
const char *new_hdr_value,
off_t old_rec_offset,
int old_rec_type,
msg_warn("%s: seek file %s: %m", myname, cleanup_path);
CLEANUP_PATCH_HEADER_RETURN(cleanup_milter_error(state, errno));
}
- vstring_sprintf(buf, "%s: %s", new_hdr_name, new_hdr_value);
+ vstring_sprintf(buf, "%s:%s%s", new_hdr_name, hdr_space, new_hdr_value);
cleanup_out_header(state, buf); /* Includes padding */
if (msg_verbose > 1)
msg_info("%s: %ld: write %.*s", myname, (long) new_hdr_offset,
/* cleanup_ins_header - insert message header */
static const char *cleanup_ins_header(void *context, ssize_t index,
- char *new_hdr_name,
- char *new_hdr_value)
+ const char *new_hdr_name,
+ const char *hdr_space,
+ const char *new_hdr_value)
{
const char *myname = "cleanup_ins_header";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
*/
if (old_rec_offset < 0)
CLEANUP_INS_HEADER_RETURN(cleanup_add_header(context, new_hdr_name,
- new_hdr_value));
+ hdr_space, new_hdr_value));
/*
* If the header does exist, save both the new and the existing header to
CLEANUP_INS_HEADER_RETURN(cleanup_milter_error(state, errno));
}
}
- ret = cleanup_patch_header(state, new_hdr_name, new_hdr_value,
+ ret = cleanup_patch_header(state, new_hdr_name, hdr_space, new_hdr_value,
old_rec_offset, old_rec_type,
old_rec_buf, next_offset);
CLEANUP_INS_HEADER_RETURN(ret);
/* cleanup_upd_header - modify or append message header */
static const char *cleanup_upd_header(void *context, ssize_t index,
- char *new_hdr_name,
- char *new_hdr_value)
+ const char *new_hdr_name,
+ const char *hdr_space,
+ const char *new_hdr_value)
{
const char *myname = "cleanup_upd_header";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
*/
if (old_rec_offset < 0)
CLEANUP_UPD_HEADER_RETURN(cleanup_add_header(context, new_hdr_name,
- new_hdr_value));
+ hdr_space, new_hdr_value));
/*
* If the old header is found, find the end of the old header, save the
if ((next_offset = cleanup_find_header_end(state, rec_buf, last_type)) < 0)
/* Warning and errno->error mapping are done elsewhere. */
CLEANUP_UPD_HEADER_RETURN(cleanup_milter_error(state, 0));
- ret = cleanup_patch_header(state, new_hdr_name, new_hdr_value,
+ ret = cleanup_patch_header(state, new_hdr_name, hdr_space, new_hdr_value,
old_rec_offset, DONT_SAVE_RECORD,
(VSTRING *) 0, next_offset);
CLEANUP_UPD_HEADER_RETURN(ret);
/* cleanup_del_header - delete message header */
static const char *cleanup_del_header(void *context, ssize_t index,
- char *hdr_name)
+ const char *hdr_name)
{
const char *myname = "cleanup_del_header";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
/* cleanup_add_rcpt - append recipient address */
-static const char *cleanup_add_rcpt(void *context, char *ext_rcpt)
+static const char *cleanup_add_rcpt(void *context, const char *ext_rcpt)
{
const char *myname = "cleanup_add_rcpt";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
/* cleanup_del_rcpt - remove recipient and all its expansions */
-static const char *cleanup_del_rcpt(void *context, char *ext_rcpt)
+static const char *cleanup_del_rcpt(void *context, const char *ext_rcpt)
{
const char *myname = "cleanup_del_rcpt";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
if (state->milters)
milter_free(state->milters);
state->milters = milter_receive(state->src, count);
+ if (state->milters == 0)
+ msg_fatal("cleanup_milter_receive: milter receive failed");
milter_macro_callback(state->milters, cleanup_milter_eval, (void *) state);
milter_edit_callback(state->milters,
cleanup_add_header, cleanup_upd_header,
msg_warn("bad add_header argument count: %d", argv->argc);
} else {
flatten_args(arg_buf, argv->argv + 2);
- cleanup_add_header(state, argv->argv[1], STR(arg_buf));
+ cleanup_add_header(state, argv->argv[1], " ", STR(arg_buf));
}
} else if (strcmp(argv->argv[0], "ins_header") == 0) {
if (argv->argc < 3) {
msg_warn("bad ins_header index value");
} else {
flatten_args(arg_buf, argv->argv + 3);
- cleanup_ins_header(state, index, argv->argv[2], STR(arg_buf));
+ cleanup_ins_header(state, index, argv->argv[2], " ", STR(arg_buf));
}
} else if (strcmp(argv->argv[0], "upd_header") == 0) {
if (argv->argc < 3) {
msg_warn("bad upd_header index value");
} else {
flatten_args(arg_buf, argv->argv + 3);
- cleanup_upd_header(state, index, argv->argv[2], STR(arg_buf));
+ cleanup_upd_header(state, index, argv->argv[2], " ", STR(arg_buf));
}
} else if (strcmp(argv->argv[0], "del_header") == 0) {
if (argv->argc != 3) {
#define DEF_MILT_UNK_MACROS ""
extern char *var_milt_unk_macros;
+#define VAR_MILT_EOH_MACROS "milter_end_of_header_macros"
+#define DEF_MILT_EOH_MACROS "i"
+extern char *var_milt_eoh_macros;
+
#define VAR_MILT_EOD_MACROS "milter_end_of_data_macros"
#define DEF_MILT_EOD_MACROS "i"
extern char *var_milt_eod_macros;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20071218"
+#define MAIL_RELEASE_DATE "20071221"
#define MAIL_VERSION_NUMBER "2.5"
#ifdef SNAPSHOT
mv junk $@.o
test-milter: test-milter.c
- cc -g -o $@ $? -lmilter -lpthread
+ cc -g -I/usr/local/include -o $@ $? -L/usr/local/lib -lmilter -lpthread
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
/* msg_timeout, protocol, def_action,
/* conn_macros, helo_macros,
/* mail_macros, rcpt_macros,
-/* data_macros, eod_macros,
-/* unk_macros)
+/* data_macros, eoh_macros,
+/* eod_macros, unk_macros)
/* const char *milter_names;
/* int conn_timeout;
/* int cmd_timeout;
/* const char *mail_macros;
/* const char *rcpt_macrps;
/* const char *data_macros;
+/* const char *eoh_macros;
/* const char *eod_macros;
/* const char *unk_macros;
/*
/* ins_header, del_header, add_rcpt,
/* del_rcpt, repl_body, context)
/* MILTERS *milters;
-/* const char *(*add_header) (void *context, char *name, char *value);
-/* const char *(*upd_header) (void *context, ssize_t index,
-/* char *name, char *value);
-/* const char *(*ins_header) (void *context, ssize_t index,
-/* char *name, char *value);
-/* const char *(*del_header) (void *context, ssize_t index, char *name);
-/* const char *(*add_rcpt) (void *context, char *rcpt);
-/* const char *(*del_rcpt) (void *context, char *rcpt);
-/* const char *(*repl_body) (void *context, VSTRING *body);
+/* MILTER_ADD_HEADER_FN add_header;
+/* MILTER_EDIT_HEADER_FN upd_header;
+/* MILTER_EDIT_HEADER_FN ins_header;
+/* MILTER_DEL_HEADER_FN del_header;
+/* MILTER_EDIT_RCPT_FN add_rcpt;
+/* MILTER_EDIT_RCPT_FN del_rcpt;
+/* MILTER_EDIT_BODY_FN repl_body;
/* void *context;
/*
/* const char *milter_conn_event(milters, client_name, client_addr,
/*
/* milter_message() sends the message header and body to the
/* to the specified milter instances, and sends the macros
-/* specified with the milter_create() eod_macros argument at
+/* specified with the milter_create() eoh_macros after the
+/* message header, and with the eod_macros argument at
/* the end. Each milter sees the result of any changes made
/* by a preceding milter. This function must be called with
/* as argument an open Postfix queue file.
/* milter_edit_callback - specify queue file edit call-back information */
void milter_edit_callback(MILTERS *milters,
- const char *(*add_header) (void *, char *, char *),
- const char *(*upd_header) (void *, ssize_t, char *, char *),
- const char *(*ins_header) (void *, ssize_t, char *, char *),
- const char *(*del_header) (void *, ssize_t, char *),
- const char *(*add_rcpt) (void *, char *),
- const char *(*del_rcpt) (void *, char *),
- const char *(*repl_body) (void *, int, VSTRING *),
+ MILTER_ADD_HEADER_FN add_header,
+ MILTER_EDIT_HEADER_FN upd_header,
+ MILTER_EDIT_HEADER_FN ins_header,
+ MILTER_DEL_HEADER_FN del_header,
+ MILTER_EDIT_RCPT_FN add_rcpt,
+ MILTER_EDIT_RCPT_FN del_rcpt,
+ MILTER_EDIT_BODY_FN repl_body,
void *chg_context)
{
milters->add_header = add_header;
{
const char *resp;
MILTER *m;
- ARGV *macros;
+ ARGV *eoh_macros;
+ ARGV *eod_macros;
if (msg_verbose)
msg_info("inspect content by all milters");
- macros = milters->eod_macros == 0 ? 0 :
+ eoh_macros = milters->eoh_macros == 0 ? 0 :
+ milter_macro_lookup(milters, milters->eoh_macros);
+ eod_macros = milters->eod_macros == 0 ? 0 :
milter_macro_lookup(milters, milters->eod_macros);
for (resp = 0, m = milters->milter_list; resp == 0 && m != 0; m = m->next)
- resp = m->message(m, fp, data_offset, macros);
- if (macros)
- argv_free(macros);
+ resp = m->message(m, fp, data_offset, eoh_macros, eod_macros);
+ if (eoh_macros)
+ argv_free(eoh_macros);
+ if (eod_macros)
+ argv_free(eod_macros);
return (resp);
}
const char *mail_macros,
const char *rcpt_macros,
const char *data_macros,
+ const char *eoh_macros,
const char *eod_macros,
const char *unk_macros)
{
milters->mail_macros = mystrdup(mail_macros);
milters->rcpt_macros = mystrdup(rcpt_macros);
milters->data_macros = mystrdup(data_macros);
+ milters->eoh_macros = mystrdup(eoh_macros);
milters->eod_macros = mystrdup(eod_macros);
milters->unk_macros = mystrdup(unk_macros);
milters->add_header = 0;
milters->upd_header = milters->ins_header = 0;
milters->del_header = 0;
milters->add_rcpt = milters->del_rcpt = 0;
+ milters->repl_body = 0;
milters->chg_context = 0;
return (milters);
}
myfree(milters->rcpt_macros);
if (milters->rcpt_macros)
myfree(milters->data_macros);
+ if (milters->eoh_macros)
+ myfree(milters->eoh_macros);
if (milters->eod_macros)
myfree(milters->eod_macros);
if (milters->unk_macros)
#define MAIL_ATTR_MILT_MAIL "mail_macros"
#define MAIL_ATTR_MILT_RCPT "rcpt_macros"
#define MAIL_ATTR_MILT_DATA "data_macros"
+#define MAIL_ATTR_MILT_EOH "eoh_macros"
#define MAIL_ATTR_MILT_EOD "eod_macros"
#define MAIL_ATTR_MILT_UNK "unk_macros"
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAIL, milters->mail_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_RCPT, milters->rcpt_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_DATA, milters->data_macros,
+ ATTR_TYPE_STR, MAIL_ATTR_MILT_EOH, milters->eoh_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_EOD, milters->eod_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_UNK, milters->unk_macros,
ATTR_TYPE_END);
VSTRING *mail_macros;
VSTRING *rcpt_macros;
VSTRING *data_macros;
+ VSTRING *eoh_macros;
VSTRING *eod_macros;
VSTRING *unk_macros;
#define FREE_BUFFERS() do { \
vstring_free(conn_macros); vstring_free(helo_macros); \
vstring_free(mail_macros); vstring_free(rcpt_macros); \
- vstring_free(data_macros); vstring_free(eod_macros); \
- vstring_free(unk_macros); \
+ vstring_free(data_macros); vstring_free(eoh_macros); \
+ vstring_free(eod_macros); vstring_free(unk_macros); \
} while (0)
conn_macros = vstring_alloc(10);
mail_macros = vstring_alloc(10);
rcpt_macros = vstring_alloc(10);
data_macros = vstring_alloc(10);
+ eoh_macros = vstring_alloc(10);
eod_macros = vstring_alloc(10);
unk_macros = vstring_alloc(10);
if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_MILT_MAIL, mail_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_RCPT, rcpt_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_DATA, data_macros,
+ ATTR_TYPE_STR, MAIL_ATTR_MILT_EOH, eoh_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_EOD, eod_macros,
ATTR_TYPE_STR, MAIL_ATTR_MILT_UNK, unk_macros,
- ATTR_TYPE_END) != 7) {
+ ATTR_TYPE_END) != 8) {
FREE_BUFFERS();
return (0);
}
milters = milter_create(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION,
STR(conn_macros), STR(helo_macros),
STR(mail_macros), STR(rcpt_macros),
- STR(data_macros), STR(eod_macros),
- STR(unk_macros));
+ STR(data_macros), STR(eoh_macros),
+ STR(eod_macros), STR(unk_macros));
FREE_BUFFERS();
/*
{
MILTERS *milters = 0;
char *conn_macros, *helo_macros, *mail_macros, *rcpt_macros;
- char *data_macros, *eod_macros, *unk_macros;
+ char *data_macros, *eoh_macros, *eod_macros, *unk_macros;
VSTRING *inbuf = vstring_alloc(100);
char *bufp;
char *cmd;
int istty = isatty(vstream_fileno(VSTREAM_IN));
conn_macros = helo_macros = mail_macros = rcpt_macros = data_macros
- = eod_macros = unk_macros = "";
+ = eoh_macros = eod_macros = unk_macros = "";
msg_vstream_init(argv[0], VSTREAM_ERR);
while ((ch = GETOPT(argc, argv, "V:v")) > 0) {
var_milt_cmd_time, var_milt_msg_time,
var_milt_protocol, var_milt_def_action,
conn_macros, helo_macros, mail_macros,
- rcpt_macros, data_macros, eod_macros,
- unk_macros);
+ rcpt_macros, data_macros, eoh_macros,
+ eod_macros, unk_macros);
} else if (strcmp(cmd, "free") == 0 && argv->argc == 0) {
if (milters == 0) {
msg_warn("no milters");
const char *(*mail_event) (struct MILTER *, const char **, ARGV *);
const char *(*rcpt_event) (struct MILTER *, const char **, ARGV *);
const char *(*data_event) (struct MILTER *, ARGV *);
- const char *(*message) (struct MILTER *, VSTREAM *, off_t, ARGV *);
+ const char *(*message) (struct MILTER *, VSTREAM *, off_t, ARGV *, ARGV *);
const char *(*unknown_event) (struct MILTER *, const char *, ARGV *);
const char *(*other_event) (struct MILTER *);
void (*abort) (struct MILTER *);
/*
* A bunch of Milters.
*/
+typedef const char *(*MILTER_MAC_LOOKUP_FN) (const char *, void *);
+typedef const char *(*MILTER_ADD_HEADER_FN) (void *, const char *, const char *, const char *);
+typedef const char *(*MILTER_EDIT_HEADER_FN) (void *, ssize_t, const char *, const char *, const char *);
+typedef const char *(*MILTER_DEL_HEADER_FN) (void *, ssize_t, const char *);
+typedef const char *(*MILTER_EDIT_RCPT_FN) (void *, const char *);
+typedef const char *(*MILTER_EDIT_BODY_FN) (void *, int, VSTRING *);
+
typedef struct MILTERS {
MILTER *milter_list; /* linked list of Milters */
- const char *(*mac_lookup) (const char *, void *);
+ MILTER_MAC_LOOKUP_FN mac_lookup;
void *mac_context; /* macro lookup context */
char *conn_macros; /* macros for connect event */
char *helo_macros; /* macros for HELO/EHLO command */
char *mail_macros; /* macros for MAIL FROM command */
char *rcpt_macros; /* macros for RCPT TO command */
char *data_macros; /* macros for DATA command */
+ char *eoh_macros; /* macros for end-of-headers */
char *eod_macros; /* macros for END-OF-DATA command */
char *unk_macros; /* macros for unknown command */
void *chg_context; /* context for queue file changes */
- const char *(*add_header) (void *, char *, char *);
- const char *(*upd_header) (void *, ssize_t, char *, char *);
- const char *(*del_header) (void *, ssize_t, char *);
- const char *(*ins_header) (void *, ssize_t, char *, char *);
- const char *(*add_rcpt) (void *, char *);
- const char *(*del_rcpt) (void *, char *);
- const char *(*repl_body) (void *, int, VSTRING *);
+ MILTER_ADD_HEADER_FN add_header;
+ MILTER_EDIT_HEADER_FN upd_header;
+ MILTER_DEL_HEADER_FN del_header;
+ MILTER_EDIT_HEADER_FN ins_header;
+ MILTER_EDIT_RCPT_FN add_rcpt;
+ MILTER_EDIT_RCPT_FN del_rcpt;
+ MILTER_EDIT_BODY_FN repl_body;
} MILTERS;
-typedef const char *(*MILTER_MAC_LOOKUP_FN) (const char *, void *);
-typedef const char *(*MILTER_ADD_HEADER_FN) (void *, char *, char *);
-typedef const char *(*MILTER_EDIT_HEADER_FN) (void *, ssize_t, char *, char *);
-typedef const char *(*MILTER_DEL_HEADER_FN) (void *, ssize_t, char *);
-typedef const char *(*MILTER_EDIT_RCPT_FN) (void *, char *);
-typedef const char *(*MILTER_EDIT_BODY_FN) (void *, int, VSTRING *);
-
extern MILTERS *milter_create(const char *, int, int, int,
const char *, const char *,
const char *, const char *,
const char *, const char *,
const char *, const char *,
- const char *);
+ const char *, const char *);
extern void milter_macro_callback(MILTERS *, MILTER_MAC_LOOKUP_FN, void *);
extern void milter_edit_callback(MILTERS *milters, MILTER_ADD_HEADER_FN,
MILTER_EDIT_HEADER_FN, MILTER_EDIT_HEADER_FN,
#define MILTER_BODY_START 1 /* start message body */
#define MILTER_BODY_LINE 2 /* message body line */
#define MILTER_BODY_END 3 /* end message body */
-
+
/*
* Sendmail 8 macro names. We support forms with and without the {}.
*/
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <stddef.h> /* offsetof() */
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define SHUT_RDWR 2
#endif
-/* Sendmail 8 Milter protocol. */
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <split_at.h>
+#include <connect.h>
+#include <argv.h>
+#include <name_mask.h>
+#include <name_code.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <mail_params.h> /* var_line_limit */
+#include <mail_proto.h>
+#include <rec_type.h>
+#include <record.h>
+#include <mime_state.h>
+#include <is_header.h>
+
+/* Postfix Milter library. */
+
+#include <milter.h>
+
+/* Application-specific. */
/*
* Use our own protocol definitions, so that Postfix can be built even when
* libmilter is not installed. This means that we must specify the libmilter
- * protocol version in main.cf. The other option (above) is to compile
- * Postfix with the installed libmilter include files and to support only
- * that protocol version.
+ * protocol version in main.cf, and that we must send only the commands that
+ * are supported for that protocol version.
*/
/*
#define SMFIC_RCPT 'R' /* RCPT to */
#define SMFIC_DATA 'T' /* DATA */
#define SMFIC_UNKNOWN 'U' /* Any unknown command */
+ /* Introduced with Sendmail 8.14. */
+#define SMFIC_QUIT_NC 'K' /* Quit + new connection */
/*
* Responses from filter to MTA.
#define SMFIR_INSHEADER 'i' /* insert header */
#define SMFIR_REPLYCODE 'y' /* reply code etc */
#define SMFIR_QUARANTINE 'q' /* quarantine */
+ /* Introduced with Sendmail 8.14. */
+#define SMFIR_SKIP 's' /* skip further events of this type */
+#define SMFIR_CHGFROM 'e' /* change sender (incl. ESMTP args) */
+#define SMFIR_ADDRCPT_PAR '2' /* add recipient (incl. ESMTP args) */
+#define SMFIR_SETSYMLIST 'l' /* set list of symbols (macros) */
/*
* Commands that the filter does not want to receive, and replies that the
- * filter will not send.
+ * filter will not send. Plus some other random stuff.
*/
-#define SMFIP_NOCONNECT (1L<<0) /* MTA should not send connect info */
-#define SMFIP_NOHELO (1L<<1) /* MTA should not send HELO info */
-#define SMFIP_NOMAIL (1L<<2) /* MTA should not send MAIL info */
-#define SMFIP_NORCPT (1L<<3) /* MTA should not send RCPT info */
-#define SMFIP_NOBODY (1L<<4) /* MTA should not send body */
-#define SMFIP_NOHDRS (1L<<5) /* MTA should not send headers */
-#define SMFIP_NOEOH (1L<<6) /* MTA should not send EOH */
-#define SMFIP_NOHREPL (1L<<7) /* filter will not reply per header */
-#define SMFIP_NOUNKNOWN (1L<<8) /* MTA should not send unknown cmd */
-#define SMFIP_NODATA (1L<<9) /* MTA should not send DATA */
+#define SMFIP_NOCONNECT (1L<<0) /* filter does not want connect info */
+#define SMFIP_NOHELO (1L<<1) /* filter does not want HELO info */
+#define SMFIP_NOMAIL (1L<<2) /* filter does not want MAIL info */
+#define SMFIP_NORCPT (1L<<3) /* filter does not want RCPT info */
+#define SMFIP_NOBODY (1L<<4) /* filter does not want body */
+#define SMFIP_NOHDRS (1L<<5) /* filter does not want headers */
+#define SMFIP_NOEOH (1L<<6) /* filter does not want EOH */
+#define SMFIP_NR_HDR (1L<<7) /* filter won't reply for header */
+#define SMFIP_NOHREPL SMFIP_NR_HDR
+#define SMFIP_NOUNKNOWN (1L<<8) /* filter does not want unknown cmd */
+#define SMFIP_NODATA (1L<<9) /* filter does not want DATA */
+ /* Introduced with Sendmail 8.14. */
+#define SMFIP_SKIP (1L<<10)/* MTA supports SMFIS_SKIP */
+#define SMFIP_RCPT_REJ (1L<<11)/* filter wants rejected RCPTs */
+#define SMFIP_NR_CONN (1L<<12)/* filter won't reply for connect */
+#define SMFIP_NR_HELO (1L<<13)/* filter won't reply for HELO */
+#define SMFIP_NR_MAIL (1L<<14)/* filter won't reply for MAIL */
+#define SMFIP_NR_RCPT (1L<<15)/* filter won't reply for RCPT */
+#define SMFIP_NR_DATA (1L<<16)/* filter won't reply for DATA */
+#define SMFIP_NR_UNKN (1L<<17)/* filter won't reply for UNKNOWN */
+#define SMFIP_NR_EOH (1L<<18)/* filter won't reply for eoh */
+#define SMFIP_NR_BODY (1L<<19)/* filter won't reply for body chunk */
+#define SMFIP_HDR_LEADSPC (1L<<20)/* header value has leading space */
+
+#define SMFIP_NOSEND_MASK \
+ (SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT \
+ | SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH | SMFIP_NOUNKNOWN \
+ | SMFIP_NODATA)
+
+#define SMFIP_NOREPLY_MASK \
+ (SMFIP_NR_CONN | SMFIP_NR_HELO | SMFIP_NR_MAIL | SMFIP_NR_RCPT \
+ | SMFIP_NR_DATA | SMFIP_NR_UNKN | SMFIP_NR_HDR | SMFIP_NR_EOH | \
+ SMFIP_NR_BODY)
/*
- * Modifications that the filter may request at the end of the message body.
+ * Options that the filter may send at initial handshake time, and message
+ * modifications that the filter may request at the end of the message body.
*/
#define SMFIF_ADDHDRS (1L<<0) /* filter may add headers */
#define SMFIF_CHGBODY (1L<<1) /* filter may replace body */
#define SMFIF_DELRCPT (1L<<3) /* filter may delete recipients */
#define SMFIF_CHGHDRS (1L<<4) /* filter may change/delete headers */
#define SMFIF_QUARANTINE (1L<<5) /* filter may quarantine envelope */
+ /* Introduced with Sendmail 8.14. */
+#define SMFIF_CHGFROM (1L<<6) /* filter may replace sender */
+#define SMFIF_ADDRCPT_PAR (1L<<7) /* filter may add recipients + args */
+#define SMFIF_SETSYMLIST (1L<<8) /* filter may send macro names */
/*
* Network protocol families, used when sending CONNECT information.
#define SMFIA_INET6 '6' /* inet6 */
/*
- * How much buffer space is available for receiving body content.
+ * External macro set numbers, to identify the optional macro name lists
+ * that may be sent after the initial negotiation header.
*/
-#define MILTER_CHUNK_SIZE 65535 /* body chunk size */
-
-/* Utility library. */
-
-#include <msg.h>
-#include <mymalloc.h>
-#include <split_at.h>
-#include <connect.h>
-#include <argv.h>
-#include <name_mask.h>
-#include <name_code.h>
-#include <stringops.h>
-
-/* Global library. */
-
-#include <mail_params.h> /* var_line_limit */
-#include <mail_proto.h>
-#include <rec_type.h>
-#include <record.h>
-#include <mime_state.h>
-#include <is_header.h>
+#define SMFIM_FIRST 0
+#define SMFIM_CONNECT 0 /* macros for connect */
+#define SMFIM_HELO 1 /* macros for HELO */
+#define SMFIM_ENVFROM 2 /* macros for MAIL */
+#define SMFIM_ENVRCPT 3 /* macros for RCPT */
+#define SMFIM_DATA 4 /* macros for DATA */
+#define SMFIM_EOM 5 /* macros for end-of-message */
+#define SMFIM_EOH 6 /* macros for end-of-header */
+#define SMFIM_LAST 6
-/* Postfix Milter library. */
+ /*
+ * Mapping from external macro set numbers to our internal MILTERS structure
+ * members, without using a switch statement.
+ */
+static size_t milter8_macro_offsets[] = {
+ offsetof(MILTERS, conn_macros), /* SMFIM_CONNECT */
+ offsetof(MILTERS, helo_macros), /* SMFIM_HELO */
+ offsetof(MILTERS, mail_macros), /* SMFIM_ENVFROM */
+ offsetof(MILTERS, rcpt_macros), /* SMFIM_ENVRCPT */
+ offsetof(MILTERS, data_macros), /* SMFIM_DATA */
+ offsetof(MILTERS, eod_macros), /* Note: SMFIM_EOM < SMFIM_EOH */
+ offsetof(MILTERS, eoh_macros), /* Note: SMFIM_EOH > SMFIM_EOM */
+};
-#include <milter.h>
+#define MILTER8_MACRO_PTR(__milters, __type) \
+ ((char **) (((char *) (__milters)) + milter8_macro_offsets[(__type)]))
-/* Application-specific. */
+ /*
+ * How much buffer space is available for sending body content.
+ */
+#define MILTER_CHUNK_SIZE 65535 /* body chunk size */
/*#define msg_verbose 2*/
*/
int state; /* MILTER8_STAT_mumble */
char *def_reply; /* error response or null */
+ int skip_event_type; /* skip operations of this type */
} MILTER8;
/*
#define MILTER8_DATA_NSHORT 4 /* network short */
#define MILTER8_DATA_ARGV 5 /* array of null-terminated strings */
#define MILTER8_DATA_OCTET 6 /* byte */
+#define MILTER8_DATA_MACROS 7 /* macro lists (receive-only) */
/*
* We don't accept insane amounts of data.
#define XXX_TIMEOUT 10
/*
- * If we're not using Sendmail's libmilter include files, then we implement
- * the protocol up to and including version 4, and configure in main.cf what
- * protocol version we will use. However, we must send only events that are
- * defined for the specified protocol version, otherwise libmilter will
- * disconnect.
+ * We implement the protocol up to and including version 6, and configure in
+ * main.cf what protocol version we will use. The version is the first data
+ * item in the SMFIC_OPTNEG packet.
*
- * The following events are supported by all milter protocol implementations.
+ * We must send only events that are defined for the specified protocol
+ * version. Libmilter may disconnect when we send unexpected events.
+ *
+ * The following events are supported in all our milter protocol versions.
*/
-#define MILTER8_V1_PROTO_MASK \
+#define MILTER8_V2_PROTO_MASK \
(SMFIP_NOCONNECT | SMFIP_NOHELO | SMFIP_NOMAIL | SMFIP_NORCPT | \
SMFIP_NOBODY | SMFIP_NOHDRS | SMFIP_NOEOH)
+ /*
+ * Events supported by later versions.
+ */
+#define MILTER8_V3_PROTO_MASK (MILTER8_V2_PROTO_MASK | SMFIP_NOUNKNOWN)
+#define MILTER8_V4_PROTO_MASK (MILTER8_V3_PROTO_MASK | SMFIP_NODATA)
+#define MILTER8_V6_PROTO_MASK \
+ (MILTER8_V4_PROTO_MASK | SMFIP_SKIP /* | SMFIP_RCPT_REJ */ \
+ | SMFIP_NOREPLY_MASK | SMFIP_HDR_LEADSPC)
+
/*
* What events we can send to the milter application. The milter8_protocol
* parameter can specify a protocol version as well as protocol extensions
*
* This looks unclean because the user can specify multiple protocol versions,
* but that is taken care of by the table that follows this one.
+ *
+ * XXX Is this still needed? Sendmail 8.14 provides a proper way to negotiate
+ * what replies the mail filter will send.
*/
static NAME_CODE milter8_event_masks[] = {
- "2", MILTER8_V1_PROTO_MASK,
- "3", MILTER8_V1_PROTO_MASK | SMFIP_NOUNKNOWN,
- "4", MILTER8_V1_PROTO_MASK | SMFIP_NOUNKNOWN | SMFIP_NODATA,
+ "2", MILTER8_V2_PROTO_MASK,
+ "3", MILTER8_V3_PROTO_MASK,
+ "4", MILTER8_V4_PROTO_MASK,
+ "6", MILTER8_V6_PROTO_MASK,
"no_header_reply", SMFIP_NOHREPL,
0, -1,
};
"2", 2,
"3", 3,
"4", 4,
+ "6", 6,
"no_header_reply", 0,
0, -1,
};
"SMFIC_OPTNEG", SMFIC_OPTNEG,
"SMFIC_QUIT", SMFIC_QUIT,
"SMFIC_RCPT", SMFIC_RCPT,
-#ifdef SMFIC_DATA
"SMFIC_DATA", SMFIC_DATA,
-#endif
-#ifdef SMFIC_UNKNOWN
"SMFIC_UNKNOWN", SMFIC_UNKNOWN,
-#endif
+ /* Introduced with Sendmail 8.14. */
+ "SMFIC_QUIT_NC", SMFIC_QUIT_NC,
0, 0,
};
"SMFIR_REPLBODY", SMFIR_REPLBODY,
"SMFIR_CONTINUE", SMFIR_CONTINUE,
"SMFIR_DISCARD", SMFIR_DISCARD,
-#ifdef SMFIR_CONN_FAIL
"SMFIR_CONN_FAIL", SMFIR_CONN_FAIL,
-#endif
-#ifdef SMFIR_CHGHEADER
"SMFIR_CHGHEADER", SMFIR_CHGHEADER,
-#endif
"SMFIR_PROGRESS", SMFIR_PROGRESS,
"SMFIR_REJECT", SMFIR_REJECT,
"SMFIR_TEMPFAIL", SMFIR_TEMPFAIL,
-#ifdef SMFIR_SHUTDOWN
"SMFIR_SHUTDOWN", SMFIR_SHUTDOWN,
-#endif
"SMFIR_ADDHEADER", SMFIR_ADDHEADER,
-#ifdef SMFIR_INSHEADER
"SMFIR_INSHEADER", SMFIR_INSHEADER,
-#endif
"SMFIR_REPLYCODE", SMFIR_REPLYCODE,
-#ifdef SMFIR_QUARANTINE
"SMFIR_QUARANTINE", SMFIR_QUARANTINE,
-#endif
+ /* Introduced with Sendmail 8.14. */
+ "SMFIR_SKIP", SMFIR_SKIP,
+ "SMFIR_CHGFROM", SMFIR_CHGFROM,
+ "SMFIR_ADDRCPT_PAR", SMFIR_ADDRCPT_PAR,
+ "SMFIR_SETSYMLIST", SMFIR_SETSYMLIST,
0, 0,
};
"SMFIP_NOBODY", SMFIP_NOBODY,
"SMFIP_NOHDRS", SMFIP_NOHDRS,
"SMFIP_NOEOH", SMFIP_NOEOH,
-#ifdef SMFIP_NOHREPL
- "SMFIP_NOHREPL", SMFIP_NOHREPL,
-#endif
-#ifdef SMFIP_NOUNKNOWN
+ "SMFIP_NR_HDR", SMFIP_NR_HDR,
"SMFIP_NOUNKNOWN", SMFIP_NOUNKNOWN,
-#endif
-#ifdef SMFIP_NODATA
"SMFIP_NODATA", SMFIP_NODATA,
-#endif
+ /* Introduced with Sendmail 8.14. */
+ "SMFIP_SKIP", SMFIP_SKIP,
+ "SMFIP_RCPT_REJ", SMFIP_RCPT_REJ,
+ "SMFIP_NR_CONN", SMFIP_NR_CONN,
+ "SMFIP_NR_HELO", SMFIP_NR_HELO,
+ "SMFIP_NR_MAIL", SMFIP_NR_MAIL,
+ "SMFIP_NR_RCPT", SMFIP_NR_RCPT,
+ "SMFIP_NR_DATA", SMFIP_NR_DATA,
+ "SMFIP_NR_UNKN", SMFIP_NR_UNKN,
+ "SMFIP_NR_EOH", SMFIP_NR_EOH,
+ "SMFIP_NR_BODY", SMFIP_NR_BODY,
+ "SMFIP_HDR_LEADSPC", SMFIP_HDR_LEADSPC,
0, 0,
};
"SMFIF_ADDRCPT", SMFIF_ADDRCPT,
"SMFIF_DELRCPT", SMFIF_DELRCPT,
"SMFIF_CHGHDRS", SMFIF_CHGHDRS,
-#ifdef SMFIF_QUARANTINE
"SMFIF_QUARANTINE", SMFIF_QUARANTINE,
-#endif
+ /* Introduced with Sendmail 8.14. */
+ "SMFIF_CHGFROM", SMFIF_CHGFROM,
+ "SMFIF_ADDRCPT_PAR", SMFIF_ADDRCPT_PAR,
+ "SMFIF_SETSYMLIST", SMFIF_SETSYMLIST,
0, 0,
};
}
}
+static int milter8_read_data(MILTER8 *milter, ssize_t *data_len,...);
+
/* vmilter8_read_data - read command data */
-static int vmilter8_read_data(MILTER8 *milter, ssize_t data_len, va_list ap)
+static int vmilter8_read_data(MILTER8 *milter, ssize_t *data_len, va_list ap)
{
const char *myname = "milter8_read_data";
int arg_type;
- int data_left;
UINT32_TYPE net_long;
UINT32_TYPE *host_long_ptr;
VSTRING *buf;
int ch;
+ int ret;
+ UINT32_TYPE mac_type;
+ char **mac_value_ptr;
- for (data_left = data_len; (arg_type = va_arg(ap, int)) > 0; /* void */ ) {
+ while ((arg_type = va_arg(ap, int)) > 0) {
switch (arg_type) {
/*
* Host order long.
*/
case MILTER8_DATA_HLONG:
- if (data_left < UINT32_SIZE) {
+ if (*data_len < UINT32_SIZE) {
msg_warn("milter %s: input packet too short for network long",
milter->m.name);
return (milter8_comm_error(milter));
milter->m.name);
return (milter8_comm_error(milter));
}
- data_left -= UINT32_SIZE;
+ *data_len -= UINT32_SIZE;
*host_long_ptr = ntohl(net_long);
break;
* Raw on-the-wire format, without explicit null terminator.
*/
case MILTER8_DATA_BUFFER:
- if (data_left < 0) {
+ if (*data_len < 0) {
msg_warn("milter %s: no data in input packet", milter->m.name);
return (milter8_comm_error(milter));
}
buf = va_arg(ap, VSTRING *);
VSTRING_RESET(buf);
- VSTRING_SPACE(buf, data_left);
- if (vstream_fread(milter->fp, (char *) STR(buf), data_left)
- != data_left) {
+ VSTRING_SPACE(buf, *data_len);
+ if (vstream_fread(milter->fp, (char *) STR(buf), *data_len)
+ != *data_len) {
msg_warn("milter %s: EOF while reading data: %m", milter->m.name);
return (milter8_comm_error(milter));
}
- VSTRING_AT_OFFSET(buf, data_left);
- data_left = 0;
+ VSTRING_AT_OFFSET(buf, *data_len);
+ *data_len = 0;
break;
/*
* Pointer to null-terminated string.
*/
case MILTER8_DATA_STRING:
- if (data_left < 1) {
+ if (*data_len < 1) {
msg_warn("milter %s: packet too short for string",
milter->m.name);
return (milter8_comm_error(milter));
myname, milter->m.name);
return (milter8_comm_error(milter));
}
- data_left -= 1;
+ *data_len -= 1;
if (ch == 0)
break;
VSTRING_ADDCH(buf, ch);
- if (data_left <= 0) {
+ if (*data_len <= 0) {
msg_warn("%s: milter %s: missing string null termimator",
myname, milter->m.name);
return (milter8_comm_error(milter));
VSTRING_TERMINATE(buf);
break;
+ /*
+ * Sequence of macro (state, names) without explicit terminator.
+ */
+ case MILTER8_DATA_MACROS:
+ if (*data_len <= 0)
+ break;
+ buf = vstring_alloc(100);
+ ret = 0;
+ while (*data_len > 0
+ && (ret = milter8_read_data(milter, data_len,
+ MILTER8_DATA_HLONG, &mac_type,
+ MILTER8_DATA_STRING, buf,
+ MILTER8_DATA_END)) == 0) {
+ if (((unsigned) mac_type) > SMFIM_LAST) {
+ msg_warn("milter %s: ignoring unknown macro type %u",
+ milter->m.name, (unsigned) mac_type);
+ } else {
+ mac_value_ptr = MILTER8_MACRO_PTR(milter->m.parent, mac_type);
+ if (*mac_value_ptr != 0)
+ myfree(*mac_value_ptr);
+ *mac_value_ptr = mystrdup(STR(buf));
+ }
+ }
+ vstring_free(buf);
+ if (ret != 0)
+ return (ret);
+ break;
+
/*
* Error.
*/
* Sanity checks. We may have excess data when the sender is confused. We
* may have a negative count when we're confused ourselves.
*/
- if (data_left > 0) {
- msg_warn("%s: left-over data %ld bytes", myname, (long) data_left);
+ if (*data_len > 0) {
+ msg_warn("%s: left-over data %ld bytes", myname, (long) *data_len);
return (milter8_comm_error(milter));
}
- if (data_left < 0)
+ if (*data_len < 0)
msg_panic("%s: bad left-over data count %ld",
- myname, (long) data_left);
+ myname, (long) *data_len);
return (0);
}
/* milter8_read_data - read command data */
-static int milter8_read_data(MILTER8 *milter, ssize_t data_len,...)
+static int milter8_read_data(MILTER8 *milter, ssize_t *data_len,...)
{
va_list ap;
int ret;
return (milter->def_reply);
}
+ /*
+ * Skip further events of this type if the filter told us so.
+ */
+ if (milter->skip_event_type != 0) {
+ if (event == milter->skip_event_type) {
+ if (msg_verbose)
+ msg_info("skipping event %s after SMFIR_SKIP from milter %s",
+ (smfic_name = str_name_code(smfic_table, event)) != 0 ?
+ smfic_name : "(unknown MTA event)", milter->m.name);
+ return (milter->def_reply);
+ } else {
+ milter->skip_event_type = 0;
+ }
+ }
+
/*
* Send the macros for this event, even when we're not reporting the
* event itself. This does not introduce a performance problem because
* we're sending macros and event parameters in one VSTREAM transaction.
+ *
+ * XXX Is this still necessary?
*/
if (msg_verbose) {
VSTRING *buf = vstring_alloc(100);
* Decision: disconnect. This decision is final (i.e. Sendmail 8
* changes receiver state).
*/
-#ifdef SMFIR_SHUTDOWN
case SMFIR_SHUTDOWN:
if (data_size != 0)
break;
#endif
milter->state = MILTER8_STAT_REJECT_CON;
MILTER8_EVENT_BREAK(milter8_def_reply(milter, "S"));
-#endif
/*
* Decision: "ddd d.d+.d+ text". This decision is final (i.e.
* by '%', and remove single (i.e. invalid) '%' characters.
*/
case SMFIR_REPLYCODE:
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_BUFFER, milter->buf,
MILTER8_DATA_END) != 0)
MILTER8_EVENT_BREAK(milter->def_reply);
* transition in the receiver state (reply, reject, tempfail,
* accept, discard).
*/
-#ifdef SMFIR_QUARANTINE
case SMFIR_QUARANTINE:
/* XXX What to do with the "reason" text? */
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_BUFFER, milter->buf,
MILTER8_DATA_END) != 0)
MILTER8_EVENT_BREAK(milter->def_reply);
MILTER8_EVENT_BREAK("H");
-#endif
+
+ /*
+ * Decision: skip further events of this type.
+ */
+ case SMFIR_SKIP:
+ if (data_size != 0)
+ break;
+ milter->skip_event_type = event;
+ MILTER8_EVENT_BREAK(milter->def_reply);
/*
* Modification request or error.
if (event == SMFIC_BODYEOB) {
switch (cmd) {
+#define MILTER8_HDR_SPACE(m) (((m)->ev_mask & SMFIP_HDR_LEADSPC) ? "" : " ")
+
/*
* Modification request: replace, insert or delete
* header. Index 1 means the first instance.
*/
-#ifdef SMFIR_CHGHEADER
case SMFIR_CHGHEADER:
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_HLONG, &index,
MILTER8_DATA_STRING, milter->buf,
MILTER8_DATA_STRING, milter->body,
edit_resp = parent->upd_header(parent->chg_context,
(ssize_t) index,
STR(milter->buf),
+ MILTER8_HDR_SPACE(milter),
STR(milter->body));
else
edit_resp = parent->del_header(parent->chg_context,
(ssize_t) index,
STR(milter->buf));
continue;
-#endif
/*
* Modification request: append header.
*/
case SMFIR_ADDHEADER:
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_STRING, milter->buf,
MILTER8_DATA_STRING, milter->body,
MILTER8_DATA_END) != 0)
continue;
edit_resp = parent->add_header(parent->chg_context,
STR(milter->buf),
+ MILTER8_HDR_SPACE(milter),
STR(milter->body));
continue;
* indexing for consistency with header change
* operations.
*/
-#ifdef SMFIR_INSHEADER
case SMFIR_INSHEADER:
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_HLONG, &index,
MILTER8_DATA_STRING, milter->buf,
MILTER8_DATA_STRING, milter->body,
edit_resp = parent->ins_header(parent->chg_context,
(ssize_t) index + 1,
STR(milter->buf),
+ MILTER8_HDR_SPACE(milter),
STR(milter->body));
continue;
-#endif
/*
* Modification request: append recipient.
*/
case SMFIR_ADDRCPT:
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_STRING, milter->buf,
MILTER8_DATA_END) != 0)
MILTER8_EVENT_BREAK(milter->def_reply);
* Modification request: delete (expansion of) recipient.
*/
case SMFIR_DELRCPT:
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_STRING, milter->buf,
MILTER8_DATA_END) != 0)
MILTER8_EVENT_BREAK(milter->def_reply);
milter8_conf_error(milter);
MILTER8_EVENT_BREAK(milter->def_reply);
}
- if (milter8_read_data(milter, data_size,
+ if (milter8_read_data(milter, &data_size,
MILTER8_DATA_BUFFER, milter->body,
MILTER8_DATA_END) != 0)
MILTER8_EVENT_BREAK(milter->def_reply);
const UINT32_TYPE my_actions = (SMFIF_ADDHDRS | SMFIF_ADDRCPT
| SMFIF_DELRCPT | SMFIF_CHGHDRS
| SMFIF_CHGBODY
-#ifdef SMFIF_QUARANTINE
| SMFIF_QUARANTINE
+#if 0
+ | SMFIF_CHGFROM
+ | SMFIF_ADDRCPT_PAR
#endif
+ | SMFIF_SETSYMLIST
);
UINT32_TYPE my_version = 0;
}
/*
- * Don't send events that aren't defined for my protocol version. This is
- * somewhat tricky: unlike the other SMFIP_mumble bits, the SMFIP_NOHREPL
- * bit specifies something that the milter application won't send. We
- * must not inadvertently turn this bit on, because the MTA would get out
- * of sync with the application.
+ * Don't send events that aren't defined for my protocol version.
*/
- milter->np_mask = ~(my_events | SMFIP_NOHREPL);
+ milter->np_mask = (SMFIP_NOSEND_MASK & ~my_events);
if (msg_verbose)
msg_info("%s: non-protocol events for protocol version %d: %s",
myname, my_version,
msg_warn("milter %s: unexpected reply \"%c\" in initial handshake",
milter->m.name, cmd);
(void) milter8_comm_error(milter);
- } else if (milter8_read_data(milter, data_len,
+ } else if (milter8_read_data(milter, &data_len,
MILTER8_DATA_HLONG, &milter->version,
MILTER8_DATA_HLONG, &milter->rq_mask,
MILTER8_DATA_HLONG, &milter->ev_mask,
+ MILTER8_DATA_MACROS,
MILTER8_DATA_END) != 0) {
msg_warn("milter %s: read error in initial handshake", milter->m.name);
/* milter8_read_data() called milter8_comm_error() */
}
milter->state = MILTER8_STAT_READY;
milter8_def_reply(milter, 0);
+ milter->skip_event_type = 0;
}
}
const char *myname = "milter8_conn_event";
MILTER8 *milter = (MILTER8 *) m;
int port;
+ int skip_reply;
/*
* XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
port = 0;
}
milter->state = MILTER8_STAT_ENVELOPE;
+ skip_reply = ((milter->ev_mask & SMFIP_NR_CONN) != 0);
switch (addr_family) {
case AF_INET:
return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_STRING, client_name,
MILTER8_DATA_OCTET, SMFIA_INET,
MILTER8_DATA_NSHORT, htons(port),
#ifdef HAS_IPV6
case AF_INET6:
return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_STRING, client_name,
MILTER8_DATA_OCTET, SMFIA_INET6,
MILTER8_DATA_NSHORT, htons(port),
#endif
case AF_UNIX:
return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_STRING, client_name,
MILTER8_DATA_OCTET, SMFIA_UNIX,
MILTER8_DATA_NSHORT, htons(0),
MILTER8_DATA_END));
default:
return (milter8_event(milter, SMFIC_CONNECT, SMFIP_NOCONNECT,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_STRING, client_name,
MILTER8_DATA_OCTET, SMFIA_UNKNOWN,
MILTER8_DATA_END));
{
const char *myname = "milter8_helo_event";
MILTER8 *milter = (MILTER8 *) m;
+ int skip_reply;
/*
* Report the event.
if (msg_verbose)
msg_info("%s: milter %s: helo %s",
myname, milter->m.name, helo_name);
+ skip_reply = ((milter->ev_mask & SMFIP_NR_HELO) != 0);
return (milter8_event(milter, SMFIC_HELO, SMFIP_NOHELO,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_STRING, helo_name,
MILTER8_DATA_END));
default:
const char *myname = "milter8_mail_event";
MILTER8 *milter = (MILTER8 *) m;
const char **cpp;
+ int skip_reply;
/*
* Report the event.
myname, milter->m.name, STR(buf));
vstring_free(buf);
}
+ skip_reply = ((milter->ev_mask & SMFIP_NR_MAIL) != 0);
return (milter8_event(milter, SMFIC_MAIL, SMFIP_NOMAIL,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_ARGV, argv,
MILTER8_DATA_END));
default:
const char *myname = "milter8_rcpt_event";
MILTER8 *milter = (MILTER8 *) m;
const char **cpp;
+ int skip_reply;
/*
* Report the event.
myname, milter->m.name, STR(buf));
vstring_free(buf);
}
+ skip_reply = ((milter->ev_mask & SMFIP_NR_RCPT) != 0);
return (milter8_event(milter, SMFIC_RCPT, SMFIP_NORCPT,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_ARGV, argv,
MILTER8_DATA_END));
default:
/* milter8_data_event - report DATA command to Sendmail 8 milter */
-#ifdef SMFIC_DATA
-
static const char *milter8_data_event(MILTER *m, ARGV *macros)
{
const char *myname = "milter8_data_event";
MILTER8 *milter = (MILTER8 *) m;
+ int skip_reply;
/*
* Report the event.
case MILTER8_STAT_ENVELOPE:
if (msg_verbose)
msg_info("%s: milter %s: data command", myname, milter->m.name);
+ skip_reply = ((milter->ev_mask & SMFIP_NR_DATA) != 0);
return (milter8_event(milter, SMFIC_DATA, SMFIP_NODATA,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_END));
default:
msg_panic("%s: milter %s: bad state %d",
}
}
-#else
-#define milter8_data_event 0
-#endif
-
/* milter8_unknown_event - report unknown SMTP command to Sendmail 8 milter */
-#ifdef SMFIC_UNKNOWN
-
static const char *milter8_unknown_event(MILTER *m, const char *command,
ARGV *macros)
{
const char *myname = "milter8_unknown_event";
MILTER8 *milter = (MILTER8 *) m;
+ int skip_reply;
/*
* Report the event.
msg_info("%s: milter %s: unknown command: %s",
myname, milter->m.name, command);
/* XXX Sendmail doesn't send macros (checked with 8.6.13). */
+ skip_reply = ((milter->ev_mask & SMFIP_NR_UNKN) != 0);
return (milter8_event(milter, SMFIC_UNKNOWN, SMFIP_NOUNKNOWN,
- DONT_SKIP_REPLY, macros,
+ skip_reply, macros,
MILTER8_DATA_STRING, command,
MILTER8_DATA_END));
default:
}
}
-#else
-#define milter8_unknown_event 0
-#endif
-
/* milter8_other_event - reply for other event */
static const char *milter8_other_event(MILTER *m)
*/
typedef struct {
MILTER8 *milter; /* milter client */
- ARGV *macros; /* end-of-body macros */
+ ARGV *eoh_macros; /* end-of-header macros */
+ ARGV *eod_macros; /* end-of-body macros */
int first_header; /* first header */
int first_body; /* first body line */
const char *resp; /* milter application response */
if (*cp != ':')
msg_panic("%s: header label not followed by ':'", myname);
*cp++ = 0;
- /* XXX Sendmail 8.13.6 eats one space (not tab) after colon. */
- if (*cp == ' ')
+ /* XXX Sendmail by default eats one space (not tab) after the colon. */
+ if ((milter->ev_mask & SMFIP_HDR_LEADSPC) == 0 && *cp == ' ')
cp++;
-#ifdef SMFIP_NOHREPL
skip_reply = ((milter->ev_mask & SMFIP_NOHREPL) != 0);
-#else
- skip_reply = DONT_SKIP_REPLY;
-#endif
msg_ctx->resp =
milter8_event(milter, SMFIC_HEADER, SMFIP_NOHDRS,
- skip_reply, msg_ctx->macros,
+ skip_reply, msg_ctx->eoh_macros,
MILTER8_DATA_STRING, STR(buf),
MILTER8_DATA_STRING, cp,
MILTER8_DATA_END);
const char *myname = "milter8_eoh";
MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
MILTER8 *milter = msg_ctx->milter;
+ int skip_reply;
if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
return;
if (msg_verbose)
msg_info("%s: eoh milter %s", myname, milter->m.name);
+ skip_reply = ((milter->ev_mask & SMFIP_NR_EOH) != 0);
msg_ctx->resp =
milter8_event(milter, SMFIC_EOH, SMFIP_NOEOH,
- DONT_SKIP_REPLY, msg_ctx->macros,
+ skip_reply, msg_ctx->eoh_macros,
MILTER8_DATA_END);
}
const char *bp = buf;
ssize_t space;
ssize_t count;
+ int skip_reply;
if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
return;
*/
if (msg_verbose > 1)
msg_info("%s: body milter %s: %.100s", myname, milter->m.name, buf);
+ skip_reply = ((milter->ev_mask & SMFIP_NR_BODY) != 0);
/* To append \r\n, simply redirect input to another buffer. */
if (rec_type == REC_TYPE_NORM && todo == 0) {
bp = "\r\n";
if (LEN(milter->body) == MILTER_CHUNK_SIZE) {
msg_ctx->resp =
milter8_event(milter, SMFIC_BODY, SMFIP_NOBODY,
- DONT_SKIP_REPLY, msg_ctx->macros,
+ skip_reply, msg_ctx->eod_macros,
MILTER8_DATA_BUFFER, milter->body,
MILTER8_DATA_END);
if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
const char *myname = "milter8_eob";
MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
MILTER8 *milter = msg_ctx->milter;
+ int skip_reply;
if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
return;
* have different macro lists.
*/
if (LEN(milter->body) > 0) {
+ skip_reply = ((milter->ev_mask & SMFIP_NR_BODY) != 0);
msg_ctx->resp =
milter8_event(milter, SMFIC_BODY, SMFIP_NOBODY,
- DONT_SKIP_REPLY, msg_ctx->macros,
+ skip_reply, msg_ctx->eod_macros,
MILTER8_DATA_BUFFER, milter->body,
MILTER8_DATA_END);
if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
}
msg_ctx->resp =
milter8_event(msg_ctx->milter, SMFIC_BODYEOB, 0,
- DONT_SKIP_REPLY, msg_ctx->macros,
+ DONT_SKIP_REPLY, msg_ctx->eod_macros,
MILTER8_DATA_END);
}
static const char *milter8_message(MILTER *m, VSTREAM *qfile,
off_t data_offset,
- ARGV *macros)
+ ARGV *eoh_macros,
+ ARGV *eod_macros)
{
const char *myname = "milter8_message";
MILTER8 *milter = (MILTER8 *) m;
return ("450 4.3.0 Queue file write error");
}
msg_ctx.milter = milter;
- msg_ctx.macros = macros;
+ msg_ctx.eoh_macros = eoh_macros;
+ msg_ctx.eod_macros = eod_macros;
msg_ctx.first_header = 1;
msg_ctx.first_body = 1;
msg_ctx.resp = 0;
milter->protocol = (protocol ? mystrdup(protocol) : 0);
milter->def_action = mystrdup(def_action);
milter->def_reply = 0;
+ milter->skip_event_type = 0;
return (milter);
}
/* to maintain compatibility between successive versions.
/*
/* Arguments (multiple alternatives are separated by "\fB|\fR"):
-/* .IP "\fB-a accept|tempfail|reject|discard|\fIddd x.y.z text\fR"
-/* Specifies a non-default reply. The default is to continue
-/* (i.e. \fBtempfail\fR).
+/* .IP "\fB-a accept|tempfail|reject|discard|skip|\fIddd x.y.z text\fR"
+/* Specifies a non-default reply for the MTA command specified
+/* with \fB-a\fR. The default is \fBtempfail\fR.
/* .IP "\fB-d\fI level\fR"
/* Enable libmilter debugging at the specified level.
/* .IP "\fB-c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort\fR"
/* The default protocol stage is \fBconnect\fR.
/* .IP "\fB-C\fI count\fR"
/* Terminate after \fIcount\fR connections.
-/* .IP "\fB-i \"\fIindex header-label header-value\"\fR"
+/* .IP "\fB-i \fI'index header-label header-value'\fR"
/* Insert header at specified position.
+/* .IP "\fB-m connect|helo|mail|rcpt|data|eoh|eom\fR"
+/* The protocol stage that receives the list of macros specified
+/* with \fB-M\fR. The default protocol stage is \fBconnect\fR.
+/* .IP "\fB-M \fIset_macro_list\fR"
+/* A non-default list of macros that the MTA should send at
+/* the protocol stage specified with \fB-m\fR.
+/* .IP "\fB-n connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown\fR"
+/* The event that the MTA should not send.
+/* .IP "\fB-N connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown\fR"
+/* The event for which the filter will not reply.
/* .IP "\fB-p inet:\fIport\fB@\fIhost\fB|unix:\fIpathname\fR"
/* The mail filter listen endpoint.
-/* .IP "\fB-r "index header-label header-value"
+/* .IP "\fB-r \fI'index header-label header-value'\fR"
/* Replace the message header at the specified position.
/* .IP "\fB-R pathname
/* Replace the message body by the content of the specified file.
"helo", &test_helo_reply,
"mail", &test_mail_reply,
"rcpt", &test_rcpt_reply,
-#if SMFI_VERSION > 3
- "data", &test_data_reply,
-#endif
"header", &test_header_reply,
"eoh", &test_eoh_reply,
"body", &test_body_reply,
"eom", &test_eom_reply,
+ "abort", &test_abort_reply,
+ "close", &test_close_reply,
#if SMFI_VERSION > 2
"unknown", &test_unknown_reply,
#endif
- "close", &test_close_reply,
- "abort", &test_abort_reply,
+#if SMFI_VERSION > 3
+ "data", &test_data_reply,
+#endif
0, 0,
};
printf("replace body with content of %s\n", body_file);
for (count = 0; fgets(buf, BUFSIZ, fp) != 0; count++) {
len = strcspn(buf, "\n");
- buf[len+0] = '\r';
- buf[len+1] = '\n';
+ buf[len + 0] = '\r';
+ buf[len + 1] = '\n';
if (smfi_replacebody(ctx, buf, len + 2) == MI_FAILURE) {
fprintf(stderr, "body replace failure\n");
exit(1);
#if SMFI_VERSION > 2
-static sfsistat test_unknown(SMFICTX *ctx)
+static sfsistat test_unknown(SMFICTX *ctx, const char *what)
{
- printf("test_unknown\n");
+ printf("test_unknown %s\n", what);
return (test_reply(ctx, test_unknown_reply));
}
#endif
+static sfsistat test_negotiate(SMFICTX *, unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *);
+
static struct smfiDesc smfilter =
{
"test-milter",
#if SMFI_VERSION > 3
test_data,
#endif
+#if SMFI_VERSION > 5
+ test_negotiate,
+#endif
};
+#if SMFI_VERSION > 5
+
+static const char *macro_states[] = {
+ "connect", /* SMFIM_CONNECT */
+ "helo", /* SMFIM_HELO */
+ "mail", /* SMFIM_ENVFROM */
+ "rcpt", /* SMFIM_ENVRCPT */
+ "data", /* SMFIM_DATA */
+ "eom", /* SMFIM_EOM < SMFIM_EOH */
+ "eoh", /* SMFIM_EOH > SMFIM_EOM */
+ 0,
+};
+
+static int set_macro_state;
+static char *set_macro_list;
+
+typedef sfsistat (*FILTER_ACTION) ();
+
+struct noproto_map {
+ const char *name;
+ int send_mask;
+ int reply_mask;
+ int *reply;
+ FILTER_ACTION *action;
+};
+
+static struct noproto_map noproto_map[] = {
+ "connect", SMFIP_NOCONNECT, SMFIP_NR_CONN, &test_connect_reply, &smfilter.xxfi_connect,
+ "helo", SMFIP_NOHELO, SMFIP_NR_HELO, &test_helo_reply, &smfilter.xxfi_helo,
+ "mail", SMFIP_NOMAIL, SMFIP_NR_MAIL, &test_mail_reply, &smfilter.xxfi_envfrom,
+ "rcpt", SMFIP_NORCPT, SMFIP_NR_RCPT, &test_rcpt_reply, &smfilter.xxfi_envrcpt,
+ "data", SMFIP_NODATA, SMFIP_NR_DATA, &test_data_reply, &smfilter.xxfi_data,
+ "header", SMFIP_NOHDRS, SMFIP_NR_HDR, &test_header_reply, &smfilter.xxfi_header,
+ "eoh", SMFIP_NOEOH, SMFIP_NR_EOH, &test_eoh_reply, &smfilter.xxfi_eoh,
+ "body", SMFIP_NOBODY, SMFIP_NR_BODY, &test_body_reply, &smfilter.xxfi_body,
+ "unknown", SMFIP_NOUNKNOWN, SMFIP_NR_UNKN, &test_connect_reply, &smfilter.xxfi_unknown,
+ 0,
+};
+
+static int nosend_mask;
+static int noreply_mask;
+
+static sfsistat test_negotiate(SMFICTX *ctx,
+ unsigned long f0,
+ unsigned long f1,
+ unsigned long f2,
+ unsigned long f3,
+ unsigned long *pf0,
+ unsigned long *pf1,
+ unsigned long *pf2,
+ unsigned long *pf3)
+{
+ if (set_macro_list) {
+ if (verbose)
+ printf("set symbol list %s to \"%s\"\n",
+ macro_states[set_macro_state], set_macro_list);
+ smfi_setsymlist(ctx, set_macro_state, set_macro_list);
+ }
+ if (verbose)
+ printf("negotiate f0=%lx *pf0 = %lx f1=%lx *pf1=%lx nosend=%lx noreply=%lx\n",
+ f0, *pf0, f1, *pf1, (long) nosend_mask, (long) noreply_mask);
+ *pf0 = f0;
+ *pf1 = f1 & (nosend_mask | noreply_mask);
+ return (SMFIS_CONTINUE);
+}
+
+#endif
+
static void parse_hdr_info(const char *optarg, int *idx,
char **hdr, char **value)
{
struct command_map *cp;
int ch;
int code;
+ const char **cpp;
+ char *set_macro_state_arg = 0;
+ char *nosend = 0;
+ char *noreply = 0;
+ struct noproto_map *np;
- while ((ch = getopt(argc, argv, "a:c:C:d:i:p:r:R:v")) > 0) {
+ while ((ch = getopt(argc, argv, "a:c:C:d:i:m:M:n:N:p:r:R:v")) > 0) {
switch (ch) {
case 'a':
action = optarg;
#else
fprintf(stderr, "no libmilter support to insert header\n");
exit(1);
+#endif
+ break;
+ case 'm':
+#if SMFI_VERSION > 5
+ if (set_macro_state_arg) {
+ fprintf(stderr, "too many -m options\n");
+ exit(1);
+ }
+ set_macro_state_arg = optarg;
+#else
+ fprintf(stderr, "no libmilter support to specify macro list\n");
+#endif
+ break;
+ case 'M':
+#if SMFI_VERSION > 5
+ if (set_macro_list) {
+ fprintf(stderr, "too many -M options\n");
+ exit(1);
+ }
+ set_macro_list = optarg;
+#else
+ fprintf(stderr, "no libmilter support to specify macro list\n");
+#endif
+ break;
+ case 'n':
+#if SMFI_VERSION > 5
+ if (nosend) {
+ fprintf(stderr, "too many -n options\n");
+ exit(1);
+ }
+ nosend = optarg;
+#else
+ fprintf(stderr, "no libmilter support for negotiate callback\n");
+#endif
+ break;
+ case 'N':
+#if SMFI_VERSION > 5
+ if (noreply) {
+ fprintf(stderr, "too many -n options\n");
+ exit(1);
+ }
+ noreply = optarg;
+#else
+ fprintf(stderr, "no libmilter support for negotiate callback\n");
#endif
break;
case 'p':
"\t[-a action] non-default action\n"
"\t[-c command] non-default action trigger\n"
"\t[-i 'index label value'] insert header\n"
+ "\t[-m macro_state] non-default macro state\n"
+ "\t[-M macro_list] non-default macro list\n"
+ "\t[-n events] don't receive these events\n"
+ "\t[-N events] don't reply to these events\n"
"\t-p port milter application\n"
"\t[-r 'index label value'] replace header\n"
"\t[-C conn_count] when to exit\n",
exit(1);
}
}
- if (smfi_register(smfilter) == MI_FAILURE) {
- fprintf(stderr, "smfi_register failed\n");
- exit(1);
- }
if (command) {
for (cp = command_map; /* see below */ ; cp++) {
if (cp->name == 0) {
cp->reply[0] = SMFIS_ACCEPT;
} else if (strcmp(action, "discard") == 0) {
cp->reply[0] = SMFIS_DISCARD;
+#ifdef SMFIS_SKIP
+ } else if (strcmp(action, "skip") == 0) {
+ cp->reply[0] = SMFIS_SKIP;
+#endif
} else if ((code = atoi(action)) >= 400
&& code <= 599
&& action[3] == ' ') {
reply_message ? reply_message : "(null)");
}
}
+#if SMFI_VERSION > 5
+ if (set_macro_state_arg) {
+ for (cpp = macro_states; /* see below */ ; cpp++) {
+ if (*cpp == 0) {
+ fprintf(stderr, "bad -m argument: %s\n", set_macro_state_arg);
+ exit(1);
+ }
+ if (strcmp(set_macro_state_arg, *cpp) == 0)
+ break;
+ }
+ set_macro_state = cpp - macro_states;
+ }
+ if (nosend) {
+ for (np = noproto_map; /* see below */ ; np++) {
+ if (np->name == 0) {
+ fprintf(stderr, "bad -n argument: %s\n", nosend);
+ exit(1);
+ }
+ if (strcmp(nosend, np->name) == 0)
+ break;
+ }
+ nosend_mask = np->send_mask;
+ np->action[0] = 0;
+ }
+ if (noreply) {
+ for (np = noproto_map; /* see below */ ; np++) {
+ if (np->name == 0) {
+ fprintf(stderr, "bad -N argument: %s\n", noreply);
+ exit(1);
+ }
+ if (strcmp(noreply, np->name) == 0)
+ break;
+ }
+ noreply_mask = np->reply_mask;
+ *np->reply = SMFIS_NOREPLY;
+ }
+#endif
+ if (smfi_register(smfilter) == MI_FAILURE) {
+ fprintf(stderr, "smfi_register failed\n");
+ exit(1);
+ }
return (smfi_main());
}
where = "performing the EHLO handshake";
if (session->features & SMTP_FEATURE_ESMTP) {
smtp_chat_cmd(session, "EHLO %s", var_smtp_helo_name);
- if ((resp = smtp_chat_resp(session))->code / 100 != 2)
- session->features &= ~SMTP_FEATURE_ESMTP;
+ if ((resp = smtp_chat_resp(session))->code / 100 != 2) {
+ if (resp->code == 421)
+ return (smtp_site_fail(state, session->host, resp,
+ "host %s refused to talk to me: %s",
+ session->namaddr,
+ translit(resp->str, "\n", " ")));
+ else
+ session->features &= ~SMTP_FEATURE_ESMTP;
+ }
}
if ((session->features & SMTP_FEATURE_ESMTP) == 0) {
where = "performing the HELO handshake";
/* .IP "\fBmilter_unknown_command_macros (see postconf -n output)\fR"
/* The macros that are sent to version 3 or higher Milter (mail
/* filter) applications after an unknown SMTP command.
+/* .IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
+/* The macros that are sent to Milter (mail filter) applications
+/* after the message header.
/* .IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
/* The macros that are sent to Milter (mail filter) applications
/* after the message end-of-data.
char *var_milt_mail_macros;
char *var_milt_rcpt_macros;
char *var_milt_data_macros;
+char *var_milt_eoh_macros;
char *var_milt_eod_macros;
char *var_milt_unk_macros;
bool var_smtpd_client_port_log;
var_milt_mail_macros,
var_milt_rcpt_macros,
var_milt_data_macros,
+ var_milt_eoh_macros,
var_milt_eod_macros,
var_milt_unk_macros);
else
VAR_MILT_MAIL_MACROS, DEF_MILT_MAIL_MACROS, &var_milt_mail_macros, 0, 0,
VAR_MILT_RCPT_MACROS, DEF_MILT_RCPT_MACROS, &var_milt_rcpt_macros, 0, 0,
VAR_MILT_DATA_MACROS, DEF_MILT_DATA_MACROS, &var_milt_data_macros, 0, 0,
+ VAR_MILT_EOH_MACROS, DEF_MILT_EOH_MACROS, &var_milt_eoh_macros, 0, 0,
VAR_MILT_EOD_MACROS, DEF_MILT_EOD_MACROS, &var_milt_eod_macros, 0, 0,
VAR_MILT_UNK_MACROS, DEF_MILT_UNK_MACROS, &var_milt_unk_macros, 0, 0,
VAR_MILT_PROTOCOL, DEF_MILT_PROTOCOL, &var_milt_protocol, 1, 0,
/* DATA, ., RSET, NOOP, and QUIT. Separate command names by
/* white space or commas, and use quotes to protect white space
/* from the shell. Command names are case-insensitive.
+/* .IP "\fB-Q \fIcommand,command,...\fR"
+/* Disconnect after sending a 431 reply after receiving one
+/* of the specified commands.
+/* .sp
+/* Examples of commands are CONNECT, HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
+/* DATA, ., RSET, NOOP, and QUIT. Separate command names by
+/* white space or commas, and use quotes to protect white space
+/* from the shell. Command names are case-insensitive.
/* .IP "\fB-r \fIcommand,command,...\fR"
/* Reject the specified commands with a soft (4xx) error code.
/* This option implies \fB-p\fR.
#define FLAG_HARD_ERR (1<<2) /* report hard error */
#define FLAG_SOFT_ERR (1<<3) /* report soft error */
#define FLAG_DISCONNECT (1<<4) /* disconnect */
+#define FLAG_CLOSE (1<<5) /* say goodbye and disconnect */
static SINK_COMMAND command_table[] = {
"connect", conn_response, hard_err_resp, soft_err_resp, 0, 0, 0,
syslog(LOG_INFO, "%s %.100s", command, args);
if (cmdp->flags & FLAG_DISCONNECT)
return (-1);
+ if (cmdp->flags & FLAG_CLOSE) {
+ smtp_printf(state->stream, "421 4.0.0 Server closing connection");
+ return (-1);
+ }
if (cmdp->flags & FLAG_HARD_ERR) {
cmdp->hard_response(state);
return (0);
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "468aA:cCd:D:eEf:Fh:Ln:m:pPq:r:R:s:S:t:u:vw:W:")) > 0) {
+ while ((ch = GETOPT(argc, argv, "468aA:cCd:D:eEf:Fh:Ln:m:pPq:Q:r:R:s:S:t:u:vw:W:")) > 0) {
switch (ch) {
case '4':
protocols = INET_PROTO_NAME_IPV4;
case 'q':
set_cmds_flags(optarg, FLAG_DISCONNECT);
break;
+ case 'Q':
+ set_cmds_flags(optarg, FLAG_CLOSE);
+ break;
case 'r':
set_cmds_flags(optarg, FLAG_SOFT_ERR);
disable_pipelining = 1;