无法使用 phpmailer 从 php 签署 DKIM 电子邮件

Posted

技术标签:

【中文标题】无法使用 phpmailer 从 php 签署 DKIM 电子邮件【英文标题】:can't sign DKIM email from php with phpmailer 【发布时间】:2015-10-13 22:49:40 【问题描述】:

我在使用 PHPMailer (v 5.2.9) 发送 DKIM 签名电子邮件时遇到问题。

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

我已经检查了 phpMailer 和 Delphi 发送的电子邮件,https://www.mail-tester.com

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(); 总是返回 true。

首先我尝试在不设置 DKIM_ 属性的情况下发送电子邮件,然后我尝试与他们一起发送。 在这两种情况下,结果都是无效的 DKIM 标志和 6.8 分。

我已向 SMTP 支持部门询问他们是否对此有所了解,但他们说这可能是 PHPMailer 本身的问题。

我可以做些什么来创建一个有效的 DKIM?

提前致谢。

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

【问题讨论】:

您是否使用var_dump 验证了DKIM_* 常量? 看看DKIM unit test。您还可以通过启用异常获得更多错误报告:$mail = new PHPMailer(true);。最新的 PHPMailer 是 5.2.10,但没有与 DKIM 相关的更改。 【参考方案1】:

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

损坏的一个可能原因是发送应用程序生成的电子邮件在某些方面与 RFC 5322 或 RFC 5321 不兼容。

超过 990 行。

Postfix SMTP 客户端将行长度保持在 1000 字节的 SMTP 协议限制以下,包括 .由于此更改是在签名后发生的,因此肯定会破坏 DKIM 签名。

为避免长行损坏问题,请以带引号的可打印或 base64 编码发送邮件,行长最多为 80 个字符。

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

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

【讨论】:

以上是关于无法使用 phpmailer 从 php 签署 DKIM 电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

警告:require_once(Composer/PHPMailer/vendor/phpmailer/phpmailer/src/autoload.php):无法打开流:没有这样的文件或目录

phpmailer无法发送电子邮件

使用 phpMailer 和 PHP 从表单发送文件附件

使用 phpmailer 从 Gmail 发送电子邮件。登录错误

无法使用 PHPMailer 和 CRON 作业发送电子邮件

phpmailer错误“无法实例化邮件功能”