DKIM configuration for Postfix & Plesk

Before starting this post I want to thanks Ilija from as this post is based on his work on SPF / DKIM for Debian. Click here to see the original post.

Let’s start with a very short description of DKIM. DomainKeys Identified Mail is a mechanism designated to detect email spoofing (i.e. be sure that the original email content is the same as the received). It works with signatures. The public key is available on a DNS entry of the sender domain zone and the private key used to generate this signature is stored on the mail server.
This post will show how to configure DKIM on a Debian server with Postfix and automatize the configuration with Plesk. I assume you have sufficient permission to run these commands.

Runing configuration

Debian wheezy 3.2.0-4-amd64
Postfix 2.9.6
Plesk 12.0
OpenDKIM 2.6.8

After a great disscussion with M. Lieske who did a new install in August 2016, I can confirm it works with Debian jessie 8.5, OpenDKIM 2.9.2 (with some adjustements in the script below, see notes) and Plesk 12.5


Let’s start with the installation of the OpenDKIM package

OpenDKIM configuration

Great ! The next part is to create the directory structure for every parts of OpenDKIM

 We have to create the key tables, signing tables and trusted hosts files

Trusted hosts file contain a list of domain / servers that is trusted. In our case every DNS name and IP of the mail server should appear in this list. Let’s setup the local server name

Key table file contain information about where the key files are for every domains. Signing Table contain information about which domain / mail address should use DKIM signature.

Next phase is to check the OpenDKIM main configuration located in /etc/opendkim.conf. Here is one possible configuration.

After any changes to OpenDKIM configuration file, restart the service

Postfix configuration

The base setup of OpenDKIM is done we have now to setup Postfix to use it as milter. Open the /etc/postfix/ and add the “inet:” value to the smtpd_milters and non_smtpd_milters configuration values. There should already have other milters configured (psa-pc-remote / OpenDMARC / SPF), it depends from your actual configuration of Postfix. The order of the milters are important, especially for OpenDMARC that should be the last one as it depends of SPF and OpenDKIM.

The reason to disable the Plesk milter for non_smtpd_milters is only because I have some local scripts that would be rejected by SPF. When the changes to is done we have to restart the Postfix daemon to apply the configuration

OpenDKIM domain scripts

At this point OpenDKIM is configured and active in Postfix, last step is to generate Keys for every domains. Here is the full script that will enable DKIM for a specific domain. This script will :

  1. Create the Keys
  2. Setup the Signing Table to enable the DKIM signature for all addresses of this domain
  3. Add the domain to the trusted hosts file
  4. Create the DNS record on the Plesk Database
  5. Update DNS configuration via a Plesk CLI command
  6. Reload services to apply the changes
  7. Be sure to enable SPF signing for this domain.

When a domain is removed from the server the configuration has to be cleaned here is the script that do all these actions :

Plesk automation

When a domain is created or removed from Plesk it would be fun to automatize DKIM activation or deactivation. Fist we have to create another custom script to handle every action for a domain creation and another one when the domain is removed. Even if Plesk events handler can have multiple command lines it’s better to only do a call to an external script.

For the example let’s have a script folder at the system root /scripts/ that will contain every scripts. The first one is “”. It contains every lines of the OpenDKIM creation script shown above. The second one is “” and contain the removal script above. These scripts can be executed only from the root user (chmod 700).

Let’s create the script “” that will be called when a new domain is created :

And the script “” that will be called when a domain is removed :

Next phase is to configure Plesk Event Manager. Log on to Plesk with administrator account an go to Server Management -> Tools & Settings -> Tools & Ressources -> Event Manager.

Create a new Event Handler for the domain creation :


Then create a new Event Handler for the domain removal :


Configure OpenDKIM for every active domains on the Plesk server

The Plesk Event Handler doesn’t help to configure OpenDKIM of all already active domains on the Plesk Server. A little command that call the script for every domain can be used :

This command line extract all domains that have a DNS zone from Plesk database and call the script with the domain name as parameter.


The easiest way to test if the DKIM signature has been applied to a specific domain, you just have to send an email from this domain to you will receive a response with the DKIM result like this :

You can also check the headers of an outgoing mail to validate that the mail has been signed :

The mail log of the server will also show your the whole process of a mail. To do a real time trace :

And that’s all for this post, thanks for reading.


  1. Dennis Meinen

    Can that updated for Debian Jessie also Debian 8?

    root@mail:~/scripts# mysql -N -u admin -pcat /etc/psa/.psa.shadow psa -e “SELECT name FROM dns_zone WHERE status = 0” | awk ‘{print “/scripts/ “$1″”}’ | bash
    bash: Zeile 1: /scripts/ Datei oder Verzeichnis nicht gefunden
    bash: Zeile 2: /scripts/ Datei oder Verzeichnis nicht gefunden
    bash: Zeile 3: /scripts/ Datei oder Verzeichnis nicht gefunden
    bash: Zeile 4: /scripts/ Datei oder Verzeichnis nicht gefunden
    bash: Zeile 5: /scripts/ Datei oder Verzeichnis nicht gefunden
    bash: Zeile 6: /scripts/ Datei oder Verzeichnis nicht gefunden

    1. Stéphane (Post author)

      Hello Denis,

      This post should also work on Debian 8. The issue you have is that the “” script is not present in the folder /scripts/ or dosen’t have the execute permission.

      To change the script location edit the part in bold in this script line : mysql -N -u admin -pcat /etc/psa/.psa.shadow psa -e "SELECT name FROM dns_zone WHERE status = 0" | awk '{print "/scripts/ "$1""}' | bash

      If this is an issue with permission, please ensure that the script is owned by root and have permission to execute it :
      chown root:root /scripts/
      chmod 740 /scripts/

      Have a nice day,

      1. Dennis Meinen

        Hello Stéphane,

        I have now against a problem and that is with the domainkeys record. There is only a mail.domainkey created and not a default how can I get it?

        1. Stéphane (Post author)

          Hello Denis,

          It’s not mandatory to have the record default._domainkey.domain.tld. You can set mail._domainkey.domain.tld or whateveryouwant._domainkey.domain.tld. The important part is to have _domainkey.domain.tld. (the remote mail server that query the DNS will just get everything in TXT under _domainkey.domain.tld.

          If you want to change the script to use default._domainkeys.domain.tld instead of “mail” you just have to change the line 34 of and replace “mail._domainkey” in the INSERT SQL query by “default._domainkey”.

          I hope it will help you.

  2. Michael

    Hi, I have some problems to put in on road. Test from fail,

    Summary of Results
    SPF check: pass
    DomainKeys check: pass
    DKIM check: fail
    Sender-ID check: pass
    SpamAssassin check: ham

    DKIM check details:
    Result: fail (signature doesn’t verify)

    I’m not sure what is wrong, because the mail._default TXT record is available.

    1. Stéphane (Post author)

      Hi Michael,
      There is multiple possiblities, but before finding the source of this issue, could you please validate in the e-mail headers that the DKIM signature is present ?
      Have a nice day,


Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.