DomainKeys Identified Mail (DKIM) is a process used to validate emails preventing someone from sending spam email using an unauthorised email address. The process works using 2 encrypted SSL keys. A public key which is obviously made available to the public and a private key which only you / your web server will know. When you send an email you will attach your private key to the email. When gmail or any other web server gets the email, it will check to see if the public key that you have made available via your DNS zone file, matches up with the private key that was sent with the email. DKIM is a one useful method to prevent your emails ending up in spam folders.
Setting up DKIM for your web server may seem like it is incredibly complicated and there is no denying..it sucks! but as long as you have some experience working with a web server and have access to everything needed, you should be able to get this setup. To make life as easy as possible I will break this down into a series of individual steps.
Step 1 – Generate a private and public key
Creating your public and private keys are less complicated than you might think. SSL keys can be generated by any machine, you don’t have to register for an account anywhere or setup anything special. You simply download an application and it will generate the keys for you. It’s best to do this on your own machine rather than use an online service as you don’t know if the online service could be saving these keys.
So to create the keys you will need to download a command line SSL tool. You can find a download link here http://slproweb.com/products/Win32OpenSSL.html . Download and install this tool. In order to run it you will need to open up a command shell window (command prompt) in administrator mode if you are running windows vista or newer.
When in a command window run the following commands. You might need to give the direct path of the .exe file in order for the command to work. This will generate 2 files (rsa.private and rsa.public) in whatever folder you are currently in. It will be best to change directory to the desktop or the root of the C drive in order to get at these files quickly.
openssl genrsa -out rsa.private 1024 openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
You now have a public and private key!
Step 2 – Add DNS records
The DNS record is where you are going to store the public key. When gmail gets an email from your server it will check the dns record for the domain and see if there is a key available. If there is one there is will have the public key which it can use with the private key that was send with the email.
This part of the guide will depend on where your DNS zone file is hosted. For most people godaddy will likely be the place where the zone file is hosted. If you don’t use godaddy then you will have to find out how to edit your zone file. This is a very important file, so if you dont know how to edit it you will have bigger issues than setting up domain keys.
You need to add 2 TXT records to your zone file. I wanted to create a record for a noreply email address so that my server could send out emails to users automatically and the emails would make it to the inbox folder and not the spam folder.
Add the following data to the Host and TXT fields of your zone file.
_domainkey.yomotherboard.com o=~; [email protected] mainkey._domainkey.yomotherboard.com k=rsa; p=PUBLIC KEY HERE
NOTE!! Make sure the public key is one long string with out any whitespace or line breaks. The SSL tool will generate the file with line breaks so make sure you remove them all and make it one long file.
Save these changes and in an hour or so (up to 48 hours in on a bad day) this TXT record will be live.
Step 3 – Sending the private key with an email
This part very much depends on your programming language and the email client you are using with that programming language.
So for example if you are using PHPMailer, you can setup the private DKIM key by adding the following lines to your code
$mail->DKIM_domain = "nerdburglars.net"; $mail->DKIM_private = "rsa.private"; //path to file on the disk. $mail->DKIM_selector = "mainkey";// change this to whatever you set during step 2 $mail->DKIM_passphrase = ""; $mail->DKIM_identifier = $mail->From;
So this is it, you are finished! Not so bad right? May take a while for the updates to show up since DNS zone file changes can take a while to update across the internet, but once they do you will be all set with DKIM keys correctly setup for your emails. Remember that this is only 1 method of improving the odds of your emails not ending up in a spam folder, but doesn’t guarantee it. You may also need to setup a reverse lookup in order to make yourself 100% safe.
excellent post, I managed to configure the DKIM on my server to improve the quality of my emails, but I am concerned about the security of the file “dkim_private.pem” since stored on the server anyone who locates the file path will have access to it, any idea how to protect it.
You should be securing your server. Don’t give access to anyone you don’t trust. I hope by file path you don’t mean that you have this file stored in a location that Apache serves and someone can access via a http request from a web browser?
Thank you for the great article, it’s very much needed. I found this from the stackoverflow thread https://stackoverflow.com/questions/24463425/send-mail-in-phpmailer-using-dkim-keys/24464694#24464694 . I suggest you edit the blog with the latest updates (like Marcus’s comment) so we don’t run into unknown errors while following it.
Dan, Great write up. I’ve been trying to get Postfix Mail server to authorize PHPMailer emails using openDKIM and stumbled on this article.
Just a note. DKIM uses a private key to sign the headers in the email. DKIM then attaches this “signature” as an additional header that the receiving MTA can verify by calling the corresponding public key from your DNS server. You don’t actually send your private key.
Terry, the record you are referring to is a DomainKeys single policy record. “o=-” means “all e-mails from this domain are signed”, and “o=~” means “some e-mails from this domain are signed.” Here is more if you want to dig in: http://support.simpledns.com/kb/a62/configuring-dns-records-for-domainkeys-dkim.aspx. “DKIM” is the successor to Yahoo’s “DomainKeys” so I’m not sure how prevalent single policy records are any more.
Finally if you are using PHPMailer you may want to upgrade APAP. All versions PHPMailer prior to 5.2.20 (released December 28th 2016) are vulnerable to a remote code execution. Here are the gory details. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html. Here is the repo to update: https://github.com/PHPMailer/PHPMailer.
Much appreciated, thank you for the detailed response. Glad to know of the security issues with phpmailer
Dan, Great write up. I’ve been trying to get Postfix Mail server to authorize PHPMailer emails using openDKIM and stumbled on this article.
Just a note. DKIM used a private key to sign the headers in the email. DKIM then attaches this “signature” as an additional header that the receiving MTA can verify by calling the corresponding public key from your DNS server. You don’t actually send your private key.
Terry, the record you are referring to is a DomainKeys single policy record. “o=-” means “all e-mails from this domain are signed”, and “o=~” means “some e-mails from this domain are signed.” Here is more if you want to dig in: http://support.simpledns.com/kb/a62/configuring-dns-records-for-domainkeys-dkim.aspx. “DKIM” is the successor to Yahoo’s “DomainKeys” so I’m not sure how prevalent single policy records are any more.
Finally if you are using PHPMailer you may want to upgrade APAP. All versions PHPMailer prior to 5.2.20 (released December 28th 2016) are vulnerable to a remote code execution vulnerability. Here are the gory details. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html. Here is the repo to update: https://github.com/PHPMailer/PHPMailer.
I only have shared hosting plan, can I still do this?
You can set the domain side of things, but the mail server wont be something you can access. You should be able to contact the hosting provider and they will help you out.
Great article! Actually the best one I found. It is really well explained and takes 10 mins to set it up. Thank you!
Thanks for this article.
You said:
_domainkey.yomotherboard.com o=~; [email protected]
Do you know what this o=~; means ???
Thanks for this article. I’ve added a DKIM example to PHPMailer’s examples folder.
One small mistake: `$mail->DKIM_identifier` should be `$mail->DKIM_identity`
In you example:
_domainkey.yomotherboard.com o=~; [email protected]
mainkey._domainkey.yomotherboard.com k=rsa; p=PUBLIC KEY HERE
Should I type “_domainkey.yomotherboard.com” in Host field and type “o=~; [email protected]” in TXT field?
oh no, you will need to replace this with the information for your domain, this was just an example of how it would be done for a domain. There are some free tools out there that will generate the lines for you if you are having trouble
I use phpmailer. But for me it is not clear where I should add the 5 lines of code into class-phpmailer.php.
You dont add them to the class you use them on an object of the class. So it will look something like this $mail = new PHPMailer().
With a fine quality CPU and few video cards installed anyone can have a dynamic gaming experience.
The slimmer design also helps it keep pace with the stylish designs
of its competitors. In addition, it is as important to
keep the i – Pad safe as well as keep it look trendy.
I’ve been working with PHPMailer and DKIM. I’m seeing conflicting things about the DNS Zone file. From the WorxWare key generation tool, they say to add this to your DNS Resource Record:
phpmailer._domainkey IN TXT “v=DKIM1; k=rsa; g=*; s=email; h=sha1; t=s; p=public key here;”
But you say to add:
_domainkey.yomotherboard.com o=~; [email protected]
mainkey._domainkey.yomotherboard.com k=rsa; p=PUBLIC KEY HERE
to both the A and TXT records.
Can you help clarify the difference in instructions?
so in this case “phpmailer” is the key. The content of the key doesnt really matter as long as its unique, but it can be whatever you want it to be
Thank you so much for your article. Found it in the replies of a stackoverflow thread.
Super helpful, a lot easier than everything else i’ve seen around 😀
Cheers