 
	Easy to follow howto on setting up a mail server with unlimited users and domains, with IMAP/Pop access, anti-spam, anti-virus, secure authentication, encrypted traffic, web mail interface and more.
Ubuntu + Postfix + Courier IMAP + MySQL + Amavisd-new + SpamAssassin + ClamAV + SASL + TLS + SquirrelMail
 
	| Edition | State | Started | Updated | Description | 
|---|---|---|---|---|
| 1st | Released (outdated) | 2004-01 | 2004-02 | Based on Mandrake 9.1. | 
| 2nd | Released (outdated) | 2004-02 | 2004-07 | Based on Mandrake 10.x, but valid for all distributions. Very thorough. Includes package description, where to get the sources and binaries, how to build them or which RPMs to use, includes many refrences, etc etc. Starts off with a basic working server, then advances, extends and tightens it in stages. | 
| 3rd (This) | Released | 2005-05 | 2005-11 | Latest released version. Based on Ubuntu 5.04, Hoary Hedgehog. More concise simplified guide to get an advanced server working quickly. Now includes SASL & TSL integration. | 
| 4th | In developement | 2005-10 | 2005-11 | Breezy Badger, Ubuntu 5.10, updated version. Tweaks to edition3, and also adding PostGrey. Please send me information on changes needed from 3rd edition to work in Ubuntu 5.10. | 
This is a step by step guide to set up a fully working and feature rich mail server for a GNU / Linux machine. The aims are to be straight forward and a simple set up, so that as many as possible can easily have a useable, respectable and secure mail server.
If you follow this howto, you end up with a mail server, which can host unlimited domains, with unlimited users, using unlimited disk space, which will be scanned for viruses and spam. You can send and read email via your favourite clients or via webmail. And it will also be very secure.
What do you need before starting this? A blank box in mail server terms. A newly installed linux puta is good or even better; installed with my chosen OS. However old machines are fine, as long as there wont be conflicts with other installed mail packages. Naturally an internet connection is crucial, and speedy as well for downloading the required software. A static, semi-static IP address or a dynamic dns service is also important for DNS resolving etc.
Do you need to be a Linux guru to follow this howto? Not at all, however you should be comfortable having root access to a box. Also you should be aware of the security implications of having open ports exposed to the internet.
					As with all guides, don't just rely on one opinion.
					Have a look at the other howtos in my references, 
					look up postfix.org's listed howtos, 
					read the excellent 
					books
					
					available (E.g. Kyle's or Hildebrandt's),
					and read postfix's documentation 
					to create your custom mail server.
				
I suggest first reading the whole how to, if not at least skim read it. Then as you start the implementation, be aware of the different sections, and how they relate, E.g configration when testing. You may have to comment things out while debugging the elements.
Feel free to contact me via the contact section in the appendix. Questions, criticism, bug reports are all welcome. Naturally I disclaim all liablities if anythings goes wrong while following my howto. Nor do I guarantee any support, but I am always willing to help, so just drop me a note and I'll see if I can assist. Paid consultancy can be done via electric ray.
About the author. I am Ivar Abrahamsen, a 28 year old Software Engineer. I am Norwegian, but based in Manchester, UK. I am not a Postfix or Linux guru, but I do know abit about both to write a good "how to". My general interest are sports, technology and my better half.
Why have I written this how to? I set up my mail server in 2003, and then did the same for a few friends and collegues. Soon I was getting more request, and being a lazy programmer, I thought.. "Why don't I write a howto and let them do it themselves..." Soon it was listed on postfix.org and I was getting thousends of hits and lots of emails. (blessing in disguise)
Some see the proliferation of howtos as a scourge of useless spam. I see it as a blessing. The more informed and varied information, assistance and opinions, the better. Much better than a single monolithic and even chargable point. I research other people's howtos on most things I do all the time. I tend to write down things I do, most of which no-one else ever reads, some are thankfully usefull for some people, which makes it all worthwhile.
Please see software links appendix for further information about these software packages. In that section there is more links to documentation or forums, and viable alternatives, downloadable packages, versions details etc.
Further software and tweaks are discussed in the extension section.
Also review other peoples opinion on these packages via my references.
#deb cdrom:[Ubuntu 5.04 _Hoary Hedgehog_ - Release i386 (20050407)]/ hoary main restricted
deb http://gb.archive.ubuntu.com/ubuntu hoary main restricted multiverse
deb-src http://gb.archive.ubuntu.com/ubuntu hoary main restricted multiverse
deb http://gb.archive.ubuntu.com/ubuntu hoary-updates main restricted multiverse
deb-src http://gb.archive.ubuntu.com/ubuntu hoary-updates main restricted multiverse
deb http://gb.archive.ubuntu.com/ubuntu hoary universe
deb-src http://gb.archive.ubuntu.com/ubuntu hoary universe
deb http://security.ubuntu.com/ubuntu hoary-security main restricted multiverse
deb-src http://security.ubuntu.com/ubuntu hoary-security main restricted multiverse
deb http://security.ubuntu.com/ubuntu hoary-security universe
deb-src http://security.ubuntu.com/ubuntu hoary-security universe
	# Log in as root
