在基于PHP的SMTP客户端中设置DomainKeys/DKIM

31

看起来有一些很好的库可以在C#/.NET上对电子邮件进行域密钥签名,但我很难找到同样支持PHP的库。也许我没有找对地方?

我唯一找到的是http://php-dkim.sourceforge.net/;它看起来非常不专业并且只支持PHP4。考虑到PHP的普及度以及域密钥对于将电子邮件分类为非垃圾邮件的重要性,我期望有更好的工具;你知道吗?你有什么其他建议吗?

额外信息:我正在使用外部SMTP提供程序,因为我每天需要发送数千封电子邮件。

4个回答

26
我建议在MTA级别支持DKIM,这样给定域的所有服务器生成的电子邮件都会默认签名(除非您有非常充分的理由不对该域的所有服务器生成的电子邮件进行签名)。
在搜索如何在LAMP上使用dkim-milter和sendmail设置DKIM(在我的情况下是CentOS 5.2)时,Jeff Atwood发布的有关通过代码发送电子邮件的帖子是最好的起点。
我同意他的看法,你应该先解决反向PTR记录和DKIM签名这两个问题。
还有一些非常重要的事项:
1. 发送电子邮件的计算机的IP地址没有被列入黑名单。 2. 确保postmaster@emailsendingdomain.com是一个有效的电子邮件邮箱。 3. 如果服务器生成的电子邮件需要显示来自其他地方(例如,联系表单需要来自表单中提供的名称/电子邮件),请遵循电子邮件标头的指南
这是我使用的电子邮件IP地址黑名单检查器
这些5个事项可能会解决95%的电子邮件可投递性问题。
Fedora/dkim-milter/postfix指南也非常好。
我使用的应用程序PHP邮件库是PHPMailer 5.1,它支持DKIM(仅适用于PHP 5),但经过研究后,我决定在sendmail级别实现更好的解决方案。正如您所看到的,即使是PHPMailer 5.1的作者也不建议在PHP邮件库级别上实现DKIM是最佳解决方案http://dkim.worxware.com/
祝你好运。

有用的信息,但不适用于我,抱歉。我正在使用外部SMTP电子邮件提供商,无法控制他们的代码。因为我要发送数千封电子邮件,所以必须使用它们。其他建议与我的问题没有直接关系。 - Alex Weinstein
@Alex:我本来想为PHP编写自己的DKIM实现,但我同意jigglee的观点:MTA应该处理它。想象一下,如果MTA更改/重新格式化电子邮件内容,PHP无法事先知道,这将导致私钥/公钥失效,产生相反的效果。 - Alix Axel
@AlexWeinstein 如果这个解决方案不适合您,为什么标记为答案?我也在使用第三方电子邮件提供商,但这似乎不是正确的答案... - Alejandro García Iglesias

17

