diff options
Diffstat (limited to 'proto/MILTER_README.html')
-rw-r--r-- | proto/MILTER_README.html | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/proto/MILTER_README.html b/proto/MILTER_README.html new file mode 100644 index 0000000..886299f --- /dev/null +++ b/proto/MILTER_README.html @@ -0,0 +1,951 @@ +<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + +<html> + +<head> + +<title>Postfix before-queue Milter support </title> + +<meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + +</head> + +<body> + +<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix before-queue Milter support </h1> + +<hr> + +<h2>Introduction</h2> + +<p> Postfix implements support for the Sendmail version 8 Milter +(mail filter) protocol. This protocol is used by applications that +run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT), +SMTP commands (HELO, MAIL FROM, etc.) as well as mail content +(headers and body). All this happens before mail is queued. </p> + +<p> The reason for adding Milter support to Postfix is that there +exists a large collection of applications, not only to block unwanted +mail, but also to verify authenticity (examples: <a +href="http://www.opendkim.org/">OpenDKIM</a> and <a +href="http://www.trusteddomain.org/opendmarc/">DMARC </a>) +or to digitally sign mail (example: <a +href="http://www.opendkim.org/">OpenDKIM</a>). +Having yet another Postfix-specific version of all that software +is a poor use of human and system resources. </p> + +<p> The Milter protocol has evolved over time, and different Postfix +versions implement different feature sets. See the <a +href="#workarounds">workarounds</a> and <a +href="#limitations">limitations</a> sections at the end of this +document for differences between Postfix and Sendmail implementations. +</p> + +<p> This document provides information on the following topics: </p> + +<ul> + +<li><a href="#plumbing">How Milter applications plug into Postfix </a> + +<li><a href="#building">Building Milter applications</a> + +<li><a href="#running">Running Milter applications</a> + +<li><a href="#config">Configuring Postfix</a> + +<li><a href="#workarounds">Workarounds</a> + +<li><a href="#limitations">Limitations</a> + +</ul> + +<h2><a name="plumbing">How Milter applications plug into Postfix </a> </h2> + +<p> The Postfix Milter implementation uses two different lists of +mail filters: one list of filters for SMTP mail only, +and one list of filters for non-SMTP mail. The two +lists have different capabilities, which is unfortunate. Avoiding +this would require major restructuring of Postfix. </p> + +<ul> + +<li> <p> The SMTP-only filters handle mail that arrives via the +Postfix smtpd(8) server. They are typically used to filter unwanted +mail and to sign mail from authorized SMTP clients. You specify +SMTP-only Milter applications with the smtpd_milters parameter as +described in a later section. Mail that arrives via the Postfix +smtpd(8) server is not filtered by the non-SMTP filters that are +described next. </p> + +<li> <p> The non-SMTP filters handle mail that arrives via the +Postfix sendmail(1) command-line or via the Postfix qmqpd(8) server. +They are typically used to digitally sign mail only. Although +non-SMTP filters can be used to filter unwanted mail, they have +limitations compared to the SMTP-only filters. You specify non-SMTP +Milter applications with the non_smtpd_milters parameter as described +in a later section. </p> + +</ul> + +<p> For those who are familiar with the Postfix architecture, the +figure below shows how Milter applications plug into Postfix. Names +followed by a number are Postfix commands or server programs, while +unnumbered names inside shaded areas represent Postfix queues. To +avoid clutter, the path for local submission is simplified (the +OVERVIEW document has a more complete description of the Postfix +architecture). </p> + +<blockquote> + +<table> + +<tr> + +<td colspan="2"> </td> + +<td align="center"> SMTP-only <br> filters </td> + +<td> </td> + +<td align="center"> non-SMTP <br> filters </td> + +</tr> + +<tr> + +<td colspan="2"> </td> + +<td align="center"> <table> <tr> <td align="center"> +^<br> <tt> | </tt> </td> <td align="center"> <tt> |<br> v </tt> +</td> </tr> </table> </td> + +<td rowspan="2"> </td> + +<td rowspan="3" align="center"> <table> <tr> <td align="center"> +^<br> <tt> |<br> |<br> | </tt> </td> <td align="center"> <tt> |<br> +|<br> |<br> v </tt> </td> </tr> </table> </td> + +</tr> + +<tr> + +<td> Network </td> <td> <tt> -> </tt> </td> + +<td bgcolor="#f0f0ff" align="center" valign="middle"> smtpd(8) +</td> + +</tr> + +<tr> + +<td colspan="3"> </td> <td> <tt> \ </tt> </td> + +</tr> + +<tr> + +<td> Network </td> <td> <tt> -> </tt> </td> + +<td bgcolor="#f0f0ff" align="center" valign="middle"> qmqpd(8) +</td> + +<td> <tt> -> </tt> </td> + +<td bgcolor="#f0f0ff" align="center" valign="middle"> cleanup(8) +</td> + +<td> <tt> -> </tt> </td> + +<td bgcolor="#f0f0ff" align="center" valign="middle"> <a +href="QSHAPE_README.html#incoming_queue"> incoming </a> </td> + +</tr> + +<tr> + +<td colspan="3"> </td> <td> <tt> / </tt> </td> + +</tr> + +<tr> + +<td colspan="2"> </td> + +<td bgcolor="#f0f0ff" align="center" valign="middle"> pickup(8) +</td> + +</tr> + +<tr> <td colspan="2"> </td> <td align="center"> : </td> </tr> + +<tr> + +<td> Local </td> <td> <tt> -> </tt> </td> + +<td bgcolor="#f0f0ff" align="center" valign="middle"> sendmail(1) +</td> + +</tr> + +</table> + +</blockquote> + +<h2><a name="building">Building Milter applications</a></h2> + +<p> Milter applications have been written in C, JAVA and Perl, but +this document deals with C applications only. For these, you need +an object library that implements the Sendmail 8 Milter protocol. +Postfix currently does not provide such a library, but Sendmail +does. </p> + +<p> Some +systems install the Sendmail libmilter library by default. With +other systems, libmilter may be provided by a package (called +"sendmail-devel" on some Linux systems). </p> + +<p> Once libmilter is installed, applications such as <a +href="http://www.opendkim.org/">OpenDKIM</a> and +<a href="http://www.trusteddomain.org/opendmarc/">OpenDMARC</a> +build out of the box without requiring any tinkering:</p> + +<blockquote> +<pre> +$ <b>gzcat opendkim-<i>x.y.z</i>.tar.gz | tar xf -</b> +$ <b>cd opendkim-<i>x.y.z</i></b> +$ <b>./configure ...<i>options</i>...</b> +$ <b>make</b> +[...<i>lots of output omitted</i>...] +$ <b>make install</b> +</pre> +</blockquote> + +<h2><a name="running">Running Milter applications</a></h2> + +<p> To run a Milter application, see the documentation of the filter +for options. A typical command looks like this:</p> + +<blockquote> +<pre> +# <b>/some/where/opendkim -l -u <i>userid</i> -p inet:<i>portnumber</i>@localhost ...<i>other options</i>...</b> +</pre> +</blockquote> + +<p> Please specify a <i>userid</i> value that isn't used for other +applications (not "postfix", not "www", etc.). </p> + +<h2><a name="config">Configuring Postfix</a></h2> + +<p> Like Sendmail, Postfix has a lot of configuration options that +control how it talks to Milter applications. Besides global options +that apply to all Milter applications, Postfix 3.0 and later +support per-Milter timeouts, per-Milter error handling, etc. </p> + +<p> Information in this section: </p> + +<ul> + +<li><a href="#smtp-only-milters">SMTP-Only Milter applications </a> + +<li><a href="#non-smtp-milters">Non-SMTP Milter applications </a> + +<li><a href="#errors">Milter error handling </a> + +<li><a href="#version">Milter protocol version</a> + +<li><a href="#timeouts">Milter protocol timeouts</a> + +<li><a href="#per-milter">Different settings for different Milter +applications </a> + +<li><a href="#per-client">Different settings for different SMTP +clients </a> + +<li><a href="#macros">Sendmail macro emulation</a> + +<li><a href="#send-macros">What macros will Postfix send to Milters?</a> + +</ul> + +<h3><a name="smtp-only-milters">SMTP-Only Milter applications</a></h3> + +<p> The SMTP-only Milter applications handle mail that arrives via +the Postfix smtpd(8) server. They are typically used to filter +unwanted mail, and to sign mail from authorized SMTP clients. Mail +that arrives via the Postfix smtpd(8) server is not filtered by the +non-SMTP filters that are described in the next section. </p> + +<blockquote> NOTE for Postfix versions that have a mail_release_date +before 20141018: do not use the header_checks(5) IGNORE action to remove +Postfix's own Received: message header. This causes problems with +mail signing filters. Instead, keep Postfix's own Received: message +header and use the header_checks(5) REPLACE action to sanitize +information. </blockquote> + +<p> You specify SMTP-only Milter applications (there can be more +than one) with the smtpd_milters parameter. Each Milter application +is identified by the name of its listening socket; other Milter +configuration options will be discussed in later sections. Milter +applications are applied in the order as specified, and the first +Milter application that rejects a command will override the responses +from other Milter applications. </p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + # Milters for mail that arrives via the smtpd(8) server. + # See below for socket address syntax. + smtpd_milters = inet:localhost:<i>portnumber</i> ...<i>other filters</i>... +</pre> +</blockquote> + +<p> The general syntax for listening sockets is as follows: </p> + +<blockquote> + +<dl> + +<dt> <b>unix:</b><i>pathname</i> </dt> <dd><p>Connect to the local +UNIX-domain server that is bound to the specified pathname. If the +smtpd(8) or cleanup(8) process runs chrooted, an absolute pathname +is interpreted relative to the Postfix queue directory.</p> </dd> + +<dt> <b> inet:</b><i>host</i><b>:</b><i>port</i> </dt> <dd> <p> +Connect to the specified TCP port on the specified local or remote +host. The host and port can be specified in numeric or symbolic +form.</p> + +<p> NOTE: Postfix syntax differs from Milter syntax which has the +form <b>inet:</b><i>port</i><b>@</b><i>host</i>. </p> </dd> + +</dl> + +</blockquote> + +<p> For advanced configuration see "<a href="#per-client">Different +settings for different SMTP clients</a>" and "<a +href="#per-milter">Different settings for different Milter +applications</a>". </p> + +<h3> <a name="non-smtp-milters">Non-SMTP Milter applications </a> </h3> + +<p> The non-SMTP Milter applications handle mail that arrives via +the Postfix sendmail(1) command-line or via the Postfix qmqpd(8) +server. They are typically used to digitally sign mail. Although +non-SMTP filters can be used to filter unwanted mail, there are +limitations as discussed later in this section. Mail that arrives +via the Postfix smtpd(8) server is not filtered by the non-SMTP +filters. </p> + +<p> NOTE: Do not use the header_checks(5) IGNORE action to remove +Postfix's own Received: message header. This causes problems with +mail signing filters. Instead, keep Postfix's own Received: message +header and use the header_checks(5) REPLACE action to sanitize +information. </p> + +<p> You specify non-SMTP Milter applications with the non_smtpd_milters +parameter. This parameter uses the same syntax as the smtpd_milters +parameter in the previous section. As with the SMTP-only filters, +you can specify more than one Milter application; they are applied +in the order as specified, and the first Milter application that +rejects a command will override the responses from the other +applications. </p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + # Milters for non-SMTP mail. + # See below for socket address syntax. + non_smtpd_milters = inet:localhost:<i>portnumber</i> ...<i>other filters</i>... +</pre> +</blockquote> + +<p> There's one small complication when using Milter applications +for non-SMTP mail: there is no SMTP session. To keep Milter +applications happy, the Postfix cleanup(8) server actually has to +simulate the SMTP client CONNECT and DISCONNECT events, and the +SMTP client EHLO, MAIL FROM, RCPT TO and DATA commands. </p> + +<ul> + +<li> <p> When new mail arrives via the sendmail(1) command line, +the Postfix cleanup(8) server pretends that the mail arrives with +ESMTP from "localhost" with IP address "127.0.0.1". The result is +very similar to what happens with command line submissions in +Sendmail version 8.12 and later, although Sendmail uses a different +mechanism to achieve this result. </p> + +<li> <p> When new mail arrives via the qmqpd(8) server, the Postfix +cleanup(8) server pretends that the mail arrives with ESMTP, and +uses the QMQPD client hostname and IP address. </p> + +<li> <p> When old mail is re-injected into the queue with "postsuper +-r", the Postfix cleanup(8) server uses the same client information +that was used when the mail arrived as new mail. </p> + +</ul> + +<p> This generally works as expected, with only one exception: +non-SMTP filters must not REJECT or TEMPFAIL simulated RCPT TO +commands. When a non_smtpd_milters application REJECTs or TEMPFAILs +a recipient, Postfix will report a configuration error, and mail +will stay in the queue. </p> + +<h4> Signing internally-generated bounce messages </h4> + +<p> Postfix normally does not apply content filters to mail +that is generated internally such as bounces or Postmaster +notifications. Filtering internally-generated bounces would result +in loss of mail when a filter rejects a message, as the resulting +double-bounce message would almost certainly also be blocked. </p> + +<p> To sign Postfix's own bounce messages, enable filtering of +internally-generated bounces (line 2 below), and don't reject any +internally-generated bounces with non_smtpd_milters, header_checks +or body_checks (lines 3-5 below). </p> + +<blockquote> +<pre> +1 /etc/postfix/main.cf: +2 internal_mail_filter_classes = bounce +3 non_smtpd_milters = <i>don't reject internally-generated bounces</i> +4 header_checks = <i>don't reject internally-generated bounces</i> +5 body_checks = <i>don't reject internally-generated bounces</i> +</pre> +</blockquote> + +<h3><a name="errors">Milter error handling</a></h3> + +<p> The milter_default_action parameter specifies how Postfix handles +Milter application errors. The default action is to respond with a +temporary error status, so that the client will try again later. +Specify "accept" if you want to receive mail as if the filter does +not exist, and "reject" to reject mail with a permanent status. +The "quarantine" action is like "accept" but freezes the message +in the "hold" queue, and is available with Postfix 2.6 or later. +</p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + # What to do in case of errors? Specify accept, reject, tempfail, + # or quarantine (Postfix 2.6 or later). + milter_default_action = tempfail +</pre> +</blockquote> + +<p> See "<a href="#per-milter">Different settings for different +Milter applications</a>" for advanced configuration options. </p> + +<h3><a name="version">Milter protocol version</a></h3> + +<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 6 (before Postfix 2.6 the default +version is 2). </p> + +<blockquote> +<pre> +/etc/postfix/main.cf: + # Postfix ≥ 2.6 + milter_protocol = 6 + # 2.3 ≤ Postfix ≤ 2.5 + milter_protocol = 2 +</pre> +</blockquote> + +<p> If the Postfix milter_protocol setting specifies a too low +version, the libmilter library will log an error message like this: +</p> + +<blockquote> +<pre> +<i>application name</i>: st_optionneg[<i>xxxxx</i>]: 0x<i>yy</i> does not fulfill action requirements 0x<i>zz</i> +</pre> +</blockquote> + +<p> The remedy is to increase the Postfix milter_protocol version +number. See, however, the <a href="#limitations">limitations</a> +section below for features that aren't supported by Postfix. </p> + +<p> With Postfix 2.7 and earlier, if the Postfix milter_protocol +setting specifies a too high +version, the libmilter library simply hangs up without logging a +warning, and you see a Postfix warning message like one of the +following: </p> + +<blockquote> +<pre> +warning: milter inet:<i>host</i>:<i>port</i>: can't read packet header: Unknown error : 0 +warning: milter inet:<i>host</i>:<i>port</i>: can't read packet header: Success +warning: milter inet:<i>host</i>:<i>port</i>: can't read SMFIC_DATA reply packet header: No such file or directory +</pre> +</blockquote> + +<p> The remedy is to lower the Postfix milter_protocol version +number. Postfix 2.8 and later will automatically turn off protocol +features that the application's libmilter library does not expect. +</p> + +<p> See "<a href="#per-milter">Different settings for different +Milter applications</a>" for advanced configuration options. </p> + +<h3><a name="timeouts">Milter protocol timeouts</a></h3> + +<p> Postfix uses different time limits at different Milter protocol +stages. The table shows the timeout settings and the corresponding +protocol stages +(EOH = end of headers; EOM = end of message). </p> + +<blockquote> + +<table border="1"> + +<tr> <th> Postfix parameter </th> <th> Time limit </th> <th> Milter +protocol stage</th> </tr> + +<tr> <td> milter_connect_timeout </td> <td> 30s </td> <td> CONNECT +</td> </tr> + +<tr> <td> milter_command_timeout </td> <td> 30s </td> <td> HELO, +MAIL, RCPT, DATA, UNKNOWN </td> </tr> + +<tr> <td> milter_content_timeout </td> <td> 300s </td> <td> HEADER, +EOH, BODY, EOM </td> </tr> + +</table> + +</blockquote> + +<p> Beware: 30s may be too short for Milter applications that do +lots of DNS lookups. However, if you increase the above timeouts +too much, remote SMTP clients may hang up and mail may be delivered +multiple times. This is an inherent problem with before-queue +filtering. </p> + +<p> See "<a href="#per-milter">Different settings for different +Milter applications</a>" for advanced configuration options. </p> + +<h3><a name="per-milter">Different settings for different Milter +applications </a></h3> + +<p> The previous sections list a number of Postfix main.cf parameters +that control time limits and other settings for all Postfix Milter +clients. This is sufficient for simple configurations. With more +complex configurations it becomes desirable to have different +settings for different Milter clients. This is supported with Postfix +3.0 and later. </p> + +<p> The following example shows a "non-critical" Milter client with +a short connect timeout, and with "accept" as default action when +the service is unvailable. </p> + +<blockquote> +<pre> +1 /etc/postfix/main.cf: +2 smtpd_milters = { inet:host:port, +3 connect_timeout=10s, default_action=accept } +</pre> +</blockquote> + +<p> Instead of a server endpoint, we now have a list enclosed in {}. </p> + +<ul> + +<li> <p> Line 2: The first item in the list is the server endpoint. +This supports the exact same "inet" and "unix" syntax as described +earlier. </p> + +<li> <p> Line 3: The remainder of the list contains per-Milter +settings. These settings override global main.cf parameters, and +have the same name as those parameters, without the "milter_" prefix. +The per-Milter settings that are supported as of Postfix 3.0 are +command_timeout, connect_timeout, content_timeout, default_action, +and protocol. </p> + +</ul> + +<p> Inside the list, syntax is similar to what we already know from +main.cf: items separated by space or comma. There is one difference: +<b>you must enclose a setting in parentheses, as in "{ name = value +}", if you want to have space or comma within a value or around +"="</b>. </p> + +<h3><a name="per-client">Different settings for different SMTP +clients </a></h3> + +<p> The smtpd_milter_maps feature supports different Milter settings +for different client IP addresses. Lookup results override the the +global smtpd_milters setting, and have the same syntax. For example, +to disable Milter settings for local address ranges: </p> + +<pre> +/etc/postfix/main.cf: + smtpd_milter_maps = cidr:/etc/postfix/smtpd_milter_map + smtpd_milters = inet:host:port, { inet:host:port, ... }, ... + +/etc/postfix/smtpd_milter_map: + # Disable Milters for local clients. + 127.0.0.0/8 DISABLE + 192.168.0.0/16 DISABLE + ::/64 DISABLE + 2001:db8::/32 DISABLE +</pre> + +<p> This feature is available with Postfix 3.2 and later. </p> + +<h3><a name="macros">Sendmail macro emulation</a></h3> + +<p> Postfix emulates a limited number of Sendmail macros, as shown +in the table. Some macro values depend on whether a recipient is +rejected (rejected recipients are available on request by the Milter +application). Different macros are available at different Milter +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> + +<blockquote> + +<table border="1"> + +<tr> <th> Sendmail macro </th> <th> Milter protocol stage </th> +<th> Description </th> </tr> + +<tr> <td> i </td> <td> DATA, EOH, EOM </td> <td> Queue ID, also +Postfix queue file name </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, EOH, EOM </td> <td> SASL +login name </td> </tr> + +<tr> <td> {auth_author} </td> <td> MAIL, DATA, EOH, EOM </td> <td> SASL +sender </td> </tr> + +<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> Remote client +IP address </td> </tr> + +<tr> <td> {client_connections} </td> <td> CONNECT </td> <td> +Connection concurrency for this client (zero if the client is +excluded from all smtpd_client_* limits). </td> </tr> + +<tr> <td> {client_name} </td> <td> Always </td> <td> Remote client +hostname <br> When address → name lookup or name → address +verification fails: "unknown" </td> </tr> + +<tr> <td> {client_port} </td> <td> Always (Postfix ≥2.5) </td> +<td> Remote client TCP port </td> </tr> + +<tr> <td> {client_ptr} </td> <td> CONNECT, HELO, MAIL, DATA </td> +<td> Client name from address → name lookup <br> When address +→ name lookup fails: "unknown" </td> </tr> + +<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, EOH, EOM </td> +<td> TLS client certificate subject </td> </tr> + +<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, EOH, EOM </td> <td> TLS +cipher </td> </tr> + +<tr> <td> {daemon_addr} </td> <td> Always (Postfix ≥3.2) </td> +<td> Local server IP address </td> </tr> + +<tr> <td> {daemon_name} </td> <td> Always </td> <td> value of +milter_macro_daemon_name </td> </tr> + +<tr> <td> {daemon_port} </td> <td> Always (Postfix ≥3.2) </td> +<td> Local server TCP port </td> </tr> + +<tr> <td> {mail_addr} </td> <td> MAIL </td> <td> Sender address +</td> </tr> + +<tr> <td> {mail_host} </td> <td> MAIL (Postfix ≥ 2.6, only with +smtpd_milters) </td> <td> Sender next-hop destination </td> </tr> + +<tr> <td> {mail_mailer} </td> <td> MAIL (Postfix ≥ 2.6, only with +smtpd_milters) </td> <td> Sender mail delivery transport </td> </tr> + +<tr> <td> {rcpt_addr} </td> <td> RCPT </td> <td> Recipient address +<br> With rejected recipient: descriptive text </td> </tr> + +<tr> <td> {rcpt_host} </td> <td> RCPT (Postfix ≥ 2.6, only with +smtpd_milters) </td> <td> Recipient next-hop destination <br> With +rejected recipient: enhanced status code </td> </tr> + +<tr> <td> {rcpt_mailer} </td> <td> RCPT (Postfix ≥ 2.6, only with +smtpd_milters) </td> <td> Recipient mail delivery transport <br> +With rejected recipient: "error" </td> </tr> + +<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 +</td> </tr> + +</table> + +</blockquote> + +<h3><a name="send-macros">What macros will Postfix send to Milters?</a></h3> + +<p> Postfix sends specific sets of macros at different Milter protocol +stages. The sets are configured with the parameters as shown in the +table below (EOH = end of headers; EOM = end of message). The +protocol version is a number that Postfix sends at the beginning +of the Milter protocol handshake. </p> + +<p> As of Sendmail 8.14.0, Milter applications can specify what +macros they want to receive at different Milter protocol stages. +An application-specified list takes precedence over a Postfix-specified +list. </p> + +<blockquote> + +<table border="1"> + +<tr> <th> Postfix parameter </th> <th> Milter protocol version </th> +<th> Milter protocol stage </th> </tr> + +<tr> <td> milter_connect_macros </td> <td> 2 or higher </td> <td> +CONNECT </td> </tr> + +<tr> <td> milter_helo_macros </td> <td> 2 or higher </td> <td> +HELO/EHLO </td> </tr> + +<tr> <td> milter_mail_macros </td> <td> 2 or higher </td> <td> MAIL +FROM </td> </tr> + +<tr> <td> milter_rcpt_macros </td> <td> 2 or higher </td> <td> RCPT +TO </td> </tr> + +<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> + +<tr> <td> milter_unknown_command_macros </td> <td> 3 or higher </td> +<td> unknown command </td> </tr> + +</table> + +</blockquote> + +<p> By default, Postfix will send only macros whose values have been +updated with information from main.cf or master.cf, from an SMTP session +(for example; SASL login, or TLS certificates) or from a Mail delivery +transaction (for example; queue ID, sender, or recipient). </p> + +<p> To force a macro to be sent even when its value has not been updated, +you may specify macro default values with the milter_macro_defaults +parameter. Specify zero or more <i>name=value</i> pairs separated by +comma or whitespace; you may even specify macro names that Postfix does +know about! </p> + +<h2><a name="workarounds">Workarounds</a></h2> + +<ul> + +<li> <p> To avoid breaking DKIM etc. signatures with an SMTP-based +content filter, update the before-filter SMTP client in master.cf, +and add a line with "-o disable_mime_output_conversion=yes" (note: +no spaces around the "="). For details, see the <a +href="FILTER_README.html#advanced_filter">advanced content filter</a> +example. </p> + +<pre> +/etc/postfix/master.cf: + # ============================================================= + # service type private unpriv chroot wakeup maxproc command + # (yes) (yes) (yes) (never) (100) + # ============================================================= + scan unix - - n - 10 smtp + -o smtp_send_xforward_command=yes + -o disable_mime_output_conversion=yes + -o smtp_generic_maps= +</pre> + +<li> <p> Some Milter applications use the "<tt>{if_addr}</tt>" macro +to recognize local mail; this macro does not exist in Postfix. +Workaround: use the "<tt>{daemon_addr}</tt>" (Postfix ≥ 3.2) or +"<tt>{client_addr}</tt>" macro instead. </p> + +<li> <p> Some Milter applications log a warning that looks like +this: </p> + +<blockquote> <pre> +sid-filter[36540]: WARNING: sendmail symbol 'i' not available +</pre> +</blockquote> + +<p> And they may insert an ugly message header with "unknown-msgid" +like this: </p> + +<blockquote> +<pre> +X-SenderID: Sendmail Sender-ID Filter vx.y.z host.example.com <unknown-msgid> +</pre> +</blockquote> + +<p> The problem is that Milter applications expect that the queue +ID is known <i>before</i> the MTA accepts the MAIL FROM (sender) +command. Postfix does not choose a queue ID, which is used as the +queue file name, until <i>after</i> it accepts the first valid RCPT +TO (recipient) command. </p> + +<p> If you experience the ugly header problem, see if a recent +version of the Milter application fixes it. For example, current +versions of dkim-filter and dk-filter already have code that looks +up the Postfix queue ID at a later protocol stage, and sid-filter +version 1.0.0 no longer includes the queue ID in the message header. +</p> + +<p> To fix the ugly message header, you will need to add code that +looks up the Postfix queue ID at some later point in time. The +example below adds the lookup after the end-of-message. </p> + +<ul> + +<li> <p> Edit the filter source file (typically named +<tt>xxx-filter/xxx-filter.c</tt> or similar). </p> + +<li> <p> Look up the <tt>mlfi_eom()</tt> function and add code near +the top shown as <b>bold</b> text below: </p> + +</ul> + +<blockquote> +<pre> +dfc = cc->cctx_msg; +assert(dfc != NULL); +<b> +/* Determine the job ID for logging. */ +if (dfc->mctx_jobid == 0 || strcmp(dfc->mctx_jobid, JOBIDUNKNOWN) == 0) { + char *jobid = smfi_getsymval(ctx, "i"); + if (jobid != 0) + dfc->mctx_jobid = jobid; +}</b> +</pre> +</blockquote> + +<p> NOTES: </p> + +<ul> + +<li> <p> Different mail filters use slightly different names for +variables. If the above code does not compile, look elsewhere in +the mail filter source file for code that looks up the "i" macro +value, and copy that code. </p> + +<li> <p> This change fixes only the ugly message header, but not +the WARNING message. Fortunately, many Milters log that message +only once. </p> + +</ul> + +</ul> + +<h2><a name="limitations">Limitations</a></h2> + +<p> This section lists limitations of the Postfix Milter implementation. +Some limitations will be removed as the implementation is extended +over time. Of course the usual limitations of before-queue filtering +will always apply. See the CONTENT_INSPECTION_README document for +a discussion. </p> + +<ul> + +<li> <p> The Milter protocol has evolved over time. Therefore, +different Postfix versions implement different feature sets. </p> + +<table border="1"> + +<tr> <th> Postfix </th> <th> Supported Milter requests </th> +</tr> + +<tr> <td align="center"> 2.6 </td> <td> All Milter requests of +Sendmail 8.14.0 (see notes below). </td> </tr> + +<tr> <td align="center"> 2.5 </td> <td> All Milter requests of +Sendmail 8.14.0, except: <br> SMFIP_RCPT_REJ (report rejected +recipients to the mail filter), <br> SMFIR_CHGFROM (replace sender, +with optional ESMTP parameters), <br> SMFIR_ADDRCPT_PAR (add +recipient, with optional ESMTP parameters). </td> </tr> + +<tr> <td align="center"> 2.4 </td> <td> All Milter requests of +Sendmail 8.13.0. </td> </tr> + +<tr> <td align="center"> 2.3 </td> <td> All Milter requests of +Sendmail 8.13.0, except: <br> SMFIR_REPLBODY (replace message body). + +</table> + +<li> <p> For Milter applications that are written in C, you need +to use the Sendmail libmilter library. </p> + +<li> <p> Postfix has TWO sets of mail filters: filters that are used +for SMTP mail only (specified with the smtpd_milters parameter), +and filters for non-SMTP mail (specified with the non_smtpd_milters +parameter). The non-SMTP filters are primarily for local submissions. +</p> + +<p> When mail is filtered by non_smtpd_milters, the Postfix cleanup(8) +server has to simulate SMTP client requests. This works as expected, +with only one exception: non_smtpd_milters must not REJECT or +TEMPFAIL simulated RCPT TO commands. When this rule is violated, +Postfix will report a configuration error, and mail will stay in +the queue. </p> + +<li> <p> When you use the before-queue content filter for incoming +SMTP mail (see SMTPD_PROXY_README), Milter applications have access +only to the SMTP command information; they have no access to the +message header or body, and cannot make modifications to the message +or to the envelope. </p> + +<li> <p> Postfix 2.6 ignores the optional ESMTP parameters in +requests to replace the sender (SMFIR_CHGFROM) or to append a +recipient (SMFIR_ADDRCPT_PAR). Postfix logs a warning message when +a Milter application supplies such ESMTP parameters: </p> + +<pre> +warning: <i>queue-id</i>: cleanup_chg_from: ignoring ESMTP arguments "<i>whatever</i>" +warning: <i>queue-id</i>: cleanup_add_rcpt: ignoring ESMTP arguments "<i>whatever</i>" +</pre> + +<li> <p> Postfix 2.3 does not implement requests to replace the +message body. Milter applications log a warning message when they +need this unsupported operation: </p> + +<pre> +st_optionneg[134563840]: 0x3d does not fulfill action requirements 0x1e +</pre> + +<p> The solution is to use Postfix version 2.4 or later. </p> + +<li> <p> Most Milter configuration options are global. Future Postfix +versions may support per-Milter timeouts, per-Milter error handling, +etc. </p> + +</ul> + +</body> + +</html> |