sudo su
# example to find what you have installed
dpkg --list | grep postfix
# example to find what is available to install
apt-cache search postfix
# then reiterate through each package
# or do a section in one go
apt-get	install insert-package-name-here
		#zone	display	comment
loc	Local	Local network
net	Net	Tinternet
		
		net	eth0	detect
		
		loc	eth0:192.168.0.0/24
		
		fw	loc	ACCEPT
fw	net	ACCEPT
loc	all	DROP	info
net	all	DROP	info
all	all	REJECT	info
		
		AllowPing	loc	fw
AllowSSH	loc	fw
AllowSMTP	loc	fw
#AllowIMAP	loc	fw
#ACCEPT		loc	fw	tcp	465	-
AllowPing	net	fw
#AllowSMTP	net	fw
		SMTP access from the web is commented out, untill we are confident everything is working and secure. Also commented out for now is IMAP and TLS SMTP traffic untill we need it.
startup=1
		#restart shorewall with
/etc/init.d/shorewall restart
		myhostname =  server.yourdomain.com		
		smtpd_banner = $myhostname ESMTP $mail_name
		
		# leave blank to do it yourself
relayhost = 
# or put it an accessible smtp server
relayhost = smtp.yourisp.com
		inet_interfaces = all
mynetworks_style = host
		masquerade_domains = sub.domain.com !sub.dyndomain.com
masquerade_exceptions = root
		local_recipient_maps = 
mydestination =
		# how long if undelivered before sending warning update to sender		
delay_warning_time = 4h 
# will it be a permanent error or temporary
unknown_local_recipient_reject_code = 450 
# how long to keep message on queue before return as failed.
# some have 3 days, I have 16 days as I am backup server for some people
# whom go on holiday with their server switched off.
maximal_queue_lifetime = 16d 
# max and min time in seconds between retries if connection failed
minimal_backoff_time = 1000s 
maximal_backoff_time = 8000s 
# how long to wait when servers connect before receiving rest of data
smtp_helo_timeout = 60s 
# how many address can be used in one message.
# effective stopper to mass spammers, accidental copy in whole address list
# but may restrict intentional mail shots.
smtpd_recipient_limit = 16 
# how many error before back off.
smtpd_soft_error_limit = 3 
# how many max errors before blocking it.
smtpd_hard_error_limit = 12
		smtpd_sender_restrictions = reject_non_fqdn_sender permit_sasl_authenticated 
		reject_unknown_sender_domain reject_unauth_pipelining permit
smtpd_client_restrictions =  reject_rbl_client sbl.spamhaus.org, reject_rbl_client relays.ordb.org, 
		reject_rbl_client blackholes.easynet.nl, reject_rbl_client dnsbl.njabl.org, 
		reject_rbl_client cbl.abuseat.org
smtpd_recipient_restrictions = permit_mynetworks, reject_non_fqdn_recipient, 
		reject_unauth_destination, check_relay_domains
smtpd_helo_required = yes
disable_vrfy_command = yes
		# not sure of the difference of the next two
# but they are needed for local aliasing
alias_maps = hash:/etc/postfix/aliases
alias_database = hash:/etc/postfix/aliases
# this specifies where the virtual mailbox folders will be located
virtual_mailbox_base = /var/spool/mail/virtual
# this is for the mailbox location for each user
virtual_mailbox_maps = mysql:/etc/postfix/mysql_mailbox.cf
# and their user id
virtual_uid_maps = mysql:/etc/postfix/mysql_uid.cf
# and group id
virtual_gid_maps =  mysql:/etc/postfix/mysql_gid.cf
# and this is for aliases
virtual_alias_maps = mysql:/etc/postfix/mysql_alias.cf
# and this is for domain lookups
virtual_mailbox_domains = mysql:/etc/postfix/mysql_domains.cf
# this is how to connect to the domains (all virtual, but the option is there)
# transport_maps = mysql:/etc/postfix/mysql_transport.cf
		cp /etc/aliases /etc/postfix/aliases
