User-supplied contributions to the Debian/Postfix tutorial

Contributions from various emails I received from readers of the Postfix tutorials can be found on this page. Most are just put here to make them available as soon as I get them. I will happily include them in the next revision of the tutorial. Thanks to everybody who contributed their work.

Christoph

Related software and articles on the internet

Migration scripts for /home/vmail directories

Script 1 from Roman2k (real name unknown):

#!/bin/bash3
PATH="/var/mail/users"
MV="/bin/mv"
MKDIR="/bin/mkdir"

cd $PATH
for i in * ; do
  if ! [[ $i =~ '(.*)@(.*)' ]] ; then
    continue
  fi

  lhs=${BASH_REMATCH[1]} ; rhs=${BASH_REMATCH[2]}

  if [ ! -d $PATH/$rhs ] ; then
    $MKDIR $PATH/$rhs
  fi

  $MV $i $PATH/$rhs/$lhs
done

Script 2 from Fabian Siegel

#!/bin/bash

MAILUSER=$( echo $1 | cut -s -d@ -f1 )
MAILDOMAIN=$( echo $1 | cut -s -d@ -f2 )

mkdir -p $MAILDOMAIN
mv $1 $MAILDOMAIN/$MAILUSER

echo $1 -\> $MAILDOMAIN/$MAILUSER

Spam learn scripts

#!/bin/bash
 
# my little spam learner
#
# this script finds IMAP folders
# and processes any mails found in it with 'sa-learn'
#
# (C) 2004 the dude
 
 
# some variables
 
# the base directory where the maildir folders are located
MAILDIRBASE="/var/vmail"
 
# the name of the IMAP folder where to-be-learned mails are stored
SPAMLEARNDIR="Spam-Learn"
 
# after how many minutes learned spam gets deleted
GRACETIME=120
 
 
 
# stuff below should need no changes
 
