I have a problem sending DKIM signed email with PHPMailer (v 5.2.9).
The SMTP Server that I use (realsender.com) should sign every email i send.
It works when I send email from a Delphi program but instead it doesn't work with PHP.
I've checked both the email sent by PHPMailer and Delphi with https://www.mail-tester.com
The results are 10/10 for Delphi and 6.8/10 for PHP.
This is a part of the file that send the email with PHPMailer:
$mail = new PHPMailer();
$mail->CharSet = 'UTF-8';
$mail->setLanguage('it');
$mail->isSMTP();
$mail->Host = SMTP_HOST;
$mail->SMTPAuth = SMTP_AUTH;
$mail->Username = SMTP_USERNAME;
$mail->Password = SMTP_PASSWORD;
if (defined('SMTP_PORT')) {
$mail->Port = SMTP_PORT;
}
if (defined('SMTP_SECURE')) {
$mail->SMTPSecure = SMTP_SECURE;
}
if(defined('DKIM_DOMAIN')){
$mail->DKIM_domain=DKIM_DOMAIN;
$mail->DKIM_selector=DKIM_SELECTOR;
$mail->DKIM_private=DKIM_PRIVATE;
}
[...]//setting from, to, subject and body
$mail->send();
Note: the $mail->send();
always return true.
Firstly I've tried to send email without setting DKIM_ property and then I tried to send with they.
in both cases the result is an invalid DKIM sign and a score of 6.8.
I have asked to the SMTP Support if they know something about this but they said that it may be a problem of PHPMailer itself.
What can i do to create a DKIM that works?
Thanks in advance.
UPDATE:
I discovered that the problem is in the body of the email.
I've also stopped using DKIM_ vars because my SMTP server automatically sign all emails.
sending the email empty, without tags or with tags but without text it's all ok (9.9), otherwise the score is 6.8.
Also a little html email (with links and divs) is ok.
What could it be?
I got it!
I had to split the body of the mail into small chunks (for a maximum of 990 characters per chunk), the reason (explained here: http://permalink.gmane.org/gmane.mail.postfix.user/223780) is:
A likely cause of breakage is that the sending application generates email that is incompatible with RFC 5322 or RFC 5321 in some respect.
Lines longer than 990.
The Postfix SMTP client keeps the line length below the SMTP protocol limit of 1000 bytes including . Since this change happens after signing, it will definitely break DKIM signatures.
To avoid long-line curruption problems send mail in quoted-printable or base64 encoding, with lines of at most 80 characters long.
This is the code I've used to split the string:
function create_html_email_from_string($str){
if(!is_string($str)){
return false;
}
return '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><body>'
.html_long_lines_split($str).'</body></html>';
}
/**
* this function insert line endings (\r\n) after the ending of <br>, <p> and <div> tags because if you only use chunk_split_unicode it can break links and any other tags and css.
*/
function html_long_lines_split($str){
$str = str_ireplace(['<br>','<br/>','<br />'], "<br/>\r\n", $str);
$str = str_ireplace('</p>', "</p>\r\n", $str);
$str = str_ireplace('</div>', "</div>\r\n", $str);
//checks if there are lines longer than 990 bytes
$chunks=explode("\r\n", $str);
foreach ($chunks as $k=>$c) {
if(strlen($chunks[$k])>990){
$chunks[$k]=chunk_split_unicode($chunks[$k], 500);
}
}
return implode("\r\n", $chunks);
}
/**
* @link http://php.net/manual/en/function.chunk-split.php#107711<br>
*/
function chunk_split_unicode($str, $l = 76, $e = "\r\n") {
$tmp = array_chunk(
preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY), $l);
$str = "";
foreach ($tmp as $t) {
$str .= join("", $t) . $e;
}
return $str;
}
//$mail is an instance of PHPMailer
$mail->msgHTML(create_html_email_from_string($body));