# may want to view the file to check if ok.
# especially that the final alias, eg root goes
# to a real person
postalias /etc/postfix/aliases
		
		# to add if there is not a virtual user
mkdir /var/spool/mail/virtual
groupadd virtual -g 5000
useradd virtual -u 5000 -g 5000
chown -R virtual:virtual /var/spool/mail/virtual
		# to modify if a virtual user is already set
groupmod -g 5000 virtual		
usermod -g virtual -u 5000 virtual
chown -R virtual:virtual /var/spool/mail/virtual		
		user=mail
password=apassword
dbname=maildb
table=users
select_field=maildir
where_field=id
hosts=127.0.0.1
additional_conditions = and enabled = 1
user=mail
password=apassword
dbname=maildb
table=users
select_field=uid
where_field=id
hosts=127.0.0.1
		user=mail
password=apassword
dbname=maildb
table=users
select_field=gid
where_field=id
hosts=127.0.0.1
		user=mail
password=apassword
dbname=maildb
table=aliases
select_field=destination
where_field=mail
hosts=127.0.0.1
additional_conditions = and enabled = 1
		user=mail
password=apassword
dbname=maildb
table=domains
select_field=domain
where_field=domain
hosts=127.0.0.1
	# If not already done...
mysqladmin -u root password new_password
# log in as root
mysql -u root -p
# then enter password for the root account when prompted
Enter password:
# then we create the mail database
create database maildb;
# then we create a new user: "mail"
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON maildb.* TO 'mail'@'localhost' IDENTIFIED by 'apassword';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON maildb.* TO 'mail'@'%' IDENTIFIED by 'apassword';
exit;
		
		# log in to mysql as the new mail user
mysql -u mail -p maildb	
# enter the newly created password
Enter password:
#then run this commands to create the tables;
CREATE TABLE `aliases` (
  `pkid` smallint(3) NOT NULL auto_increment,
  `mail` varchar(120) NOT NULL default '',
  `destination` varchar(120) NOT NULL default '',
  `enabled` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`pkid`),
  UNIQUE KEY `mail` (`mail`)
) ;
CREATE TABLE `domains` (
  `pkid` smallint(6) NOT NULL auto_increment,
  `domain` varchar(120) NOT NULL default '',
  `transport` varchar(120) NOT NULL default 'virtual:',
  PRIMARY KEY  (`pkid`)
) ;
CREATE TABLE `users` (
  `id` varchar(128) NOT NULL default '',
  `crypt` varchar(128) NOT NULL default 'sdtrusfX0Jj66',
  `name` varchar(128) NOT NULL default '',
  `uid` smallint(5) unsigned NOT NULL default '5000',
  `gid` smallint(5) unsigned NOT NULL default '5000',
  `home` varchar(255) NOT NULL default '/var/spool/mail/virtual/',
  `maildir` varchar(255) NOT NULL default '',
  `quota` varchar(255) NOT NULL default '',
  `enabled` tinyint(3) unsigned NOT NULL default '1',
  `change_password` tinyint(3) unsigned NOT NULL default '1',
  `procmailrc` varchar(128) NOT NULL default '',
  `spamassassinrc` varchar(128) NOT NULL default '',
  `clear` varchar(128) NOT NULL default 'ChangeMe',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `id` (`id`)
) ;
		
		# comment out this line
#skip-networking
# Make sure this is set
log             = /var/log/mysql/mysql.log
		
		# restart MySQL to make sure 
# its picking up the new settings.
sudo /etc/init.d/mysql restart
		
	authmodulelist="authmysql"
		
		MYSQL_SERVER		localhost
MYSQL_USERNAME		mail
MYSQL_PASSWORD		apassword
MYSQL_PORT		0
MYSQL_OPT		0
MYSQL_DATABASE		maildb
MYSQL_USER_TABLE	users
# comment out this field,
# as I now longer use the encrypted pw options
#MYSQL_CRYPT_PWFIELD	crypt
MYSQL_CLEAR_PWFIELD	clear
MYSQL_UID_FIELD		uid
MYSQL_GID_FIELD		gid
MYSQL_LOGIN_FIELD	id
MYSQL_HOME_FIELD	home
MYSQL_NAME_FIELD	name
MYSQL_MAILDIR_FIELD	concat(home,'/',maildir)
MYSQL_WHERE_CLAUSE	enabled=1
		
		# set how many connections to use per person.
Easy to underestimate if you have 6 mailboxes set up.
MAXPERIP=20
# high debug to start with
DEBUG_LOGIN=2
IMAPDSTART=YES
		
		$mydomain 'yourdomian.com';
