use entirely at your own risk cd /usr/local/src wget http://pldaniels.com/altermime/altermime-0.3-dev.tar.gz tar xzf altermime-0.3-dev.tar.gz cd altermime-0.3-dev make && make install groupadd filter useradd -d /var/spool/altermime -g filter filter mkdir /var/spool/altermime chown filter:filter /var/spool/altermime mkdir /etc/postfix/filter chown root:filter /etc/postfix/filter chmod 770 /etc/postfix/filter cd /etc/postfix/filter wget http://verchick.com/mecham/public_html/spam/add_disclaimer.sh wget http://verchick.com/mecham/public_html/spam/disclaimer.txt chown root:filter add_disclaimer.sh chmod 750 add_disclaimer.sh chown root:filter disclaimer.txt chmod 640 disclaimer.txt vi disclaimer.txt in master.cf: 127.0.0.1:10037 inet n - n - - smtpd -o content_filter=disclaimer: -o smtpd_restriction_classes= -o smtpd_delay_reject=no -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions -o smtpd_end_of_data_restrictions= -o mynetworks=127.0.0.0/8 -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 -o smtpd_client_connection_count_limit=0 -o smtpd_client_connection_rate_limit=0 -o smtpd_milters= -o local_header_rewrite_clients= -o local_recipient_maps= -o relay_recipient_maps= -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings disclaimer unix - n n - - pipe flags=Rq user=filter argv=/etc/postfix/filter/add_disclaimer.sh -f ${sender} -- ${recipient} In add_disclaimer.sh you can see that once processed, mail is returned to Postfix via the sendmail command. This is important to know because it greatly affects how the content filters (amavisd-new and disclaimer) are chained together and what path a message takes through the system. We need to differentiate between incoming and outgoing messages (so you can direct only outgoing messages to the disclaimer filter). One way to do so is by using the amavisd-new MYNETS policy bank. To use this policy bank, in master.cf you must use smtp_send_xforward_command=yes for the smtp-amavis transport (or lmtp_send_xforward_command=yes if using lmtp): smtp-amavis unix - - n - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes -o disable_dns_lookups=yes and in amavisd.conf you would include internal clients in @mynetworks: @mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 ); # default and then create the MYNETS policy bank, for example: $policy_bank{'MYNETS'} = { # mail originating from @mynetworks bypass_spam_checks_maps => [1], # don't spam-check internal mail bypass_banned_checks_maps => [1], # don't banned-check internal mail bypass_header_checks_maps => [1], # don't header-check internal mail forward_method => 'smtp:[127.0.0.1]:10037', # relay to Postfix listener on port 10037 # which in turn calls the disclaimer filter }; Another way to perform the differentiation (which I consider preferable) would be to use a Postfix access map that uses the FILTER directive to override the content filter for selected clients/networks. This could be useful if your internal server uses this machine as a smarthost and all clients send mail out through your internal server (common in an MS Exchange environment) but with the use of a cidr: map could also include entire networks. Create the policy bank in amavisd.conf: Change this from the default (add port 10026): $inet_socket_port = [10024, 10026]; Then add a policy bank to the listener on 10026: $interface_policy{'10026'} = 'INTERNAL'; $policy_bank{'INTERNAL'} = { # mail originating from clients in cidr:/etc/postfix/internal_clients_filter bypass_spam_checks_maps => [1], # don't spam-check outgoing mail bypass_banned_checks_maps => [1], # don't banned-check outgoing mail bypass_header_checks_maps => [1], # don't header-check outgoing mail forward_method => 'smtp:[127.0.0.1]:10037', # relay to Postfix listener on port 10037 # which in turn calls the disclaimer filter }; Then in main.cf: smtpd_sender_restrictions = check_client_access cidr:/etc/postfix/internal_clients_filter [... possible other stuff ... ] contents of: /etc/postfix/internal_clients_filter: # this cidr: map is used to override the content_filter for selected clients # the policy bank listening on 10026 will relay mail to the disclaimer filter 192.168.0.41/32 FILTER smtp:[127.0.0.1]:10026 10.0.0.0/24 FILTER smtp:[127.0.0.1]:10026 By the way, because we are overriding forward_method in these policy banks (the default is $forward_method = 'smtp:[127.0.0.1]:10025';) and the default for $notify_method is $notify_method = $forward_method; we should explicity set: $notify_method = 'smtp:[127.0.0.1]:10025'; so we are not sending amavisd-new notifications through the disclaimer filter. Here is the path a message from a remote client follows when our disclaimer filter is not used but amavisd-new is used (inbound mail follows this route): -> Postfix port 25 -> amavisd-new content_filter port 10024 -> Postfix reinjection port 10025 -> next destination and when using the disclaimer filter with the amavisd-new MYNETS policy bank (clients in the amavisd-new @mynetworks IP range could use this): -> Postfix port 25 -> amavisd-new content_filter port 10024 -> Postfix reinjection port 10037 -> disclaimer content_filter -> Postfix 'pickup' daemon -> next destination and if you were to alternately set up a client based policy bank that listens on port 10026 (clients in a special access map that use the FILTER directive could follow this route): -> Postfix port 25 -> amavisd-new content_filter port 10026 -> Postfix reinjection port 10037 -> disclaimer content_filter -> Postfix 'pickup' daemon -> next destination If you set the amavisd-new content_filter globally by placing this in main.cf: content_filter = smtp-amavis:[127.0.0.1]:10024 then mail picked up by the pickup daemon will be fed to amavisd-new causing mail to be processed twice by amavisd-new, e.g.: -> Postfix port 25 -> amavisd-new port content_filter 10024 -> Postfix reinjection port 10037 -> disclaimer content_filter -> Postfix 'pickup' daemon -> amavisd-new content_filter port 10024 -> Postfix reinjection port 10025 -> next destination This example is using the MYNETS policy bank. If your policy bank disables some amavisd-new checks these checks will likely not be disabled the second time through amavisd-new (and subsequently your message may get quarantined). The MYNETS policy bank is used the first time through, but not the second (because the pickup daemon does not provide amavisd-new with an xforwarded IP address). With amavisd-new 2.4.5 or newer it is possible for mail submitted to the pickup daemon to be included in @mynetworks. You would add 0.0.0.0/8 to @mynetworks. However, doing so in this case would cause an infinite loop (Ok, it is limited by hopcount_limit) and mail would not get delivered. This is possibly one argument against using the MYNETS policy bank and instead using the client map based method. Either way, to prevent feeding amavisd-new twice, you must either disable content_filter for the pickup daemon: pickup fifo n - n 60 1 pickup -o content_filter= or remove the content_filter from main.cf and confine the amavisd-new content_filter to messages coming in the front door: smtp inet n - n - - smtpd -o content_filter=smtp-amavis:[127.0.0.1]:10024 Regardless, you must not feed messages submitted to the pickup daemon back through any content_filter that may again submit messages to the pickup daemon. You can still direct locally generated or locally submitted 'sendmail' type mail to a content_filter however. For example, we could create another amavisd-new policy bank that only scans for viruses: $inet_socket_port = [10024, 10026. 10028]; $interface_policy{'10028'} = 'VIRUSONLY'; $policy_bank{'VIRUSONLY'} = { # mail from the pickup daemon bypass_spam_checks_maps => [1], # don't spam-check this mail bypass_banned_checks_maps => [1], # don't banned-check this mail bypass_header_checks_maps => [1], # don't header-check this mail }; and then 'pickup' mail to this policy bank: pickup fifo n - n 60 1 pickup -o content_filter=smtp-amavis:[127.0.0.1]:10028 and since we are not overriding the amavisd-new $forward_method amavisd-new would return messages to port 10025 via smtp. Now, what all of this sending does to your statistical data is another matter. Sorry, I can't help you re-write your log analyzer software. But what if your users connect via SASL authentication? Hopefully you have configured your SASL clients to connect either to the submission port (587) or the smtps port (465) (and you have restricted those ports so only SASL auth users can connect to them). If so you can simply override the content filter for mail submitted to those ports. Here we use the same INTERNAL policy bank used for internal clients: submission inet n - n - - smtpd -o smtpd_etrn_restrictions=reject -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o content_filter=smtp-amavis:[127.0.0.1]:10026 smtps inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o content_filter=smtp-amavis:[127.0.0.1]:10026 If they connect to port 25 and you have a public IP address to spare you could break out the smtpd listener into two addresses (and 127.0.0.1) and have them connect to the newly added IP address: 1.2.3.4:smtp inet n - n - - smtpd -o content_filter=smtp-amavis:[127.0.0.1]:10024 127.0.0.1:smtp inet n - n - - smtpd -o content_filter=smtp-amavis:[127.0.0.1]:10024 1.2.3.5:smtp inet n - n - - smtpd -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o content_filter=smtp-amavis:[127.0.0.1]:10026 A third possible method you could use to send all SASL clients (and optionally clients in mynetworks) to the policy bank listening on port 10026 would be to set smtp-amavis:[127.0.0.1]:10026 as the default content_filter. Then set up a restriction that will let all clients except SASL (and optionally clients in mynetworks) fall through to a catchall access map that sets the amavis content_filter back to port 10024: In main.cf: content_filter = smtp-amavis:[127.0.0.1]:10026 or in master.cf: smtp inet n - n - - smtpd -o content_filter=smtp-amavis:[127.0.0.1]:10026 Then: smtpd_data_restrictions = reject_unauth_pipelining permit_mynetworks permit_sasl_authenticated check_client_access regexp:/etc/postfix/filter-catchall.regexp With the contents of /etc/postfix/filter-catchall.regexp: /^/ FILTER smtp-amavis:[127.0.0.1]:10024 If necessary, you could exclude certain SASL or $mynetworks clients from the policy bank by creating another access map (here I place it in smtpd_sender_restrictions): smtpd_sender_restrictions = check_client_access hash:/etc/postfix/use_normal_amavis # contents of /etc/postfix/use_normal_amavis: 192.168.1.13 FILTER smtp-amavis:[127.0.0.1]:10024 The main drawback to this whole approach is you have to be careful about adding any access lists or restrictions in smtpd_data_restrictions that OK/PERMIT something/someone prior to "check_sender_access regexp:/etc/postfix/filter-catchall.regexp" because they would use the more permissive default policy bank. This approach uses a sort of 'permit then deny' as opposed to 'deny then permit'. I'm sure there are other methods that could be used to differentiate our clients from the rest of the world but I leave that up to you to find them. Now there is the issue with address rewriting. Let's take an example where this is in a virtual alias map: user@example.com user@example.com, user@localhost This sends one copy of a message to user@example.com, and another copy to user@localhost. Messages that will not go through the disclaimer filter will get rewriten twice, once when the message is received at port 25 and once again when the message is received at port 10025 (the amavisd-new reinjection port). This results in user@localhost receiving two copies of the message. -> Postfix port 25 -> addresses rewritten -> amavisd-new content_filter port 10024 -> Postfix reinjection port 10025 -> addresses rewritten Messages that go through the disclaimer filter are rewritten three times: -> Postfix port 25 -> addresses rewritten -> amavisd-new port content_filter 10024 -> Postfix reinjection port 10037 -> addresses rewritten -> disclaimer content_filter -> Postfix 'pickup' daemon -> addresses rewritten In this case However, for outbound messages due to the fact that the address is rewritten once when the message is received on port 25 and once again when amavisd-new reinjects the message, user@localhost will recieve two copies of the message. You can choose to disable rewriting before or after amavisd-new, but I find it makes more sense to do it before: smtp inet n - n - - smtpd -o receive_override_options=no_address_mappings