在基于 PHP 的 SMTP 客户端中设置 DomainKeys/DKIM
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/2799611/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting up DomainKeys/DKIM in a PHP-based SMTP client
提问by Alex Weinstein
It looks like there are some great libraries out there to do DomainKeys signing of emails on C#/.NET, but I'm having a really hard time finding the same kind of support for PHP. Maybe I'm not looking in the right place?
看起来有一些很棒的库可以在 C#/.NET 上对电子邮件进行 DomainKeys 签名,但是我很难找到对 PHP 的相同类型的支持。也许我没有找对地方?
The only one I found is http://php-dkim.sourceforge.net/; it looks incredibly hacky and supports PHP4 only. Considering how popular PHP is, and how critical DomainKeys are for email classification as non-spam, I'd expect better tools; do you know of any? Any other tricks you'd recommend?
我发现的唯一一个是http://php-dkim.sourceforge.net/;它看起来非常hacky 并且只支持PHP4。考虑到 PHP 的流行程度,以及 DomainKeys 对于将电子邮件分类为非垃圾邮件的重要性,我希望有更好的工具;你知道吗?你有什么其他的技巧推荐吗?
Extra info: I'm using an external SMTP provider because I need to send out thousands of emails per day.
额外信息:我正在使用外部 SMTP 提供商,因为我每天需要发送数千封电子邮件。
采纳答案by codercake
I'd recommend DKIM support at the MTA level so all your server generated email for a given domain is signed by default. (unless you have a really good reason to not sign all server generated email for a domain).
我建议在 MTA 级别提供 DKIM 支持,以便默认情况下对给定域的所有服务器生成的电子邮件进行签名。(除非您有充分的理由不对域的所有服务器生成的电子邮件进行签名)。
The best starting point in my googling to get DKIM setup on LAMP with dkim-milter and sendmail (on CentOS 5.2 in my case) was Jeff Atwood's post about sending emails through code.
我使用 dkim-milter 和 sendmail(在我的情况下在 CentOS 5.2 上)在 LAMP 上使用谷歌搜索设置 DKIM 的最佳起点是Jeff Atwood 关于通过代码发送电子邮件的帖子。
I would agree with him that the first 2 things you should address are reverse PTR record and DKIM signing.
我同意他的观点,你应该解决的前两件事是反向 PTR 记录和 DKIM 签名。
Also very important:
也很重要:
- IP address of the box to send email not already being blacklisted.
 - make sure [email protected] is a valid email box
 - if your server generated email needs to appear to come from somewhere else (like a contact form needing to come from name/email provided in a form) follow these guidelines for email headers.
 
- 发送电子邮件的邮箱的 IP 地址尚未被列入黑名单。
 - 确保 [email protected] 是一个有效的邮箱
 - 如果您的服务器生成的电子邮件需要看起来来自其他地方(例如联系表单需要来自表单中提供的姓名/电子邮件),请遵循这些电子邮件标题指南。
 
