If you are running Debian-Woody (Postfix 1.x) please stick to the Woody tutorial. This part is for Sarge/Sid users only!
Import Warning!
The SASL library from version 2.1.16 upwards has changed fundamentally in
its behavior. This has been reported as bug 248333
and will hopefully be fixed soon. Until then please do not upgrade to higher
versions than 2.1.15. If you need the package to downgrade then get them from
here and "dpkg -i ..." them. (Thanks to Jesper
Krogh.) Also important to know: the new Postfix packages (version 2.1.3)
are available. However these demand the newer SASL versions. Until
this is resolved (I have already mailed the package maintainer)
please do not update the Postfix packages higher than 2.0!
You have been warned.
Obviously you won't want to waste hours just to discover that the result is not what you expected. So let me draw a quick picture of what you will get when you follow these instructions. Imagine you run a mail server where you receive emails for many different users on many different domains. Of course you can add a system account (in /etc/passwd) for every user and administer a large number of aliases. This approach may appear feasible but after a while you will get tired of users asking for new aliases. Plus you rip holes in your system because every system account is a potential security risk.
The solution described below uses MySQL as a database containing all the information about your users, their passwords, the domains and email forwardings. There is even a whole SourceForge project that provides a management web interface based on this setup if you don't want to add users to the database manually. Your users will be able to receive email on your server, fetch it via POP3 or IMAP and even use any web browser to read email using a web mail interface. Of course the users can send email as well by using authenticated SMTP. And finally you can filter all your incoming email for spam and viruses. All this is done using free tools (licensed under the GNU public license) so you won't need to spend a buck.
Make sure you have these tools ready before you begin:
I tried to take to care not to miss anything. And a number of people has already confirmed that this howto works. But alot of common mistakes can keep you occupied. There is a dedicated troubleshooting chapter later on that will help you identify the cause and give a solution. Other resources are the postfix-users mailing list or feel welcome at the IRC channel #postfix at freenode.net. I will attend there as <ChrisH>. Please understand that I can't give you personal support via email. I have a life, too.
Don't be scared. The setup is nothing for the faint hearted but - once you got it up - very nifty and reliable. A funny jester on the postfix-users mailing list wondered why it took me more than 15 minutes to set it up. But be assured that there are hardly any people that do this setup while waiting for the bus.
The whole setup depends on different software components that play together nicely. Let me clarify what each of them does:
My goal is to have as few information as possible about a virtual user. Users are dumb (who wants to doubt that) and can't remember much information. In this case I want their username to be identical to the email address.

