Configuring email
This chapter explains how to install and configure email (including setting up the Postfix MTA). It also describes how to implement email authentication to ensure delivery to mail providers that use milters to block spam..
Table of contents
- Introduction
- Set hostname and mailname
- Set up MX
- Install PostFix MTA
- Use a relay MTA
- Bypass milters
- Security
- Troubleshooting
- Final word
Introduction
This chapter explains how to install and configure email.
Set hostname and mailname
Before proceeding to install the email software, make sure that the system's hostname and mailname sorted out.
A fully qualified domain name (FQDN) is typecally consists of
a domain name followed by a tld.  In this
tutorial, example.com will be used.
We may need to change the configuration of the hostname. For instance, just after creating a DO droplet, the “Static hostname” will by default be the internal DO host identifier:
$ sudo hostnamectl status
   Static hostname: ubuntu-s-1vcpu-2gb-fra1-01
         Icon name: computer-vm
           Chassis: vm
        Machine ID: 5099201dc607419e84f16a61b370e286
           Boot ID: 047255feeb9a444fb932055d98ffff73
    Virtualization: kvm
  Operating System: Ubuntu 20.04.4 LTS
            Kernel: Linux 5.4.0-28-generic
      Architecture: x86-64
To be able to use Gnu mail out of the box, it should be set the hostname to the site's FQDN.
$ sudo hostnamectl set-hostname example.com
This puts the hostname in the file /etc/hostame and
the next time you log on, the domain part of the hostname will appear
in the CLI prompt on a vanilla Ubuntu configuration.
Next, edit the /etc/hosts file. The values you need to
set are at the top of the file. Remember to
replace example.com with your FQDN
and 192.0.2.0 with your server's public IP
address.
127.0.0.1 localhost 127.0.1.1 mail.example.com mail 192.0.2.0 mail.example.com mail
The one line plain text file /etc/mailname (Ubuntu
18.04 LTS) or /etc/hostname (Ubuntu 20.04 LTS) is used by
the the s-nail Mail Transfer Agent (i.e. mail server) to know
its own hostname.  Check that it contains the FQDN and edit it to
match if necessary. Example:
example.com
This sets up all the names required for sending and receiving email.
Set up MX
You may want to set up a MX (Mail eXchange) record to
direct the emails sent to your domain name to the a appropriate mail
server.
Your registrar usually provide a default, but sometimes you will
need to add the proper MX records and A
records to take more control over email delivery, or
to bypass milters.
To set up MX and other advanced settings of your DNS zone at domeneshop, click on “Vis avanserte innstillinger (SRV, TXT, TTL, etc.)”. The result may look like the screen dump below [not yet anonymized]:
 
Here, the MX record says that mail is handled by “mail.example.com”.
Also make sure an A-record exits for
“mail.example.com”, otherwise, mail will not be delivered
and you will see the following warning
in /var/log/mail.log: “warning: no MX host for
example.com has a valid address record”.
Make sure both these tests passes:
$ dig +short example.com mx 10 mail.example.com. $ host mail.example.com mail.example.com has address 192.0.2.0
I've also seen this:
$ host mail.example.com mail.example.com has address 192.0.2.0 Host mail.example.com not found: 3(NXDOMAIN)
Seems to be a transient glitch, so wait until stable. Up to one hour.
Relevant FAQs at Domeneshop and other relevant documentation:
- 054: Hva er en MX host?
- 310: Diverse MX-svar.
- 337: Legge til Domeneshop i SPF-oppføringen.
- Copernica.com: A-record and MX-record: how does it work?
Install PostFix MTA
https://serverfault.com/questions/953104/postfix-connection-refused-error https://www.linuxbabe.com/mail-server/postfixadmin-create-virtual-mailboxes-ubuntu-20-04 http://techslides.com/mail-server-for-multiple-domains-with-postfix
Postfix is an application to send and receive email (aka. mail transfer agent or MTA).
If you handle your personal mail elsewhere, you do not need to run your own mail server. However, if you manage a web server with applications (such as Drupal) that need to send email notifications, running a send-only SMTP server for that specific purpose is required.
 A
tutorial for setting up a local send-only SMTP server is on
How to Install and Configure Postfix as a Send-Only SMTP Server
on DigitalOcean. For a description of setting up a full Postfix configuration, see
How To Install and Configure Postfix on DigitalOcean.
You may also want to read these pages:
Hostadvice.com,
PostFix.org,
Change hostname,
Configure Postfix to Send Email Using External SMTP Servers.
A
tutorial for setting up a local send-only SMTP server is on
How to Install and Configure Postfix as a Send-Only SMTP Server
on DigitalOcean. For a description of setting up a full Postfix configuration, see
How To Install and Configure Postfix on DigitalOcean.
You may also want to read these pages:
Hostadvice.com,
PostFix.org,
Change hostname,
Configure Postfix to Send Email Using External SMTP Servers.
The most efficient way to install Postfix and other
programs needed for testing email is to install
the mailutils package.  This will
install Postfix as well as a few other programs needed
for Postfix to function.  You should also
install s-nail, which is less fussy about hostname than the
default Gnu mail.
$ sudo apt update $ sudo apt install mailutils $ sudo apt install s-nail
You will be prompted to configure Postfix during installation.
On the general type of email configuration, select ‘Internet Site’. Press TAB to highlight ‘OK’ and then press Enter.
 
