Purpose of the before-queue content filter feature
==================================================

Normally, Postfix receives mail, stores it in the mail queue and
then delivers it.  The Postfix SMTP server can be configured to
forward all incoming mail to a content filter (for example, a
real-time SPAM filter) that inspects all mail BEFORE it is stored
in the Postfix mail queue.

[This is not to be confused with the approach described in the
FILTER_README document, where all mail is inspected AFTER it is
stored in the Postfix mail queue]

The before-queue content filter is meant to be used as follows:

                        before                               / smtp
    Internet -> smtpd -> queue -> smtpd -> cleanup -> queue -> local
               Postfix  filter   Postfix                     \ virtual etc.

For reference, this is the normal path through Postfix:

                                           / smtp
    Internet -> smtpd -> cleanup -> queue -> local
                Postfix                    \ virtual etc.

For comparison, this is the FILTER_README approach with an SMTP-based
after-queue content filter:
                                           / smtp
    Internet -> smtpd -> cleanup -> queue -> local
               Postfix      ^         v    \ virtual etc.
                          smtpd      smtp
                         Postfix   Postfix
                            \ after   /
                              queue <-
			      filter

The before-queue content filter receives unfiltered SMTP mail from
Postfix and does one of the following:

1 - Re-inject the mail back into Postfix via SMTP, perhaps after
    changing content.

2 - Reject the mail by sending a suitable SMTP status code back
    to Postfix. Postfix passes the status back to the remote SMTP
    client. This way, Postfix does not have to send a bounce message.

3 - Send the mail somewhere else.

Limitations
===========

The before-queue content filter allows Postfix to reject mail before
the incoming SMTP mail transfer completes, so that Postfix does
not have to send rejected mail back to the sender.  Mail that is
not accepted remains the responsibility of the remote SMTP client.

The problem with before-queue content filtering is that the remote
SMTP client expects an SMTP reply within a deadline. As the system
load increases, fewer and fewer CPU cycles remain available to
answer within the deadline, and eventually you either have to stop
accepting mail or you have to stop filtering the mail.

How Postfix talks to the before-queue content filter
==================================================

Postfix makes one connection per email message.  Postfix speaks
ESMTP, but uses no command pipelining. Postfix generates its own
EHLO, DATA and QUIT commands, and forwards unmodified copies of
all the MAIL FROM and RCPT TO commands that the Postfix SMTP server
didn't reject itself. The SMTP proxy server should accept the same
MAIL FROM and RCPT TO command syntax as the Postfix SMTP server.
Postfix sends no other SMTP commands.

The content filter is expected to pass on unmodified SMTP commands
from a before-filter Postfix SMTP server to an after-filter Postfix
SMTP server that listens on a non-standard port.  When the filter
rejects content, it should send a negative SMTP response back to
the before-filter Postfix SMTP server, and it should abort any
connection with the after-filter Postfix SMTP server without
completing the SMTP conversation with the after-filter Postfix SMTP
server.

Configuration parameters 
========================

Parameters that control proxying:

smtpd_proxy_filter (syntax: host:port)

    The host and TCP port of the before-queue content filter.  When
    no host or host:  is specified, localhost is assumed.

smtpd_proxy_timeout (default: 100s)

    Timeout for connecting to the before-queue content filter and
    for sending and receiving commands and data.  All proxy errors
    are logged to the maillog file. For privacy reasons, all the
    remote SMTP client sees is "451 Error:  queue file write error".

smtpd_proxy_ehlo (default: $myhostname)

    The hostname to use when sending an EHLO command to the
    before-queue content filter.

Testing the SMTP pass-through proxy feature
===========================================

The following example sets up a null content filter, that is, the
Postfix SMTP server gives the mail directly to another Postfix SMTP
server process without intervening content filter. This useful only
for testing, of course.

/etc/postfix/master.cf
    smtp      inet  n       -       n       -       -       smtpd 
        -o smtpd_proxy_filter=26
    :26       inet  n       -       n       -       -       smtpd
	-o smtpd_client_restrictions=
	-o smtpd_helo_restrictions=
	-o smtpd_sender_restrictions=
	-o smtpd_recipient_restrictions=permit_mynetworks,reject
	-o mynetworks=127.0.0.0/8
        -o receive_override_options=no_unknown_recipient_checks

Note: do not specify spaces around the "=" or "," characters.

The ":26" causes Postfix to listen on the localhost address only.
DO NOT expose the secondary SMTP server to the Internet :-)

The result is as follows:

    Internet -> smtpd on port 25 -> smtpd on port 26 -> cleanup -> queue

This configuration is sufficient for stress testing.

Other suggestions for test configurations: use the Postfix smtp-sink
command as the proxy, or something as basic as netcat.