# get a list of mail user directories to check
DIRSTOCHECK=`/usr/bin/find $MAILDIRBASE -maxdepth 1 -type d -name "*@*"`
 
 
# do the actual work
for CURRDIR in $DIRSTOCHECK
do
    # learn the spam and
    # (if exist) delete mails older than $GRACETIME minutes
    # so folder doesn't fill up
    nice /usr/bin/find $CURRDIR/.$SPAMLEARNDIR/cur/* -type f -exec sa-learn --no-sync --spam {} \; >/dev/null 2>&1 &&
    /usr/bin/find $CURRDIR/.$SPAMLEARNDIR/cur/* -type f -mmin +$GRACETIME -exec rm {} \;
done
 
sleep 1

# sync the bayes database
sa-learn --rebuild >/dev/null 2>&1
 
exit 0

Another one from Ben that learns spam from all users' spam folders:

!/bin/bash -e

DBPATH=/var/lib/amavis/.spamassassin/bayes

##############################################################################
#       SPAM
##############################################################################

# Every user's .Junk folder is considered Spam.
SPAMFOLDER='.Junk/cur'

DOMAINS=/home/vmail/*
for domain in $DOMAINS ; do
        INBOXES=$domain/*
done

for inbox in $INBOXES ; do \
        echo "====  $inbox/$SPAMFOLDER ===="
        nice sa-learn --spam --dbpath $DBPATH --showdots $inbox/$SPAMFOLDER
        echo ""
done

##############################################################################
#       HAM
##############################################################################

# Only certain user's top level folder is considered Ham.
HAMFOLDERS="\
        /home/vmail/example.com/root/cur \
        "

for hamfolder in $HAMFOLDERS ; do \
        echo "====  $hamfolder  ===="
        nice sa-learn --ham  --dbpath $DBPATH --showdots $hamfolder
        echo ""
done

chown amavis:amavis $DBPATH*

Autoresponder

Contributed by Bjoern Meier

Another contribution (real name of the author unknown)

Here is how it works.

virtualar.py

Mailman

Although the tutorial already describes some basic steps to run mailing lists with mailman Kevin Koyner provided a detailed write-up of how things could be done:

Kevin Coyner, kevin@rustybear.com, Sept 2005


Mailman using Postfix on Debian

    The following is a description on how to set up the list manager Mailman
    on a Debian system that uses Postfix-MySQL-Apache for virtual websites and
    email.  It uses a Python script that makes it unnecessary to make entries
    into /etc/aliases.  This script traces its orgins back to Bruce Perens,
    Siggy Brentrup, Dax Kelson and Simen E. Sandberg.  Without their work this
    would not have been possible.
    
    For this Python script to work, you must be willing to prefix the FQDN
    portion of your listname with "lists"...

        correct:  mylist@lists.virtdomain1.org

        incorrect:  mylist@virtdomain1.org

    While this may seem a sacrifice, it can easily be overcome later by simply
    creating an alias in your MySQL table from mylist@virtdomain1.org to
    mylist@list.virtdomain1.org.  This is far easier than adding in all of the
    Mailman aliases that would normally have to be added to /etc/aliases if
    you were not using the Python script.  This is covered below.

    1.  Make sure your virtual websites and virtual email setups are all
    working before doing anything with Mailman.

    2.  Install Mailman via apt-get using normal defaults for the base website
    that runs on the server.

    3.  Edit /etc/mailman/mm_cfg.py
        
        add:
            VIRTUAL_HOSTS.clear()
            add_virtualhost('virtdomain1.org','lists.virtdomain1.org')
            add_virtualhost('virtdomain2.org','lists.virtdomain2.org')

        change DEFAULT_EMAIL_HOST to include the prefix 'lists' to the FQDN
        as in:
            DEFAULT_EMAIL_HOST = 'lists.defaultWebsite.com'

        change IMAGE_LOGOS from whatever default is to:
            IMAGE_LOGOS = /'icons'/ 

    4.  copy Mailman images over to default /icons/ directory for Apache

            cp /usr/share/images/mailman/*  /usr/share/apache/icons/.

    5.  Edit /etc/apache/httpd.conf

        for any <VirtualHost> you have configured, add in:
            ScriptAlias /mailman/  /usr/lib/cgi-bin/mailman/
        in the <VirtualHost> section.

        and in an appropriate place (not within a VirtualHost directive) in
        httpd.conf add in:

            <Directory /var/lib/mailman/archives>
                Options +FollowSymLinks
            </Directory>

        you'll need the above to get pipermail (archives) working.

    6.  Get this python script:

        If you are installing via Debian apt-get this section is probably
        mostly done for you, but check anyway.

        http://www.gurulabs.com/files/postfix-to-mailman-2.1.py

        and drop it in /etc/mailman/ and rename it without the version number

            mv postfix-to-mailman-x.xx.py  postfix-to-mailman.py

        edit it by changing the entry for MailmanHome
             MailmanHome = "/var/lib/mailman"; 
        
        the Mailman home directory is where the lists are kept.

        Then cd to /usr/lib/mailman/bin and symlink back to
        postfix-to-mailman.py

            cd /usr/lib/mailman/bin
            ln -s /etc/mailman/postfix-to-mailman.py

    7.  Next go to /etc/mailman/postfix-to-mailman.py and read all of the
        comments/instructions.

        Note that in the recommended changes to /etc/postfix/master.cf, that
        you must set the uid:gid as list:list, not as mailman:mailman.
        This is probably specific to Debian only as the deb package has
        Mailman using 'list' as UID/GID where source versions of Mailman
        probably have 'mailman' as a default UID.

        Note also that in the changes to master.cf, you need to change the
        argv argument to point to /etc/mailman/postfix-to-mailman.py.

        This is also a good time to:

            chmod 755 /etc/mailman/postfix-to-mailman.py
            chown root:list /etc/mailman/postfix-to-mailman.py

        The instructions in postfix-to-mailman.py point out how to set up
        /etc/postfix/tranport and mail.cf.  You can do it that way, but here's
        a suggested alternative that works quite well:

        A. Create a new file /etc/mysql-virtual_lists_transports.cf with
        content as follows:

            user = vmail
            password = xxxxxxxx
            dbname = provider
            table = lists
            select_field = transport
            where_field = domain
            hosts = 127.0.0.1

        B.  Make entries into your /etc/postfix/main.cf file as follows:

            transport_maps = mysql:/etc/postfix/mysql-virtual_lists_transport.cf
            relay domains = lists.virtdomain1.org lists.virtdomain2.org ...
            mailman_destination_recipient_limit = 1

        C.  Make an entry into your /etc/postfix/master.cf file as follows:

            # following added for mailman
            # see http://www.gurulabs.com/files/postfix-to-mailman-2.1.py
            mailman unix  -       n       n       -       -       pipe
                flags=FR user=list 
                argv=/etc/mailman/postfix-to-mailman.py ${nexthop} ${user}

        D.  In your provider database, make a new table called lists.  This
        table, in combination with the transport_maps setting in main.cf, will
        cause incoming email to be routed to Mailman (via the
        postfix-to-mailman.py script).

            CREATE TABLE lists (
              domain varchar(80) NOT NULL,
              transport varchar(80) NOT NULL default 'mailman:',
              PRIMARY KEY  (domain)
            ) ENGINE=MyISAM;

        E.  Populate the lists table:

                domain                          transport
                ------                          -----
                lists.virtdomain1.org           mailman:
                lists.virtdomain2.org           mailman:

            Note all entries will have a value of mailman: in the transport
            column.  This might seem superfluous as far as database usage is
            concerned, but it keeps things neat and organized since we're
            assuming the Admin wants to do most things via the database rather
            than flat files in /etc/postfix.

    8.  Make sure you have a DNS entry in your DNS server for
        lists.virtdomain1.org, or at least a wildcard entry, that resolves to
        virtdomain1.org.

    9.  Restart Apache and Mailman (/etc/init.d/mailman restart).

    10. To create a new list for one of the virtual websites, at the prompt
        execute:

        newlist myNewList@lists.virtdomain1.org

        It will prompt you for a couple things that are obvious.  Make sure
        you include the 'lists' prefix before the FQDN, as having 'lists'
        there is what makes this whole thing work via the python script we put
        in -- /etc/mailman/postfix-to-mailman.py.

        You should get an email regarding the newly created list you
        just made.

        Note also that simply executing 'newlist --help' gives some help too.
        Also, reading the docs at /usr/share/docs/mailman is a good idea too.
        
        You should now be able to see your admin page at:
        http://lists.virtdomain1.org/cgi-bin/mailman/admin/myNewList

    11. In your provider database, in the table forwardings, now would be an
    appropriate time to make a forwarding entry for your new list:

        myNewList@virtdomain1.org   myNewList@lists.virtdomain1.org

    So while the beginning of this document insisted that you set up the
    Mailman lists using the prefix 'lists' with the FQDN, you don't have to
    leave it that way.  Just use a forward.

    12. Thing should be working and you should be able to subscribe new users
        and send emails to be posted, etc.  Try sending test posts and
        watching /var/log/syslog or wherever you have you email logs set up
        and watching for errors as the test posts go through Postfix.  It's
        best to watch this live using 'tail -f /var/log/syslog'.

    13. Good luck!


A german blog entry about mailman and virtual domains

http://www.allweil.net/blog/item/115/


Gasper Zejn sent a patch for mailman to keep rejecting mail for unexisting users

I've used your sarge postfix 2.0 tutorial to put up a mail server. But I needed mail lists too, but didnt want to lose postfix' ability to reject mail that is sent to unexisting users.

I modified python a bit, so it creates an address map instead of alias map, check the attached patch. It was made against the current sarge mailman. It's not the prettiest solution, but it works very well.

mailman-2.1.5-8_postfix-reject.patch

Certificates

Tilo Ermlich found a way to convert the SSL certificate to a format readable by Windows/Outlook:

cd /etc/ssl/postfix

openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -certfile demoCA/cacert.pem -name "email services" -out mailcert.p12
Enter Export Password:a password that is asked for when installing the certificate in Windows
Verifying - Enter Export Password:same password again

The certificate must be copied to the Windows computer and installed by right-clicking the icon and selecting "Install PFX". During the import you are getting asked for the password and which certificate storage should be used. Finally tell Outlook to use a "secure connection (SSL)" on port 25.


Hendrik P. sent further hints to use the generated SSL certificate for POP/IMAP too

I found it on http://www.trekweb.com/~jasonb/articles/exim4_courier/courierimap.html

You just need to change /etc/courier/imapd.cnf and /etc/courier/pop3d.cnf and set the value for CN to your own domain (like in the Postfix certificate).

Next remove the pop3d.pem and imapd.pem and re-create them using mkpop3dcert and mkimapdcert.

Transport maps

For those who would like to control the transport_maps from MySQL, too, here is a contribution from Jon Cox:

It might be nice if you also set up transport_maps within /etc/postfix/main.cf so that you had:

transport_maps = proxy:mysql:/etc/postfix/mysql-virtual_transports.cf

And then create a table for it in MySQL by issuing the following SQL command:

CREATE TABLE transport (
  domain varchar(128) NOT NULL default '',
  transport varchar(128) NOT NULL default '',
  UNIQUE KEY domain (domain)
) TYPE=MyISAM;

And a corresponding database mapping definition for it:

user = provider_admin
password = ...
dbname = provider
table = transport
select_field = transport
where_field = domain
hosts = 127.0.0.1

Script to create new user accounts

Marc sent this shell script to simplify creating new email accounts:

I've made a bash script to create new users. My problem was that the maildir of the new user is only created when this user recieves the first mail so, until this user recieves his first mail he's not able to log in (it recieves an error saying that the maildir doesn't exists). So I managed to do a script to create an user account and then send to this user a welcome mail. This script detects if the domain exisit and create it if necessary. Here is my script:

marc-create-user.sh

This script also creates the spam folder in the user's directory tree. But be aware, that you need a welcome message text file and a spam folder in maildir format

Selectively disabling individual forwardings

Michael Siebenborn sent this proposal:

I have added a way to comfortably deactivate individual forwardings. In the respective tables I added a column "status" that gets considered by the SQL queries Postfix does. Add this line to the appropriate mapping configuation files (e.g. mysql_virtual_alias_maps.cf):

additional_conditions = and status = '1'

Using the Sarge database scheme in the Etch tutorial

Tomas Bakke's suggestion:

The new layout of the database in Etch tutorial did not suite me.
I wanted to get the new setup with Dovecot and Postfix, but keep my old
database (provider) from the Sarge tutorial.

So I customized the mysql-* files for postfix and thought maybe others may
want the same thing.

Here goes:

## mysql-email2email.cf ##
user = mailuser
password = not_my_real_pw
hosts = 127.0.0.1
dbname = provider
query = SELECT email FROM users WHERE email='%s'

## mysql-virtual-alias-maps.cf ##
user = mailuser
password = not_my_real_pw
hosts = 127.0.0.1
dbname = provider
query = SELECT destination FROM forwardings WHERE source='%s'

## mysql-virtual-mailbox-domains.cf ##
user = mailuser
password = not_my_real_pw
hosts = 127.0.0.1
dbname = provider
query = SELECT 1 FROM domains WHERE domain='%s'

## mysql-virtual-mailbox-maps.cf ##
user = mailuser
password = not_my_real_pw
hosts = 127.0.0.1
dbname = provider
query = SELECT 1 FROM users WHERE email='%s'

## dovecot-sql.conf ##
driver = mysql
connect = host=127.0.0.1 dbname=provider user=mailuser
password=not_my_real_pw
default_pass_scheme = PLAIN
password_query = SELECT email as user, password FROM users WHERE email='%u';


and that's it. Same DB layout as in sarge, but working on Postfix and
Dovecot.

WorkaroundOrg: PostfixTutorialContributions (last edited 2007-11-13 07:50:22 by ChristophHaas)