Here is the email ip address blacklist checkerthat I used.
这是我使用的电子邮件 IP 地址黑名单检查器。
Those 5 things will solve perhaps 95% of your email deliverability issues.
这 5 件事可能会解决 95% 的电子邮件送达率问题。
This Guide for Fedora/dkim-milter/postfixis also very good.
这个Fedora/dkim-milter/postfix 的指南也很好。
The PHP mail library I use for my app is PHPMailer 5.1 which has DKIM support (and is PHP 5 only), but after doing the research, I decided implementing at the sendmail level was a better solution. As you can see, even the author of PHPMailer 5.1 does not suggest DKIM at the PHP mail library level is the best solution http://dkim.worxware.com/.
我用于我的应用程序的 PHP 邮件库是 PHPMailer 5.1,它具有 DKIM 支持(并且仅支持 PHP 5),但在进行研究后,我决定在 sendmail 级别实施是一个更好的解决方案。如您所见,即使是 PHPMailer 5.1 的作者也不建议在 PHP 邮件库级别使用 DKIM 是最佳解决方案http://dkim.worxware.com/。
Best of luck to you.
祝你好运。
回答by Nepaluz
This is one that has been on my radar for a while and could not find a definitive answer to the original question in this thread anywhere on the web. I have now been able to implement sending DKIM signed SMTP email with PHP/Pear. Below are the steps required.
这是一个已经在我的雷达上一段时间并且无法在网络上的任何地方找到该线程中原始问题的明确答案的问题。我现在已经能够使用 PHP/Pear 实现发送 DKIM 签名的 SMTP 电子邮件。以下是所需的步骤。
I found a modified version of the DKIM from http://www.ra726.net/blog/2010/07/20/sending-email-to-gmail-from-php-without-being-marked-as-spam/(you can download it via http://www.ra726.net/php-dkim.zip). If you have already implemented DKIM and just need to make it work with SMP mail then all you need from this is the dkim.php file which, as the blog says, is slightly modified to handle headers passed as an array. In my code, I have named it dkimNEW.php.
Ensure you include most headers so that the MTA does not modify the message after you have signed it. In my limited research, the most added headers are the Date and Message-ID headers, thus my header array looks like this: Note: I used this for sending an html email, change to suit! Also, add your domain as the last part of the Message-ID
$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 $headersYou will then get to utilize the modified dkim.php mentioned above to sign your email AND add the signature to the headers array, aka
require 'dkimNEW.php'; $dkim = AddDKIM($headers, $subject, $body); $headers['DKIM-Signature'] = $dkim;
我从http://www.ra726.net/blog/2010/07/20/sending-email-to-gmail-from-php-without-being-marked-as-spam/(您可以通过http://www.ra726.net/php-dkim.zip下载)。如果您已经实现了 DKIM 并且只需要使其与 SMP 邮件一起使用,那么您需要的只是 dkim.php 文件,正如博客所说,该文件经过轻微修改以处理作为数组传递的标头。在我的代码中,我将其命名为 dkimNEW.php。
确保包含大多数标题,以便 MTA 在您签署邮件后不会修改邮件。在我有限的研究中,添加最多的标头是 Date 和 Message-ID 标头,因此我的标头数组如下所示: 注意:我用它来发送 html 电子邮件,更改以适应!此外,将您的域添加为 Message-ID 的最后一部分
$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然后,您将可以使用上面提到的修改后的 dkim.php 来签署您的电子邮件并将签名添加到 headers 数组,也就是
require 'dkimNEW.php'; $dkim = AddDKIM($headers, $subject, $body); $headers['DKIM-Signature'] = $dkim;
The rest of the code is the normal code to send email via SMTP with PHP/Pear. The full working code is:
其余代码是使用 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 <[email protected]>';
    $to = 'First Recipient <[email protected]>';
    $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('[email protected]', '[email protected]');
    $mail = $smtp->send($recipients, $headers, $body);
?>
PS. Just in case you did not notice, replace values with your own!
附注。以防万一您没有注意到,用您自己的值替换值!
Therefore, all that is essentially needed to make DKIM to work with SMTP email (or indeed the PHP mail) is to ensure that you specify all the headers that are added to your email by your MTA, then sign the headers, subject and body of the message, and finally include that signed portion with your header.
因此,使 DKIM 与 SMTP 电子邮件(或实际上是 PHP 邮件)一起工作所需要做的就是确保您指定由 MTA 添加到您的电子邮件的所有标头,然后对标头、主题和正文进行签名消息,最后在您的标题中包含该签名部分。
回答by amarullz
Have you try : phpMailDomainSignerIt support DKIM-Signature and DomainKey-Signature in Object Oriented Style.
您是否尝试过:phpMailDomainSigner它支持面向对象风格的 DKIM-Signature 和 DomainKey-Signature。
Here some example:
这里有一些例子:
// 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);
回答by Louis Ameline
A class solely for DKIM which is a spin-off from PHPMailer, but with improvements regarding the respect of the RFC and nice-and-clean code :
一个专门用于 DKIM 的类,它是 PHPMailer 的衍生产品,但在尊重 RFC 和简洁的代码方面进行了改进:
https://sourceforge.net/projects/dkim-class-php/
https://sourceforge.net/projects/dkim-class-php/
Example :
例子 :
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);

