Many people who have personal servers handle email for a number of domains, and struggle to deal with the ever-increasing volume of spam, junk, and virus-laden email.
There are solutions for dealing with this problem, ranging from hosted services, to software you must run yourself.
This page documents a consistent and extensible solution built around open source software, which allows you to handle mail filtering for multiple domains without complex configuration.
The software presented here consists of a co-ordinated collection of plugins that can be used with the qpsmtpd SMTP server to offer a system that will filter email for a number of domains, and allow you to specify different filtering for different domains.
It is helpful if you're familiar with qpsmtpd so that you can install it and and understand how it works, but that isn't entirely necesary.
Once installed this collection of plugins will give you:
- A simple system for handling mail for a number of domains on a single host.
- Different domains can have independant settings.
- A simple browsable archive of rejected mails.
- A consistant experience where mail is either:
- Rejected at SMTP-time and archived to a local quarantine.
- Or accepted for delivery and passed to a local installation of exim4 to actually be delivered.
To get started please see the code on github:git clone https://github.com/skx/ms-lite.git
To get started you'll need to install
qpsmtpdand configure it to use the ms-lite plugins.
qpsmtpd, and configuring it to listen upon your public IP on port 25 is outside the scope of our documentation.
Once you've configured
qpsmtpdto load the plugins there are three things you must do to get up and running:
- Create the quarantine/archive directory.
- Specify users & the filtering options for your domains.
- Configuring The Rejection Quarantine
Configuring the quarantine directory is as simple making a directory and then configuring the permissions on it:root@host:~# mkdir /spam root@host:~# chown qpsmtpd.qpsmtpd /spam root@host:~# chmod 750 /spam
This will give you a local directory to which the
qpsmtpduser can both read and write.
- Configuring The Domains
Configuring the domains is a simple process of creating files and directories, but we'll come back to that later.
To configure which domains and users will have their mail accepted we need to create a couple of directories for each domain beneath
/srv. (This prefix
/srvis fixed, just as the quarantine directory must be located at
For each domain you specify users by creating entries in the directories:
To demonstrate how this works we'll show how you'd configure the two domains "
example.com" and "
invalid.org". We'll configure these domains to work like this:
This will accept mail for only a few local users.
This domain will have wildcard handling so any account will accept mail, with the one exception that mail addressed to
firstname.lastname@example.org be rejected.
To get started we configure
example.com:mkdir -p /srv/example.com/users/valid/ touch /srv/example.com/users/valid/steve touch /srv/example.com/users/valid/root touch /srv/example.com/users/valid/abuse touch /srv/example.com/users/valid/postmaster
Here we've configured the domain
example.comto accept mail addressed to
email@example.com- mail to all other accounts will be rejected (and stored in the quarantine)
invalid.orgthe setup is almost the same. We use the same "/users/valid" path, but instead of creating accounts we create a file called
*:# wildcard users - except the user "spam" is invalid mkdir -p /srv/invalid.org/users/valid/ touch /srv/invalid.org/users/valid/\* mkdir -p /srv/invalid.org/users/invalid touch /srv/invalid.org/users/invalid/spam
As you can see we've configured this domain to accept mail to all users except the user
Now that you've configured the users and the domain names mail will start to be accepted be delivered as expected - however we've not yet configured any filtering.
The configuration of filters follows the same pattern as the user setup, it merely involves the creation of a couple more files and directories.
We've already seen that to get a new domain going you need to create entries in the special directories:
Configuring the various filters is achieved in the same fashion. You must merely touch files in the directory
There are several filters included in the distributed list and we can enable all of them for our two example domains by running:mkdir -p /srv/example.com/checks touch /srv/example.com/checks/all mkdir -p /srv/invalid.org/checks touch /srv/invalid.org/checks/all
However you might prefer to enable different checks on a per-domain basis. That is also possible - rather than creating
/checks/allcreate one file for each test you wish to be enabled on this domain.
For example to only enable the
datechecks for the domain you'd run this:rm -rf /srv/invalid.org/checks mkdir -p /srv/invalid.org/checks touch /srv/invalid.org/checks/helo touch /srv/invalid.org/checks/date
How do you know what filenames to use? That is simple. The filename you create matches the name of the plugin in the source - this is also documented in the example plugins file.
Any anti-spam system will make mistakes from time to time, and the simplest way of avoiding repeats is to make use of whitelisting.
We allow messages to be whitelisted based upon either the email address that sent the message, the account it is addressed to, or the host that delivered the mail to us.
Like the prior setup this is again configured by creating files in a particular set of directories:
- Whitelisting Senders
Create files in
/srv/domain/whitelisted/senders/. For example if you wish to always accept email from the user
firstname.lastname@example.org'd run this:mkdir -p /srv/example.com/whitelisted/senders touch /email@example.com
- Whitelisting Recipients
Create the files in the directory
/srv/$domain/whitelisted/recipients/. Note the domain name is implied by the directory name, so you don't need to repeat it.
For example if you run a helpdesk and people forward spam complaints to the address
firstname.lastname@example.org'd always want to accept them even if they looked like spam so you'd run this:mkdir -p /srv/example.com/whitelisted/recipients touch /srv/example.com/whitelisted/recipients/abuse
- Whitelisting Hosts
Finally to whitelist the hosts that are sending you email you need to create files beneath
/srv/domain/whitelisted/ips/. As an example to always accept mail addressed
examle.comfrom the IP address
188.8.131.52you'd run:mkdir -p /srv/example.com/whitelisted/ips touch /srv/example.com/whitelisted/ips/184.108.40.206
These whitelisting settings are applied to all mails, and you don't need to restart the service for changes to take effect.
Blacklisting is achieved in a virtually identical fashion, the only change is that you use
/srv/$domian/blacklistedas the prefix instead. So you might blacklist a hostname, an IP address, or even a sending address or domain via commands like:# Blacklist the IP address 220.127.116.11 from sending you mail. touch /srv/example.com/blacklisted/ips/18.104.22.168 # Block all mail from linkedin.com touch /srv/example.com/blacklisted/domains/linkedin.com # Blacklist mail from email@example.com touch /firstname.lastname@example.org
For each of the blacklist and whitelist options you can choose to apply these overrides or blacklists on a per-domain basis, as we have done above, or globally via the magic prefix of
For example if you never wished to receive mail from AOL users you could run this:mkdir -p /srv/_global_/blacklisted/domains/ touch /srv/_global_/blacklisted/domains/aol.com