summaryrefslogtreecommitdiffstats
path: root/README_FILES/MILTER_README
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README_FILES/MILTER_README648
1 files changed, 648 insertions, 0 deletions
diff --git a/README_FILES/MILTER_README b/README_FILES/MILTER_README
new file mode 100644
index 0000000..9e866d4
--- /dev/null
+++ b/README_FILES/MILTER_README
@@ -0,0 +1,648 @@
+PPoossttffiixx bbeeffoorree--qquueeuuee MMiilltteerr ssuuppppoorrtt
+
+-------------------------------------------------------------------------------
+
+IInnttrroodduuccttiioonn
+
+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.
+
+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: OpenDKIM and DMARC) or to digitally sign mail (example:
+OpenDKIM). Having yet another Postfix-specific version of all that software is
+a poor use of human and system resources.
+
+The Milter protocol has evolved over time, and different Postfix versions
+implement different feature sets. See the workarounds and limitations sections
+at the end of this document for differences between Postfix and Sendmail
+implementations.
+
+This document provides information on the following topics:
+
+ * How Milter applications plug into Postfix
+ * Building Milter applications
+ * Running Milter applications
+ * Configuring Postfix
+ * Workarounds
+ * Limitations
+
+HHooww MMiilltteerr aapppplliiccaattiioonnss pplluugg iinnttoo PPoossttffiixx
+
+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.
+
+ * 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.
+
+ * 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.
+
+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).
+
+ SMTP-only non-SMTP
+ filters filters
+
+ ^ |
+ | v
+ ^ |
+ | |
+ Network -> smtpd(8) | |
+ | v
+
+ \
+
+ Network -> qmqpd(8) -> cleanup(8) -> incoming
+
+ /
+
+ pickup(8)
+
+ :
+
+ Local -> sendmail(1)
+
+BBuuiillddiinngg MMiilltteerr aapppplliiccaattiioonnss
+
+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.
+
+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).
+
+Once libmilter is installed, applications such as OpenDKIM and OpenDMARC build
+out of the box without requiring any tinkering:
+
+ $ ggzzccaatt ooppeennddkkiimm--xx..yy..zz..ttaarr..ggzz || ttaarr xxff --
+ $ ccdd ooppeennddkkiimm--xx..yy..zz
+ $ ..//ccoonnffiigguurree ......ooppttiioonnss......
+ $ mmaakkee
+ [...lots of output omitted...]
+ $ mmaakkee iinnssttaallll
+
+RRuunnnniinngg MMiilltteerr aapppplliiccaattiioonnss
+
+To run a Milter application, see the documentation of the filter for options. A
+typical command looks like this:
+
+ # //ssoommee//wwhheerree//ooppeennddkkiimm --ll --uu uusseerriidd --pp iinneett::ppoorrttnnuummbbeerr@@llooccaallhhoosstt ......ootthheerr
+ ooppttiioonnss......
+
+Please specify a userid value that isn't used for other applications (not
+"postfix", not "www", etc.).
+
+CCoonnffiigguurriinngg PPoossttffiixx
+
+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.
+
+Information in this section:
+
+ * SMTP-Only Milter applications
+ * Non-SMTP Milter applications
+ * Milter error handling
+ * Milter protocol version
+ * Milter protocol timeouts
+ * Different settings for different Milter applications
+ * Different settings for different SMTP clients
+ * Sendmail macro emulation
+ * What macros will Postfix send to Milters?
+
+SSMMTTPP--OOnnllyy MMiilltteerr aapppplliiccaattiioonnss
+
+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.
+
+ 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.
+
+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.
+
+ /etc/postfix/main.cf:
+ # Milters for mail that arrives via the smtpd(8) server.
+ # See below for socket address syntax.
+ smtpd_milters = inet:localhost:portnumber ...other filters...
+
+The general syntax for listening sockets is as follows:
+
+ uunniixx::pathname
+ 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. On many systems, llooccaall is a synonym for uunniixx
+
+ iinneett::host::port
+ 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.
+
+ NOTE: Postfix syntax differs from Milter syntax which has the form
+ iinneett::port@@host.
+
+For advanced configuration see "Different settings for different SMTP clients"
+and "Different settings for different Milter applications".
+
+NNoonn--SSMMTTPP MMiilltteerr aapppplliiccaattiioonnss
+
+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.
+
+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.
+
+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.
+
+ /etc/postfix/main.cf:
+ # Milters for non-SMTP mail.
+ # See below for socket address syntax.
+ non_smtpd_milters = inet:localhost:portnumber ...other filters...
+
+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.
+
+ * 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.
+
+ * 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.
+
+ * 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.
+
+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.
+
+SSiiggnniinngg iinntteerrnnaallllyy--ggeenneerraatteedd bboouunnccee mmeessssaaggeess
+
+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.
+
+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).
+
+ 1 /etc/postfix/main.cf:
+ 2 internal_mail_filter_classes = bounce
+ 3 non_smtpd_milters = don't reject internally-generated bounces
+ 4 header_checks = don't reject internally-generated bounces
+ 5 body_checks = don't reject internally-generated bounces
+
+MMiilltteerr eerrrroorr hhaannddlliinngg
+
+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.
+
+ /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
+
+See "Different settings for different Milter applications" for advanced
+configuration options.
+
+MMiilltteerr pprroottooccooll vveerrssiioonn
+
+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).
+
+ /etc/postfix/main.cf:
+ # Postfix >= 2.6
+ milter_protocol = 6
+ # 2.3 <= Postfix <= 2.5
+ milter_protocol = 2
+
+If the Postfix milter_protocol setting specifies a too low version, the
+libmilter library will log an error message like this:
+
+ application name: st_optionneg[xxxxx]: 0xyy does not fulfill action
+ requirements 0xzz
+
+The remedy is to increase the Postfix milter_protocol version number. See,
+however, the limitations section below for features that aren't supported by
+Postfix.
+
+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:
+
+ warning: milter inet:host:port: can't read packet header: Unknown error : 0
+ warning: milter inet:host:port: can't read packet header: Success
+ warning: milter inet:host:port: can't read SMFIC_DATA reply packet header:
+ No such file or directory
+
+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.
+
+See "Different settings for different Milter applications" for advanced
+configuration options.
+
+MMiilltteerr pprroottooccooll ttiimmeeoouuttss
+
+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).
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |PPoossttffiixx ppaarraammeetteerr |TTiimmee lliimmiitt|MMiilltteerr pprroottooccooll ssttaaggee |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_connect_timeout|30s |CONNECT |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_command_timeout|30s |HELO, MAIL, RCPT, DATA, UNKNOWN|
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_content_timeout|300s |HEADER, EOH, BODY, EOM |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+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.
+
+See "Different settings for different Milter applications" for advanced
+configuration options.
+
+DDiiffffeerreenntt sseettttiinnggss ffoorr ddiiffffeerreenntt MMiilltteerr aapppplliiccaattiioonnss
+
+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.
+
+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.
+
+ 1 /etc/postfix/main.cf:
+ 2 smtpd_milters = { inet:host:port,
+ 3 connect_timeout=10s, default_action=accept }
+
+Instead of a server endpoint, we now have a list enclosed in {}.
+
+ * Line 2: The first item in the list is the server endpoint. This supports
+ the exact same "inet" and "unix" syntax as described earlier.
+
+ * 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.
+
+Inside the list, syntax is similar to what we already know from main.cf: items
+separated by space or comma. There is one difference: yyoouu mmuusstt eenncclloossee aa
+sseettttiinngg iinn ppaarreenntthheesseess,, aass iinn ""{{ nnaammee == vvaalluuee }}"",, iiff yyoouu wwaanntt ttoo hhaavvee ssppaaccee oorr
+ccoommmmaa wwiitthhiinn aa vvaalluuee oorr aarroouunndd ""=="".
+
+DDiiffffeerreenntt sseettttiinnggss ffoorr ddiiffffeerreenntt SSMMTTPP cclliieennttss
+
+The smtpd_milter_maps feature supports different Milter settings for different
+client IP addresses. Lookup results override the the global smtpd_milters
+setting, and have the same syntax. For example, to disable Milter settings for
+local address ranges:
+
+/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
+
+This feature is available with Postfix 3.2 and later.
+
+SSeennddmmaaiill mmaaccrroo eemmuullaattiioonn
+
+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 workarounds section below for solutions.
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |SSeennddmmaaiill mmaaccrroo |MMiilltteerr pprroottooccooll ssttaaggee |DDeessccrriippttiioonn |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |i |DATA, EOH, EOM |Queue ID, also Postfix |
+ | | |queue file name |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |j |Always |Value of myhostname |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |_ |Always |The validated client name |
+ | | |and address |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{auth_authen} |MAIL, DATA, EOH, EOM |SASL login name |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{auth_author} |MAIL, DATA, EOH, EOM |SASL sender |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{auth_type} |MAIL, DATA, EOH, EOM |SASL login method |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{client_addr} |Always |Remote client IP address |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Connection concurrency for|
+ | | |this client (zero if the |
+ |{client_connections}|CONNECT |client is excluded from |
+ | | |all smtpd_client_* |
+ | | |limits). |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Remote client hostname |
+ | | |When address -> name |
+ |{client_name} |Always |lookup or name -> address |
+ | | |verification fails: |
+ | | |"unknown" |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{client_port} |Always (Postfix >=2.5) |Remote client TCP port |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Client name from address -|
+ |{client_ptr} |CONNECT, HELO, MAIL, DATA|> name lookup |
+ | | |When address -> name |
+ | | |lookup fails: "unknown" |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{cert_issuer} |HELO, MAIL, DATA, EOH, |TLS client certificate |
+ | |EOM |issuer |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{cert_subject} |HELO, MAIL, DATA, EOH, |TLS client certificate |
+ | |EOM |subject |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{cipher_bits} |HELO, MAIL, DATA, EOH, |TLS session key size |
+ | |EOM | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{cipher} |HELO, MAIL, DATA, EOH, |TLS cipher |
+ | |EOM | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{daemon_addr} |Always (Postfix >=3.2) |Local server IP address |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{daemon_name} |Always |value of |
+ | | |milter_macro_daemon_name |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{daemon_port} |Always (Postfix >=3.2) |Local server TCP port |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{mail_addr} |MAIL |Sender address |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{mail_host} |MAIL (Postfix >= 2.6, |Sender next-hop |
+ | |only with smtpd_milters) |destination |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{mail_mailer} |MAIL (Postfix >= 2.6, |Sender mail delivery |
+ | |only with smtpd_milters) |transport |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Recipient address |
+ |{rcpt_addr} |RCPT |With rejected recipient: |
+ | | |descriptive text |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Recipient next-hop |
+ |{rcpt_host} |RCPT (Postfix >= 2.6, |destination |
+ | |only with smtpd_milters) |With rejected recipient: |
+ | | |enhanced status code |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | | |Recipient mail delivery |
+ |{rcpt_mailer} |RCPT (Postfix >= 2.6, |transport |
+ | |only with smtpd_milters) |With rejected recipient: |
+ | | |"error" |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |{tls_version} |HELO, MAIL, DATA, EOH, |TLS protocol version |
+ | |EOM | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |v |Always |value of milter_macro_v |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+WWhhaatt mmaaccrrooss wwiillll PPoossttffiixx sseenndd ttoo MMiilltteerrss??
+
+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.
+
+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.
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |PPoossttffiixx ppaarraammeetteerr |MMiilltteerr pprroottooccooll|MMiilltteerr pprroottooccooll ssttaaggee|
+ | |vveerrssiioonn | |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_connect_macros |2 or higher |CONNECT |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_helo_macros |2 or higher |HELO/EHLO |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_mail_macros |2 or higher |MAIL FROM |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_rcpt_macros |2 or higher |RCPT TO |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_data_macros |4 or higher |DATA |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_end_of_header_macros |6 or higher |EOH |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_end_of_data_macros |2 or higher |EOM |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ |milter_unknown_command_macros|3 or higher |unknown command |
+ |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+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).
+
+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 name=value pairs separated by comma or whitespace; you may even
+specify macro names that Postfix does not know about!
+
+WWoorrkkaarroouunnddss
+
+ * 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 advanced content filter example.
+
+ /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=
+
+ * Some Milter applications use the "{if_addr}" macro to recognize local mail;
+ this macro does not exist in Postfix. Workaround: use the "{daemon_addr}"
+ (Postfix >= 3.2) or "{client_addr}" macro instead.
+
+ * Some Milter applications log a warning that looks like this:
+
+ sid-filter[36540]: WARNING: sendmail symbol 'i' not available
+
+ And they may insert an ugly message header with "unknown-msgid" like this:
+
+ X-SenderID: Sendmail Sender-ID Filter vx.y.z host.example.com <unknown-
+ msgid>
+
+ The problem is that Milter applications expect that the queue ID is known
+ before the MTA accepts the MAIL FROM (sender) command. Postfix does not
+ choose a queue ID, which is used as the queue file name, until after it
+ accepts the first valid RCPT TO (recipient) command.
+
+ 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.
+
+ 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.
+
+ o Edit the filter source file (typically named xxx-filter/xxx-filter.c or
+ similar).
+
+ o Look up the mlfi_eom() function and add code near the top shown as bboolldd
+ text below:
+
+ dfc = cc->cctx_msg;
+ assert(dfc != NULL);
+
+ //** DDeetteerrmmiinnee tthhee jjoobb IIDD ffoorr llooggggiinngg.. **//
+ iiff ((ddffcc-->>mmccttxx__jjoobbiidd ==== 00 |||| ssttrrccmmpp((ddffcc-->>mmccttxx__jjoobbiidd,, JJOOBBIIDDUUNNKKNNOOWWNN)) ==== 00))
+ {{
+ cchhaarr **jjoobbiidd == ssmmffii__ggeettssyymmvvaall((ccttxx,, ""ii""));;
+ iiff ((jjoobbiidd !!== 00))
+ ddffcc-->>mmccttxx__jjoobbiidd == jjoobbiidd;;
+ }}
+
+ NOTES:
+
+ o 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.
+
+ o This change fixes only the ugly message header, but not the WARNING
+ message. Fortunately, many Milters log that message only once.
+
+LLiimmiittaattiioonnss
+
+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.
+
+ * The Milter protocol has evolved over time. Therefore, different Postfix
+ versions implement different feature sets.
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ |PPoossttffiixx|SSuuppppoorrtteedd MMiilltteerr rreeqquueessttss |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | 2.6 |All Milter requests of Sendmail 8.14.0 (see notes below). |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | |All Milter requests of Sendmail 8.14.0, except: |
+ | |SMFIP_RCPT_REJ (report rejected recipients to the mail filter), |
+ | 2.5 |SMFIR_CHGFROM (replace sender, with optional ESMTP parameters), |
+ | |SMFIR_ADDRCPT_PAR (add recipient, with optional ESMTP |
+ | |parameters). |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | 2.4 |All Milter requests of Sendmail 8.13.0. |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+ | 2.3 |All Milter requests of Sendmail 8.13.0, except: |
+ | |SMFIR_REPLBODY (replace message body). |
+ |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
+
+ * For Milter applications that are written in C, you need to use the Sendmail
+ libmilter library.
+
+ * 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.
+
+ 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.
+
+ * 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.
+
+ * 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:
+
+ warning: queue-id: cleanup_chg_from: ignoring ESMTP arguments "whatever"
+ warning: queue-id: cleanup_add_rcpt: ignoring ESMTP arguments "whatever"
+
+ * Postfix 2.3 does not implement requests to replace the message body. Milter
+ applications log a warning message when they need this unsupported
+ operation:
+
+ st_optionneg[134563840]: 0x3d does not fulfill action requirements 0x1e
+
+ The solution is to use Postfix version 2.4 or later.
+
+ * Most Milter configuration options are global. Future Postfix versions may
+ support per-Milter timeouts, per-Milter error handling, etc.
+