List of requirements

    Test emails

      Validators

      Commandline

    Exim

      Rewriting

      Display configuration information

      Queue

    Certificates

    Postfix

      Configuration

      Queue

      Canonical maps

    Blocked by other servers

      Microsoft

        Unblock requests

        Smart Network Data Service

    SPF / DKIM

      SPF

      DKIM

      Resources

    Spamassassin

      DKIM scores

      Domain names including the IP

      Testing email files

    Miscellaneous

    ClamAV

      Unoffical signatures for ClamAV

    Blocking incoming email

    Monitoring with check_mk

    Logs

List of requirements

  • Mailserver needs an MX record

  • Reverse DNS record (PTR) which is not a boilerplate one

  • Domain name resolves to mail server's IP

  • HELO needs sane hostname too

  • SPF for all domains and subdomains

  • DKIM for all domains and subdomains

Test emails

Validators

Commandline

Swaks is a nice tool to send test emails, e.g.

swaks --from="racke@linuxia.de" --to="racke@nite.si" --header="Subject: Hello world!" --server=localhost

Exim

A specific from address for a local accounts can be configured in /etc/email-addresses:

stefan: racke@linuxia.de

Rewriting

In order to prevent emails going out from a development system to real users you can force all outgoing emails to a specific account:

*@* test@example.com Tt

Display configuration information

~# exim -bP '+local_domains'
domainlist local_domains = @:localhost:linuxia.de:icdev.de

Queue

List emails in the queue:

~# exim -bp

Number of emails in the queue:

~# exim -bpc
815

Thaw all frozen emails:

# exiqgrep -z -i | xargs exim -Mt
Message 1kne6n-0003fU-A5 is no longer frozen
Message 1kneBc-0003w9-7A is no longer frozen
Message 1kneFz-0004BK-NF is no longer frozen

Remove all emails:

$  exiqgrep -i | xargs exim -Mrm
Message 1lj449-0002VX-8z has been removed
Message 1ljEag-0004uV-4h has been removed
Message 1ljKxR-0007JM-L7 has been removed

Certificates

Display certificate for IMAPS:

openssl s_client -connect mail.linuxia.de:993 -showcerts | openssl x509 -text

Postfix

Configuration

You can test the Postfix configuration with postfix check.

Shows all settings from main.cf in alphabetic order which differ from the default value:

~# postconf -n

List of default values for main.cf:

~# postconf -d
2bounce_notice_recipient = postmaster
access_map_defer_code = 450
access_map_reject_code = 554
address_verify_cache_cleanup_interval = 12h
address_verify_default_transport = $default_transport
address_verify_local_transport = $local_transport
...

Queue

List emails in the queue:

~ postqueue -p

Flush (aka retry) all emails in the queue:

~ postqueue -f

Delete all emails from the queue:

~ postsuper -d ALL
postsuper: Deleted: 46 messages

Canonical maps

It is recommended to prevent email to real persons leaking from your laptop or a development server. You still want to check these emails on a personal email account.

You can achieve that with canonical maps for recipients.

Create a file canonical_redirect in your Postfix configuration directory (usually /etc/postfix) with the following contents:

/^.*$/ test@example.com

Prepare the file for postfix with postmap:

postmap canonical_redirect

Add the following line to your main.cf and restart postfix:

recipient_canonical_maps = regexp:/etc/postfix/canonical-redirect

Blocked by other servers

Microsoft

This applies to the following mail services:

Hotmail

hotmail.*

Live

live.*

Outlook

outlook.*

Unblock requests

Unblock requests

Smart Network Data Service

SNDS

SPF / DKIM

Testing records:

Mail tester

SPF

The mail server needs a SPF record in DNS, e.g. for example.com it could look like that:

v=spf1 a mx ip4:93.184.216.34 ~all

You can lookup the SPF record from the commandline with:

~ dig +short -t TXT linuxia.de
"v=spf1 a mx ip4:95.216.116.54 ip4:62.192.27.135 ip4:146.0.35.17 ~all"

DKIM

DKIM on multiple domains with Exim4

Notes:

Rather than modifying a configuration file registered with the package system, I would create a new file for local macros, e.g. /etc/exim4/conf.d/main/00_local_macros.

After adding resp. updating this file, update the Exim configuration with:

update-exim4.conf

and restart exim:

systemctl restart exim4

Script for creating keys:

#! /bin/bash -e
#
# Copyright 2015-2021 by Stefan Hornburg (Racke) <racke@linuxia.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.

