Prefix
Developing a solution for serving multiple domains on a single e-mail server can prove to be a challenge. I hope this can help those of you who are having trouble coming up with a good solution.
When developing a solution for the new services.x2studios.com server I had the following requirements to satisfy:
- Server must be fast and reliable
- User names must be unique to their domain
- POP3 and IMAP
- SMTP users must be authenticated
I almost immediately eliminated send mail from the list of candidate MTA's. The first solution I considered implementing was Virtual Domains and Users w/ Postfix / Courier-IMAP / MySQL. This is a good solution for many users, however I found Postfix to be almost as archaic as sendmail. I had previously used EXIM for my home FreeBSD server and was interested in giving it a try. Minimal research lead me to a site with a solution for Virtual Domains with Exim + Courier-IMAP + MySQL. This is an example that I borrowed a lot from when developing our solution.
Overview
This document describes how to set up Exim and Courier IMAP on a MySQL database in order to handle "virtual domains", which means here accepting mails for several domains which must not be local, but the MX record of the domain points to your server. All informations about the domains and the users are stored in a SQL-database. This article also covers how to enable SMTP authentication, setup and use the X2 mailAdmin PHP control panel and my random bitching.This article does not cover how to set up from scratch any of the above mentioned programs. They should already working, and need only to be adapted for this solution.
Just a side note: usernames are e-mail addresses in this solution (so the user name is joe@domain.com not joe).
Requirements
EXIM and Courier IMAP must be compiled with support for mysql (there are other ways, but I'm not going there)
Preparing the DB
We are now ready to create our database structure. Don't worry about copy-pasting from the web page, I have provided a 'dbdump' file along with the X2 Mail Admin package. (remember however that the defaults for uid and gid in the passwd table must be that of the mail user)
|
#
# # Create Database and User: 'maildb' / 'mail' / 'secret' # -------------------------------------------------------- create database maildb; grant select,insert,update,delete on maildb.* to mail@localhost identified by 'secret'; flush privileges; # # Database : `maildb` # -------------------------------------------------------- # # Table structure for table `admin` # CREATE TABLE admin ( id int(11) NOT NULL auto_increment, username varchar(255) NOT NULL default '', password varchar(255) NOT NULL default '', domainID int(11) NOT NULL default '0', KEY id (id) ) TYPE=MyISAM; # -------------------------------------------------------- # # Table structure for table `aliases` # CREATE TABLE aliases ( id int(11) NOT NULL auto_increment, domainID int(11) NOT NULL default '0', type set('site','system') NOT NULL default 'site', email char(128) NOT NULL default '', dest char(128) NOT NULL default '', KEY id (id) ) TYPE=MyISAM; # -------------------------------------------------------- # # Table structure for table `domains` # CREATE TABLE domains ( id int(11) NOT NULL auto_increment, domain char(128) NOT NULL default '', type enum('local','relay','manual_relay') NOT NULL default 'local', relay_host char(128) NOT NULL default '', KEY id (id) ) TYPE=MyISAM; # -------------------------------------------------------- # # Table structure for table `passwd` # CREATE TABLE passwd ( id int(11) NOT NULL auto_increment, email varchar(128) NOT NULL default '', crypt varchar(128) NOT NULL default '', clear varchar(128) NOT NULL default '', name varchar(128) NOT NULL default '', uid int(10) unsigned NOT NULL default '26', gid int(10) unsigned NOT NULL default '26', home varchar(255) NOT NULL default '', maildir varchar(255) NOT NULL default '', quota varchar(255) NOT NULL default '', domainID int(11) NOT NULL default '0', smtp text NOT NULL, KEY id (id) ) TYPE=MyISAM; |
Setting Up Courier IMAP
Starting from a running IMAP-Installation, the authmysql module has to be added to the authmodulelist in the configuration file of authdaemon. Edit authmysqlrc; be sure to set up properly MYSQL_SERVER, MYSQL_USERNAME, MYSQL_PASSWORD andMYSQL_DATABASE. Again don't worry I have provided a configuration file for you in the package. They are authdaemonrc and authmysqlrc; simply copy these files to /usr/local/etc/courier-imap/ (for FreeBSD).
Setting up EXIM
Again, I have provided the configuration files for this. All that needs to be done is to change the authentication so that it uses the mysql-database. If you are overly interested in how this works, take a look at the two above mentioned inspirations I used.
Here is the major difference between my solution and the one from Virtual Domains with Exim + Courier-IMAP + MySQL. I have added SMTP authentication. There are three types of common SMTP authentication, as such the following lines were added to the end of the exim configuration file:
|
#####################
# AUTHENTICATION #CONFIGURATION ##################### # There are no authenticator specifications in this default configuration file. begin authenticators cram: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup mysql{select clear from passwd where email = '${quote_mysql:$1}' and clear != '' and smtp = 'yes'}} server_set_id = $1 plain: driver = plaintext public_name = PLAIN server_condition = ${lookup mysql{select count(*) from passwd where email = '${quote_mysql:$2}' and clear = '${quote_mysql:$3}' and clear != '' and smtp = 'yes'}} server_set_id = $2 login: driver = plaintext public_name = LOGIN server_prompts = Username:: : Password:: server_condition = ${lookup mysql{select count(*) from passwd where email = '${quote_mysql:$1}' and clear = '${quote_mysql:$2}' and clear != '' and smtp = 'yes'}} server_set_id = $1 |
You will want to copy the exim_configuration file to /usr/local/etc/exim/configure (for FreeBSD).
Adding the web control panel
I created a web control panel to allow a typical ISP style experience. It has 3 levels of control:
- Admin of the Admin:
Allowing the addition and subtraction of domains which are controlled by their postmasters. - Admin:
The postmaster of each domain is in control of all users and forwards of that domain. - User:
Anyone with an e-mail address can change their password using the 'change password' page.
To install the X2 mailAdmin, simple move (or sym-link) the mailAdmin dir into a path accessible by your php enabled webserevr. Now we have to setup the local directory for the vdomains. This directory should be (unless you want to change all my code) /usr/local/vdomains and you must chown the dir to that of the mail user.
This is important!!! You must use a .htaccess file to control access to the /mailAdmin/admin dir. Do not leave this directory publicly available.
Once the mailAdmin is 'installed', open http://yourdomain.com/mailAdmin/admin. You can then add a domain. This will create a postmaster@domain.com account that will be used to admin the domain. You may also remove domains from this page.
Have fun!












