Ok, here we go...
I needed to quickly configure a mailserver, initially - for a single domain (but probably will host more later).
I am using exim over the last two years, I don't like qmail because it's
very old, and to add some new feature to it - requires patching it. BTW,
did you ever try reading qmail's logs? :D
I don't like postfix, but this is probably because I didn't use it too
often.
Also, as an Imap/POP3 server, I do like dovecot, easy to configure, yet
very comfortable to use, and also quite stable.
Adding domains/users manually isn't too much fun, we need some sort of
web interface too, to manage virtual domains, mailboxes, aliases.
Prerequisites:
- apache
- php
- mysql
I will leave this as an exercise to the reader :)
All this setup was done on a CentOS 5.3 system, so I'll give examples using yum to install the packages (on Fedora/RedHat you could use the same yum, on Debian/Ubuntu - use aptitude or apt-get)
First of all, create a MySQL database to store all the settings:
mysql> CREATE DATABASE vexim;
mysql> GRANT ALL ON vexim.* to vexim@localhost identified by 'kieHeed3ailuph8b';
Next, download the latest postfixadmin tarball from http://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.2.1.1/postfixadmin-2.2.1.1.tar.gz, and unpack it to /var/www/html/mailadmin/
Adjust: /var/www/html/mailadmin/config.inc.php, more exactly, the following section:
...
// Database Config
// mysql = MySQL 3.23 and 4.0
// mysqli = MySQL 4.1
// pgsql = PostgreSQL
$CONF['database_type'] = 'mysql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'vexim';
$CONF['database_password'] = 'kieHeed3ailuph8b';
$CONF['database_name'] = 'vexim';
$CONF['database_prefix'] = '';...
We will need clamd installed, in order to enable virus checks in exim. Debian/Ubuntu have this in the base repositories, CentOS - doesn't. We can use the rpmforge packages, see http://dag.wieers.com/rpm/FAQ.php#B2 on how to add the rpmforge repositories to your system.
Install clamd:
[root@server #] yum install clamd
Adjust the following parameters in clamd settings:
#In /etc/clamd.conf:
...
User exim
...
#In /etc/freshclam.conf:
...
DatabaseOwner exim
...
Adjust permissions/ownership:
[root@server #] chown -R exim:exim /var/log/clamav/
[root@server #] chown -R exim:exim /var/clamav/
Now on to exim, dovecot and postfixadmin.
Install exim and dovecot from repositories,
[root@server #] yum install dovecot exim
[root@server #] mv /etc/exim/exim.conf /etc/exim/exim.conf-orig
[root@server #] mv /etc/dovecot.conf /etc/dovecot.conf-orig
Sample config used for exim, this doesn't include spam filtering, or rbl checks, but this can be easily added:
primary_hostname = mail.eulinux.org
hide mysql_servers = localhost/vexim/vexim/kieHeed3ailuph8b
domainlist local_domains = ${lookup mysql{SELECT `domain` \
FROM `domain` WHERE \
`domain`='${quote_mysql:$domain}' AND \
`active`='1'}}
domainlist relay_to_domains = ${lookup mysql{SELECT `domain` \
FROM `domain` WHERE \
`domain`='${quote_mysql:$domain}' AND \
`active`='1'}}
hostlist relay_from_hosts = localhost:127.0.0.0/8:192.168.0.0/16 #add the hosts from which you allow relaying here
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
av_scanner = clamd:/var/run/clamav/clamd.sock
# spamd_address = 127.0.0.1 783
qualify_domain = mail.playlainc.com
qualify_recipient = mail.playlainc.com
allow_domain_literals = false
exim_user = exim
exim_group = exim
never_users = root
rfc1413_query_timeout = 0s
sender_unqualified_hosts = +relay_from_hosts
recipient_unqualified_hosts = +relay_from_hosts
ignore_bounce_errors_after = 45m
timeout_frozen_after = 15d
helo_accept_junk_hosts = 192.168.0.0/16
auto_thaw = 1h
smtp_banner = "$primary_hostname, ESMTP EXIM $version_number"
smtp_accept_max = 50
smtp_accept_max_per_connection = 25
smtp_connect_backlog = 30
smtp_accept_max_per_host = 20
split_spool_directory = true
remote_max_parallel = 15
return_size_limit = 70k
message_size_limit = 64M
helo_allow_chars = _
smtp_enforce_sync = true
log_selector = \
+all_parents \
+connection_reject \
+incoming_interface \
+lost_incoming_connection \
+received_sender \
+received_recipients \
+smtp_confirmation \
+smtp_syntax_error \
+smtp_protocol_error \
-queue_run
syslog_timestamp = no
begin acl
acl_check_rcpt:
accept hosts = :
deny message = "incorrect symbol in address"
domains = +local_domains
local_parts = ^[.] : ^.*[@%!/|]
deny message = "incorrect symbol in address"
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
accept local_parts = postmaster
domains = +local_domains
deny message = "HELO/EHLO required by SMTP RFC"
condition = ${if eq{$sender_helo_name}{}{yes}{no}}
accept authenticated = *
deny message = "Your IP in HELO - access denied!"
hosts = * : !+relay_from_hosts : !81-196.lissyara.su
condition = ${if eq{$sender_helo_name}\
{$sender_host_address}{true}{false}}
deny condition = ${if eq{$sender_helo_name}\
{$interface_address}{yes}{no}}
hosts = !127.0.0.1 : !localhost : *
message = "My IP in your HELO! Access denied!"
deny condition = ${if match{$sender_helo_name}\
{\N^\d+$\N}{yes}{no}}
hosts = !127.0.0.1 : !localhost : *
message = "Incorrect HELO string"
# filter spammers from dynamic ips
deny message = "your hostname is bad (adsl, poll, ppp & etc)."
condition = ${if match{$sender_host_name} \
{adsl|dialup|pool|peer|dhcp} \
{yes}{no}}
warn
set acl_m0 = 30s
warn
hosts = +relay_from_hosts:4.3.2.1/32:192.168.0.0/16 #disable waits for 'friendly' hosts
set acl_m0 = 0s
warn
logwrite = Delay $acl_m0 for $sender_host_name \
[$sender_host_address] with HELO=$sender_helo_name. Mail \
from $sender_address to $local_part@$domain.
delay = $acl_m0
accept domains = +local_domains
endpass
message = "No such user"
verify = recipient
accept domains = +relay_to_domains
endpass
message = "i don't know how to relay to this address"
verify = recipient
# deny message = "you in blacklist - $dnslist_domain \n $dnslist_text"
# dnslists = opm.blitzed.org : \
# cbl.abuseat.org : \
# bl.csma.biz
accept hosts = +relay_from_hosts
deny message = "Homo hominus lupus est"
acl_check_data:
# check for viruses
deny malware = *
message = "Your message contains viruses: $malware_name"
# if needed - add spam filtering here
# permit everything else
accept
begin routers
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more
system_aliases:
driver = redirect
allow_fail
allow_defer
data = ${lookup mysql{SELECT `goto` FROM `alias` WHERE \
`address`='${quote_mysql:$local_part@$domain}' OR \
`address`='${quote_mysql:@$domain}'}}
dovecot_user:
driver = accept
condition = ${lookup mysql{SELECT `goto` FROM \
`alias` WHERE \
`address`='${quote_mysql:$local_part@$domain}' OR \
`address`='${quote_mysql:@$domain}'}{yes}{no}}
transport = dovecot_delivery
begin transports
remote_smtp:
driver = smtp
interface = 4.3.2.1 #your public ip address, if it's the main server ip - you could skip this parameter. if it's an alias- it must be specified in clear
dovecot_delivery:
driver = pipe
command = /usr/libexec/dovecot/deliver -d $local_part@$domain
message_prefix =
message_suffix =
delivery_date_add
envelope_to_add
return_path_add
log_output
user = exim
address_pipe:
driver = pipe
return_output
address_reply:
driver = autoreply
begin retry
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
begin rewrite
begin authenticators
auth_plain:
driver = plaintext
public_name = PLAIN
server_condition = ${lookup mysql{SELECT `username` FROM \
`mailbox` WHERE `username` = \
'${quote_mysql:$auth2}' AND `password` = \
'${quote_mysql:$auth3}'}{yes}{no}}
server_prompts = :
server_set_id = $auth2
auth_login:
driver = plaintext
public_name = LOGIN
server_condition = ${lookup mysql{SELECT `username` FROM \
`mailbox` WHERE `username` = \
'${quote_mysql:$auth1}' AND `password` = \
'${quote_mysql:$auth2}'}{yes}{no}}
server_prompts = Username:: : Password::
server_set_id = $auth1
auth_cram_md5:
driver = cram_md5
public_name = CRAM-MD5
server_secret = ${lookup mysql{SELECT `password` FROM \
`mailbox` WHERE `username` \
= '${quote_mysql:$auth1}'}{$value}fail}
server_set_id = $auth2
Now, on to dovecot:
#File: /etc/dovecot.conf
base_dir = /var/run/dovecot/
protocols = imap pop3
listen = *
disable_plaintext_auth = no
shutdown_clients = yes
log_timestamp = "%b %d %H:%M:%S "
syslog_facility = mail
ssl_disable = yes
login_dir = /var/run/dovecot/login
login_chroot = no
login_process_size = 64
login_process_per_connection = yes
login_processes_count = 3
login_max_processes_count = 128
login_max_connections = 256
login_greeting = Dovecot ready man.
login_log_format_elements = user=<%u> method=%m rip=%r lip=%l %c
login_log_format = %$: %s
mail_location = maildir:~/home/vmail/%d/%n
first_valid_uid=93
last_valid_uid=0
protocol imap {
mail_plugins = quota imap_quota
imap_client_workarounds = outlook-idle netscape-eoh tb-extra-mailbox-sep
}
protocol pop3 {
pop3_uidl_format = %08Xu%08Xv
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
protocol lda {
postmaster_address = admin@eulinux.org
auth_socket_path = /var/run/dovecot/auth-master
}
auth default {
mechanisms = plain
passdb pam {
}
passdb sql {
args = /etc/dovecot-mysql.conf
}
userdb passwd {
}
userdb sql {
args = /etc/dovecot-mysql.conf
}
user = root
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0660
user = exim
group = exim
}
}
}
dict {
}
plugin {
}
#File: /etc/dovecot-mysql.conf
driver = mysql
connect = host=localhost dbname=vexim user=vexim password=kieHeed3ailuph8b
default_pass_scheme = CRYPT
password_query = SELECT `username` as `user`, `password` FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
user_query = SELECT "" AS `home`, 93 AS `uid`, 93 AS `gid` FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
Now, start the services:
for srv in exim dovecot clamd; do service ${srv} start; done
Access your postfixadmin configuration file at: http://hostname/mailadmin/setup.php
You should see a list of 'OK' messages.
The setup.php script will attempt to create the database structure (or upgrade it if you're coming from a previous version).
Assuming everything is OK you can create the admin user using the form displayed. Once you submit the form, all that's left to do is to delete "setup.php"
That seems to be all! ;)
If you notice any errors or have any questions on this - please comment