On the ‘System mail name’ field, enter your FQDN. Do not include “mail.” (e.g. example.com, not ‘mail.example.com’).
 
Edit /etc/postfix/main.cfd (Ubuntu 18.04 LTS)
or /etc/postfix/main.cf (Ubuntu 20.04 LTS).
- Check the entry myhostname and change its value to “mail.”, followed by the FQDN.
- The mydestinationentry specifies what domains this machine will deliver locally, instead of forwarding to another machine. Make sure it contains the FQDN and all vhosts that will receive incomping email.
- Check entry inet_interfacesand make sure its value is “all” (use “loopback-only” to configure a local send-only SMTP server).
Example:
… myhostname = mail.example.com … mydestination = $myhostname, example.com, example.net, localhost.localdomain, localhost … inet_interfaces = all …
Restart Postfix:
$ sudo systemctl restart postfix
To test that your web server is also capable of sending email, set up s-nail as described in Step 6 and 7 in: How To Install and Configure Postfix on DigitalOcean.
To test, use one of the following:
$ echo "This is the body." | s-nail -s "This is the subject" test@example.com $ echo "This is the body." | mail -s "This is the subject" test@example.com
The difference is that “s-nail” uses the
Gnu/Linux Maildir directory structure to store mail, while
“mail” legacy Unix mbox textfile format.
You should also test that the server is capable of receiving email addressed to an exisiting username@FQDN. Doing this will also create your mailbox.
 Note
that your mailbox will not exist until it receives its first email. So
make sure you have sent an email to yourself before further
troubleshooting.
Note
that your mailbox will not exist until it receives its first email. So
make sure you have sent an email to yourself before further
troubleshooting.
 Gnu
mail is part of the mailutils package. If the sender's domain
is not a valid FQDN, outgoing email may be rejected
by most recipients with (“550 Unroutable address”) or (“550 Unable to
verify sender address”).
Gnu
mail is part of the mailutils package. If the sender's domain
is not a valid FQDN, outgoing email may be rejected
by most recipients with (“550 Unroutable address”) or (“550 Unable to
verify sender address”).
If the mail is not accepted by the destination, it is returned to sender:
U 1 Mail Delivery Syst Thu Feb 27 10:00 72/2326 Undelivered Mail Returned to Sender … Subject: Undelivered Mail Returned to Sender … Diagnostic code: smtp; 550-Improper HELO/EHLO (ubuntu-s-1vcpu-2gb-fra1-01) Not fully qualified. 550-RFC 5321, section 4.1.1.1: "The argument clause contains the 550-fully-qualified domain name of the SMTP client [...]" 550 See …
Errors (inluding bounced emails), for s-nail and Gnu mail are recorded here:
/var/log/mail.log
The log should tell you more about why the mail was rejected.
To check the status of postfix do:
$ sudo service postfix status
  postfix.service - Postfix Mail Transport Agent
   Loaded: loaded (/lib/systemd/system/postfix.service; enabled; vendor preset: enabled)
   Active: active (exited) since Sun 2020-02-23 18:40:13 UTC; 2 days ago
 Main PID: 1151 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 1151)
   CGroup: /system.slice/postfix.service
