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
qpsmtpd
and configure it to use the ms-lite plugins.Actually installing
qpsmtpd
, and configuring it to listen upon your public IP on port 25 is outside the scope of our documentation.Once you've configured
qpsmtpd
to 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 /spamThis will give you a local directory to which the
qpsmtpd
user 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/srv
is fixed, just as the quarantine directory must be located at/spam
.)For each domain you specify users by creating entries in the directories:
/srv/$domain/users/valid
/srv/$domain/users/invalid
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:
- example.com
This will accept mail for only a few local users.
- invalid.org
This domain will have wildcard handling so any account will accept mail, with the one exception that mail addressed to
spam@invalid.org
will 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/postmasterHere we've configured the domain
example.com
to accept mail addressed tosteve@example.com
,root@example.com
,abuse@example.com
, andpostmaster@example.com
- mail to all other accounts will be rejected (and stored in the quarantine)For
invalid.org
the 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/spamAs you can see we've configured this domain to accept mail to all users except the user
spam@invadid.org
.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:
/srv/$domain/users/valid
/srv/$domain/users/invalid
Configuring the various filters is achieved in the same fashion. You must merely touch files in the directory
/srv/$domain/checks
.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/allHowever you might prefer to enable different checks on a per-domain basis. That is also possible - rather than creating
/checks/all
create one file for each test you wish to be enabled on this domain.For example to only enable the
helo
anddate
checks 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/dateHow 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 userbob@smith.com
you'd run this:mkdir -p /srv/example.com/whitelisted/senders touch /srv/example.com/whitelisted/senders/bob@smith.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
abuse@example.com
you'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 addressedexamle.com
from the IP address1.2.3.4
you'd run:mkdir -p /srv/example.com/whitelisted/ips touch /srv/example.com/whitelisted/ips/1.2.3.4These 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/blacklisted
as 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 1.2.3.4 from sending you mail. touch /srv/example.com/blacklisted/ips/1.2.3.4 # Block all mail from linkedin.com touch /srv/example.com/blacklisted/domains/linkedin.com # Blacklist mail from alice@evil.com touch /srv/example.com/blacklisted/senders/alice@evil.comFor 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
/srv/_global_/
.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