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
http://syscp.de (A web interface for configuring mail/web servers)
http://www.xs4all.nl/~jaspersl/howto/ (An alternative to amavis - clamsmtp and maildrop) [Jasper Slits]
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
Use an entry in the forwardings table to forward email for a certain user to the email address user@domain.tld@autoreply.domain.tld
Add an entry to the transport file that sends email for the doman autoreply.domain.tld to the autoreply: transport service:
autoreply.domain.tld autoreply:
Add a service to the master.cf like this:
autoreply unix - n n - - pipe flags= user=mailer argv=/usr/local/bin/autoreply $sender $recipient
- Create an executable batch script in
/usr/local/bin/autoreply: mail -s"Zur Zeit im Urlaub" -a"From: <$2>" $1 < /etc/postfix/autoreply.txt
Put an autoreply text into the file /etc/postfix/autoreply.txt
- Reload Postfix
Another contribution (real name of the author unknown)
Here is how it works.
Virtual-User sets Away status to on.-> activates auto-responses for that user (php+mysql..not implement in script)
- Auto Response runs every X minutes, depending on what you set in crontab
- if the script sees that a user has set away status on, then check in that user's mailbox for new mail, if new mail found, respond to the email that virtual user is away. Move the new mail to cur mail to prevent the script from resending.
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:
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.