As usual the software you need is already packaged for Debian. So all you need to do is 'apt-get install' these packages:
Your first step will be to create the database that stores all the information. Please first grab this SQL dump and throw it into MySQL to create all necessary database structures automatically. Browse your new database with phpmyadmin to see what tables you have received. I will now describe the purpose of each database table.
This table defines local aliases. Use it to forward all email to "root" to another (virtual) user. Keep in mind that this is for local delivery only - you cannot alias virtual delivery. See man 5 aliases to learn more.
| column | content |
|---|---|
| id | A unique index number |
| alias | Local part (not the domain) of an email address |
| destination | Where to forward email for the above local user |
| column | content |
|---|---|
| id | A unique index number |
| A user name (user@), a domain name (@domain.tld) or a complete email address (user@domain.tld) | |
| destination | The new email address of the user |
Postfix will query the transport table to find out whether you want to do anything special with email for this domain. You can use this feature to forward all emails for a certain domain to another SMTP server. You don't need to put your virtual or local domains here. This table is usually just empty. Eager to know more? Read man 5 transport.
| column | content |
|---|---|
| id | A unique index number |
| domain | A user name (user@), a domain name (@domain.tld) or a complete email address (user@domain.tld) |
| destination | The new email address of the user |
Still awake? Okay, let's get to a more interesting table. The virtual table is the central place to store information on virtual mail redirection. Imagine you have a user that wants different email addresses that he wants all be forwarded to a single address. Like this: all email for info@domain.tld, support@domain.tld and service@domain.tld needs to be forwarded to jack@domain.tld. Then this table must contain three rows each forwarding from the email address to jack@domain.tld. man 5 virtual will teach you more.
| column | content |
|---|---|
| id | A unique index number |
| A user name (user@), a domain name (@domain.tld) or a complete email address (user@domain.tld) you wish to have email forwarded for | |
| destination | The email address of the user who will receive these emails |
Another very important table. I promised that you will no longer need a system account for every email user who has a password. Now this table will hold all this data usually found in /etc/passwd. Let's see.
| column | content |
|---|---|
| id | A unique index number |
| The complete email address (user@domain.tld) of the virtual user. This field is also used as a login name. | |
| password | The access password (pop3, imap, smtp-auth or webmail) of this user. It is stored in encrypted password (MD5 hashed) just like your /etc/passwd. The MySQL encrypt() function also produces this format. |
| uid | User ID of this user. Although you can assign each user a unique UID (if you want to enforce quotas for every user) I recommend assigning the same UID for all users. The UID defaults to 1008 if you used the above MySQL dump. |
| gid | The Group ID of this user. Same think as for the UID. This also defaults to 1008. |
| homedir | Every user needs a home directory - even virtual users. This directory defaults to /home/vmail (vmail=virtual mail). You are free to put this directory anywhere you like. And don't worry that all users seem to have to same home directory. Emails are still delivered in subdirectories of /home/vmail. See the next entry: |
| maildir | The maildir is the place in the homedir (see above) where emails for this user will be stored. I prefer to store it in a directory named like the email address. Example: "user@domain.tld/". Have you noticed the trailing slash? This tells the delivery system to use the maildir format (subdirectories called tmp, new and cur). If you omit the slash you will get emails delivered in mbox format (single file). I will assume that you will use the maildir format because courier (needed for POP3, IMAP and the web mail interfce) expects it this way.. |
| quota | I would like to define quota restrictions so my users won't fill up my disk. Unfortunately nobody could yet tell me how to enforce quotas for virtual users. :( So this field is still unused. |
First you will need to add a system user account:
groupadd -g 1008 vmail![]()
useradd -g vmail -u 1008 vmail
You have also learned that all virtual users share a home directory. Of course you need to create it and give it the correct permissions:
mkdir /home/vmail![]()
chown vmail:vmail /home/vmail
Usually Postfix uses the files in /etc/postfix (aliases, relocated, virtual, transport, ...) to know how to handle emails. So your next step will be to make Postfix use your MySQL database.
Postfix has a very nice security feature: it can run in a chroot jail. "chroot'ed" means that the "/var/spool/postfix" directory is pretended to be "/" - so Postfix cannot move out of this secure subdirectory. Anyone who finds a security problem and messes with Postfix can only do harm to that very subdirectory and not screw your whole system. This however can drive system administrators nuts if Postfix needs to communicate with the (unreachable) outside (file system) world. (All this applies only if you run the database on the same system as your mail server - otherwise just skip this section.)
Postfix's chroot directory is /var/spool/postfix - so it can only access files that are below this directory. Obviously MySQL's socket (usually found in /var/run/mysqld/...) isn't in this path so we must find a workaround. Other tutorials suggest you disable the chroot feature. There are better ways than shooting holes in your system.
Either you make MySQL put its socket into /var/spool/postfix. This would mean you will need to add the following lines to the start section of the MySQL start/stop skript at /etc/init.d/mysql:
mkdir -p /var/spool/postfix/var/run/mysqld![]()
chown mysql /var/spool/postfix/var/run/mysqld![]()
ln /var/run/mysqld/mysqld.sock /var/spool/postfix/var/run/mysqld/mysqld.sock![]()
Or you make Postfix use TCP/IP communication to reach the database. If you specify your database server as 'localhost' Postfix will always try to use the UNIX socket on the file system. But if you use the real name (the hostname bound to an ethernet interface) Postfix will magically use network communication to reach the database. If this is your preferred way then do not forget to remove the line "skip-networking" from the /etc/mysql/my.cnf to enable the UDP listener. Just make sure that you use a firewall and/or limit the database access to your local host or you have just ripped open another security hole.
Your /etc/postfix/main.cf contains is Postfix's main configuration file. Please validate that your config looks similar to this. Words in bold mean you need to change them to fit your system.
# My local host name
myhostname = mailgateway
# My domain name
mydomain = domain.tld
# For what hosts/domains do we receive local email for.
# Do not list virtual domains here.
mydestination = $myhostname $mydomain localhost localhost.$mydomain
# Define the trustred networks. Postfix allows mail relaying for
# all client hosts in these networks.
mynetworks = 127.0.0.0/8, 131.59.12.0/24
# What recipient addresses do we accept email for.
# (permit_mynetworks: permit all mail from $mynetworks)
# (permit_sasl_authenticates: trust SMTP-AUTH users)
smtpd_recipient_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination
# Where are virtual mailboxes locate on the disk
virtual_mailbox_base = /home/vmail
# Where in the above directory are the user's mailboxes.
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf
# What virtual domains are there?
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_mailbox_domains.cf
# No virtual alias domains
# (which are used to forward virtual addresses to local users)
virtual_alias_domains =
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_alias_maps.cf
# What user/group ownerships are used when writing to the mailbox?
virtual_uid_maps = static:1008
virtual_gid_maps = static:1008
# SMTP AUTH (SASL)
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_sasl_security_options = noanonymous
# Be nice to brokenware like Outlook Express:
broken_sasl_auth_clients = yes
# Send all email through Amavis (leave it out if you don't want amavis)
content_filter = smtp-amavis:[127.0.0.1]:10024
All those virtual_ definitions are scary, hardly documented and misleading. With the introduction of Postfix 2.x virtual handling has changed a lot. I will try to shed a little light on it. Postfix 1.x used so called "postfix virtual domains". You had an entry "virtualdomain.tld anything" to tell Postfix that you want to receive email for this domain. This is deprecated.
Postifx 2.x now uses the virtual_mailbox_domains directive to tell what virtual domains are allowed to receive email. The parameter virtual_mailbox_maps tells Postfix where to find the mailbox files/directories for the virtual users.
There are another two new directives dealing with aliasing (forwarding). virtual_alias_maps defines where to forward email for virtual users. You can have all email for support@domain.tld be forwarded to info@domain.tld and receive email for both accounts at the info@ account. And finally the parameter virtual_alias_domains is... well, I must admit that I don't know what it's really for. Perhaps is allows whole domains to be forwarded one to another (like: @domain1.tld => @domain2.tld). It defaults to the same as the virtual_alias_maps (for Postfix 1.x compatability reasons) so until this secret is uncovered you better leave it that way.
You will have noticed that I used directives like ''virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf' in the main.cf. This tells Postfix to use the MySQL method to get the needed information and that 'mysql-virtual_mailbox_maps.cf' is a file where we define where the data is hidden in the database. So just copy and paste the following sections to the appropriate files in /etc/postfix/:
user = [database user]
password = [database password]
dbname = provider
table = users
select_field = maildir
where_field = email
hosts = [database server]
user = [database user]
password = [database password]
dbname = provider
table = domains
select_field = domain
where_field = domain
hosts = [database server]
user = [database user]
password = [database password]
dbname = provider
table = virtual
select_field = destination
where_field = email
hosts = [database server]
In theory you can also use MySQL tables for rarely used features like 'relocated' or 'transport' but it will be equally good to keep on using the files in /etc/postfix for that.
One important security notice: make sure these files are not accessible for everybody. Otherwise any user can read your database password from a local account. That should do it:
chmod o= /etc/postfix/mysql-*.cf
chgrp postfix /etc/postfix/mysql-*.cf
Imagine your users fetch their email using POP3. Now they need a way to send mails back via your mail server. For security reasons Postfix only allows users in the local (=$mynetwork) network to send emails. This means that their email clients provide a username and password to the mail server to make them "trusted". Most email cilents have this feature included. You obviously need this security measure if you don't want to be abused as an open relay by spammers.
There are different ways to offer authentication in conjunction with SMTP. The way I will describe here may sound totally insane but it seems to be the most common way. So give me a chance. When a road warrior (a user who is outside your local network) sends an email he contacts your Postfix mail server. Postfix then asks the 'saslauthdaemon' (a component of the courier mail server). The authentication daemon in turn checks the appropriate PAM (pluggable authentication module). And finally PAM queries the MySQL database to check the username and password. Weird, huh? But it works reliably in the end. (I was told that there is a patch that allows Postfix to query the database directly but I wanted to stick to the ready Debian packages.)
You already did this part by adding smtpd_sasl_auth_enable=yes to the /etc/postfix/main.cf. Nothing to do here.
Create a directory /etc/postfix/sasl. Then create a file smtpd.conf there and put these two lines into it:
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN
There are different ways to check the password. You just told SASL to use the autentication daemon (saslauthd).
Edit the file /etc/default/saslauthd so the following lines are not commented out:
START=yes
MECHANISMS="pam"
A stupid bug (#201826) in the sasl2-bin package forbids Postfix to access the /var/run/saslauthd directory if the user 'postfix' is not member of the 'sasl' group. Execute this line to fix it:
adduser postfix sasl
Another issue must be taken care of: the mux file (a pipe used for communicating with other processes) is stored outside the Postfix chroot jail by default. Just add the following line to the header of /etc/init.d/saslauthd to move it into the jail.
PARAMS="-m /var/spool/postfix/var/run/saslauthd"
Restart the daemon and make sure no old processes are running (ps ax | grep saslauthd must show only processes with the '-m ...' option).
The final step is to tell PAM to use the MySQL database. Edit the file /etc/pam.d/smtp and make it look like this:
auth required pam_mysql.so user=[database user] passwd=[database
password] host=[database server] db=provider table=users usercolumn=email
passwdcolumn=password crypt=1![]()
account sufficient pam_mysql.so user=[database user] passwd=[database password]
host=[database server] db=provider table=users usercolumn=email passwdcolumn=password
crypt=1![]()
This step if optional but I recommend you do it. It deals with securing authenticated SMTP. TLS is short for Transport Layer Security (RFC2246) and in short terms uses SSL (Secure Socket Layer) which encrypts the mail connection between the road-warrior and the mail server.
First you will need an SSL certificate. If you don't want to pay for one
from your favorite trustcenter you can well use a self-signed one. The only
drawback: the mail clients don't know about your CA (certificate authority)
and will spit out a warning to the user. Either tell the users to ignore the
warning or let them install the certificate on their computers. Making your
own certificate is very easy thanks to a script called mkx509cert
from Rene Mayrhofer. You can either install the freeswan
package and then find the script at /usr/lib/ipsec/mkx509cert or get it from
here. To generate the certificate you call this script
using these parameters:
key-length valid-days
key-file cert-file
self-signed country-code
state locality organisation
organisational-unit host-name
email-address
For a certificate that is valid for one year for smtp.domain.tld you would run something like this:
mkx509cert 2048 365 smtpd.key smtpd.cert true "" "" "" "" "" smtp.domain.tld support@domain.tld
You should end up with the two files "smtpd.key" (the private key file) and "smtpd.cert" (the certificate). Move these two files into /etc/postfix. Make sure at least the key file is only readable for the 'postfix' user or security will be seriously compromised.
Yet only a few lines need to get added to the main.cf to make Postfix allow TLS:
# Enable SASL authentication
smtpd_sasl_auth_enable = yes
# Enable TLS encryption
smtpd_use_tls = yes
# Disable anonymous login
smtpd_sasl_security_options = noanonymous
# Be nice to ancient Microsoft clients
broken_sasl_auth_clients = yes
# The location of the SSL certificate
smtpd_tls_cert_file = /etc/postfix/smtpd.cert
# The location of the SSL private key
smtpd_tls_key_file = /etc/postfix/smtpd.key
Run "postfix reload" to restart Postfix. When running a "telnet mailserver 25" and enter "EHLO anywhere.org" you should get a line reading "250-STARTTLS". Bingo - TLS is running.
The final step is now to tell the Courier POP3 daemon to use MySQL to access the username and password for authentication. First edit the file /etc/courier/authdaemonrc and change the directive authmodulelist to "authmysql" like this:
authmodulelist="authmysql"
Then you need to define the fields of the MySQL database table in /etc/courier/authmysqlrc like this:
MYSQL_SERVER [database server hostname]![]()
MYSQL_USERNAME [database admin user]![]()
MYSQL_PASSWORD [database admin password]![]()
MYSQL_PORT 0![]()
MYSQL_DATABASE provider![]()
MYSQL_USER_TABLE users![]()
MYSQL_CRYPT_PWFIELD password![]()
MYSQL_UID_FIELD uid![]()
MYSQL_GID_FIELD gid![]()
MYSQL_LOGIN_FIELD email![]()
MYSQL_HOME_FIELD homedir![]()
MYSQL_MAILDIR_FIELD maildir
Do not forget to restart the authdaemon process using "/etc/init.d/courier-authdaemon restart". If you like IMAP better you may also install "courier-imap" or "courier-imap-ssl" to provide IMAP services.
Of course your setup will need some control information to know about users and domains.
Filtering viruses out of incoming email has become quite easy. Even a large amount of spam can be kept outside automatically with little effort.
Make sure you have the 'amavisd-new' package installed. Don't be confused - amavis is not a virus scanner! It is a helper tool that receives email, processes it (checks it for viruses and spam) and hands it back to the mail server. It will need a command-line virus scanner.
First you will need to tell Postfix to use amavis as a content filter. Add this line to the /etc/postfix/main.cf:
content_filter = smtp-amavis:[127.0.0.1]:10024
This will make Postfix send all received email out again on port 10024 to localhost. Apparently amavis is listening on this port and receive the emails via SMTP.
Then edit the /etc/postfix/master.cf to add the according service:
smtp-amavis unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o disable_dns_lookups=yes
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
After amavis has processed the email it will re-inject it into postfix on port 10025. Note that many postfix variables are blanked - most important of all the content_filter (because otherwise the mail would loop through amavis again and again).
You will need to configure amavis. Edit the /etc/amavis/amavisd.conf file and comment out the appropriate bypass directives (look for @bypass_virus_checks_acl and @bypass_spam_checks_acl). If you want to enable the virus scan feature you will also need to configure your command-line virus scanner (look for @av_scanners). I recommend installing ClamAV because it's free (GPL) and supported by amavis. To check if your virus scanner is working properly you can download the eicar.com test signature and attach it to an email.
AMaViS can do much more and is very customisable. I recommend browsing the configuration file and see what you want to do.
Now that you know how your users can get and send their emails via POP3, IMAP and SMTP you may wonder if there is a comfy way to give your users access to their mailbox via a web interface. The package you need is called "sqwebmail" - a web mail system that uses the Courier services and can be told (via PAMs) to use any authentication scheme. Install it using "apt-get install sqwebmail".
To make sqwebmail use your MySQL database you need to change the /etc/pam.d/webmail file like this:
auth required pam_mysql.so user=[database
user] passwd=[database password] host=[database
host] \
db=provider table=users usercolumn=email passwdcolumn=password crypt=1![]()
account sufficient pam_permit.so
There is a little bug in the sqwebmail package. It seems like you need to set the webmail binary suid root. Use this command to do it:
chmod u+s /usr/lib/courier/courier/webmail/webmail
You also need to make the webmail CGI, icons and the style sheet visible for your web users. Assumed that you use an Apache web server you just put these lines in the /etc/apache/httpd.conf and you are set:
Alias /sqwebmail /usr/share/sqwebmail![]()
ScriptAlias /webmail /usr/lib/courier/courier/webmail
Now access your web server like http://<hostname>/webmail/webmail and you should get a login dialog.
The delivery process isn't well documented. But by reading a few kilobytes of debug output I researched what steps Postfix takes to deliver an email:
| Action | SQL Query | Result |
|---|---|---|
| Who shall be the recipient of the email? | select destination from virtual where email='user@domain.tld' | Either 'username' (if email is delivered locally) or 'username@domain.tld' (if email is forwarded to another address). |
| Is a relocation defined for this email address? | select destination from relocated where email='user@domain.tld' | Either there is no entry (which means there is no relocation) or an email address to the new user's email address at another place. |
| What transport shall be used for this domain? | select destination from transport where domain = 'domain.tld' | This defined the transport mode. 'virtual:' means to use virtual domains. Postfix delivers locally if no entry is found. |
| Is a relocation defined for this user? | select destination from relocated where email = 'user' | Either there is no entry (which means there is no relocation) or an email address where all emails of this domain are forwarded to. |
| Is a relocation defined for this domain? | select destination from relocated where email = '@domain.tld' | Either there is no entry (which means there is no relocation) or an email address where all emails of this domain are forwarded to. |
| Where shall the email be delivered? | select maildir from users where email='user@domain.tld' and postfix='y' |
The file system location where the email is delivered. The result is added to the homedir entry. If the result has a trailing slash then the email will be delivered in this directory in maildir format. If it has no trailing slash then this is the file where the email will be appended in mailbox format. |
| Who will be the owner of this email file? | select uid from users where email = 'user@domain.tld' and postfix = 'y' | A numerical UID. This should default to the user id of the "vmail" user. |
| Who will be the group of this email file? | select gid from users where email = 'user@domain.tld' and postfix = 'y' | A numerical GID. This should default to the group id of the "vmail" user. |
Now that all your information is stored in a database you can change the
database the way you like. I wrote a little CGI-based web interface that allows
you to easily manage domains, users and even POP3/IMAP accounts. Feel free
to use it.
To make it fly you will need the following three files:
| File | Meaning |
|---|---|
| ispmailadmin | The main CGI file. Put this into your CGI directory and call it from your web browser (e.g. http://myserver/cgi-bin/ispmailadmin). Make sure this file is executable for your web server. Please verify if the configuration I define in the first lines of the Perl script suits your needs. |
| sqlutil.pm | This is a MySQL utility class in Perl which I use for most of my database applications. Put it into the same directory as the 'ispmailadmin' file. You will need to change the lines at the beginning to tell it the hostname, username and password for accessing your MySQL database server or it will not work. Make sure it is not readable by others for security reasons. |
| style.css | A CSS (cascading style sheet) file which should make the GUI look nice. It is not needed but you may want to copy it into your DocumentRoot path on the web server (or change a line in 'ispmailadmin' and put it somewhere else). |
Please note that the CGI expects to called in an authenticated directory. If you forget this you will get a "Nobody logged on" error message. Make sure that you installed the 'libapache-mod-auth-mysql' package. To make your Apache web server ask the user for a name and password before using the web GUI you can use the following configuration directives in your httpd.conf:
Auth_MySQL_Info databaseserver databaseuser databasepassword![]()
<Location /cgi-bin/ispmailadmin>![]()
AuthType Basic![]()
AuthName "Customer login"![]()
Auth_MySQL_DB provider![]()
Auth_MySQL_Password_Table customers![]()
Auth_MySQL_Username_Field customer![]()
Auth_MySQL_Password_Field password![]()
Auth_MySQL_Empty_Passwords off![]()
#Auth_MySQL_Scrambled_Passwords on![]()
Auth_MySQL_Encryption_Types Crypt_DES![]()
require valid-user![]()
</Location>
This assumes that you also have a MySQL table 'customers':
CREATE TABLE customers (
customer varchar(8) NOT NULL default '',
realname varchar(30) NOT NULL default '',
password tinytext NOT NULL,
PRIMARY KEY (customer)
) TYPE=MyISAM
In this table the customer and password fields are equivalent to the username and password fields your customers needs for logging in. The passwords must be encrypted by the ENCRYPT() function. The realname is the customers full name only used for display.
To make sure that a customer only changes the email aliases for his own domain(s) you must also create the table 'domains':
CREATE TABLE domains (
customer varchar(8) NOT NULL default '',
domain varchar(60) NOT NULL default ''
) TYPE=MyISAM
The customer field holds the same name as the field in the 'customers' table. The domain field holds the name of a domain this customers should gain access to. Of course there can be multiple entries if a customers has more than one domain.
There is a project on SourceForge called phpmywebhosting which uses a setup close to this tutorial. It's worth taking a look.
Sorry that I have no transition guide ready. Many things have changed. Please go through all the steps and check your configuration. At least you won't need to change your database format. Just add the table 'domains'.
The sasl2-bin package comes with a test tool called testsaslauthd. Run it like this:
testsaslauthd -u username@domain -p password -f /var/spool/postfix/var/run/saslauthd/mux -s smtp
If the result reads 0: OK "Success." then the authentication worked. Otherwise you will get 0: NO "authentication failed".
Try a "postmap -q domain.tld mysql:/etc/postfix/mysql-virtual_mailbox_domains.cf". You should get the domain name back out. If not please check the "domains" table if the domain is really listed there.
You may wonder why I introduced the extra step of using PAM during the SASL authentication. Unfortunately this seems to be necessary when you want to use encrypted passwords. Using the saslauthd.mysql directly means using plain text passwords (which I don't like).
This setup uses PAM (pluggable authentication modules) for authentication. PAM's drawback is that it can only return 'success' or 'failure'. CRAM-MD5 and DIGEST-MD5 would need to get cleartext passwords back. So you are limited to PLAIN authentication. I know that it's not the best idea to use encrypted passwords in the database and rely on plaintext authentication through the internet.
Using "proxy:" via the 'proxymap' process is a great feature. Unfortunately due to security limitations it can not be used for all lookup methods. The man page for proxymap(8) reads: "The proxymap server is not a trusted daemon process, and must not be used to look up sensitive information such as user or group IDs, mailbox file/directory names or external commands." Therefore the very important setting virtual_mailbox_base cannot be used via proxymap. So although proxymap should generally be used it does not solve our problems here.
I haven't set this up, yet. If you find a working solution please tell me what you did.
You forgot to edit the /etc/postfix/sasl/smtpd.conf.
Wrong password:
Dec 20 12:22:17 mx1 postfix/smtpd[12084]: connect from simon.workaround.org[212.12.58.136]
Dec 20 12:22:18 mx1 postfix/smtpd[12084]: warning: SASL authentication failure:
Password verification failed
Dec 20 12:22:18 mx1 postfix/smtpd[12084]: warning: simon.workaround.org[212.12.58.136]:
SASL PLAIN authentication failed
Correct password:
Dec 20 12:22:32 mx1 postfix/smtpd[12084]: A6B00624A2: client=simon.workaround.org[212.12.58.136], sasl_method=PLAIN, sasl_username=email@christoph-haas.de
Wrong password:
Dec 20 12:25:15 mx1 courierpop3login: LOGIN FAILED, ip=[::ffff:212.12.58.136]
Correct password:
Dec 20 12:24:18 mx1 courierpop3login: Connection, ip=[::ffff:213.39.145.214]
Dec 20 12:24:18 mx1 courierpop3login: LOGIN, user=email@christoph-haas.de,
ip=[::ffff:213.39.145.214]
Dec 20 12:24:18 mx1 courierpop3login: LOGOUT, user=email@christoph-haas.de,
ip=[::ffff:213.39.145.214], top=0, retr=0
Sure. Edit the file /etc/mysql/my.cnf, go to the [mysqld] section and append a line like "log = /var/log/mysql.log". Restart the MySQL daemon and you will get all queries logged into /var/log/mysql.log.
Your postfix server runs in a chroot jail and tries to connect to your MySQL server via the socket at /var/run/mysqld/mysqld.sock which is not inside the jail. See section "trapped in a jail".
Make sure you have added a trailing '/' (slash) to the mailbox paths. Plus you must not list your virtual domains in the $mydestination variable (defining local domains). Local domains have precedence over virtual domains!
Just remove your local domain from $mydestination in the /etc/postfix/main.cf and put it into the domains table.
Set the virtual_mailbox_limit at least as high as the message_size_limit. Example:
mailbox_size_limit = 15728640
message_size_limit = 10240000
virtual_mailbox_limit = 15728640
Sure. I hope people find this tutorial before they pull their hair out.
Well, ooookay. Just leave my name in there. :)
Other similar tutorials can be found at:
Okay, show's over, no refunds, you heard the robot...
Christoph Haas (last change: 20.06.2004 ) ( 8629 hits since 25.4.2005 )