$daemon_user= 'virtual';		
$daemon_group= 'virtual';		
@local_domains_acl = qw();
$inet_socket_port = 10024;
$forward_method = 'smtp:127.0.0.1:10025';
# @bypass_virus_checks_acl  = qw( . );
# @bypass_spam_checks_acl  = qw( . );
	# I also change these
$TEMPBASE = "$MYHOME/tmp";
# Whilst debugging
$log_level = 2; 
$warnbannedrecip = 1;
$warn_offsite = 1; 
$warnvirusrecip = 1;
$spam_quarantine_to = "spam-quarantine\@$mydomain";
$virus_quarantine_to = "virus-quarantine\@$mydomain";
$sa_local_tests_only = 0;
		# You may have to do this
cd /var/lib/amavis
mkdir tmp
chown virtual:virtual tmp
chown virtual:virtual virusmails	
	
		#edit about line 31
#chown -c -h "$1:$2" "$4"
chown -c -h "virtual:virtual" "$4"
		#smtp      inet  n       -       n       -       -       smtpd
smtp      inet  n       -       -       -       -       smtpd
	-o cleanup_service_name=pre-cleanup
		
#cleanup   unix  n       -       -       -       0       cleanup
cleanup   unix  n       -       -       -       0       cleanup
 	-o mime_header_checks=
	-o nested_header_checks=
	-o body_checks=
	-o header_checks=
	
amavis unix        -       -       -       -       2       smtp
	-o smtp_data_done_timeout=1200
	-o smtp_send_xforward_command=yes
127.0.0.1:10025 inet    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 strict_rfc821_envelopes=yes
	-o mynetworks=127.0.0.0/8
	-o smtpd_error_sleep_time=0
	-o smtpd_soft_error_limit=1001
	-o smtpd_hard_error_limit=1001
pre-cleanup unix n - - - 0 cleanup
	-o virtual_alias_maps=
	-o canonical_maps=
	-o sender_canonical_maps=
	-o recipient_canonical_maps=
	-o masquerade_domains=
		content_filter = amavis:[127.0.0.1]:10024
#receieve_override_options = no_address_mappings
	# User clamav
User virtual
		chown virtual:virtual /var/run/clamav
		
		# how frequent per day. default is once an hourwhich is a bit excesive.
Checks 1
	SpamAssassin's default settings were fine, but you can tweak them at /etc/spamassassin/local.cf and review the defauls at /usr/share/spamassassin/. E.g. you can in/decrease the levels needed before emails are marked as spam and before rejections.
Here is an example of my local.cf.
skip_rbl_checks         0
use_razor2              0
use_dcc                 0
use_pyzor               0
use_bayes               1
bayes_path 		/etc/spamassassin/bayes
bayes_file_mode    	0770
		
		Once you have a collection of spam and non spam (200+ of each), you can train the Bayes filter in SpamAssassin with these emails. Review this on the SpamAssassin web site.
