Virtual Users And Domains With Postfix, Courier, MySQL And SquirrelMail (Mandriva 2009.0 i386) - Page 2
5 Create The MySQL Database For Postfix/Courier
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 a password of your choice) 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 that Postfix and Courier need:
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 INT(10) 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 [email protected] to [email protected].
source | destination |
[email protected] | [email protected] |
The users table stores all virtual users (i.e. email addresses, because theemail 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).
password | quota | |
[email protected] | 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.).
6 Configure Postfix
Now we have to tell Postfix where it can find all the information in the database. Therefore we have to create six text files. You will notice that I tell Postfix to connect to MySQL on the IP address 127.0.0.1 instead of localhost. This is because Postfix is running in a chroot jail and does not have access to the MySQL socket which it would try to connect to if I told Postfix to use localhost. If I use 127.0.0.1 Postfix uses TCP networking to connect to MySQL which is no problem even in a chroot jail (the alternative would be to move the MySQL socket into the chroot jail which causes some other problems).
Now let's create our six text files.
vi /etc/postfix/mysql-virtual_domains.cf
user = mail_admin password = mail_admin_password dbname = mail query = SELECT domain AS virtual FROM domains WHERE domain='%s' hosts = 127.0.0.1 |
vi /etc/postfix/mysql-virtual_forwardings.cf
user = mail_admin password = mail_admin_password dbname = mail query = SELECT destination FROM forwardings WHERE source='%s' hosts = 127.0.0.1 |
vi /etc/postfix/mysql-virtual_mailboxes.cf
user = mail_admin password = mail_admin_password dbname = mail query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s' hosts = 127.0.0.1 |
vi /etc/postfix/mysql-virtual_email2email.cf
user = mail_admin password = mail_admin_password dbname = mail query = SELECT email FROM users WHERE email='%s' hosts = 127.0.0.1 |
vi /etc/postfix/mysql-virtual_transports.cf
user = mail_admin password = mail_admin_password dbname = mail query = SELECT transport FROM transport WHERE domain='%s' hosts = 127.0.0.1 |
vi /etc/postfix/mysql-virtual_mailbox_limit_maps.cf
user = mail_admin password = mail_admin_password dbname = mail query = SELECT quota FROM users WHERE email='%s' hosts = 127.0.0.1 |
chmod o= /etc/postfix/mysql-virtual_*.cf
chgrp postfix /etc/postfix/mysql-virtual_*.cf
Now we create a user and group called vmail with the home directory /home/vmail. This is where all mail boxes will be stored.
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m
Next we do some Postfix configuration. Go sure that you replace server1.example.com with a valid FQDN, otherwise your Postfix might not work properly!
postconf -e 'myhostname = server1.example.com'
postconf -e 'mydestination = server1.example.com, localhost, localhost.localdomain'
postconf -e 'mynetworks = 127.0.0.0/8'
postconf -e 'virtual_alias_domains ='
postconf -e ' virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf'
postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf'
postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf'
postconf -e 'virtual_mailbox_base = /home/vmail'
postconf -e 'virtual_uid_maps = static:5000'
postconf -e 'virtual_gid_maps = static:5000'
postconf -e 'smtpd_sasl_auth_enable = yes'
postconf -e 'broken_sasl_auth_clients = yes'
postconf -e 'smtpd_sasl_authenticated_header = yes'
postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'
postconf -e 'smtpd_use_tls = yes'
postconf -e 'smtpd_tls_cert_file = /etc/postfix/smtpd.cert'
postconf -e 'smtpd_tls_key_file = /etc/postfix/smtpd.key'
postconf -e 'transport_maps = proxy:mysql:/etc/postfix/mysql-virtual_transports.cf'
postconf -e 'virtual_create_maildirsize = yes'
postconf -e 'virtual_maildir_extended = yes'
postconf -e 'virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_limit_maps.cf'
postconf -e 'virtual_mailbox_limit_override = yes'
postconf -e 'virtual_maildir_limit_message = "The user you are trying to reach is over quota."'
postconf -e 'virtual_overquota_bounce = yes'
postconf -e 'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps'
postconf -e 'inet_interfaces = all'
postconf -e 'alias_database = hash:/etc/postfix/aliases'
postconf -e 'alias_maps = hash:/etc/postfix/aliases'
Afterwards we create the SSL certificate that is needed for TLS:
cd /etc/postfix
openssl req -new -outform PEM -out smtpd.cert -newkey rsa:2048 -nodes -keyout smtpd.key -keyform PEM -days 365 -x509
Country Name (2 letter code) [GB]: <-- Enter your Country Name (e.g., "DE").
State or Province Name (full name) [Berkshire]: <-- Enter your State or Province Name.
Locality Name (eg, city) [Newbury]: <-- Enter your City.
Organization Name (eg, company) [My Company Ltd]: <-- Enter your Organization Name (e.g., the name of your company).
Organizational Unit Name (eg, section) []: <-- Enter your Organizational Unit Name (e.g. "IT Department").
Common Name (eg, your name or your server's hostname) []: <-- Enter the Fully Qualified Domain Name of the system (e.g. "server1.example.com").
Email Address []: <-- Enter your Email Address.
Then change the permissions of the smtpd.key:
chmod o= /etc/postfix/smtpd.key
7 Configure Saslauthd
Edit /etc/sasl2/smtpd.conf. It should look like this:
vi /etc/sasl2/smtpd.conf
# SASL library configuration file for postfix # all parameters are documented into: # /usr/share/doc/cyrus-sasl/options.html # The mech_list parameters list the sasl mechanisms to use, # default being all mechs found. #mech_list: plain login # To authenticate using the separate saslauthd daemon, (e.g. for # system or ldap users). Also see /etc/sysconfig/saslauthd. #pwcheck_method: saslauthd #saslauthd_path: /var/lib/sasl2/mux # To authenticate against users stored in sasldb. #pwcheck_method: auxprop #auxprop_plugin: sasldb #sasldb_path: /var/lib/sasl2/sasl.db pwcheck_method: authdaemond log_level: 3 mech_list: PLAIN LOGIN authdaemond_path:/var/lib/authdaemon/socket |
Then create the system startup links for Postfix and start Postfix, saslauthd, and courier-authdaemon:
chmod 755 /var/lib/authdaemon
chkconfig postfix on
/etc/init.d/courier-authdaemon start
/etc/init.d/postfix start
/etc/init.d/saslauthd start
8 Configure Courier
Now we have to tell Courier that it should authenticate against our MySQL database. First, edit /etc/courier/authdaemonrc and change the value of authmodulelist so that it reads
vi /etc/courier/authdaemonrc
[...] authmodulelist="authmysql" #authmodulelist="authpam authpwd authshadow" [...] |
Then edit /etc/courier/authmysqlrc. It should look exactly like this (again, make sure to fill in the correct database details):
cp /etc/courier/authmysqlrc /etc/courier/authmysqlrc_orig
cat /dev/null > /etc/courier/authmysqlrc
vi /etc/courier/authmysqlrc
MYSQL_SERVER localhost MYSQL_USERNAME mail_admin MYSQL_PASSWORD mail_admin_password MYSQL_PORT 0 MYSQL_DATABASE mail MYSQL_USER_TABLE users MYSQL_CRYPT_PWFIELD password #MYSQL_CLEAR_PWFIELD password MYSQL_UID_FIELD 5000 MYSQL_GID_FIELD 5000 MYSQL_LOGIN_FIELD email MYSQL_HOME_FIELD "/home/vmail" MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') #MYSQL_NAME_FIELD MYSQL_QUOTA_FIELD quota |
Then restart Courier:
/etc/init.d/courier-authdaemon restart
/etc/init.d/courier-imapd restart
/etc/init.d/courier-pop3d restart
By running
telnet localhost pop3
you can see if your POP3 server is working correctly. It should give back +OK Hello there. (type quit to get back to the Linux shell):
[root@server1 ~]# telnet localhost pop3
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
+OK Hello there.
quit
+OK Better luck next time.
Connection closed by foreign host.
[root@server1 ~]#