An Example of Postfix Mail System on Ubuntu Server 9.10

Once time I had to make a corporate mail system with some special requirements.

- copying of all sended messages to the special e-mail folder
- restriction of multi-volume archives
- flexible message size restrictions

At first I made it on Exim, but there was a big problem - It hasn't the Delivery Status Notification function.
I tryed to fix it by unoffical patch (http://sourceforge.net/projects/eximdsn/) but it didn't help me.
So I decided to make the next system:
Ubuntu Server 9.10
MTA - Postix
Database - MySQL
POP3/IMAP server - Dovecot
Antivirus - ClamAV
Antispam - Spamassassin, Razor, Pyzor
Web Interface - Postfixadmin
Restrictions - Apolicy

Install Ubuntu with LAMP, DNS and OpenSSH, than update it and install all required software.

# aptitude update
# aptitude upgrade
# aptitude install mc htop dovecot-postfix postfix-mysql amavisd-new clamav razor pyzor spamassassin

Configure Dovecot:

# nano /etc/dovecot/dovecot-postfix.conf

                base_dir = /var/run/dovecot/
                protocols = imap pop3
                listen = *
                disable_plaintext_auth = no
                shutdown_clients = yes
                log_path = /var/log/dovecot.log
                info_log_path = /var/log/dovecot.log
                log_timestamp = "%Y-%m-%d %H:%M:%S "
                login_dir = /var/run/dovecot/login
                login_chroot = yes
                login_user = dovecot
                login_process_size = 64
                login_process_per_connection = yes
                login_processes_count = 3
                login_max_processes_count = 128
                login_max_connections = 256
                login_greeting = Hell-o!.
                login_log_format_elements = user=<%u> method=%m rip=%r lip=%l %c
                login_log_format = %$: %s
                mail_location = maildir:/var/mail/%d/%n
                mail_privileged_group = mail
                mail_access_groups = mail
                first_valid_uid = 7
                first_valid_gid = 7

                protocol imap {
                    imap_client_workarounds = delay-newmail outlook-idle netscape-eoh tb-extra-mailbox-sep
                }

                protocol pop3 {
                    pop3_uidl_format = %08Xu%08Xv
                    pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
                }

                protocol managesieve {
                    sieve=~/.dovecot.sieve
                    sieve_storage=~/sieve
                }

                protocol lda {
                    postmaster_address = admin@domain.ru
                    mail_plugin_dir = /usr/lib/dovecot/modules/lda
                    auth_socket_path = /var/run/dovecot/auth-master
                }

                auth default {
                    mechanisms = plain login cram-md5

                    passdb sql {
                        args = /etc/dovecot/dovecot-sql.conf
                    }
                    userdb passwd {
                    }

                    userdb sql {
                        args = /etc/dovecot/dovecot-sql.conf
                    }

                    socket listen {
                        master {
                                path = /var/run/dovecot/auth-master
                                mode = 0660
                                user = dovecot
                                group = mail
                        }
                        client {
                                path = /var/run/dovecot/auth-client
                                mode = 0660
                                user = postfix
                                group = postfix
                        }
                    }
                }

# nano /etc/dovecot/dovecot-sql.conf

                driver = mysql
                connect = host=localhost dbname=mail user=mail password=password
                default_pass_scheme = MD5
                password_query = SELECT `username` as `user`, `password` FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
                user_query = SELECT `maildir` AS `home`, 8 AS `uid`, 8 AS `gid` FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'

Configure Postfix:

# nano /etc/postfix/main.cf

                biff = no
                append_dot_mydomain = no
                readme_directory = no

                alias_database = hash:/etc/aliases
                alias_maps = hash:/etc/aliases

                # Virtual mailbox settings
                virtual_mailbox_base = /var/mail
                virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf
                virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
                virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf
                virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf

                # Network settings
                mydomain = domain.ru
                myhostname = mail.domain.ru
                myorigin = $mydomain
                #mydestination = $myhostname, localhost, localhost.$myhostname, localhost.$mydomain, $mydomain, 063.su, furgonz.ru, domain.net
                mydestination = $myhostname, localhost, localhost.$myhostname, localhost.$mydomain
                mynetworks = 127.0.0.0/8, 192.168.0.0/16
                smtp_helo_name=$myhostname
                smtpd_banner = $myhostname ESMTP Mail Server
                inet_protocols = ipv4
                inet_interfaces = all

                # Dovecot transport
                mailbox_transport = dovecot
                mailbox_command = /usr/lib/dovecot/deliver
                dovecot_destination_recipient_limit = 1
                virtual_transport = dovecot

                # Mailbox settings
                mailbox_size_limit = 1024000000
                message_size_limit = 10240000
                virtual_mailbox_base = /var/mail
                recipient_delimiter = +

                # Restrictions

                smtpd_client_restrictions = permit_mynetworks,
                    check_client_access mysql:/etc/postfix/mysql_virtual_alias_maps.cf,
                    reject_unknown_client_hostname,
                    reject_unauth_pipelining

                smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10001,
                    permit_mynetworks,
                    reject_unauth_destination,
                    reject_invalid_hostname,
                    reject_non_fqdn_hostname,
                    reject_non_fqdn_sender,
                    reject_non_fqdn_recipient,
                    reject_unknown_sender_domain,
                    reject_unknown_recipient_domain,
                    reject_unauth_pipelining,
                    permit_auth_destination,
                    reject_unlisted_recipient,
                    reject_unauth_destination,
                    reject_rbl_client opm.blitzed.org,
                    reject_rbl_client list.dsbl.org,
                    reject_rbl_client zen.spamhaus.org,
                    reject_rbl_client dul.dnsbl.sorbs.net,
                    reject_rbl_client dnsbl.njabl.org,
                    reject_rbl_client dynablock.njabl.org,
                    reject_rbl_client bl.spamcop.net,
                    reject_rbl_client bl.csma.biz,
                    reject_rbl_client dnsbl.sorbs.net,
                    reject_rbl_client smtp.dnsbl.sorbs.net,
                    reject_rbl_client combined.njabl.org,
                    reject_rbl_client rbl.majordomo.ru,

                smtpd_sender_restrictions = check_policy_service inet:127.0.0.1:10001,
                    permit_mynetworks,
                    check_sender_access hash:/etc/postfix/sender_access,
                    reject_unknown_sender_domain,
                    reject_unlisted_sender,
                    reject_non_fqdn_sender

                smtpd_helo_restrictions = permit_mynetworks,
                    check_helo_access hash:/etc/postfix/helo_access,
                    reject_invalid_helo_hostname,
                    reject_unknown_helo_hostname,
                    reject_non_fqdn_helo_hostname

                smtpd_data_restrictions = permit_mynetworks,
                    reject_multi_recipient_bounce,
                    reject_unauth_pipelining

                smtpd_etrn_restrictions = permit_mynetworks,reject

                header_checks = regexp:/etc/postfix/header_checks
                sender_bcc_maps = hash:/etc/postfix/sender_bcc_maps
                #recipient_bcc_maps = hash:/etc/postfix/recipient_bcc_maps

                strict_rfc821_envelopes = yes
                smtpd_reject_unlisted_sender = yes
                smtpd_reject_unlisted_recipient=yes
                disable_vrfy_command = yes
                show_user_unknown_table_name = no
                smtpd_helo_required = yes
                smtp_always_send_ehlo = yes
                smtp_never_send_ehlo=no
                smtpd_delay_reject=no
                address_verify_sender= <>
                address_verify_negative_cache=yes
                address_verify_poll_count=1
                address_verify_positive_expire_time=31d
                address_verify_positive_refresh_time=7d
                address_verife_negative_expire_time=3d
                address_verify_negative_refresh_time=3h
                allow_untrusted_routing=no
                resolve_null_domain=no
                resolve_numeric_domain=no
                smtpd_recipient_limit=100
                smtp_quote_rfc821_envelope=yes
                smtpd_soft_error_limit = 2
                smtpd_error_sleep_time = ${stress?0}${stress:10s}
                smtpd_hard_error_limit = ${stress?3}${stress:20}
                smtpd_timeout = ${stress?30}${stress:300}

                # Timeouts RFC 2821
                smtpd_timeout=5m
                smtpd_starttls_timeout=5m
                smtp_mail_timeout=5m
                smtp_rcpt_timeout=5m
                smtp_data_init_timeout=2m
                smtp_data_xfer_timeout=3m
                smtp_data_done_timeout=10m
                maximal_queue_lifetime=4d
                bounce_queue_lifetime=4d
                queue_run_delay=30m
                minimal_backoff_time=3h
                maximal_backoff_time=5h

                # Amavis
                content_filter = smtp-amavis:[127.0.0.1]:10024

/etc/postfix/master.cf

                #
                # Postfix master process configuration file.  For details on the format
                # of the file, see the master(5) manual page (command: "man 5 master").
                #
                # Do not forget to execute "postfix reload" after editing this file.
                #
                # ==========================================================================
                # service type  private unpriv  chroot  wakeup  maxproc command + args
                #               (yes)   (yes)   (yes)   (never) (100)
                # ==========================================================================
                smtp      inet  n       -       n       -       -       smtpd

                #submission inet n       -       -       -       -       smtpd
                #  -o smtpd_tls_security_level=encrypt
                #  -o smtpd_sasl_auth_enable=yes
                #  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
                #  -o milter_macro_daemon_name=ORIGINATING
                #smtps     inet  n       -       -       -       -       smtpd
                #  -o smtpd_tls_wrappermode=yes
                #  -o smtpd_sasl_auth_enable=yes
                #  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
                #  -o milter_macro_daemon_name=ORIGINATING
                #628      inet  n       -       -       -       -       qmqpd
                pickup    fifo  n       -       -       60      1       pickup
                cleanup   unix  n       -       -       -       0       cleanup
                qmgr      fifo  n       -       n       300     1       qmgr
                #qmgr     fifo  n       -       -       300     1       oqmgr
                tlsmgr    unix  -       -       -       1000?   1       tlsmgr
                rewrite   unix  -       -       -       -       -       trivial-rewrite
                bounce    unix  -       -       -       -       0       bounce
                defer     unix  -       -       -       -       0       bounce
                trace     unix  -       -       -       -       0       bounce
                verify    unix  -       -       -       -       1       verify
                flush     unix  n       -       -       1000?   0       flush
                proxymap  unix  -       -       n       -       -       proxymap
                proxywrite unix -       -       n       -       1       proxymap
                smtp      unix  -       -       -       -       -       smtp
                # When relaying mail as backup MX, disable fallback_relay to avoid MX loops
                relay     unix  -       -       -       -       -       smtp
                -o smtp_fallback_relay=
                #       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
                showq     unix  n       -       -       -       -       showq
                error     unix  -       -       -       -       -       error
                retry     unix  -       -       -       -       -       error
                discard   unix  -       -       -       -       -       discard
                local     unix  -       n       n       -       -       local
                virtual   unix  -       n       n       -       -       virtual
                lmtp      unix  -       -       -       -       -       lmtp
                anvil     unix  -       -       -       -       1       anvil
                scache    unix  -       -       -       -       1       scache
                #
                # ====================================================================
                # Interfaces to non-Postfix software. Be sure to examine the manual
                # pages of the non-Postfix software to find out what options it wants.
                #
                # Many of the following services use the Postfix pipe(8) delivery
                # agent.  See the pipe(8) man page for information about ${recipient}
                # and other message envelope options.
                # ====================================================================
                #
                # maildrop. See the Postfix MAILDROP_README file for details.
                # Also specify in main.cf: maildrop_destination_recipient_limit=1
                #
                maildrop  unix  -       n       n       -       -       pipe
                flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
                #
                # See the Postfix UUCP_README file for configuration details.
                #
                uucp      unix  -       n       n       -       -       pipe
                flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
                #
                # Other external delivery methods.
                #
                ifmail    unix  -       n       n       -       -       pipe
                flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
                bsmtp     unix  -       n       n       -       -       pipe
                flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
                scalemail-backend unix  -       n       n       -       2       pipe
                flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
                mailman   unix  -       n       n       -       -       pipe
                flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
                ${nexthop} ${user}

                # delivery through dovecot
                dovecot   unix  -       n       n       -       -       pipe
                flags=DRhu user=mail:mail argv=/usr/lib/dovecot/deliver -d $(recipient)

                # Amavis                                                                                                                                                                                -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
                smtp-amavis     unix    -       -       -       -       2       smtp
                -o smtp_data_done_timeout=1200
                -o smtp_send_xforward_command=yes
                -o disable_dns_lookups=yes
                -o max_use=20

                127.0.0.1:10025 inet    n       -       -       -       -       smtpd
                -o content_filter=
                -o local_recipient_maps=
                -o relay_recipient_maps=
                -o smtpd_restriction_classes=
                -o smtpd_delay_reject=no
                -o smtpd_client_restrictions=permit_mynetworks,reject
                -o smtpd_helo_restrictions=
                -o smtpd_sender_restrictions=
                -o smtpd_recipient_restrictions=permit_mynetworks,reject
                -o smtpd_data_restrictions=reject_unauth_pipelining
                -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 receive_override_options=no_header_body_checks,no_unknown_recipient_checks

Main files and their functions:

Restrict file extensions.
# nano /etc/postfix/header_checks

                /^(.*)name=\"(.*)\.(exe|bat|cmd|mp3|avi|asf|mov|part1)\"$/ REJECT Attachment type not allowed. File "$2" has unacceptable extension: "$3"
             
Don't use our server name.             
# nano /etc/postfix/helo_access

                mail.domain.ru REJECT  Don't use my server name!

Copy messages to defined e-mail folder
# nano /etc/postfix/recipient_bcc_maps
                @domain1.ru     audit@domain.ru
                @domain2.ru     audit@domain.ru
# nano /etc/postfix/sender_bcc_maps
                @domain1.ru     audit@domain.ru
                @domain2.ru     audit@domain.ru

Black and White sender lists.
# nano /etc/postfix/sender_access
                @superjob.ru            OK
                @spammer.ru            REJECT

Don't forget to do this for every file:
# postmap /etc/postfix/header_checks

MySQL files:

# nano /etc/postfix/mysql_virtual_alias_maps.cf
                user = mail
                password = password
                hosts = localhost
                dbname = mail
                table = alias
                select_field = goto
                where_field = address
                additional_conditions = and active = '1'
                query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

# nano /etc/postfix/mysql_virtual_domains_maps.cf
                user = mail
                password = password
                hosts = localhost
                dbname = mail
                table = domain
                select_field = domain
                where_field = domain
                additional_conditions = and backupmx = '0' and active = '1'
                query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'

# nano /etc/postfix/mysql_virtual_mailbox_limit_maps.cf
                user = mail
                password = password
                hosts = localhost
                dbname = mail
                table = mailbox
                select_field = quota
                where_field = username
                additional_conditions = and active = '1'
                query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'

# nano /etc/postfix/mysql_virtual_mailbox_maps.cf
                user = mail
                password = password
                hosts = localhost
                dbname = mail
                table = mailbox
                select_field = CONCAT(domain,'/',maildir)
                where_field = username
                additional_conditions = and active = '1'
                query = SELECT CONCAT(domain,'/',maildir) FROM mailbox WHERE username='%s' AND active = '1'

Configure Amavis:

# nano /etc/amavis/conf.d/15-content_filter_mode
                use strict;
                @bypass_virus_checks_maps = (
                \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
                @bypass_spam_checks_maps = (
                \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
                1;  # ensure a defined return

nano /etc/amavis/conf.d/20-debian_defaults
$final_spam_destiny D_DISCARD;

/etc/spamassassin/local.cf
                rewrite_header Subject *****SPAM*****
                report_safe 1
                trusted_networks 192.168.
                required_score 5.0
                use_bayes 1
                bayes_auto_learn 1
                bayes_ignore_header X-Bogosity
                bayes_ignore_header X-Spam-Flag
                bayes_ignore_header X-Spam-Status
                skip_rbl_checks 0
                use_razor2 1
                use_pyzor 1
                dns_available yes
                ## Optional Score Increases
                score SPF_FAIL 10.000
                score SPF_HELO_FAIL 10.000
                score RAZOR2_CHECK 2.500
                score PYZOR_CHECK 2.500
                score BAYES_99 4.300
                score BAYES_95 3.500
                score BAYES_80 3.000
                whitelist_from @host.superjob.ru

Change permissions:

# chmod -R 770 /var/mail
# chmod u+s /usr/lib/dovecot/deliver
# chmod -R 777 /var/lib/amavis/tmp
# usermod -a -G amavis mail
# usermod -a -G amavis dovecot
# usermod -a -G amavis clamav
# usermod -a -G amavis postfix
# usermod -a -G clamav dovecot
# usermod -a -G dovecot amavis

Make a base:

# mysql -p
mysql> create database mail;
mysql> grant all on mail.* to mail identified by 'password';
mysql> bye

Download Postfixadmin from there: http://sourceforge.net/projects/postfixadmin/
Unpack files into /var/www/, restart Apache, edit config.inc.php and go to http://your-ip/setup.php.

Download Apolicy: http://download.gna.org/apolicy/apolicy-0.73.tar.gz

Unpack files into /usr/src/ and install it:

# aptitude install python-ipy python-dns python-twisted-core python-twisted-bin python-spf
# cd /usr/src/apolicy-0.73
# python setup.py install
# cp ./debian/apolicy.init /etc/init.d/apolicy
# update-rc.d apolicy defaults
# /etc/init.d/apolicy start

Fix errors:
# mkdir /usr/lib/python2.6/dist-packages/apolicy
# cp /usr/src/apolicy-0.73/build/lib.linux-x86_64-2.6/apolicy/* /usr/lib/python2.6/dist-packages/apolicy

Check installation:
# /etc/init.d/apolicy start
# /etc/init.d/apolicy restart
#  lsof -i | grep twistd

Configure Apolicy:

# nano /etc/apolicy/policy.conf

                acl local_domains sender @domain.ru
                acl local_domains sender @domain2.ru

                acl privileged_users sender admin@domain.ru
                acl privileged_users sender office@domain.ru

                acl 1mb size 1024000

                action deny_max_1mb REJECT Sorry, but You can't sent more than 1mb

                access local_domains !privileged_users 1mb deny_max_1mb

Check our mail system:

# telnet localhost 110
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
+OK Hell-o!.

# telnet localhost 25
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.domain.ru ESMTP Mail Server

If something isn't working - check the logs, there are a lot of interesting!