Feb 23 18:40:13 pvn-do-e.roztr.com systemd[1]: Starting Postfix Mail Transport Agent...
Feb 23 18:40:13 pvn-do-e.roztr.com systemd[1]: Started Postfix Mail Transport Agent.
This alternative ending does not necessarily mean trouble:
Oct 21 07:14:06 fqdn.example.com systemd[1]: Starting Postfix Mail Transport Agent... Oct 21 07:14:06 fqdn.example.com systemd[1]: Finished Postfix Mail Transport Agent.
Set up Postfix to map to users
You should now be able to send mail to your FQDN. You still need to set up Postfix to recognize your vhosts in order to receive mail sent to their users.
Rather than editing /etc/postfix/main.cf directly, you
can use Postfix's postconf command to query or set
configuration settings.
In these notes we shall use the Gnu/Linux Maildir
format, which separates messages into individual files that are then
moved between directories based on user action. The alternative (not
futher discussed) is legacy Unix mbox textfile format,
which stores all messages within a single file.
In /etc/postfix/main.cf, set home_mailbox
to Maildir/:
$ sudo postconf -e 'home_mailbox= Maildir/'
Next, set the location of the virtual_alias_maps
table, which maps email accounts to Unix system accounts:
$ sudo postconf -e 'virtual_alias_maps= hash:/etc/postfix/virtual'
This maps the table location to a hash database file
named /etc/postfix/virtual.db.
Now that you've defined the location of the virtual maps file in your main.cf file, you can create the file itself and begin mapping email accounts to user accounts on your Linux system. Create the file with your preferred text editor. In the file, on each line, list any email addresses that you wish to accept email for, followed by the username of the Unix user you'd like that mail delivered to.
bob@example.com bob admin@example.com bob
When done, save the file and exit.
Create the hash database file:
$ sudo postmap /etc/postfix/virtual
Restart the Postfix process to apply your changes yo the configuration:
$ sudo systemctl restart postfix
If you've set up ufw, this firewall will block external connections to services on your server by default unless those connections are explicitly allowed. Make sure Postfix (port 25) is allowed:
$ sudo ufw allow Postfix
To make sure you're able to connect, from another computer do:
$ telnet example.com 25 Trying 192.0.2.0 Connected to example.com Escape character is '^]'. 220 example.com ESMTP Postfix (Ubuntu) quit 221 2.0.0 Bye Connection closed by foreign host.
Initialize the Maildir structure
First, meke sure your MAIL environment variable is et
correctly.  The s-nail client we shall use for testing will
look for this variable to figure out where to find mail for your user.
Add the following line to /etc/bash.bashrc
and /etc/profile.d/mail.sh (if the latter do not exist,
create it):
export MAIL=~/Maildir
To read the variable into your current shell:
$ source /etc/profile.d/mail.sh
Before running s-nail, there are a few settings you need
to adjust. Open /etc/s-nail.rc in your preferred text
editor and add at the end:
set emptystart set folder=Maildir set record=+sent
Here is what these lines do:
- set emptystart: allows the client to open even with an empty inbox
- set folder=Maildir: sets the Maildir directory to the internal folder variable
- set record=+sent: creates a sent mbox file for storing sent mail within whichever directory is set as the folder variable, in this case Maildir
To create the Maildir structure within your home own
directory is to send yourself an email with s-nail.
The -s defines the subject. Because
the sent file will only be available once the Maildir is created, you
should disable writing to it for this initial email. Do this by passing the
-Snorecord option.  Provided your username is “bob”, do:
$ echo 'init' | s-nail -s 'init' -Snorecord bob
Verify that it has been created:
$ ls -R ~/Maildir /home/bob/Maildir: cur new tmp /home/bob/Maildir/cur: /home/bob/Maildir/new: 1463177269.Vfd01I40e4dM691221.mail.example.com /home/bob/Maildir/tmp:
Test that email works
Finally, you should test that both local and remote email works.
To test that the “init” email used to initalize
the Maildir structure is received, open the client:
$ s-nail s-nail version v14.9.15. Type `?' for help /home/bob/Maildir: 1 message 1 new >N 1 bob@example.com 2020-05-19 15:40 14/392 init
Press [Enter] to display the message.
You also should test the following:
- That the PHP-mailer (used by Drupal) is able to send mail
- That the sending domain in the “From” field is that of the vhost (not necessarely the FQDN).
- That the account is capable of receiving mail from remote machines.
The simplest way to do this is to use the custom project Testmail from HNM. See section about Email authentication tools for more.
Block spam
Use a relay MTA
- Kifarunix.com: Configure Postfix to Use Gmail SMTP on Ubuntu 20.04.
Bypass milters
Due to email spoofing, spam, phishing and other fraudulent practices, some ISPs have introduced use milters (mail filters) that may reject messages that do not authenticate or fail other tests. For instance, AOL will reject any message sent from a server without rDNS, gmail will reject any message that does not use SPF for authentication, and SpamAssassin will penalize missing rDNS and SPF.
You should implement all of the following four concepts to make sure the emails your site send bypass milters:
- rDNS (reverse DNS lookup or reverse DNS resolution) is using
a PTRrecord to tell recipients that a specific domain name that is associated with a given IP address.
- The SPF (Sender Policy Framework) record specifies which hosts or IP addresses are allowed to send emails on behalf of a domain.
- DKIM (DomainKeys Identified Mail) uses a private key to add a signature to emails sent from your domain. Receiving SMTP servers verify the signature by using the corresponding public key, which is published in your DNS registrar.
- DMARC (Domain-based Message Authentication, Reporting, and
Conformance) is a TXTRecord that can be published for a domain to control what happens if a message fails SPF or DKIM authentication.
 Please
note that GMail
will classify an email as spam if a PTR record with a valid
reverse DNS record for the sending domain's IP address is not set up.
The other concepts will also help getting email delivered to GMail.
For background, see:
Prevent mail to Gmail users from being blocked or sent to spam.
Please
note that GMail
will classify an email as spam if a PTR record with a valid
reverse DNS record for the sending domain's IP address is not set up.
The other concepts will also help getting email delivered to GMail.
For background, see:
Prevent mail to Gmail users from being blocked or sent to spam.
Set up rDNS and PTR records
Reverse DNS lookup or reverse DNS resolution (rDNS) is the determination of a domain name that is associated with a given IP address.
 Please
note that registrars such as Domeneshop does not
provide rDNS or PTR records.  This is normally provided by your
vhost provider (i.e. the owner of the IP-address, such as
e.g. DigitalOcean). Turn to you provider for exact instructions.
Please
note that registrars such as Domeneshop does not
provide rDNS or PTR records.  This is normally provided by your
vhost provider (i.e. the owner of the IP-address, such as
e.g. DigitalOcean). Turn to you provider for exact instructions.
The rDNS for a single IP address cannot have a PTR
record for more than one domain name with a single IP-address. AFAIK,
this is not a problem. Milters check that the PTR record
for reverse DNS exists, not that it is equivalent to the sending
domain.  However, SpamAssasin checks that the rDNS match your
sending IP.
On DigitalOcean no PTR record is initially configured, but one is created if you rename a droplet via the control panel. The steps are:
- Login to the DigitalOcean Control Panel.
- Select “Droplets” in the left margin.
- In the list, click on the droplet you want to rename.
- The screen now shows details about the droplets, as well as name on top. Click on the current name.
- It now can be edited. Edit (set it to FQDN), and click on the checkbox on the right to save the change.
- Update /etc/hostname/etc/hostson the server.
- Reboot the droplet.
The PTR should be automatically adjusted in few hours
due to DNS caching.
Source: DO community: How do I create a reverse DNS (PTR) Record.
Use the CLI and dig to look up the PTR record for the IP-address (this does not work with the FQDN as argument):
$ dig -x 192.0.2.0 … ;; QUESTION SECTION: ;0.2.0.192.in-addr.arpa. IN PTR ;; ANSWER SECTION: 0.2.0.192.in-addr.arpa. 79 IN PTR fqdn.example.com. …
The output shows that the IP address is associated with “fqdn.example.com”.
You can see the details in the report from mail-tester.com:
Your server 192.0.2.0 is successfully associated with fqdn.example.com
Here are the tested values for this check:
    IP: 192.0.2.0
    HELO: fqdn.example.com
    rDNS: fqdn.example.com.
You can see the details in the report from IsNotSpam.com:
HELO hostname: fqdn.example.com Source IP: 192.0.2.0
Postfix uses the value set for “myhostname” in “/etc/postfix/main.cf” for HELO hostname.
If you see the following error:
Your IP address 192.0.2.0 is associated with the domain example.com. Nevertheless your message appears to be sent from mail.example.com.
Check /etc/postfix/main.cf and that the following line matches the rDNS for the domain.
myhostname = fqdn.example.com
Cloud based tools for rDNS lookup:
ComputerWorld: How to setup Reverse DNS and PTR records.
Azure: rDNS.
Set up SPF
A SPF record is a TXT record, that means that the
primary record for the domain must be an A record./p>
If email is not included in domain package, create the following TXT record:
"v=spf1 a mx ip4:192.0.2.0 ~all"
If email is included in domain package, change from first to second line.
"v=spf1 include:_spf.domeneshop.no ~all" "v=spf1 include:_spf.domeneshop.no ip4:192.0.2.0 ~all"
The SPF is validated against the domain indicated by the sender field.
[SPF] ifi.uio.no does not allow your server 167.172.177.32 to use user@ifi.uio.no
Ifi is set up using “?all” in the SPF, instead of “~all”. This resolves to “Neutral”, and also that the recipients can't verify ther SPF isOK, although it might probably be. Most recipents will accept mail when the SPF evaluation resolves to neutral + Pass - Fail ~ SoftFail ? Neutral HELO hostname: do20.roztr.org Source IP: 167.172.177.32 mail-from: gisle@d8.roztr.org
Set up DKIM
First, install OpenDKIM which is an open-source implementation of the DKIM sender authentication system.
$ sudo apt install opendkim opendkim-tools
Then add user postfix to group opendkim.
$ sudo gpasswd -a postfix opendkim
Edit the OpenDKIM main configuration file: /etc/opendkim.conf.
Locate the commonly used options. Uncomment the all three
lines. Replace simple
with relaxed/simple. After editing, it should look like
this:
# Commonly-used options; the commented-out versions show the defaults. Canonicalization relaxed/simple Mode sv SubDomains no
Then add the following lines below #ADSPAction
continue line. If your file doesn't have that line, then just
add them below SubDomains no.
AutoRestart yes AutoRestartRate 10/1M Background yes DNSTimeout 5 SignatureAlgorithm rsa-sha256
Add the following lines at the end of this file if missing (on Ubuntu 18.04 and 20.04, the UserID has already been set to opendkim):
#OpenDKIM user # Remember to add user postfix to group opendkim UserID opendkim # Map domains in From addresses to keys used to sign messages KeyTable refile:/etc/opendkim/key.table SigningTable refile:/etc/opendkim/signing.table # Hosts to ignore when verifying signatures ExternalIgnoreList /etc/opendkim/trusted.hosts # A set of internal hosts whose mail should be signed InternalHosts /etc/opendkim/trusted.hosts
To create a signing table, key table and trusted hosts file, first create a directory structure for OpenDKIM, and change the owner from root to opendkim and make sure only opendkim user can read and write to the keys directory:
$ sudo mkdir /etc/opendkim $ sudo mkdir /etc/opendkim/keys $ sudo chown -R opendkim:opendkim /etc/opendkim $ sudo chmod go-rw /etc/opendkim/keys
Use preferred editor to
create /etc/opendkim/signing.table and add this line to
the file. This tells OpenDKIM that if a sender on your server is using
a @example.com address, then it should be signed with the private
key identified by default._domainkey.example.com.
*@example.com default._domainkey.example.com
Save and close the file.
Create /etc/opendkim/key.table and make it contain the
following line, which tells the location of the private key:
default._domainkey.example.com \ example.com:default:/etc/opendkim/keys/example.com/default.private
Save and close the file.
Create /etc/opendkim/trusted.hosts, and make sure it
contains the following lines:
127.0.0.1 localhost *.example.com
This tells OpenDKIM that if an email is coming from localhost or from the same domain, then OpenDKIM should not perform DKIM verification on the email.
Save and close the file.
Since DKIM is used to sign outgoing messages and verify incoming messages, we need to generate a private key for signing and a public key for remote verifier. Public key will be published in DNS.
Create a separate folder for the domain:
$ sudo mkdir /etc/opendkim/keys/example.com
Generate the keys:
$ sudo opendkim-genkey -b 2048 -d example.com \ -D /etc/opendkim/keys/example.com -s default -v opendkim-genkey: generate private key opendkim-genkey: private ke ywritten to default.private opendkim-genkey: exteacting public key opendkim-genkey: DNS TXT record written to default.txt
This will create 2048 bits keys. The -d option
specifies the domain. The -D opton specifies the
directory where the keys will be stored. The -s opton
specifies that we use default as the selector (also known as the
name). The private key will be written to a file named
default.private and the public key will be written to a file named default.txt.
Make opendkim the owner of the private key:
$ sudo chown opendkim:opendkim /etc/opendkim/keys/example.com/default.private
You need to publish your public key as a TXT record in
your zone file.  First, examine the contents of the file containing
the public key:
$ cat /etc/opendkim/keys/example.com/default.txt default._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; t=y; " "p=KAABIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/fedRNEFQvCdtN0akUCMG686…" "WN8G0212XiFLyyQuxJixQL04BMG0bvBW8xrNDiNuiAkDGea/nUxKRMnuVKOvAa5JAhi/hN…" ) ; ----- DKIM key default for example.com
The canidate for the TXT record is the text inside
parentheses. However, only the version (v) and the public
key (p) is required.  To clean up, remove all double
quotes, all white space and all parameters except v
and p.  The result should be a single line like this.
v=DKIM1;p=KAABIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/fedRNEFQvCdtN0akUCMG686…
In your DNS manager, create a TXT record,
enter default._domainkey.example.com in the name field
and paste the single line into the value field of the DNS record.
 
Wait for the TXT record to become visible.  You may
use dig to check:
$ $ dig default._domainkey.example.com txt … ;; QUESTION SECTION: ;default._domainkey.example.com. IN TXT ;; ANSWER SECTION: default._domainkey.example.com. 3599 IN TXT "v=DKIM1;p=KAABIjANBgkqhkiG9w0BAQEFA…" …
To test the newly created key pair, enter the following command:
$ sudo opendkim-testkey -d example.com -s default -vvv opendkim-testkey: using default configfile /etc/opendkim.conf opendkim-testkey: checking key 'default._domainkey.example.com' opendkim-testkey: key secure opendkim-testkey: key OK
If you get the above response, everything is fine.
If you see “key OK”, but also “key not secure”, don't panic. This is because DNSSEC isn't enabled on your domain name. DNSSEC is a security standard for secure DNS query. Some domains haven't enabled DNSSEC. There's no need to worry about this. You can continue the setup.
The final step is to set up a connection between Postfix and OpenDKIM.
Postfix can talk to OpenDKIM via a Unix socket file. The default
socket file used by OpenDKIM
is /var/run/opendkim/opendkim.sock, as shown
in /etc/opendkim.conf. But the postfix SMTP daemon
shipped with Ubuntu runs in a chroot jail, which means the SMTP daemon
resolves all filenames relative to the Postfix queue directory
(/var/spool/postfix). So we need to change the OpenDKIM
Unix socket file.
Create a directory to hold the OpenDKIM socket file and allow only
the user opendkim and the group postfix to
access it.
$ sudo mkdir /var/spool/postfix/opendkim $ sudo chown opendkim:postfix /var/spool/postfix/opendkim
Edit the OpenDKIM main configuration file  /etc/opendkim.conf.
Find one of the following lines (the first is Ubuntu 18.04 the second is Ubuntu 20.04):
Socket local:/var/run/opendkim/opendkim.sock Socket local:/run/opendkim/opendkim.sock
Replace it with the following line. (If you can't find the above line, then add the following line.)
Socket local:/var/spool/postfix/opendkim/opendkim.sock
Save and close the file.
If you can find the following line in /etc/default/opendkim:
SOCKET="local:/var/run/opendkim/opendkim.sock" SOCKET=local:$RUNDIR/opendkim.sock
Change it to:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
Save and close the file.
Finally, you need to edit the Postfix main configuration file /etc/postfix/main.cf:
Add the following lines at the end of this file, so Postfix will be able to call OpenDKIM via the milter protocol.
# Milter configuration milter_default_action = accept milter_protocol = 6 smtpd_milters = local:opendkim/opendkim.sock non_smtpd_milters = $smtpd_milters
Save and close the file.
Restart opendkim and postfix.
$ sudo systemctl restart opendkim postfix
That's it! You can now proceed to test that your email authenticates.
Sources:
- linuxbabe.com: How to Set up SPF and DKIM with Postfix on Ubuntu Server (this is the one I followed).
- tutorials24x7.com: DKIM for 20.04 LTS (multiple domains).
- DO community: DKIM for Debian Wheezy (too old?).
Set up DMARC
DMARC (Domain-based Message Authentication, Reporting, and
Conformance), is a TXT Record that can be published for a
domain to control what happens if a message fails authentication
(i.e. the recipient server can't verify that the message's sender is
who they say they are). A DMARC record serves two purposes:
- Tell the recipient server to either: Quarantine the message or Reject the message or Allow the message to continue delivery.
- Sends reports to an email address or addresses with data about all the messages seen from the domain.
Those two benefits alone drive home the huge value of setting up DMARC! Once published, a DMARC record is used by receiving mail servers (think Gmail or Yahoo! Mail) to determine what to do with a failed message. The receiving mail server at Gmail looks at the DMARC record for the policy to follow from the following choices:
- none: Do nothing to the message.
- quarantine: Quarantine the message.
- reject: Reject the message.
Action is taken by the recipient mail server on one of those 3 options above if the domain has published a DMARC record. If the domain has not published a DMARC record, the recipient server makes its own determination if the message should be delivered. With phishing, malware threats, and a variety of other security concerns; the direct value of being able to tell recipient mail servers to quarantine or reject messages that fail DMARC has now become the gold standard for sending legitimate email by blocking spammers.
A DMARC policy allows a sender to indicate that their emails are protected by SPF and/or DKIM, and give instruction if neither of those authentication methods passes. Please be sure you have a DKIM and SPF set before using DMARC.
To have one add a TXT record to a subdomain
named _dmarc.example.com with the following inital
value:
v=DMARC1; p=none
However, if you have a DMARC DNS entry, it is ignored until SPF is set up and message is signed with DKIM.
MXtoolbox.com: How to Add DMARC at your DNS Provider.
Test tool: MXtoolbox.
The List-Unsubscribe header field
The USA CAN-SPAM (Controlling the Assault of Non-Solicited Pornography And Marketing) act obligates senders of bulk email to implement opt-out mechanisms. One of these was the “List-Unsubscribe” header field.
This field is also described in RFC 2369. It is a header field that may look like this:
List-Unsubscribe: <mailto:unsubscribe@example.com?subject=unsubscribe>, <https://www.example.com/unsubscribe.html?address=user@example.net>
The above provide two common unsubscibe methods: mailto
and http. The first lets the user send a mail to a
special addrees. When a mail is received, the sender address should
automatically ore manually unsubscribed.  The second provides a link that, when clicked,
automatically unsubscribes the address.
Currently, this header is not supported by very many email clients, and Gmail.com and Outlook.com only make the method available to the user if the sender has a high reputation. If you send bulk email, you may need to use this header to satisfy the law in the USA, but to provide recipients with a working unsubscribe option, you must also embed a unsubscribe link in the body of the mail.
 See
emailtrap.io: List-Unsubscribe header in email to see how various email clients support this.
You may also want to read SO: Gmail unsubscribe link does not appear.
See
emailtrap.io: List-Unsubscribe header in email to see how various email clients support this.
You may also want to read SO: Gmail unsubscribe link does not appear.
Email authentication tools
To make sure that your email hardening works as intended, you need to test them.
The simplest way to test is to use the email authentication tools listed below is to use the custom project Testmail from HNM. Install it, and navigate to to send mail to various email-addresses, with instructions about how to check the resuilts.
See also: woodpecker.co.
Gmail
If you have a Gmail account, you can use it to check email authentication.
To see if SPF, DKIM and DMARC checks are passed, send a test email from your mail server to your Gmail account. Open the test message, expand the drop-down menu on the right under the three vertical dots, and select “Show original”. Authentication results are shown above the original message.
 
Failing tests are not listed.
This tool is free.
Website: mail.google.com.
mail-tester.com
Mail-tester.com is well made. When you vist their website it will generate an unique email address for you. You send sample email to this address and visit a link to view an easy to understand report.
The report will show you your email server IP, info about your SPF, DKIM and DMARC configuration, the score from SpamAssassin, the assessment of your message content as viewed by spam filters, your potential presence on some deny-lists, and info about any broken links in your message. The report also provide helpful hints about how to fix what is wrong.
Then, based on all those factors, you'l get a score from zero to ten. The screenshot below shows a perfect result.
 
A score less than five indicates that there are serious problems with your email configuration.
It is free for up to three checks per day, then paid:
- 5 € – Get access to the next 20 tests you perform.
- 10 € – Perform as many tests as you want during the next 7 days.
- 25 € – Perform as many tests as you want during the next 30 days.
- 200 € – Perform as many tests as you want during the next 365 days.
There is also a different price list for a white label reseller service.
Website: mail-tester.com.
Check-auth
This free email-tool allows you to check the SPF records, rDNS, DKIM, DomainKey, SenderID and SpamAssasin score for your domain and to see an evalutation of these authentication checks on any message you send.
To use the tool, simply send an empty email from the domain you
want to test to this email-address:
check-auth@verifier.port25.com.
You will receive a return email containing a report with an analysis of the
status of the message you sent.  The report
is useful, but IMHO not as easy to read and helpful as the report provided
by mail-tester.com.
The first section in the report is headed “Summary of Results”. It provides four key data points. Example:
SPF check: pass "iprev" check: pass DKIM check: pass SpamAssassin check: ham
The “SPF”, “DKIM” and “SpamAssassin” checks are what they say. The “iprev check” does a rDNS (reverse IP) and forward IP lookup and pass if they are in agreement.
The next section is headed “Details” and provides the following details at the top:
HELO hostname: fqdn.example.com Source IP: 192.0.2.0 mail-from: bob@example.com
The rest of this section expands on the tests that is presented in the summary in the first section.
The last section is headed “Original Email” and provides the the full message source.
This tool is free.
Website: ESPC.
IsNotSpam.com
This tool uses a slightly different version version of the software used by Check-auth to perform roughly the same checks, but the report are available as a web page instead of being returned by email.
One difference: The "iprev" (rDNS) check is replaced by something called an “Sender-ID Check” that just look like a repeat of the SPF check.
This tool is free.
Website: IsNotSpam.com.
Xeams.com
This free email-tool allows you to check HELO, rDNS, SPF, [DKIM] and DMARC for outgoing email from your domain and to see an evalutation of these authentication checks on any message you send.
It also does some checks that affects incoming emils: MX, IP-address, STARTTLS, SMTP Auth., that your MTA is not and open relay, and that you reject emails for invalid users.
To use the tool, simply send an email to with the word “validate”
in the subject line.  from the domain you want to test to this
email-address:
validate.server@synametrics.com.
The tool will mail you back a HTML report. If your email UA does not parse HTML, save the file and inspect it using a web browser.
 
Clicking on “Details…” for the DKIM check takes you to the following explanation:
“DKIM is a mechanism that checks if an incoming email's FROM address is forged.
You see this warning in two case:
- Your email did not have a DKIM signature
- An invalid signature was found”
The test message used to produce the above report was signed with a valid DKIM signature (accepted by Gmail, mail-tester.com, IsNotSpam.com et al), so I think the DKIM test in this tool is broken..
This tool is free.
Website: Xeams.com.
Not tested
Websites:
- ESPC (promising).
- GlockApps.com (recommended by Linuxbabe).
- SendForensics.com.
Unwashed:
https://www.sparkpost.com/blog/understanding-spf-and-dkim/ https://www.emailonacid.com/signup https://www.litmus.com/spam-filter-tests/ https://talosintelligence.com/reputation_center/lookup https://www.senderscore.org/ https://www.validity.com/products/250ok/ (being reworked)
Case: example.com
Below is a breakdown of testing one of my domains (here anonymized to “example.com”) on mail-tester.com.
Here is the ratings I've seen during testing:
10 - Wow! Perfect, you can send. 9.0 - Wow! Perfect, you can send. 8.0 - Good stuff. Your email is almost perfect. 7.3 - Good stuff. Your email is almost perfect. 7.0 - Good stuff. Your email is almost perfect. 6.8 - Not bad. Some inboxes might still refuse you. 6.1 - Not bad. Some inboxes might still refuse you. 5.0 - Not bad. Some inboxes might still refuse you. 3.8 - Consider yourself lucky if your email goes to an inbox. 3.1 - Consider yourself lucky if your email goes to an inbox. 0.8 - Your email may never see the light of an inbox.
Below is a breakdown of the segments that make up their report:
Message
Adresses:
From : bob@example.com Bounce address : postmaster@example.net
Text:
Greetings test-XXX@srvX.mail-tester.com, this is sent to you from Testmail Blåbærsyltetøy. -- This is an automatic email sent from Testmail to test email.
Source. This sample was recorded early on in the process, with a lot of failures.
Received: by mail-tester.com (Postfix, from userid 500)
	id B3DB7A8922; Tue, 20 Oct 2020 18:49:27 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on mail-tester.com
X-Spam-Level: **
X-Spam-Status: No/2.2/5.0
X-Spam-Test-Scores: RDNS_NONE=1.274,SPF_SOFTFAIL=0.972,URIBL_BLOCKED=0.001
X-Spam-Last-External-IP: 192.0.2.0
X-Spam-Last-External-HELO: fqdn.example.com
X-Spam-Last-External-rDNS: 
X-Spam-Date-of-Scan: Tue, 20 Oct 2020 21:07:09 +0200
X-Spam-Report: 
	*  0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was
	*      blocked.  See
	*      http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block
	*      for more information.
        *      [URIs: mail-tester.com]
        *  1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail)
        *  1.3 RDNS_NONE Delivered to internal network by a host with no rDNS
Received-SPF: Softfail (domain owner discourages use of this host) identity=mailfrom;
  client-ip=192.0.2.0; \
  helo=fqdn.example.com; \
  envelope-from=bob@example.com; \
  receiver=test-XXX@srvX.mail-tester.com 
DMARC-Filter: OpenDMARC Filter v1.3.1 mail-tester.com A87E1A6EFA
Authentication-Results: mail-tester.com; dmarc=none header.from=example.com
Received: from fqdn.example.com (unknown [192.0.2.0])
	(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by mail-tester.com (Postfix) with ESMTPS id 41B9FA8E66
	for ; Tue, 20 Oct 2020 21:07:05 +0200 (CEST)
Received: by fqdn.example.com (Postfix, from userid 33)
	id CF5E0FF621; Tue, 20 Oct 2020 19:07:04 +0000 (UTC)
To: test-XXX@srvX.mail-tester.com
Subject: Testmail for test-XXX@srvX.mail-tester.com from Testmail
MIME-Version: 1.0
Content-Type: text/plain;charset=utf-8
X-Mailer: Drupal
Sender: postmaster@example.net
From: bob@example.com
List-Unsubscribe: 
Message-Id: <20201020190704.CF5E0FF621@fqdn.example.com>
Date: Tue, 20 Oct 2020 19:07:04 +0000 (UTC)
Content-Transfer-Encoding: quoted-printable
Greetings test-XXX@srvX.mail-tester.com, this is sent to you from
Testmail.
Bl=C3=A5b=C3=A6rsyltet=C3=B8y.
--=20
This is an automatic email sent from Testmail to test email.
  
SpamAssassin
During the testing, I noticed various SpamAssassin failures. Below are the keys recorded, and scores associated with them:
SPF_PASS [+0.001] SPF_NEUTRAL [-0.652] SPF_SOFTFAIL [-0.972] SPF_HELO_SOFTFAIL [-0.896] SPF: HELO does not match SPF record (softfail) RDNS_NONE [-1.274] Delivered to internal network by a host with no rDNS
Authentication
During the testing, I noticed various authentication failures. Below are these recorded, and the scores associated with them.
- [SPF] example.com does not allow your server 192.0.2.0 to use bob@example.com [-3]
- Your message is not signed with DKIM [-1]
- You do not have a DMARC record [-].
- We didn't find a server (A Record) behind your hostname mail.example.com[-3].
- Your domain name example.com is assigned to a mail server. [+]
- Your server 192.0.2.0 is successfully associated with fqdn.example.com [+].
Format
- You have no images in your message.
- Your content is safe (no dangerous HTML-elements).
- Does not use an URL shortener system.
- Your message contains a List-Unsubscribe header.
Blacklist or deny-list
Your IP-address is not deny-listed.
Security
To able three conditions need to be satisfied:
- Trustworthy certificates
- Trustworthy protocol
- DANE (DNS-based Authentication of Named Entities)
STARTTLS
https://howtoinstall.co/en/starttlsEnforce TLS
Security check tools
https://serverfault.com/questions/131627/how-to-inspect-remote-smtp-servers-tls-certificateThis webbased tool: www.checktls.com
Will just returm the TLS vesion the site is running.
This webbased tool: ssl-tools.net/mailservers will check:
- STARTTLS support
- SSL certificate quality
- PFS (Perfect Forward Secrecy)
- Heartbleed
However, many properly configured servers are protected against port-scanning and you will only get:
No connection to the mailservers of example.net could be established.
This does not mean that the server is unable to receive encrypted email.
Troubleshooting
If you see the following log message in /var/log/mail.log:
… opendkim …: signing table references unknown key 'default._domainkey.example.com'
… check for typos in /etc/opendkim/key.table.
Final word
[TBA]
Last update: 2020-10-25 [gh].