DKIMDIR=/etc/exim4/dkim
EXIMUSER=Debian-exim
EXIMGROUP=Debian-exim

umask o-rwx

if [ ! -d $DKIMDIR ]; then
    mkdir $DKIMDIR
    chown $EXIMUSER:$EXIMGROUP $DKIMDIR
fi

pubkey_slurp () {
    local buf
    while read line; do
        [[ $line =~ PUBLIC ]] || buf="$buf$line"
    done < $1
    pubkey=$buf
}

cd $DKIMDIR

# generate private and public key for each domain
# supplied on the command line
for domain do
    echo "Domain $domain"

    if [ -f $domain-private.pem ]; then
        echo "Private key for $domain exists!" >&2
    else
        openssl genrsa -out $domain-private.pem 2048
        chown $EXIMUSER:$EXIMGROUP $domain-private.pem
    fi

    if [ ! -f $domain.pub ]; then
        openssl rsa -in $domain-private.pem -pubout > $domain.pub
        chown $EXIMUSER:$EXIMGROUP $domain.pub
    fi

    # post DNS entry
    echo "DNS entry: "
    pubkey_slurp $domain.pub
    echo 'v=DKIM1; p='$pubkey
done

Resources

DKIM for subdomains

Check new and published DNS records

Spamassassin

You need to install the Mail::DKIM Perl module in order to verify DKIM signatures:

apt-get install libmail-dkim-perl

Otherwise all emails will be flagged with T_DKIM_INVALID.

DKIM scores

DKIM_SIGNED

signed with DKIM, not necessarily valid (default score 0.1)

DKIM_VALID

signed with DKIM, valid (default score -0.1)

DKIM_VALID_AU

signed with DKIM, valid, matches author's domain (default score 0.1)

So all your email should show DKIM_VALID_AU.

Domain names including the IP

E.g. ds10-11-12-13.dedicated.hosteurope.de

HELO_DYNAMIC_IPADDR

high negative score

Testing email files

You can get a SPAM report from a EML file with spamc:

spamc -R < organic-spam.eml

This requires that the Spamassassin server is running on the same host.

Miscellaneous

Keep your mail server from blacklists.

Spamhaus is used by a lot of email providers, e.g. GMX and Yahoo, to refuse incoming emails from

IPs listed there.

You can check the Spamhaus blacklists (SBL,PBL, XBL) at http://www.spamhaus.org/query/bl?ip=IP.

Instructions for avoiding the CBL are here.

The answer to the HELO should be fully qualified domain name (e.g. "mail.linuxia.de"), with correct reverse DNS lookup.

ClamAV

Enable logging of found virus/malware:

LogVerbose true in /etc/clamav/clamd.conf.

Unoffical signatures for ClamAV

Debian provides clamav-unofficial-sigs package with a script that adds and updates really useful third party signatures for ClamAV.

We recommend the following adjustment to the configuration.

/etc/clamav-unofficial-sigs.conf.d/50-local.conf should read:

# http://lists.clamav.net/pipermail/clamav-users/2015-April/001459.html
# SecuriteInfo Databases as not operating anymore and spams the logs
si_dbs=""
ss_dbs="$ss_dbs foxhole_generic.cdb
   foxhole_filename.cdb
   foxhole_js.cdb
"

Which removes the securiteinfo and adds foxhole low and mid.

Blocking incoming email

Some SPAM attacks are send from IPs from all over the world, but they provide the same hostname as HELO.

In Exim you can deny or drop them as follows with the following ACL rule:

drop
     condition = ${lookup{$sender_helo_name}lsearch{/etc/exim4/deny_helos}{yes}{no}}
     log_message = HELO on black list

The file /etc/exim4/deny_helos contains the HELO host names which should be blocked.

~# cat /etc/exim4/deny_helos
ymlf-pc
kontrollprozesse.contabo.host

Monitoring with check_mk

We add the following services to /etc/check_mk/mrpe.cfg:

Eximailqueue /usr/lib/nagios/plugins/check_eximailqueue -w 600 -c 800
LocalSMTP /usr/lib/nagios/plugins/check_smtp -H localhost
Spamd /usr/bin/sa-check_spamd --socketpath=/var/run/spamd.sock

Run a service discovery for this host to get the new services added.

Logs

It is often useful to include the email subject into the logs for Exim, so add it to the log_selector:

log_selector = +subject

Or to the MAIN_LOG_SELECTOR variable in a Debian setup:

MAIN_LOG_SELECTOR = +tls_peerdn +subject