这是一件我已经关注了一段时间的事情,在整个网络上都找不到对原问题的明确定义,现在我已经能够使用PHP/Pear发送带有DKIM签名的SMTP电子邮件。以下是所需步骤:

  1. 我在 http://www.ra726.net/blog/2010/07/20/sending-email-to-gmail-from-php-without-being-marked-as-spam/ 找到了一个修改过的DKIM版本(您可以通过 http://www.ra726.net/php-dkim.zip 下载它)。如果您已经实现了DKIM并且只需要使其与SMP邮件配合工作,则只需从中获取dkim.php文件,如博客所述,该文件稍微修改以处理作为数组传递的头部。在我的代码中,将其命名为dkimNEW.php。

  2. 确保包含大多数标题,以便MTA在您签署之后不会修改消息。根据我的有限研究,最常添加的标题是日期和Message-ID标头,因此我的标头数组如下所示:注意:我将其用于发送HTML电子邮件,更改以适应您的需求!此外,请将您的域添加为Message-ID的最后部分。

  3. $headers = array(
        'Subject' => $subject,
        'From' => $from,
        'To' => $to,
        'MIME-Version' => '1.0',
        'Date' => date('r'),
        'Message-ID' => '<'.sha1(microtime(true)).'@yourdomain.com>',
        'Content-Type' => 'text/html',
        'Content-Transfer-Encoding' => 'quoted-printable',
    ); // end $headers
    
  4. 然后,您将能够使用上述修改后的 dkim.php 对您的电子邮件进行签名,并将签名添加到头部数组中,即

    require 'dkimNEW.php';
    $dkim = AddDKIM($headers, $subject, $body);
    $headers['DKIM-Signature'] = $dkim;
    
    其余的代码是使用PHP/Pear通过SMTP发送电子邮件的常规代码。 完整的工作代码如下:
    <?php
        require_once 'Mail.php';
        require_once 'Mail/mime.php';
      // set all of the parameters
        $subject = 'Test of DKIM';
        $from = 'My Name <myname@mydomain.com>';
        $to = 'First Recipient <recipient1@domain.com>';
        $pbody ='<html><head></head><body><h1>Done! DKIM test</h1>Result, next?</body></html>';
        $text = strip_tags($pbody);
    
        // create the headers
        $headers = array(
            'Subject' => $subject,
            'From' => $from,
            'To' => $to,
            'MIME-Version' => '1.0',
            'Date' => date('r'),
            'Message-ID' => '<'.sha1(microtime(true)).'@mydomain.com>',
            'Content-Type' => 'text/html',
            'Content-Transfer-Encoding' => 'quoted-printable',
        ); // end $headers
    
    
        // create the message
        $mime = new Mail_mime("\n");
        $mime->setTXTBody($text);
        $mime->setHTMLBody($pbody);
    
        // always call these methods in this order
        $body = $mime->get();
        $headers = $mime->headers($headers);
    
        require 'dkimNEW.php' ;
        $dkim = AddDKIM($headers, $subject, $body);
        $headers['DKIM-Signature'] = $dkim;
    
        // create the smtp mail object
        $smtp_params = array(
            'host' => 'mail.mydomain.com',
            'auth' => true,
            'username' => 'myUserName',
            'password' => 'myPassWord',
        ); // end $smtp_params
        $smtp = Mail::factory('smtp', $smtp_params);
    
        // send the message
    
        $recipients = array('recipient1@domain.com', 'recipient2@domain.com');
        $mail = $smtp->send($recipients, $headers, $body);
    
    ?>
    

    顺便提醒一下,将数值替换为您自己的数值!

    因此,要使DKIM与SMTP电子邮件(或PHP邮件)正常工作,基本上需要确保您指定了由您的MTA添加到电子邮件中的所有标头,然后对消息的标头、主题和正文进行签名,并最终将签名部分与标头一起包含。


11

你尝试过这个吗:phpMailDomainSigner 它以面向对象的方式支持DKIM-Signature和DomainKey-Signature。

以下是一些示例:

// Create mailDomainSigner Object
include_once './lib/class.mailDomainSigner.php';

$mds = &new mailDomainSigner($domain_priv,$domain_d,$domain_s);
$new_data = $mds->sign(
                $mail_data,
                "Message-ID:Subject:From:Content-Type:MIME-Version:Content-Transfer-Encoding:Received:To:Date",
                true,true,false);

这将带您前往最新版本的下载链接:http://code.google.com/a/apache-extras.org/p/phpmailer/downloads/list此外,PHPMailer 的原始项目管理员创建了一个用于创建 DKIM 文件以使用 PHPMailer 签署电子邮件的网站:http://dkim.worxware.com/ - Cameron

10

这是一个专门用于DKIM的类,它是由PHPMailer分支而来,但在尊重RFC方面进行了改进,并且代码易读易懂:

https://sourceforge.net/projects/dkim-class-php/

示例:

include_once('dkim.class.php');
$dkim = new DKIM();
$dkim_header = $dkim -> get_DKIM_header($to, $subject, $message, $headers);
mail($to, $subject, $message, $dkim_header.$headers);

该项目已迁移到GitHub:https://github.com/louisameline/php-mail-signature - Gerald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接