Virtual Users And Domains With Postfix, Courier, MySQL And SquirrelMail (Debian Lenny)

Version 1.0
Author: Falko Timme
Last edited 02/20/2009

This tutorial is Copyright (c) 2009 by Falko Timme. It is derived from a tutorial from Christoph Haas which you can find at http://workaround.org. You are free to use this tutorial under the Creative Commons license 2.5 or any later version.

This document describes how to install a Postfix mail server that is based on virtual users and domains, i.e. users and domains that are in a MySQL database. I'll also demonstrate the installation and configuration of Courier (Courier-POP3, Courier-IMAP), so that Courier can authenticate against the same MySQL database Postfix uses.

The resulting Postfix server is capable of SMTP-AUTH and TLS and quota (quota is not built into Postfix by default, I'll show how to patch your Postfix appropriately). Passwords are stored in encrypted form in the database (most documents I found were dealing with plain text passwords which is a security risk). In addition to that, this tutorial covers the installation of Amavisd, SpamAssassin and ClamAV so that emails will be scanned for spam and viruses. I will also show how to install SquirrelMail as a webmail interface so that users can read and send emails and change their passwords.

The advantage of such a "virtual" setup (virtual users and domains in a MySQL database) is that it is far more performant than a setup that is based on "real" system users. With this virtual setup your mail server can handle thousands of domains and users. Besides, it is easier to administrate because you only have to deal with the MySQL database when you add new users/domains or edit existing ones. No more postmap commands to create db files, no more reloading of Postfix, etc. For the administration of the MySQL database you can use web based tools like phpMyAdmin which will also be installed in this howto. The third advantage is that users have an email address as user name (instead of a user name + an email address) which is easier to understand and keep in mind.

This howto is meant as a practical guide; it does not cover the theoretical backgrounds. They are treated in a lot of other documents in the web.

This document comes without warranty of any kind! I want to say that this is not the only way of setting up such a system. There are many ways of achieving this goal but this is the way I take. I do not issue any guarantee that this will work for you!

 

1 Preliminary Note

This tutorial is based on Debian Lenny, so you should set up a basic Debian Lenny server installation before you continue with this tutorial (e.g. as shown in the chapters 1 -7 of this tutorial: The Perfect Server - Debian Lenny (Debian 5.0) [ISPConfig 2]). The system should have a static IP address. I use 192.168.0.100 as my IP address in this tutorial and server1.example.com as the hostname.

 

2 Install Postfix, Courier, Saslauthd, MySQL, phpMyAdmin

To install Postfix, Courier, Saslauthd, MySQL, and phpMyAdmin, we simply run

apt-get install postfix postfix-mysql postfix-doc mysql-client mysql-server courier-authdaemon courier-authlib-mysql courier-pop courier-pop-ssl courier-imap courier-imap-ssl postfix-tls libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql openssl phpmyadmin apache2 libapache2-mod-php5 php5 php5-mysql libpam-smbpass

You will be asked a few questions:

New password for the MySQL "root" user: <-- yourrootsqlpassword
Repeat password for the MySQL "root" user: <-- yourrootsqlpassword
Create directories for web-based administration? <-- No
General type of mail configuration: <-- Internet Site
System mail name: <-- server1.example.com
SSL certificate required <-- Ok
Workgroup/Domain Name: <-- WORKGROUP
Modify smb.conf to use WINS settings from DHCP? <-- No
Web server to reconfigure automatically: <-- apache2

 

3 Apply The Quota Patch To Postfix

We have to get the Postfix sources, patch it with the quota patch, build new Postfix .deb packages and install those .deb packages:

apt-get build-dep postfix

cd /usr/src
apt-get source postfix

(Make sure you use the correct Postfix version in the following commands. I have Postfix 2.5.5 installed. You can find out your Postfix version by running

postconf -d | grep mail_version

The output should look like this:

server1:/usr/src# postconf -d | grep mail_version
mail_version = 2.5.5
milter_macro_v = $mail_name $mail_version
server1:/usr/src#

)

wget http://vda.sourceforge.net/VDA/postfix-2.5.5-vda-ng.patch.gz
gunzip postfix-2.5.5-vda-ng.patch.gz
cd postfix-2.5.5
patch -p1 < ../postfix-2.5.5-vda-ng.patch
dpkg-buildpackage

You might see a warning like this at the end of the dpkg-buildpackage command:

dpkg-buildpackage: warning: Failed to sign .dsc and .changes file

You can ignore this message.

Now we go one directory up, that's where the new .deb packages have been created:

cd ..

The command

ls -l

shows you the available packages:

server1:/usr/src# ls -l
total 5880
drwxr-xr-x 19 root root    4096 2009-02-20 14:15 postfix-2.5.5
-rw-r--r--  1 root src   236910 2009-02-20 14:12 postfix_2.5.5-1.1.diff.gz
-rw-r--r--  1 root src     1178 2009-02-20 14:12 postfix_2.5.5-1.1.dsc
-rw-r--r--  1 root src     3695 2009-02-20 14:17 postfix_2.5.5-1.1_i386.changes
-rw-r--r--  1 root src  1233138 2009-02-20 14:17 postfix_2.5.5-1.1_i386.deb
-rw-r--r--  1 root src  3157877 2008-09-02 23:18 postfix_2.5.5.orig.tar.gz
-rw-r--r--  1 root src    58389 2008-09-06 05:02 postfix-2.5.5-vda-ng.patch
-rw-r--r--  1 root src    41572 2009-02-20 14:17 postfix-cdb_2.5.5-1.1_i386.deb
-rw-r--r--  1 root src   141394 2009-02-20 14:17 postfix-dev_2.5.5-1.1_all.deb
-rw-r--r--  1 root src   915978 2009-02-20 14:17 postfix-doc_2.5.5-1.1_all.deb
-rw-r--r--  1 root src    48934 2009-02-20 14:17 postfix-ldap_2.5.5-1.1_i386.deb
-rw-r--r--  1 root src    43512 2009-02-20 14:17 postfix-mysql_2.5.5-1.1_i386.deb
-rw-r--r--  1 root src    43448 2009-02-20 14:17 postfix-pcre_2.5.5-1.1_i386.deb
-rw-r--r--  1 root src    43586 2009-02-20 14:17 postfix-pgsql_2.5.5-1.1_i386.deb
server1:/usr/src#

Pick the postfix and postfix-mysql packages and install them like this:

dpkg -i postfix_2.5.5-1.1_i386.deb postfix-mysql_2.5.5-1.1_i386.deb

 

4 Create The MySQL Database For Postfix/Courier

Now we create a database called mail:

mysqladmin -u root -p create mail

Next, we go to the MySQL shell:

mysql -u root -p

On the MySQL shell, we create the user mail_admin with the passwort mail_admin_password (replace it with your own password) who has SELECT,INSERT,UPDATE,DELETE privileges on the mail database. This user will be used by Postfix and Courier to connect to the mail database:

GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost' IDENTIFIED BY 'mail_admin_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost.localdomain' IDENTIFIED BY 'mail_admin_password';
FLUSH PRIVILEGES;

Still on the MySQL shell, we create the tables needed by Postfix and Courier:

USE mail;

CREATE TABLE domains (
domain varchar(50) NOT NULL,
PRIMARY KEY (domain) )
TYPE=MyISAM;

CREATE TABLE forwardings (
source varchar(80) NOT NULL,
destination TEXT NOT NULL,
PRIMARY KEY (source) )
TYPE=MyISAM;

CREATE TABLE users (
email varchar(80) NOT NULL,
password varchar(20) NOT NULL,
quota bigint(20) DEFAULT '10485760',
PRIMARY KEY (email)
) TYPE=MyISAM;

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

quit;

As you may have noticed, with the quit; command we have left the MySQL shell and are back on the Linux shell.

The domains table will store each virtual domain that Postfix should receive emails for (e.g. example.com).

domain
example.com

The forwardings table is for aliasing one email address to another, e.g. forward emails for info@example.com to sales@example.com.

source destination
info@example.com sales@example.com

The users table stores all virtual users (i.e. email addresses, because the email address and user name is the same) and passwords (in encrypted form!) and a quota value for each mail box (in this example the default value is 10485760 bytes which means 10MB).

email password quota
sales@example.com No9.E4skNvGa. ("secret" in encrypted form) 10485760

The transport table is optional, it is for advanced users. It allows to forward mails for single users, whole domains or all mails to another server. For example,

domain transport
example.com smtp:[1.2.3.4]

would forward all emails for example.com via the smtp protocol to the server with the IP address 1.2.3.4 (the square brackets [] mean "do not make a lookup of the MX DNS record" (which makes sense for IP addresses...). If you use a fully qualified domain name (FQDN) instead you would not use the square brackets.).

BTW, (I'm assuming that the IP address of your mail server system is 192.168.0.100) you can access phpMyAdmin over http://192.168.0.100/phpmyadmin/ in a browser and log in as mail_admin. Then you can have a look at the database. Later on you can use phpMyAdmin to administrate your mail server.

Share this page:

45 Comment(s)

Add comment

Comments

From: at: 2009-03-12 04:20:33

how can i write one script after user run this script they log in to root user?

 This script contain username and password of root.

 

 

From: sektalah at: 2010-06-22 14:10:31

Help me please...

How to integrated with postfixadmin...

 I'm try and ...

Error connection DROPED by IMAP

Thank's 

From: rieschl at: 2009-04-11 21:32:28

You should consider changing the permission of the "/etc/postfix/sasl/smtpd.conf" and "/etc/pam.d/smtp" files (chmod o= [filename]) so that the mysql mail-admin-password is not world-readable.

From: at: 2009-11-15 09:10:49

On Mail Clients (Outlook etc.) can the option SMTP Authentification not be activated. Is that correct?

From: Anonymous at: 2010-03-08 17:45:07

cuando entro por el telnet al puerto 25 me da el siguiente error:

 Trying 192.168.1.4...
Connected to 192.168.1.4.
Escape character is '^]'.
+OK Hello there.
user eduardo
+OK Password required.
pass eduardo
-ERR Login failed.

 he seguido el tutorial al pie de la letra, incluso lo hice dos veces, pero me sigue dando error

¿que puedo hacer?

From: Anonymous at: 2010-03-08 15:57:51

seguí los pasos al pie de la letra, pero cuando hago lo siguiente: Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. +OK Hello there. user eduardo +OK Password required. pass eduardo -ERR Login failed. ¿que puedo hacer? Saludos

From: Anonymous at: 2009-03-09 14:02:55

pls update dcc-dccproc

cd dcc-dccproc-1.3.103 acctually

From: White at: 2009-08-27 20:13:48

cd dcc-dccproc-1.3.102 this is now cd dcc-dccproc-1.3.115

 Falko it may be worth placing a note in the instructions that say check to see what level this program is and update the text prior to entering it into the shell.

White

From: hstoellinger at: 2009-11-17 10:19:22

cd dcc-dccproc-1.3.102 this is now cd dcc-dccproc-1.3.116

From: at: 2009-11-11 16:17:12

Please, someone, post the quota.txt file here, the website is no longer available

From: at: 2009-11-15 08:57:08

Hope, that helps:

 

#!/usr/bin/perl -w

# Author <jps@tntmax.com>
#
# This script assumes that virtual_mailbox_base in defined
# in postfix's main.cf file. This directory is assumed to contain
# directories which themselves contain your virtual user's maildirs.
# For example:
#
# -----------/
#            |
#            |
#    home/vmail/domains/
#        |          |
#        |          |
#  example.com/  foo.com/
#                   |
#                   |
#           -----------------
#           |       |       |
#           |       |       |
#         user1/   user2/  user3/
#                           |
#                           |
#                        maildirsize
#

use strict;

my $POSTFIX_CF = "/etc/postfix/main.cf";
my $MAILPROG = "/usr/sbin/sendmail -t";
my $WARNPERCENT = 80;
my @POSTMASTERS = ('postmaster@domain.tld');
my $CONAME = 'My Company';
my $COADDR = 'postmaster@domain.tld';
my $SUADDR = 'postmaster@domain.tld';
my $MAIL_REPORT = 1;
my $MAIL_WARNING = 1;

#get virtual mailbox base from postfix config
open(PCF, "< $POSTFIX_CF") or die $!;
my $mboxBase;
while (<PCF>) {
   next unless /virtual_mailbox_base\s*=\s*(.*)\s*/;
   $mboxBase = $1;
}
close(PCF);

#assume one level of subdirectories for domain names
my @domains;
opendir(DIR, $mboxBase) or die $!;
while (defined(my $name = readdir(DIR))) {
   next if $name =~ /^\.\.?$/;        #skip '.' and '..'
   next unless (-d "$mboxBase/$name");
   push(@domains, $name);
}
closedir(DIR);
#iterate through domains for username/maildirsize files
my @users;
chdir($mboxBase);
foreach my $domain (@domains) {
        opendir(DIR, $domain) or die $!;
        while (defined(my $name = readdir(DIR))) {
           next if $name =~ /^\.\.?$/;        #skip '.' and '..'
           next unless (-d "$domain/$name");
      push(@users, {"$name\@$domain" => "$mboxBase/$domain/$name"});
        }
}
closedir(DIR);

#get user quotas and percent used
my (%lusers, $report);
foreach my $href (@users) {
   foreach my $user (keys %$href) {
      my $quotafile = "$href->{$user}/maildirsize";
      next unless (-f $quotafile);
      open(QF, "< $quotafile") or die $!;
      my ($firstln, $quota, $used);
      while (<QF>) {
         my $line = $_;
              if (! $firstln) {
                 $firstln = 1;
                 die "Error: corrupt quotafile $quotafile"
                    unless ($line =~ /^(\d+)S/);
                 $quota = $1;
            last if (! $quota);
            next;
         }
         die "Error: corrupt quotafile $quotafile"
            unless ($line =~ /\s*(-?\d+)/);
         $used += $1;
      }
      close(QF);
      next if (! $used);
      my $percent = int($used / $quota * 100);
      $lusers{$user} = $percent unless not $percent;
   }
}

#send a report to the postmasters
if ($MAIL_REPORT) {
   open(MAIL, "| $MAILPROG");
   select(MAIL);
   map {print "To: $_\n"} @POSTMASTERS;
   print "From: $COADDR\n";
   print "Subject: Daily Quota Report.\n";
   print "DAILY QUOTA REPORT:\n\n";
   print "----------------------------------------------\n";
   print "| % USAGE |            ACCOUNT NAME          |\n";
   print "----------------------------------------------\n";
   foreach my $luser ( sort { $lusers{$b} <=> $lusers{$a} } keys %lusers ) {
      printf("|   %3d   | %32s |\n", $lusers{$luser}, $luser);
      print "---------------------------------------------\n";
   }
        print "\n--\n";
        print "$CONAME\n";
        close(MAIL);
}

#email a warning to people over quota
if ($MAIL_WARNING) {
        foreach my $luser (keys (%lusers)) {
           next unless $lusers{$luser} >= $WARNPERCENT;       # skip those under quota
           open(MAIL, "| $MAILPROG");
           select(MAIL);
           print "To: $luser\n";
      map {print "BCC: $_\n"} @POSTMASTERS;
           print "From: $SUADDR\n";
           print "Subject: WARNING: Your mailbox is $lusers{$luser}% full.\n";
           print "Reply-to: $SUADDR\n";
           print "Your mailbox: $luser is $lusers{$luser}% full.\n\n";
           print "Once your e-mail box has exceeded your monthly storage quota\n";
      print "your monthly billing will be automatically adjusted.\n";
      print "Please consider deleting e-mail and emptying your trash folder to clear some space.\n\n";
           print "Contact <$SUADDR> for further assistance.\n\n";
           print "Thank You.\n\n";
           print "--\n";
           print "$CONAME\n";
           close(MAIL);
        }
}

From: Den at: 2010-06-02 08:35:20

That helps a lot!

Thanks :)

Den

From: Anonymous at: 2009-10-21 07:45:34

Can sombody send me quota.txt or post some other link cose this isnt working

From: Marco at: 2009-10-01 12:36:19

The quata.txt page you mention is not there anymore (http://puuhis.net/vhcs/quota.txt).

By the way: this is a great tutorial!

Best regards.
Marco

From: timv at: 2010-11-22 08:00:08

Here is the info for quota.txt as the link in the document is dead.

 

11 Quota Exceedance Notifications

If you want to get notifications about all the email accounts that are over quota, then do this:

cd /usr/local/sbin/
nano quota.txt

#!/usr/bin/perl -w

# Author <jps@tntmax.com>
#
# This script assumes that virtual_mailbox_base in defined
# in postfix's main.cf file. This directory is assumed to contain
# directories which themselves contain your virtual user's maildirs.
# For example:
#
# -----------/
#            |
#            |
#    home/vmail/domains/
#        |          |
#        |          |
#  example.com/  foo.com/
#                   |
#                   |
#           -----------------
#           |       |       |
#           |       |       |
#         user1/   user2/  user3/
#                           |
#                           |
#                        maildirsize
#

use strict;

my $POSTFIX_CF = "/etc/postfix/main.cf";
my $MAILPROG = "/usr/sbin/sendmail -t";
my $WARNPERCENT = 80;
my @POSTMASTERS = ('postmaster@domain.tld');
my $CONAME = 'My Company';
my $COADDR = 'postmaster@domain.tld';
my $SUADDR = 'postmaster@domain.tld';
my $MAIL_REPORT = 1;
my $MAIL_WARNING = 1;

#get virtual mailbox base from postfix config
open(PCF, "< $POSTFIX_CF") or die $!;
my $mboxBase;
while (<PCF>) {
   next unless /virtual_mailbox_base\s*=\s*(.*)\s*/;
   $mboxBase = $1;
}
close(PCF);

#assume one level of subdirectories for domain names
my @domains;
opendir(DIR, $mboxBase) or die $!;
while (defined(my $name = readdir(DIR))) {
   next if $name =~ /^\.\.?$/;        #skip '.' and '..'
   next unless (-d "$mboxBase/$name");
   push(@domains, $name);
}
closedir(DIR);
#iterate through domains for username/maildirsize files
my @users;
chdir($mboxBase);
foreach my $domain (@domains) {
        opendir(DIR, $domain) or die $!;
        while (defined(my $name = readdir(DIR))) {
           next if $name =~ /^\.\.?$/;        #skip '.' and '..'
           next unless (-d "$domain/$name");
      push(@users, {"$name\@$domain" => "$mboxBase/$domain/$name"});
        }
}
closedir(DIR);

#get user quotas and percent used
my (%lusers, $report);
foreach my $href (@users) {
   foreach my $user (keys %$href) {
      my $quotafile = "$href->{$user}/maildirsize";
      next unless (-f $quotafile);
      open(QF, "< $quotafile") or die $!;
      my ($firstln, $quota, $used);
      while (<QF>) {
         my $line = $_;
              if (! $firstln) {
                 $firstln = 1;
                 die "Error: corrupt quotafile $quotafile"
                    unless ($line =~ /^(\d+)S/);
                 $quota = $1;
            last if (! $quota);
            next;
         }
         die "Error: corrupt quotafile $quotafile"
            unless ($line =~ /\s*(-?\d+)/);
         $used += $1;
      }
      close(QF);
      next if (! $used);
      my $percent = int($used / $quota * 100);
      $lusers{$user} = $percent unless not $percent;
   }
}

#send a report to the postmasters
if ($MAIL_REPORT) {
   open(MAIL, "| $MAILPROG");
   select(MAIL);
   map {print "To: $_\n"} @POSTMASTERS;
   print "From: $COADDR\n";
   print "Subject: Daily Quota Report.\n";
   print "DAILY QUOTA REPORT:\n\n";
   print "----------------------------------------------\n";
   print "| % USAGE |            ACCOUNT NAME          |\n";
   print "----------------------------------------------\n";
   foreach my $luser ( sort { $lusers{$b} <=> $lusers{$a} } keys %lusers ) {
      printf("|   %3d   | %32s |\n", $lusers{$luser}, $luser);
      print "---------------------------------------------\n";
   }
        print "\n--\n";
        print "$CONAME\n";
        close(MAIL);
}

#email a warning to people over quota
if ($MAIL_WARNING) {
        foreach my $luser (keys (%lusers)) {
           next unless $lusers{$luser} >= $WARNPERCENT;       # skip those under quota
           open(MAIL, "| $MAILPROG");
           select(MAIL);
           print "To: $luser\n";
      map {print "BCC: $_\n"} @POSTMASTERS;
           print "From: $SUADDR\n";
           print "Subject: WARNING: Your mailbox is $lusers{$luser}% full.\n";
           print "Reply-to: $SUADDR\n";
           print "Your mailbox: $luser is $lusers{$luser}% full.\n\n";
           print "Once your e-mail box has exceeded your monthly storage quota\n";
      print "your monthly billing will be automatically adjusted.\n";
      print "Please consider deleting e-mail and emptying your trash folder to clear some space.\n\n";
           print "Contact <$SUADDR> for further assistance.\n\n";
           print "Thank You.\n\n";
           print "--\n";
           print "$CONAME\n";
           close(MAIL);
        }
}
 

From: LightVision at: 2011-01-26 04:03:45

Those who are using your tutorial with copy and paste will stuck with vim and the certainly woul'nt know how to use it.

Default editor should be left as it is, in Debian: nano; advanced users would know how to change it anyway.

Besides the fact that I alway use dpkg -P vim-tiny vim-common tasksel tasksel-data and other few packages which are never used in a server.


In Debian Lenny 5.0.3 $pax='pax'; is enabled by default so it isn't necesary to include in /etc/amavis/conf.d/50-user


Two questions:

-For what is the cron? Ok, update database but with what and for what?

-How clamav update it's virus database ?


Thank You

From: Anonymous at: 2009-05-01 07:24:00

Hi, is it possible to put more than 1 address in field "destination" of  forwardings table? it doesn't seem to work. Can you help me?

 Very good work! thk

 

 

From: Anonymous at: 2009-09-15 07:43:25

You don't add several to the destination, you just insert a second row with all fields the same, but the destination differing.

 

from/to:

test@test.com/destination@test.com

test@test.com/otherdestination@test.com

 

If, for example, only the destination differs, you still insert a row for each unique forwarding.

 

Tim

From: Karolis Tamutis at: 2010-01-04 20:35:33

Please save yourself some frustration and know that passwords encrypted with crypt are salted, up to 8 characters long.

You may enter 9+ char password into PMA which would discard everything after 8th char, this can lead to some weird scenarions, like users being able to authenticate with other users passwords (which match up to 8 first chars).

In short: be aware of the 8 char limit, users with MySQL setup passwords such as 123456781 and 123456782 will be able to authenticate with either password.

From: at: 2010-02-01 14:42:16

If I setup as a local user an email like user@gmail.com then when I want to send an email to externaluser@gmail.com, postfix will try to send that email locally, because match gmail.com in mail_domains and it think that that is an internal email...

 Any idea how to solve this problem?

 

Thanks

MiK

From: Anonymous2 at: 2010-02-24 23:39:56

Hey!

When I try to send an email from yahoo/google to the email account which I inserted into the databases, the email isn't delivered.

The mail from yahoo says:

 test@mydomain.com: unknown user: test


From: tomiC at: 2010-09-30 14:57:03

When i try to start postfix /etc/init.d/postfix restart i get the following message in the mail.log

fatal: /etc/postfix/master.cf: line 83: missing "transport type" field

What's the problem?

regards

From: Pete at: 2011-03-08 01:46:54

This is a superb tutorial, I learnt so much from it, and best of all, it works!  Thanks very much for all your time and effort.

From: at: 2009-04-10 05:05:40

If you try to apt-upgrade the system, it will report that postfix and postfix-mysql should be upgraded too. To prevent this from happening you could run the following command (become root first):

 echo postfix hold | dpkg --set-selections && echo postfix-mysql hold | dpkg --set-selections

 This should prevent apt from upgrading the package (with upgrade or dist-upgrade).

 To restore it (when actually a new version comes out) use:

  echo postfix install | dpkg --set-selections && echo postfix-mysql install | dpkg --set-selections

 

From: Cory LYnch at: 2009-11-11 12:15:42

ok so after following this tutorial completely for about an hour or so i finished went and restarted apache noticed the squirrellmail page wasnt loading or any of my other previous functional websites.

the errors apache are spiting at me are:

 [Wed Nov 11 12:01:55 2009] [info] mod_fcgid: Process manager 2031 started
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: insufficient configuration info to establish database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: child spawned but unable to open database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: insufficient configuration info to establish database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: child spawned but unable to open database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: insufficient configuration info to establish database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: child spawned but unable to open database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: insufficient configuration info to establish database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: child spawned but unable to open database link
[Wed Nov 11 12:01:55 2009] [notice] Apache/2.2.9 (Debian) mod_perl/2.0.4 Perl/v5.10.0 configured -- resuming normal operations
[Wed Nov 11 12:01:55 2009] [info] Server built: Jul 14 2009 20:03:28
[Wed Nov 11 12:01:55 2009] [debug] prefork.c(1032): AcceptMutex: sysvsem (default: sysvsem)
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: insufficient configuration info to establish database link
[Wed Nov 11 12:01:55 2009] [error] mod_log_sql: child spawned but unable to open database link

if you can help i would greatly appreciate it.

From: admin at: 2009-04-08 08:42:04

You probably made a syntax error when you edited the change_sqlpass configuration file:

http://www.howtoforge.com/forums/showthread.php?t=32673&highlight=syntax+error+squirrelmail

From: at: 2009-09-13 11:16:38

The mistake that I made was here:

$password_update_queries = array('UPDATE users SET password = %4 WHERE email = "%1"');

 

The line in the default config file is split over several lines:

 $password_update_queries = array(

                  'UPDATE users SET password = %4 WHERE email = "%1"'

                   );

 

So blindly copying and pasting resulted in me having a duplicate `);`.

From: Anonymous at: 2009-04-07 23:26:54

I only ran into two small problems:

Problem: postfix/tlsmgr[31109]: warning: request to update table btree:/var/spool/postfix/smtpd_scache in non-postfix directory /var/spool/postfix

Solution: Change both smtp*_tls_session_cache_database in /etc/postfix/main.cf from "$queue_directory" to "$data_directory".

# mkdir /var/spool/postfix/smtp_scache

# mkdir /var/spool/postfix/smptd_scache

# chown -R postfix /var/spool/postfix/smtp_scache

# chown -R postfix /var/spool/postfix/smtpd_scache

----------------------------------

 Problem: Blank page after squirrelmail login.

Solution: Well, it's not really a solution - more of a workaround.   Run /usr/sbin/squirrelmail-configure and remove the change_sqlpass plugin.  If someone discovers a real solution, please post it here.

From: Anonymous at: 2009-07-15 14:03:34

http://www.postfix.org/postconf.5.html#smtp_tls_session_cache_database

"As of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged."

I believe that /var/spool/postfix is not you data_directory.

From: A Happy Reader at: 2009-03-25 02:33:30

Hello! Your Guide is Great! i managed to put together a mail server! my only tiny problem is whit SquirrelMaill PW change feature. it says  "ERROR Could not make database connection"  So if you could plz help me out. I don't wana rush you its not so big problem :) And Tanks again.!   

From: at: 2009-07-01 11:47:07

Only 1 problem :

ERROR: Connection dropped by IMAP server.

From: hstoellinger at: 2009-11-17 12:03:54

Has anybody found a solution to this issue. The only thing I can think of regarding my own "walk" through this excellent tutorial is that this is my test system I am using a dynamic IP address established by my provider. Therefore I thought that using "localhost" as the FQDN might be appropriate. Is this assumption wrong? I do want to test everything before I go live on my production system.

Again, I don't remember ever going through a better tutorial than this one. Congratulations!

Any help would be greatly appreciated. As usual, I am pressed for time and the mailserver should go online within the coming two weeks.

Regards

H. Stoellinger

From: fulm at: 2009-12-18 13:16:32

someone has a solution to solve the problem?

From: mitja at: 2009-11-20 01:29:49

ERROR: Connection dropped by IMAP server.

 

I get the same problem... Any idea how to solve this? It seems i'm not the only one with the problem

From: Fejame at: 2010-04-27 18:15:30

ERROR: Connection dropped by IMAP server.

login squirrelmail??

 

From: Anonymous at: 2009-09-18 01:24:44

same problem

From: Anonymous at: 2009-08-29 06:57:28

Same problem here

From: Yogalu at: 2010-11-05 14:01:01

Well, i had the same problem as all you guys...

 I did some testing and log checking

 tail -f /var/log/mail.log &

 which kept giving me:

authdaemond: failed to connect to mysql server (server=localhost, userid=mail_admin): Access denied for user 'mail_admin'@'localhost' (using password: YES)

 So in the end (and with a little help from another page) i found out there was a 'SPACE' behind the password in the file  /etc/courier/authmysqlrc

So edit that file, make sure there is no space behind the password and restart the authdaemon

/etc/init.d/courier-authdaemon restart

And try again.

From: ifos at: 2010-07-15 05:32:47

maildirmake /home/vmail/example.com/sales

chown -hR vmail:vmail /home/vmail/example.com/sales

From: catchu at: 2011-04-26 16:50:25

tail -f /var/log/mail.log &

 I found:
failed to connect to mysql server (server=localhost, userid=mail_admin): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'

 So I have to excute:
ln -s  /tmp/mysql.sock  /var/run/mysqld/mysqld.sock

But it still doesn't work.

Then:
maildirmake /home/vmail/example.com/sales
chown -hR vmail:vmail /home/vmail/example.com/sales


it works :)

 

THX to ifos & Yogalu.

 

From: Anonymous at: 2010-03-12 09:45:12

Hi,

thanks for this really great howto, I appreciate the work and knowledge given here.

I would like to add two notes:

ClamAV is, as all on-access virus scanners, very ressource intensive. After testing it on a general purpose webserver hosted on vps, I decided to remove it to have more ram for the apache processes.

The command:
postconf -e 'mydestination = server1.example.com, localhost, localhost.localdomain'
did not work in my case.  Yes, I have replaced "server1.example.com" with the correct FQDN. No mail got through postfix and mailboxes were not created, which triggered the Squirrelmail error "Connection dropped by IMAP server". I was able to fix this by altering the command to:
postconf -e 'mydestination = '
Sorry, I don't know why, maybe because of double clarifications of the hostname there and in the database. I use the hostname of the mailserver also in the virtual users database, to create email adresses for this domain. Now it's working.

Thanks again for the great work.

Best Regards
Anonymous

From: catchu at: 2011-04-27 15:12:46

 I couldn't receive mail too and found the following when ’tail -f /var/log/mail.log &‘

warning: do not list domain ltns.info in BOTH mydestination and virtual_mailbox_domains

 Then I modified /etc/postfix/main.cf as you mentioned.  It works.  :)