# E.g. like this
sa-learn --showdots -C /etc/spamassassin --spam /var/spool/mail/virtual/quarantine/.spam/*
sa-learn --showdots -C /etc/spamassassin --ham /var/spool/mail/virtual/mine/cur/*
		If you notice too much spam is being let through, then do more tweaking. If you get too many false postives, ie real emails marked as spam, loosen the set up slightly. A properly configured SpamAssassin should catch 97% of all spam. With probably 1 in 1000 false positives.
The SpamAssassin site has a lot of information on setting it up. It is worth a good read through. Some usefull tips are automatic learning, cronjobs to learn user marked spam and ham, etc.
Cyrus SASL provide a secure method of authenticating users. This type of authentication is required by two methods, one is by postfix when sending email and the other is by Courier when reading emails.
First we wil will deal with postfix. Add these lines to main.cf
# modify the existing smtpd_recipient_restrictions
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unauth_destination, check_relay_domains
# modify the existing smtpd_sender_restrictions
smtpd_sender_restrictions = reject_non_fqdn_sender permit_sasl_authenticated 
	reject_unknown_sender_domain reject_unauth_pipelining permit
# then add these
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_path = /etc/postfix/sasl:/usr/lib/sasl2
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
		# May already exist
mkdir /etc/postfix/sasl
# Then create the conf file.
vi /etc/postfix/sasl/smtpd.conf
		
		pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: plain login cram-md5 digest-md5
sql_engine: mysql
sql_hostnames: 127.0.0.1
sql_user: mail
sql_passwd: apasswd
sql_database: maildb
sql_select: select clear from users where id='%u@%r'
		That is all that should be required for sending email.
Next is to configure Courier to authenticate via SASL as well.
In Ubuntu all this was preset so the only line I needed to modify / confirm in /etc/courier/imapd is:
IMAP_CAPABILITY="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE 
	THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA 
	AUTH=CRAM-MD5 AUTH=CRAM-SHA1 IDLE"
	cd /etc/postfix
openssl req -new -outform PEM -out \
			postfix.cert -newkey rsa:2048 -nodes -keyout \
			postfix.key -keyform PEM -days 999 -x509
		smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/postfix/postfix.cert
smtpd_tls_key_file = /etc/postfix/postfix.key 
smtpd_data_restrictions = reject_unauth_pipelining		
		openssl req -x509 -newkey rsa:1024 -keyout imapd.pem -out \
imapd.pem -nodes -days 999
	
		TLS_CERTFILE=/etc/courier/imapd.pem
		This will enable secure traffic of emails via your clients and the server. As these are not signed certificates, some may be prompted to accept license. You could get people to import your certificates, if only a few is accessing you imap/smtp server, or purchase a signed one if you have a large number of users, especially if corporate. Outlook is known as stuburn to accept the certificates.
There are some issues with using SALS and TLS at the same time. Since all the traffic is encrypted with TLS, then the need for SASL is less.
ln -s /usr/share/squirrelmail /var/www/squirrelmail
		<VirtualHost *>
	ServerAdmin webmaster@localhost
	ServerName webmail.yourdomain.com
	DocumentRoot /var/www/squirrelmail
	<Directory /var/www/squirrelmail>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride AuthConfig
		Order allow,deny
		allow from all
	</Directory>
	ErrorLog /var/log/apache2/error-webmail.log
	LogLevel warn
	CustomLog /var/log/apache2/access-webmail.log combined
	ServerSignature On
</VirtualHost>
		
		ln -s /etc/apache2/sites-available/webmail /etc/apache2/sites-enabled/810-webmail
/etc/init.d/apache2 restart
		
		/var/www/squirrelmail/config/conf.pl
		
		# Enter this
mysql://mail:apassword@127.0.0.1/maildb
		
		mysql://mail:apassword@127.0.0.1/maildb
		
		mysql -u mail -p maildb
		
		CREATE TABLE `address` (
  `owner` varchar(128) NOT NULL default '',
  `nickname` varchar(16) NOT NULL default '',
  `firstname` varchar(128) NOT NULL default '',
  `lastname` varchar(128) NOT NULL default '',
  `email` varchar(128) NOT NULL default '',
  `label` varchar(255) default NULL,
  PRIMARY KEY  (`owner`,`nickname`),
  KEY `firstname` (`firstname`,`lastname`)
) ;
CREATE TABLE `userprefs` (
  `user` varchar(128) NOT NULL default '',
  `prefkey` varchar(50) NOT NULL default '',
  `prefval` varchar(255) default NULL,
  `modified` timestamp(14) NOT NULL,
  PRIMARY KEY  (`user`,`prefkey`)
) ;	
		
		# cd into web root where phpMyAdmin is installed,  e.g. /var/www 
# Again in Ubuntu a soft link is needed to /usr/share
# this time however the apt-get has done it for you. (check though)
# If the folder contains the version in its name.
# do this for ease of access and if later upgrading
ln -s phpMyAdmin1.6.2 phpMyAdmin
		# either reuse an old .htpasswd file
# or as below , create one when you add the first user
htpasswd2 -c /path/to/htpasswd/file/outside/www/.htpasswd ausername
# then enter desired passwd
	AuthType Basic
AuthName "A Bit Hush and all that"
AuthUserFile "/path/to/htpasswd/file/outside/www/.htpasswd"
require valid-user
		$cfg['Servers'][$i]['host']          = 'localhost';
$cfg['Servers'][$i]['user']          = 'mail';
$cfg['Servers'][$i]['password']      = 'apassword';
$cfg['Servers'][$i]['only_db']       = 'maildb';
		
		domain.tld	IN	MX	10	your.mailserver.name.tld
		
	So we got a fully set up mail server... Well no, there is no users, domains, no nothing!
Okay, first you need add some default data, some which are required, some which make sense.
Then we'll add your own users and domains.
# Use phpMyAdmin or command line mysql
INSERT INTO domains (domain) VALUES
('localhost'),
('localhost.localdomain');
		
		INSERT INTO aliases (mail,destination) VALUES
('postmaster@localhost','root@localhost'),
('sysadmin@localhost','root@localhost'),
('webmaster@localhost','root@localhost'),
('abuse@localhost','root@localhost'),
('root@localhost','root@localhost'),
('@localhost','root@localhost'),
('@localhost.localdomain','@localhost');
		INSERT INTO users (id,name,maildir,clear) VALUES 
('root@localhost','root','root/','apassword');
		
		INSERT INTO domains (domain) VALUES
('blobber.org'),
('whopper.nu'),
('lala.com');
INSERT INTO aliases (mail,destination) VALUES
('[email protected]','[email protected]'),
('[email protected]','[email protected]'),
('[email protected]','[email protected]'),
('@whopper.nu','[email protected]'),
('@lala.com','@blobber.org'),
('[email protected]','postmaster@localhost'),
('[email protected]','abuse@localhost'),
('[email protected]','postmaster@localhost'),
('[email protected]','abuse@localhost');
INSERT INTO users (id,name,maildir,clear) VALUES 
('[email protected]','xandros','xandros/','apassword'),
('[email protected]','vivita','vivita/','anotherpassword');
		
		So what does each of these lines do? Well the domains are pretty straight forward. The users are as well, it requires four fields. ID is the email address of the user, and also its username when loggin in, described later on. NAME is optional description of the user. MAILDIR is the name of the folder inside /var/spool/mail/virtual. It must end in a /, otherwise it wont be used as a unix maildir format. CLEAR is the clear text password to use.
The alises are the interesting part. Lets start from a top down view. Say an email arrives addressed to "[email protected]". Postfix looks up aliases and searches for a row where the mail field matches "[email protected]". None does so it next searches for "@whopper.nu", which is the way to specify catch all others for that domain. It finds one row and its destination is "[email protected]". It then searches for "[email protected]" and finds one, which destination is the same as the mail, therefor it is the final destination. It then tries to deliver this mail. The look up says blobber.org is a local mail so it looks up users for a matching id and delivers it to its maildir.
Lets try "[email protected]". First lookup does not find this user, but the next finds the catchall "@lala.com". But its destination is another catchall, "@blobber.org". This means Postfix will look for "[email protected]". This address is not found either, nor is a catchall for blobber.org. Therefor this address is not valid and the message will be bounced.
Any mail arriving for "[email protected]" or "[email protected]", gets forward to an external address of "[email protected]". So forwarding is simple. I tend to use a subdomain for all my friends addresses as easily I forget what their real addresses are, and I use different email clients all the time.
I also added the required aliases of postmaster and abuse to blobber.org and whopper.nu. The catchall for lala.com means they are not required for that domain. You can add them though if you do not want xandros to get the admin emails. Another usefull alias to add is root, as often you get admin mail from e.g cron jobs within those domains etc. Other often used aliases are info, support, sales and all. But they are also honeypots for spam, so just include the ones you think you will need.
INSERT INTO domains (domain) VALUES ('domain.tld');
INSERT INTO aliases (mail,destination) VALUES
('@domain.tld','email@address'),
('[email protected]','email@address'),
('[email protected]','email@address');
		INSERT INTO users (id,name,maildir,clear) VALUES
('email@address','short description','foldername/','password');
INSERT INTO aliases (mail,destination) VALUES
('email@address','email@address');
		
	This is a small and simple section, but this will be the one you spend the longest on!
There will be spelling errors(by you and me), difference in setups, external factors etc, so this server is guaranteed not to work first time. Great eh?
But don't worry, we can quickly track down which section is at fault, and solve the issues one by one.
I hope you blocked external acces to your SMTP port (25) in your firewall setting. Otherwise you might have become an open relay for spammers. (Okay unlikely unless you have been running exposed for a few weeks). You will have to unblock it soon, but not yet. Lets first be 100% sure the system works, so only local access to SMTP should be allowed for now.
We will test each section bit by bit to black box certify each bit. First test that postfix delivery works (by exluding content checks and ignoring courier). We will check if it can connect to MySQL for its lookups, if maildir are created and if it can send messages. Then we'll re-enable content checks to see if they work. Then we start testing courier, see if it can access MySQL and if it shows the right mailboxes.
The easiest way to do the testing is with telnet. Turn on full debuggon, tail a few logs a lets get started.
# Making sure nothing is running
/etc/init.d/courier stop
/etc/init.d/postfix stop
/etc/init.d/amavisd stop
/etc/init.d/spamassassin stop
/etc/init.d/clamav stop
/etc/init.d/mysqld stop
# Then to check if they really stopped
ps aux
netstat -tnp
		smtp      inet  n       -       n       -       -       smtpd
#smtp      inet  n       -       -       -       -       smtpd
#	-o cleanup_service_name=pre-cleanup
cleanup   unix  n       -       -       -       0       cleanup
#cleanup   unix  n       -       -       -       0       cleanup
# 	-o mime_header_checks=
#	-o nested_header_checks=
#	-o body_checks=
#	-o header_checks=
		#content_filter = amavis:[127.0.0.1]:10024
		# In one window do this
tail -f /var/log/mysql/mysql.log
# then in another
tail -f /var/log/maillog.info
/etc/init.d/mysqld start
# then
/etc/init.d/postfix start
# then check if postfix is listening on 25 and mysql on 3306
netstat -tnp
		
		Okay up and running (hopefully).
First we will telnet in and try and send a message to a local user.
Then we will try and send to an external user via postfix.
# Lets try and send a message to [email protected]
# (replace with your own user in this setup, or use postmaster@localhost)
telnet localhost 25
# reponse back:
>
>
>
# then open the hand shake with ehlo and the server name you are connecting from...
EHLO mail.domain.tld
>
>
>
# then say who is the sender of this email
MAIL FROM: <[email protected]>
> 250 Ok
# then say who the mail is for
RCPT TO: <[email protected]>
> 250 Ok
data
> 354 End data with <CR><LF>.<CR><LF></LF></CR></LF></CR>
# enter message bodyand end with a line with only a full stop.
blah blah blah
more blah
.
> 250 Ok; queued as QWKJDKASAS
# end the connection with
quit
> 221 BYE
		The postfix log should then start showing up what is happening. If something happens in the mysql log, it means that connection if working.
Then the next step is to test Courier-IMAP.
Again tail the maillog, syslog and mysql log. Turn on DEBULEVEL in /etc/courier/imap to 2.
telnet localhost 143
>
>
>
		
		telnet 127.0.0.1 10024
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
		
		debug_peer_list = 127.0.0.1
		
		Doing a full reboot to test if everything comes up as desired is probably a good idea as well.
Congratulations, you have a working mail server! Now send me a note to let me know about it.
With MX backup loosing emails are unlikely.
Normally if someone sends an email destined for you, their server will try and connect to your server. If it can't reach your server for whatever reason ( it is down, dns issues, there is network problems, or just too busy ), the other server will back off and try again in a bit. How many and for how long it will try again is determined by the sending server. Some of them are not very patience, and it will report undelivered after only a few attempts. So you would have lost that email.
If you had specified a backup MX, this email may not have been lost. Upon first failure to connect to your server, the sender would see if there is any alternative server to send to. So it connects to your backup mx server. This server spools and queues your message and will try at intervals to send the message to you. It too will though eventually give up.
What is the difference? Simple, you (or whoever controls the backup mx ) is in control how long and often to try connecting to your machine. So if you have a reasonable values and your server is not down for weeks, no mail is lost.
How to implement it? First edit the DNS records again, and add a backup mx with a higher value.
# your server details
domain.tld	IN	MX	10	your.mailserver.name.tld
# new backup server
domain.tld	IN	MX	20	your.backupserver.name.tld
		
		CREATE TABLE `backups` (
  `pkid` smallint(6) NOT NULL auto_increment,
  `domain` varchar(128) NOT NULL default '',
  `transport` varchar(128) NOT NULL default '',
  PRIMARY KEY  (`pkid`),
  UNIQUE KEY `domain` (`domain`)
); 
		
		relay_domains = mysql:/etc/postfix/mysql_backups.cf
transport_maps = mysql:/etc/postfix/mysql_transport.cf
		proxy_interfaces = 1.2.3.4
		user=mail
password=apassword			
dbname=maildb
table=backups		
select_field=domain
where_field=domain
hosts=127.0.0.1
		
		user=mail
password=apassword			
dbname=maildb
table=backups		
select_field=transport
where_field=domain
hosts=127.0.0.1
		
		You noticed I added a transport lookup. This is a field in both the domain and the backup tables. In domains it is used to determine how to deliver the email, ie either virtual (correct) or local (not used in this howto). When backing up servers, your also need to specify in the transport field how to connect to the correct servers.
Say you are backiup for a friends server, mail.friend.com, for the domains of friend1.com and friend2.com. So you should insert this into your backup table.
INSERT INTO backups (domain,transport)
VALUES ('friend1.com' , ':[mail.friend.com]' ),
('friend2.com' , ':[mail.friend.com]' );
		The :[] tells to connect directly to this server, not doing any more look ups for valid MX servers.
This shouls now work fine. Further tweaking of the queue values, review these and modify as appropiate. Shorter warning times are good for the sender, so that they realise the email has not arrived yet, but may also be annoying. Tradeoffs.. Look in the first main.cf configurations for ways to do so.
tar czf mail-config.xxxxx.tgz /etc/postfic /etc/courier /etc/spamassassin /etc/clamav /etc/amavis /etc/mysql/my.cnf
tar czf mail-fold.xxxx.tgz /var/spool/mail/virtual
mysqldump -u mail -papassword -t maildb > data.sql
mysqldump -u mail -papassword -d maildb > schema.sql
tar czf mail-data.xxx.tgz schema.sql data.sql
tar cf mail.xxxxx.tar  mail-*.xxxxx.tgz 
		tar --newer-mtime "2005-01-01"
		
		www.microsoft.com/mscorp/safety/technologies/senderid/
While SPF should limit who can send mail on behalf of your domains, ( so basically less spoofed spam addresses ), I do have some technical issues with SPF as the design of it is a bit iffy. That is because of the limitation of DNS and that it has to fit inside the limited TEXT part. No nice XML config file....
While Microsoft is not always entirely evil, as sometimes they do nice things and make some usefull software, I would prefer not to be locked into their Sender ID technology.
Reporting spam to Pyzor, Razor and SpamCop, for collaboration in spam fighting.
More detail on SpamCop is here.
http://pyzor.sourceforge.net/
http://razor.sourceforge.net/
You can implement white and black lists to explicitly allow or block domains and users.
You have already visited the option of a blackhole list of known open relays in the postfix configuration.
You can implement further lists inside Postfix or SpamAssassin. Amavisd-new already has a few well known white/black listed items in its config files. SpamAssissin also as a feture to automaticly learn white lists.
Adding support for GnuPG and S/MIME increases indiviual security.
This is not implemented on the postfix server side, as this totally a client side option.
However SquirrelMail has a GnuPG option. It is a plugin that can be downloaded from their website. Which can then be enabled via SquirrelMail's config script.
Here is how to create a GnuPG key pair.
# check you have not already got a key
gpg --list-keys
# then create one
gpg --gen-key
		
		To import GnuPG into Evolution; in your settings/preferences edit your account settings and add you private key under the security tab. The private key is found via listing the GnuPG keys as above, then it is the 8 characters after the "sub 1024g/" bit of you key.
To use GnuPG with Thunderbird you need to install EnigMail.
S/MIME is another way to encrypt and/or sign messages. You can create you own certificate or use known organizations like Thawte. (Thawte was originally set up by the Ubuntu founder)
CREATE TABLE `relocated` (
  `pkid` smallint(6) NOT NULL auto_increment,
  `oldadr` varchar(128) NOT NULL default '',
  `newadr` varchar(128) NOT NULL default '',
  `enabled` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`pkid`),
  UNIQUE KEY `oldadr` (`oldadr`)
) ;
		
		relocated_maps = mysql:/etc/postfix/mysql_relocated.cf
		
		user=mail
password=apassword			
dbname=maildb
table=relocated		
select_field=newadr
where_field=oldadr
hosts=127.0.0.1
		INSERT INTO relocated (oldadr,newadr)VALUES
('[email protected]','[email protected]');
		
		Trying out a few admin software might make you life easier, if phpMyAdmin gets to crude. Quick search
More to come later.
Postfix have now features to auto reply to an email, while still delivering it to its alias.
If you use catch alls, which are usefull for some domains, then eventually some addresses will be target for spam. You can then either stop the catch all, or stop indivdual addresses.
By implementing a lookup and adding this restriction to smtpd_recipient_restrictions accomplises this.
check_recipient_access mysql:/etc/postfix/mysql_block_recip.cf,smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, \
		check_recipient_access mysql:/etc/postfix/mysql_block_recip.cf, \
		reject_non_fqdn_recipient, reject_unauth_destination, \
		check_relay_domains
			
		Beware of the order is important here, if any options says ok before check_recipient_access it will ignore it.
Next create mysql_block_recip.cf to lookup addresses. Either create a another table, or add a blocked field to aliases table.
Interaction with Majordome etc is not covered here. However a simple mailling list can be implemented, by simply seperating aliases in the destination field in the aliases table with a comma.
INSERT INTO aliases (mail,destination) VALUES
( '[email protected]' , '[email protected],[email protected],[email protected]' );
		You can contact me directly, however the best way to talk about this howto is to use the Ubuntu forums web site. There is a thread for this howto in the Ubuntu 5.04 (Hoary) section, and soon there will be one for 5.10 (Breezy).
But if you would like to contact me, and I do like to hear from people using this howto, then use the form below, or at a flurdy.com. I can't guarantee when I will reply though.. :)
I would like to hear from people whom have written howtos to extend this howto or recommend links for extensions.
