无法使用 phpmailer 为来自 php 的 DKIM 电子邮件签名

can't sign DKIM email from php with phpmailer


我在使用 PHPMailer (v 5.2.9).

发送 DKIM 签名电子邮件时遇到问题

我使用的 SMTP 服务器 (realsender.com) 应该对我发送的每封电子邮件进行签名。
当我从 Delphi 程序发送电子邮件时它有效,但它不适用于 PHP.

我已经用 https://www.mail-tester.com

检查了 PHPMailer 和 Delphi 发送的电子邮件

Delphi 的结果为 10/10,PHP 的结果为 6.8/10。

这是使用 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();

注意:$mail->send(); 始终 return 为真。

首先,我尝试在不设置 DKIM_ 的情况下发送电子邮件 属性,然后我尝试使用它们发送。
在这两种情况下,结果都是无效的 DKIM 符号和 6.8 分。

我问过 SMTP 支持,他们是否知道这件事,但他们说这可能是 PHPMailer 本身的问题。

我该怎么做才能创建有效的 DKIM?

提前致谢。

更新:
我发现问题出在邮件正文中。
我也停止使用 DKIM_ vars,因为我的 SMTP 服务器会自动签署所有电子邮件。
发送空邮件,没有标签或有标签但没有文本都可以(9.9),否则分数为6.8.
还有一点 html 电子邮件(带有链接和 div)也可以。
可能是什么?

我明白了!
我不得不将邮件正文分成小块(每块最多 990 个字符),原因(此处解释:http://permalink.gmane.org/gmane.mail.postfix.user/223780)是:

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.

这是我用来拆分字符串的代码:

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));