'mydestination = '

Thank you, and falko's great hwoto.

From: Niklas C Aden at: 2011-01-31 12:07:49

Hey, all is good!

Except one thing, when I try to enter the squirrelmail it just gives me a blank page.

I've checked the apache2 log file and the mail.log file without success, there's simply no error msg when I try to sign in :/
Tried it with 2 different accounts in 2 different domains, just to see what could cause it.

From: michael at: 2011-02-24 17:01:59

Amavis-ng won't scan mails in that configuration. At least not the current version ( amavisd-new-2.6.4 ) on debian squeeze.

As it only scans outgoing mails it needs to determine which domains are local. You need to edit the file /etc/amavis/conf.d/50-user and add the following lines (replacing your password off course):

 @lookup_sql_dsn = (
    ['DBI:mysql:database=mail;host=127.0.0.1;port=3306',
     'mail_admin',
     'mail_admin_password']);

$sql_select_policy = 'SELECT domain FROM domains WHERE CONCAT("@",domain) IN (%k)';


From: dynamike at: 2011-10-05 13:19:33

Hey,

first of all, thank you so much for this great tutorial. My mail infrastructure is up and running.

What I am wondering is how and which server-side filtering solution can be integrated to e.g. move the emails marked as SPAM etc. to specific folders.

Any help more than appreciated.

Cheers,

Dynamike