Skip to content

Postfix filter outbound email

wordpress meta

title: 'Postfix Filter Outbound Email'
date: '2013-12-29T07:44:57-06:00'
status: publish
permalink: /postfix-filter-outbound-email
author: admin
excerpt: ''
type: post
id: 510
category:
    - SMTP
    - Solaris
tag:
    - Postfix
post_format: []

In a previous article I wrote about using Sendmail to block outbound email and at the same time allow email to specific domains or specific email addresses.

As I explained Sendmail could handle blocking and selective relaying to domains effectively but could not easily handle adding specific email addresses to the mix. Below is a quick howto on setting up Postfix on Solaris 11 and configuring the blocking as required.

# svcadm disable svc:/network/smtp:sendmail

# pkg install developer/gcc-45
# pkg install library/gnutls

** Note that the postfix-install script kicks off during gmake install. You will note I used /usr/local for install_root since I do not want to taint anything on the regular paths. However that does not work very well. I ended up having to move quite a few folders and files from /usr/local/usr/local to /usr/local. I will have to try this again and see if using / for install_root is acceptable for keeping things separate and not taint system paths.

# wget http://postfix.bbnx.net/postfix-release/official/postfix-2.10.2.tar.gz
# gzip -d postfix-2.10.2.tar.gz
# tar xf postfix-2.10.2.tar
# pwd
/usr/src/postfix-2.10.2

# gmake clean
# gmake makefiles MAKE=gmake CCARGS='-DNO_NIS -DUSE_TLS -lssl -lcrypto'
# gmake
# gmake install
...
/bin/sh postfix-install
...
install_root: [/] /usr/local/
tempdir: [/usr/src/postfix-2.10.2]
config_directory: [/etc/postfix]
command_directory: [/usr/sbin] /usr/local/sbin
daemon_directory: [/usr/libexec/postfix] /usr/local/libexec/postfix
data_directory: [/var/lib/postfix]
html_directory: [no]
mail_owner: [postfix]
mailq_path: [/usr/bin/mailq] /usr/local/bin/mailq
manpage_directory: [/usr/local/man]
newaliases_path: [/usr/bin/newaliases] /usr/local/bin/newaliases
queue_directory: [/var/spool/postfix]
readme_directory: [no]
sendmail_path: [/usr/lib/sendmail]
setgid_group: [postdrop]
...

Setup user, group and configure Postfix:

# groupadd postdrop
# useradd -d /export/home/postfix -s /usr/bin/bash -m postfix
80 blocks

# mkdir /etc/postfix
# pwd
/etc/postfix

# grep -v ^# main.cf | grep ".$"
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
unknown_local_recipient_reject_code = 550
mynetworks = 10.2.0.0/16, 127.0.0.0/8
debug_peer_level = 2
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
 ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/lib/sendmail
newaliases_path = /usr/local/bin/newaliases
mailq_path = /usr/local/bin/mailq
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/local/man
sample_directory = /etc/postfix
readme_directory = no
inet_protocols = ipv4
header_checks = pcre:/etc/postfix/header_checks

# tail -4 header_checks
/^To: .*@domain1\.com/ FILTER smtp:mail.domain1.com
/^To: .*@domain2\.com/ ACCEPT
/^To: user@domain3\.com/ ACCEPT
/^To: .*/ REJECT

*** ACCEPT is not really a defined ACTION but for me this works. I will have to look into this closer. Maybe action should be INFO.

*** Note that domain1 needed to relay to a specific internal host whereas domain2 is an example of direct forwarding to the Internet.

Fix the /usr/local/usr/local installation. Should do a re-install and fix this.

mv /usr/local/etc/postfix/* /etc/postfix/

mkdir /usr/local/sbin
mkdir /usr/local/libexec/
mkdir /usr/local/libexec/postfix
mkdir /var/spool/postfix

mv /usr/local/usr/local/libexec/ /usr/local/
mv /usr/local/usr/local/libexec/postfix/postfix-script /usr/local/libexec/postfix/
mv /usr/local/usr/local/sbin/post* /usr/local/sbin/
mv /usr/local/usr/local/libexec/postfix/* /usr/local/libexec/postfix/

chgrp postdrop /usr/local/sbin/postqueue
chgrp postdrop /usr/local/sbin/postdrop
chmod +x /usr/local/sbin/postqueue
chmod +x /usr/local/sbin/postdrop

chmod +s /usr/local/sbin/postqueue
chmod +s /usr/local/sbin/postdrop

Start and test:

# /usr/local/sbin/postfix start

# tail -f /var/log/syslog

TODO: Redo and fix installation and add to Solaris SMF.

Update 12.30.13:

More testing showed that this solution does not work well with mailing lists ie multiple recipients in the To: field. After playing with a lot of different options I finally liked the idea of running multi-postfix. In short that entails a 1st instance accepting mail on port 25 and then split the message into multiple messages and feed it to the 2nd instance on 127.0.0.1:10026 or whatever addresses and ports you prefer. The trick is to use default_destination_recipient_limit = 1 option on the frontend instance. This seemed like an elegant solution, but for me my header checks were still not working like I want. After a lot of fiddling I decided to use a different approach. At some point I will document the two postfix instance solution since it might fit a lot of use cases.

The solution that I finally used was accepting mail on port 25 with python smtplib and then sanitizing the list before injecting back into sendmail on say127.0.0.1:10026. The article here: <>