通过 Zend Mail 发送邮件未通过 DKIM 签名并在 qq.com 中变成垃圾邮件
Sending mails via Zend Mail failing DKIM signature and going to spam in qq.com
我正在努力使用 ZF2 发送电子邮件。问题是它们在我测试过的其他邮件客户端中都运行良好,但在 qq.com 中,所有邮件都会进入垃圾邮件文件夹。这是我用来发送邮件的代码:
$mailTransportModel = $sl->get('MailTransportModel');
$transport = $mailTransportModel->getMailTransport($parameters['api_key']);
$messageIdHost = $config['mailServers'][$parameters['api_key']]['messageIdHost'];
$mail = new Zend\Mail\Message();
$mail->addTo($parameters['to'])
->setFrom($parameters['from_email'], $parameters['from_name'])
->setSubject(CommonLib::assignTemplateVariables($parameters['template']['subject'], $parameters['context_variables']));
if(!empty($parameters['replyto_email'])) {
if(!empty($parameters['replyto_name'])) {
$mail->addReplyTo($parameters['replyto_email'], $parameters['replyto_name']);
} else {
$mail->addReplyTo($parameters['replyto_email']);
}
}
$headers = $mail->getHeaders();
$messageId = sha1($config['salt'] . microtime());
$headers->addHeaderLine('Message-Id', "<" . $messageId . "@" . $messageIdHost . ">");
$html = new Part(CommonLib::assignTemplateVariables($parameters['template']['body'], $parameters['context_variables']));
$body = new Zend\Mime\Message();
// Create HTML part
$html = new Part(CommonLib::assignTemplateVariables($parameters['template']['body'], $parameters['context_variables']));
$html->type = Mime::TYPE_HTML;
$html->charset = 'utf-8';
// Create plain text part
$stripTagsFilter = new \Zend\Filter\StripTags();
$textContent = str_ireplace(array("<br />", "<br>"), "\r\n", CommonLib::assignTemplateVariables($parameters['template']['body'], $parameters['context_variables']));
$textContent = $stripTagsFilter->filter($textContent);
$textPart = new Zend\Mime\Part($textContent);
$textPart->type = Mime::TYPE_TEXT;
// Create separate alternative parts object
$alternatives = new Zend\Mime\Message();
$alternatives->setParts(array($textPart, $html));
$alternativesPart = new Zend\Mime\Part($alternatives->generateMessage());
$alternativesPart->type = Mime::MULTIPART_ALTERNATIVE . "; \n boundary=\"" . $alternatives->getMime()->boundary() . "\"";
$body->addPart($alternativesPart);
$mail->setBody($body);
$mail->setEncoding("UTF-8");
$headers->get('content-type')->setType('multipart/alternative');
$transport->send($mail);
这里是收到的邮件中的示例 header:
Delivered-To: CUSTOMER_EMAIL
Received: by SOMEIP with SMTP id e9csp1233069oid;
Thu, 2 Apr 2015 07:35:03 -0700 (PDT)
X-Received: by SOMEIP with SMTP id eg3mr25568854wib.11.1427985302528;
Thu, 02 Apr 2015 07:35:02 -0700 (PDT)
Return-Path: <something@something.com>
Received: from something (something. [OTHERIP])
by mx.google.com with ESMTP id ew1si9167339wjb.35.2015.04.02.07.35.01
for <CUSTOMER_EMAIL>;
Thu, 02 Apr 2015 07:35:02 -0700 (PDT)
Received-SPF: pass (google.com: domain of something@something.com designates OTHERIP as permitted sender) client-ip=OTHERIP;
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of something@something.com designates OTHERIP as permitted sender) smtp.mail=something@something.com
Message-ID: <551d5394.4164c20a.5989.fffff01fSMTPIN_ADDED_BROKEN@mx.google.com>
X-Google-Original-Message-ID: =?UTF-8?Q?<LONGID@something.com>?=
Received: from HOST (OTHERHOST [SOMEIP])
by HOST (Postfix) with ESMTP id 834E3195
for <CUSTOMER_EMAIL>; Thu, 2 Apr 2015 17:35:01 +0300 (EEST)
X-DKIM: Sendmail DKIM Filter v2.8.3 HOST 834E3196
Date: Thu, 02 Apr 2015 17:35:01 +0300
To: CUSTOMER_EMAIL
From: =?UTF-8?Q?SOMETHING.COM?= <something@something.com>
Subject: =?UTF-8?Q?Daily=20Statement?=
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="=_c802aad96623e4d95c320e2cbceca602"
Content-Transfer-Encoding: =?UTF-8?Q?8bit?=
Sender:
This is a message in Mime Format. If you see this, your mail reader does not support this format.
--=_c802aad96623e4d95c320e2cbceca603
Content-Type: text/plain
Content-Transfer-Encoding: 8bit
<SOME HTML THINGS HERE>
--=_c802aad96623e4d95c320e2cbceca603--
我注意到 DKIM 签名失败了...我怀疑它可能来自空的发件人:header 行,但我尝试了一些方法但 none 可以将其删除.. .
提前致谢!
哇,我终于找到了解决问题的方法。事实证明,我的 ZF2 版本太旧了。实际上是2.2.4。问题是,在我将电子邮件消息传递给传输之后,Zend 在内部(Smtp.php class、准备Headers() 函数)克隆了 Headers object并且出于某种原因,删除了 Bcc header。不仅如此,它还添加了空的 Sender header(因为我没有在客户端代码中为它设置任何值)。因此,在将消息传递给 Postfix 后,它有一个空的发件人:header,它无法在 DKIM-filter 中解析。 PHP-side 解决方案是在构建消息本身时为发件人添加一个值:header:
$mail->addTo($parameters['to'])
->setFrom($parameters['from_email'], $parameters['from_name'])
->setSubject(CommonLib::assignTemplateVariables($parameters['template']['subject'], $parameters['context_variables']))
->setSender($parameters['from_email'], $parameters['from_name']);
最后一点是让 DKIM-filter 知道发送电子邮件的主机是可信的。
我花了很长时间才弄明白这一点。我希望它对其他人有用:)
我正在努力使用 ZF2 发送电子邮件。问题是它们在我测试过的其他邮件客户端中都运行良好,但在 qq.com 中,所有邮件都会进入垃圾邮件文件夹。这是我用来发送邮件的代码:
$mailTransportModel = $sl->get('MailTransportModel');
$transport = $mailTransportModel->getMailTransport($parameters['api_key']);
$messageIdHost = $config['mailServers'][$parameters['api_key']]['messageIdHost'];
$mail = new Zend\Mail\Message();
$mail->addTo($parameters['to'])
->setFrom($parameters['from_email'], $parameters['from_name'])
->setSubject(CommonLib::assignTemplateVariables($parameters['template']['subject'], $parameters['context_variables']));
if(!empty($parameters['replyto_email'])) {
if(!empty($parameters['replyto_name'])) {
$mail->addReplyTo($parameters['replyto_email'], $parameters['replyto_name']);
} else {
$mail->addReplyTo($parameters['replyto_email']);
}
}
$headers = $mail->getHeaders();
$messageId = sha1($config['salt'] . microtime());
$headers->addHeaderLine('Message-Id', "<" . $messageId . "@" . $messageIdHost . ">");
$html = new Part(CommonLib::assignTemplateVariables($parameters['template']['body'], $parameters['context_variables']));
$body = new Zend\Mime\Message();
// Create HTML part
$html = new Part(CommonLib::assignTemplateVariables($parameters['template']['body'], $parameters['context_variables']));
$html->type = Mime::TYPE_HTML;
$html->charset = 'utf-8';
// Create plain text part
$stripTagsFilter = new \Zend\Filter\StripTags();
$textContent = str_ireplace(array("<br />", "<br>"), "\r\n", CommonLib::assignTemplateVariables($parameters['template']['body'], $parameters['context_variables']));
$textContent = $stripTagsFilter->filter($textContent);
$textPart = new Zend\Mime\Part($textContent);
$textPart->type = Mime::TYPE_TEXT;
// Create separate alternative parts object
$alternatives = new Zend\Mime\Message();
$alternatives->setParts(array($textPart, $html));
$alternativesPart = new Zend\Mime\Part($alternatives->generateMessage());
$alternativesPart->type = Mime::MULTIPART_ALTERNATIVE . "; \n boundary=\"" . $alternatives->getMime()->boundary() . "\"";
$body->addPart($alternativesPart);
$mail->setBody($body);
$mail->setEncoding("UTF-8");
$headers->get('content-type')->setType('multipart/alternative');
$transport->send($mail);
这里是收到的邮件中的示例 header:
Delivered-To: CUSTOMER_EMAIL
Received: by SOMEIP with SMTP id e9csp1233069oid;
Thu, 2 Apr 2015 07:35:03 -0700 (PDT)
X-Received: by SOMEIP with SMTP id eg3mr25568854wib.11.1427985302528;
Thu, 02 Apr 2015 07:35:02 -0700 (PDT)
Return-Path: <something@something.com>
Received: from something (something. [OTHERIP])
by mx.google.com with ESMTP id ew1si9167339wjb.35.2015.04.02.07.35.01
for <CUSTOMER_EMAIL>;
Thu, 02 Apr 2015 07:35:02 -0700 (PDT)
Received-SPF: pass (google.com: domain of something@something.com designates OTHERIP as permitted sender) client-ip=OTHERIP;
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of something@something.com designates OTHERIP as permitted sender) smtp.mail=something@something.com
Message-ID: <551d5394.4164c20a.5989.fffff01fSMTPIN_ADDED_BROKEN@mx.google.com>
X-Google-Original-Message-ID: =?UTF-8?Q?<LONGID@something.com>?=
Received: from HOST (OTHERHOST [SOMEIP])
by HOST (Postfix) with ESMTP id 834E3195
for <CUSTOMER_EMAIL>; Thu, 2 Apr 2015 17:35:01 +0300 (EEST)
X-DKIM: Sendmail DKIM Filter v2.8.3 HOST 834E3196
Date: Thu, 02 Apr 2015 17:35:01 +0300
To: CUSTOMER_EMAIL
From: =?UTF-8?Q?SOMETHING.COM?= <something@something.com>
Subject: =?UTF-8?Q?Daily=20Statement?=
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="=_c802aad96623e4d95c320e2cbceca602"
Content-Transfer-Encoding: =?UTF-8?Q?8bit?=
Sender:
This is a message in Mime Format. If you see this, your mail reader does not support this format.
--=_c802aad96623e4d95c320e2cbceca603
Content-Type: text/plain
Content-Transfer-Encoding: 8bit
<SOME HTML THINGS HERE>
--=_c802aad96623e4d95c320e2cbceca603--
我注意到 DKIM 签名失败了...我怀疑它可能来自空的发件人:header 行,但我尝试了一些方法但 none 可以将其删除.. .
提前致谢!
哇,我终于找到了解决问题的方法。事实证明,我的 ZF2 版本太旧了。实际上是2.2.4。问题是,在我将电子邮件消息传递给传输之后,Zend 在内部(Smtp.php class、准备Headers() 函数)克隆了 Headers object并且出于某种原因,删除了 Bcc header。不仅如此,它还添加了空的 Sender header(因为我没有在客户端代码中为它设置任何值)。因此,在将消息传递给 Postfix 后,它有一个空的发件人:header,它无法在 DKIM-filter 中解析。 PHP-side 解决方案是在构建消息本身时为发件人添加一个值:header:
$mail->addTo($parameters['to'])
->setFrom($parameters['from_email'], $parameters['from_name'])
->setSubject(CommonLib::assignTemplateVariables($parameters['template']['subject'], $parameters['context_variables']))
->setSender($parameters['from_email'], $parameters['from_name']);
最后一点是让 DKIM-filter 知道发送电子邮件的主机是可信的。
我花了很长时间才弄明白这一点。我希望它对其他人有用:)