There have been much written about DKIM signing for phpList and I just wanted to tell everyone that it is in fact possible to sign messages from within phpList. The reason why this is possible is that phpList relies on PHPMailer and this library actually supports DKIM.
First the disclamers
- I know that its possible and probably better to setup your own mail server with DKIM signing and route all messages though this. But as One.com customer I did not have that luxury, so I decided to have a look into the code and see what was needed to implement a php dkim solution into the code.
- This example and code have not been tested extensively yet, but I have successfully signed messages to be properly approved by multiple large mail vendors.
- I know that a proper solution will include config file options, and admin panels, but that is outside the scope for this post.
- I will not try to teach you how DKIM works in this post, search google. There are many sources out there much more capable than me
- I am not affiliated with phpList or One.com
So the steps required (domain example.com used):
Step 1:
Create DKIM private and public keys. I used openssl, but there are also web sites that can do this if you trust them. I chose to call the key s1, you can call it whatever you like.
$ openssl genrsa -out s1.example.com.pem 1024
$ openssl rsa -in s1.example.com.pem -pubout > s1.example.com.pub
For my test I did not create a passkey for the private certificate.
Step 2:
Open file s1.example.com.pub and remove first and last lines (the ones starting with âââ), and remove all linefeeds so that you have one long line without spaces etc.
Step 3:
I used One.com DNS panel to create one TXT record called s1._domainkey.example.com with TTL 900 and value :
v=DKIM1; k=rsa; s=email; p=<paste in long key from step 2 here>
Although unrelated to DKIM , if you are also using One.com you should probably also create an DNS record named .example.com of type TXT with TTL 3600 and value :
v=spf1 include:_custspf.one.com ~all
This will ensure that you also get spf=pass in Step 8.
Step 4:
Upload private key to web server. I used the phpList config directory for my test but I also changed .htaccess to disallow access to pem files.
copy s1.example.com.pem -> //lists/config/s1.example.com.pem
Step 5:
Modify first line of lists/config/.htaccess
<FilesMatch "\.(php|inc|pem)$">
Step 6:
Modify file lists/admin/class.phplistmailer.php
In public function __construct add the following lines after $this->addCustomHeader
// Test of DKIM
$this->DKIM_domain = 'example.com';
$this->DKIM_selector = 's1';
$this->DKIM_private = '/customers/8/d/3/example.com/httpd.www/lists/config/s1.example.com.pem';
$this->DKIM_passphrase = '';
$this->DKIM_identity = 'newsletter@example.com';
For One.com the full file system path is available under Advanced in the Control Panel.
Step 7:
Send a test mail to mail provider that will verify DKIM and check the raw email source
Step 8:
Look for a block like this:
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; l=10578; s=s1;
t=1497644660; c=relaxed/simple;
h=From:To:Date:Subject;
.
.
This proves that the email was signed by phpList with key s1.
Then look for a block that looks like this (format might vary between providers) :
Authentication-Results: spf=pass (sender IP is xx.xx.xx.xx)
smtp.mailfrom=example.com; vendor.com; dkim=pass (signature was verified)
header.d=example.com;vendor.com; dmarc=bestguesspass action=none
header.from=example.com;
This message should contain dkim=pass which proves that this email vendor verified the signed mail to our public key in DNS.
Regards Kjetil