Nicholas Lindley

I told somebody I’d never met in person on App.net that I would send a link of how I had set up my mail server, but there are a couple of things I did differently (though not drastically), and I thought I could document them here. So, for the majority of you that are happy with your email as-is, just ignore this post.

I initially had set up my email by following this tutorial which seems to be kept up-to-date with each release of Debian. I know Ubuntu is the popular kid on the block right now, but I’ve always had better luck with the stability Debian offers for what I do.

My mail server is running on the smallest Cloud Server that Rackspace offers, which is just fine for the amount of traffic I receive. I also have a very basic management interface that runs on Heroku. If you choose to run a web interface on Heroku, you will need to allow database connections from the outside world and set the DATABASE_URL in the config.

heroku config:set DATABASE_URL=mysql2://mailadmin:passw0rd@173.203.249.123:3306/mailserver

Obviously that’s not my real information.

The first variation from the tutorial was in the database table names. Instead of using virtual_users, virtual_domains, and virtual_aliases, I dropped the virtual_ part. This makes it a little friendlier to work with in ActiveRecord. Next, I don’t use the full email address for users’ names, which makes the database queries slightly more complex, but still not bad. I’ve included mine below, but if you are using a different database you might need to make sure case-sensitivity won’t be a problem for you.

# /etc/postfix/mysql-email2email.cf
user = mailuser
password = passw0rd
hosts = 127.0.0.1
dbname = mailserver
query = SELECT CONCAT(u.username, '@', d.name) FROM users AS u LEFT JOIN domains AS d ON u.domain_id = d.id WHERE u.username = SUBSTRING_INDEX('%u', '+', 1) AND d.name = '%d' 
# /etc/postfix/mysql-virtual-alias-maps.cf
user = mailuser
password = passw0rd
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM aliases AS a LEFT JOIN domains AS d ON a.domain_id = d.id WHERE a.source = '%u' AND d.name = '%d'
# /etc/postfix/mysql-virtual-mailbox-domains.cf
user = mailuser
password = passw0rd
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM domains WHERE name='%s'
# mysql-virtual-mailbox-maps.cf
user = mailuser
password = passw0rd
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM users AS u LEFT JOIN domains AS d ON u.domain_id = d.id WHERE u.username = SUBSTRING_INDEX('%u', '+', 1) AND d.name = '%d'

In that last query, you’ll notice the SUBSTRING_INDEX function, which simply allows you to have email addresses like me+omnifocus@example.com.

I also added a couple of columns for admin and super_admin that allow other people to manage their domains and for me to manage any domain. (This part of the interface could be better, but it gets me by.)

The thing the tutorial leaves out in this version, but had included in the previous version for Lenny is automatically sieving spam into a separate folder. Since I use a variety of clients, I prefer this to be done on the server-side. The only difference I made to the globalsieverc file is filtering into Junk instead of spam, but that’s just personal preference. I don’t remember having to make any other changes from the tutorial version for Lenny.

There have been several times I’ve been tempted to use a hosted service, but I don’t want to give up the ability to quickly and easily add accounts, aliases, multiple domains, change my attachment limit, or completely move to another host. This is one service I have not yet been willing to let out of my control.