808 lines
25 KiB
HTML
808 lines
25 KiB
HTML
<!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 version 2.3 introduces 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. 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://sourceforge.net/projects/sid-milter/">SenderID+SPF</a> and
|
|
<a href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>)
|
|
or to digitally sign mail (example: <a
|
|
href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>).
|
|
Having yet another Postfix-specific version of all that software
|
|
is a poor use of human and system resources. </p>
|
|
|
|
<p> Postfix 2.3 implements all the requests of Sendmail version 8
|
|
Milter protocols up to version 4, except one: message body replacement.
|
|
See, however, the <a href="#workarounds">workarounds</a> and <a
|
|
href="#limitations">limitations</a> sections at the end of this
|
|
document. </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 that are used for SMTP mail only,
|
|
and one list of filters that are used 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). </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> On some Linux and *BSD distributions, the Sendmail libmilter
|
|
library is installed by default. With this, applications such as
|
|
<a href="http://sourceforge.net/projects/dk-milter/">dk-milter</a>
|
|
and <a href="http://sourceforge.net/projects/sid-milter/">sid-milter</a>
|
|
build out of the box without requiring any tinkering:</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
$ <b>gzcat dk-milter-<i>x.y.z</i>.tar.gz | tar xf -</b>
|
|
$ <b>cd dk-milter-<i>x.y.z</i></b>
|
|
$ <b>make</b>
|
|
[...<i>lots of output omitted</i>...]
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p> On other platforms you have two options: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p>Install the Sendmail libmilter object library and include
|
|
files. On Linux systems, libmilter may be provided by the
|
|
sendmail-devel package. After installing libmilter, build the
|
|
Milter applications as described in the preceding paragraph. </p>
|
|
|
|
<li> <p>Don't install the Sendmail libmilter library, but build the
|
|
library from Sendmail source code instead: </p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
$ <b>gzcat sendmail-<i>x.y.z</i>.tar.gz | tar xf -</b>
|
|
$ <b>cd sendmail-<i>x.y.z</i>/libmilter</b>
|
|
$ <b>make</b>
|
|
[...<i>lots of output omitted</i>...]
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p> After building your own libmilter library, follow the installation
|
|
instructions in the Milter application source distribution to specify
|
|
the location of the libmilter include files and object library.
|
|
Typically, these settings are configured in a file named
|
|
<tt>sid-filter/Makefile.m4</tt> or similar:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
APPENDDEF(`confINCDIRS', `-I/some/where/sendmail-x.y.z/include')
|
|
APPENDDEF(`confLIBDIRS', `-L/some/where/sendmail-x.y.z/obj.<i>systemtype</i>/libmilter')
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>Then build the Milter application. </p>
|
|
|
|
</ul>
|
|
|
|
<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/dk-filter -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. With the initial Postfix
|
|
Milter protocol implementation, many options are global, that is,
|
|
they apply to all Milter applications. Future Postfix versions may
|
|
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="#macros">Sendmail macro emulation</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>
|
|
|
|
<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 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>
|
|
|
|
<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>
|
|
|
|
<p> None of this is a problem for mail filters that digitally sign
|
|
mail. </p>
|
|
|
|
<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.
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
# What to do in case of errors? Specify accept, reject, or tempfail.
|
|
milter_default_action = tempfail
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<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 2. </p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
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> 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>
|
|
postfix/smtpd[21045]: warning: milter inet:<i>host</i>:<i>port</i>: can't read packet header: Unknown error : 0
|
|
postfix/cleanup[15190]: warning: milter inet:<i>host</i>:<i>port</i>: can't read packet header: Success
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p> The remedy is to lower the Postfix milter_protocol version
|
|
number. </p>
|
|
|
|
<h3><a name="timeouts">Milter protocol timeouts</a></h3>
|
|
|
|
<p> Postfix uses different time limits at different Milter protocol
|
|
stages. The table shows wich timeouts are used and when
|
|
(EOH = end of headers; EOM = end of message). </p>
|
|
|
|
<blockquote>
|
|
|
|
<table border="1">
|
|
|
|
<tr> <th> Parameter </th> <th> Time limit </th> <th> 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 is not a lot for applications that do a lot 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>
|
|
|
|
<h3><a name="macros">Sendmail macro emulation</a></h3>
|
|
|
|
<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
|
|
always the same as in Sendmail. See the <a
|
|
href="#workarounds">workarounds</a> section below for solutions.
|
|
</p>
|
|
|
|
<blockquote>
|
|
|
|
<table border="1">
|
|
|
|
<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> 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
|
|
login name </td> </tr>
|
|
|
|
<tr> <td> {auth_author} </td> <td> MAIL, DATA, EOM </td> <td> SASL
|
|
sender </td> </tr>
|
|
|
|
<tr> <td> {auth_type} </td> <td> MAIL, DATA, EOM </td> <td> SASL
|
|
login method </td> </tr>
|
|
|
|
<tr> <td> {client_addr} </td> <td> Always </td> <td> Client IP
|
|
address </td> </tr>
|
|
|
|
<tr> <td> {client_connections} </td> <td> CONNECT </td> <td>
|
|
Connection concurrency for this client </td> </tr>
|
|
|
|
<tr> <td> {client_name} </td> <td> Always </td> <td> Client hostname,
|
|
"unknown" when lookup or verification fails </td> </tr>
|
|
|
|
<tr> <td> {client_ptr} </td> <td> CONNECT, HELO, MAIL, DATA </td>
|
|
<td> Client name from reverse lookup, "unknown" when lookup fails
|
|
</td> </tr>
|
|
|
|
<tr> <td> {cert_issuer} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
|
|
TLS client certificate issuer </td> </tr>
|
|
|
|
<tr> <td> {cert_subject} </td> <td> HELO, MAIL, DATA, EOM </td>
|
|
<td> TLS client certificate subject </td> </tr>
|
|
|
|
<tr> <td> {cipher_bits} </td> <td> HELO, MAIL, DATA, EOM </td> <td>
|
|
TLS session key size </td> </tr>
|
|
|
|
<tr> <td> {cipher} </td> <td> HELO, MAIL, DATA, EOM </td> <td> TLS
|
|
cipher </td> </tr>
|
|
|
|
<tr> <td> {daemon_name} </td> <td> Always </td> <td> value of
|
|
milter_macro_daemon_name </td> </tr>
|
|
|
|
<tr> <td> {mail_addr} </td> <td> MAIL </td> <td> Sender address
|
|
</td> </tr>
|
|
|
|
<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>
|
|
TLS protocol version </td> </tr>
|
|
|
|
<tr> <td> v </td> <td> Always </td> <td> value of milter_macro_v
|
|
</td> </tr>
|
|
|
|
</table>
|
|
|
|
</blockquote>
|
|
|
|
<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>
|
|
|
|
<blockquote>
|
|
|
|
<table border="1">
|
|
|
|
<tr> <th> Parameter name </th> <th> Protocol version </th> <th>
|
|
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_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>
|
|
|
|
<h2><a name="workarounds">Workarounds</a></h2>
|
|
|
|
<p> Content filters may break domain key etc. signatures. If you
|
|
use an SMTP-based content filter, then you should add a line to
|
|
master.cf with "-o disable_mime_output_conversion=yes" (note: no
|
|
spaces around the "="), as described in the <a
|
|
href="FILTER_README.html#advanced_filter">advanced content filter</a>
|
|
example. </p>
|
|
|
|
<p> Sendmail Milter applications were originally developed for the
|
|
Sendmail version 8 MTA, which has a different architecture than
|
|
Postfix. The result is that some Milter applications make assumptions
|
|
that aren't true in a Postfix environment. </p>
|
|
|
|
<ul>
|
|
|
|
<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>{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 a 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> This happens because some Milter applications expect that the
|
|
queue ID is known <i>before</i> the MTA accepts the MAIL FROM
|
|
(sender) command. Postfix, on the other hand, does not choose a
|
|
queue file name until <i>after</i> it accepts the first valid RCPT
|
|
TO (recipient) command. Postfix queue file names must be unique
|
|
across multiple directories, so the name can't be chosen before the
|
|
file is created. If multiple messages were to use the same queue
|
|
ID <i>simultaneously</i>, mail would be lost. </p>
|
|
|
|
<p> To work around the ugly message header from Milter applications,
|
|
we add a little code to the Milter source to look up the queue ID
|
|
after Postfix receives the end of the message. </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> Edit the filter source file (typically named
|
|
<tt>dk-filter/dk-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>
|
|
|
|
/* get hostname; used in the X header and in new MIME boundaries */
|
|
</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 for the code
|
|
at the start of the <tt>mlfi_eoh()</tt> routine. </p>
|
|
|
|
<li> <p> This fixes only the ugly message header, but not the WARNING
|
|
message. Fortunately, dk-filter logs that message only once. </p>
|
|
|
|
</ul>
|
|
|
|
<p> With some Milter applications we can fix both the WARNING and
|
|
the "unknown-msgid" by postponing the call of <tt>mlfi_eoh()</tt>
|
|
(or whatever routine logs the WARNING) until the end of the message.
|
|
</p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> Edit the filter source file (typically named
|
|
<tt>sid-filter/sid-filter.c</tt> or similar). </p>
|
|
|
|
<li> <p> Look up the <tt>smfilter</tt> table and replace
|
|
<tt>mlfi_eoh</tt> (or whatever routine logs the WARNING) by NULL.
|
|
</p>
|
|
|
|
<li> <p> Look up the <tt>mlfi_eom()</tt> function and add code near
|
|
the top that calls <tt>mlfi_eoh()</tt> as shown by the <b>bold</b>
|
|
text below: </p>
|
|
|
|
</ul>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
assert(ctx != NULL);
|
|
#endif /* !DEBUG */
|
|
<b>
|
|
ret = mlfi_eoh(ctx);
|
|
if (ret != SMFIS_CONTINUE)
|
|
return ret;</b>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p> This works with sid-milter-0.2.10. Other Milter applications
|
|
will dump core when you do this. </p>
|
|
|
|
</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> 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> For applications that are written in C, you need to use
|
|
the Sendmail libmilter library. A Postfix replacement may be
|
|
provided in the future. </p>
|
|
|
|
<li> <p> There are 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>
|
|
|
|
<li> <p> When mail is filtered by non-SMTP filters, the Postfix
|
|
cleanup(8) server has to simulate the SMTP client CONNECT and
|
|
DISCONNECT events, and the SMTP client EHLO, MAIL FROM, RCPT TO and
|
|
DATA commands. This works as expected, with only one exception:
|
|
non-SMTP filters must not REJECT or TEMPFAIL simulated RCPT TO
|
|
commands. When a non-SMTP filter REJECTs or TEMPFAILs a recipient,
|
|
Postfix will report a configuration error, and mail will stay in
|
|
the queue. </p>
|
|
|
|
<li> <p> Postfix currently does not apply content filters to mail
|
|
that is forwarded or aliased internally, or to mail that is generated
|
|
internally such as bounces or Postmaster notifications. This may
|
|
be a problem when you want to apply a signing Milter to such mail.
|
|
</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.3 does not support Milter requests to replace
|
|
the message body. Milter applications that request this unsupported
|
|
operation will log a warning like this: </p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
<i>application name</i>: st_optionneg[134563840]: 0x3d does not fulfill action requirements 0x1e
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p> The solution is (to wait for) a Postfix version that supports
|
|
the missing functionality.
|
|
|
|
<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>
|