绕过 Gmail 的垃圾邮件过滤器(使用 PHP 从共享主机发送的邮件)

Posted

技术标签:

【中文标题】绕过 Gmail 的垃圾邮件过滤器(使用 PHP 从共享主机发送的邮件)【英文标题】:Bypass Gmail's spam filter (mails sent with PHP from a shared host) 【发布时间】:2013-02-22 19:50:09 【问题描述】:

TL;DR:从共享主机(例如 Unoeuro 或 One.com 的廉价域名)发送的邮件最终会成为垃圾邮件。如何解决?


我制作了一个邮件系统,它首先生成了一个 PDF 文件(使用 FPDF),然后它使用 php 的 Swiftmailer 将 PDF 文件作为附件发送。这封电子邮件已发送给 130 人(作为“一张”发票)。但它进入了几乎每个人的垃圾邮件过滤器。我尝试调整 SwiftMailers 标头设置,但没有任何运气。甚至是我以前没有发送过的邮件(经过彻底测试)。这是我的初始设置:

function sendMailEt($toEmail, $toName, $invoiceNumber)

require_once('includes/lib/swift_required.php');

$transport = Swift_SmtpTransport::newInstance('mailout.one.com', 25)
  ->setUsername('EMAIL-ACCOUNT1@THE-DOMAIN.DK')
  ->setPassword('THE-PASSWORD')
  ;    

$mailer = Swift_Mailer::newInstance($transport);

$message = Swift_Message::newInstance('FROM COMPANY')
      ->setSubject('Thanks for signing up - COMPANY')
  ->setFrom(array('EMAIL-ACCOUNT1@THE-DOMAIN.DK' => 'Company name'))
  ->setTo(array($toEmail => $toName))
      ->setBody('A brief body, that explains that this is an invoice and that it has to be paid within 5 days. (written in danish)')
      ->addPart('A brief body, that explains that this is an invoice and that it has to be paid within 5 days. (written in danish)', 'text/html')

   ->attach(Swift_Attachment::fromPath('/URL-TO-THE-PDF-FILE.pdf'))
  ;

$result = $mailer->send($message);

我还尝试使用 PHP 的原生 mail()-函数发送电子邮件,然后简单地链接到发票 (http://www.company-domain-name.dk/invoice/base64_encoded-name.pdf)...同样的结果(垃圾邮件)。

我尝试自己编写整个标题。我已经阅读了大量关于标题应包含哪些内容的论坛,但他们都写了不同的东西。所以我尝试了一些不同的东西(我之前发送过的电子邮件和我没有发送过的电子邮件)......结果相同(垃圾邮件)。

然后我尝试在它们的标题中完全按照 MailChimps 的方式编写标题。这导致我这样做:

 $headers = "Reply-To: Company name <UNUSED-EMAIL-ACCOUNT-FROM-DOMAIN@DOMAIN-NAME.DK>\r\n"; 
 $headers .= "Return-Path: Company name <UNUSED-EMAIL-ACCOUNT-FROM-DOMAIN@DOMAIN-NAME.DK>\r\n"; 
 $headers .= "From: Message from Company name <UNUSED-EMAIL-ACCOUNT-FROM-DOMAIN@DOMAIN-NAME.DK>\r\n"; 
 $headers .= "MIME-Version: 1.0\r\n";
 $headers .= "Sender: Message from Company name <UNUSED-EMAIL-ACCOUNT-FROM-DOMAIN@DOMAIN-NAME.DK>\r\n";
 $headers .= "Content-type: text/plain; charset=\"utf-8\"; \r\n";
 $headers .= "X-Mailer: PHP". phpversion() ."\r\n";

然后我这样发送邮件:

mail($toName . '<'.$toEmail.'>', utf8_decode('Faktura på depositumet'), utf8_decode($someMessage), $headers);

...相同的结果(垃圾邮件)。

网络空间是 One.com 的,所以我不能使用 PHPmailer(因为必须安装,并且不能在 one.com 的服务器上完成)。而且我无法使用 One.com 定义 SPF。

我想要的只是能够发送不会成为垃圾邮件的电子邮件。

这是我的问题:

    是因为我的标题已关闭,还是因为“更深”?

    Gmail 垃圾邮件过滤器是否禁止单个电子邮件帐户(例如 this@example.com) 还是禁止整个域(例如 @example.com)?

    可以将列入黑名单的电子邮件列入白名单吗 不知何故?

* 加法 1 *

好的...我现在尝试了很多方法:

我尝试像推荐的那样添加 LoneWolfPR 的返回路径,但没有帮助。 我联系了 One.com(托管公司)并与他们确认,无法设置 SPF 记录或 DKIM 记录。它仍然不是。 我考虑过设置一个“取消订阅”链接,其中包含一个带有表单的网站链接,但我不相信这种方法。我的意思是 - 发票一直通过电子邮件发送。为什么你应该能够取消订阅发票?!由于这在我的脑海中毫无意义,所以我只尝试了大约 20 分钟(显然,没有结果)。

这是我当前的电子邮件标题(从 Gmail 中获取,点击“查看原件”):

Delivered-To: NEWLY-CREATED-GMAIL-ACCOUNT@gmail.com
Received: by 10.76.75.104 with SMTP id b8csp48728oaw;
        Sat, 16 Mar 2013 17:32:56 -0700 (PDT)
X-Received: by 10.152.116.45 with SMTP id jt13mr7897860lab.0.1363480376067;
        Sat, 16 Mar 2013 17:32:56 -0700 (PDT)
Return-Path: <XXX111@DOMAIN-NAME.dk>
Received: from mail-out2.b-one.net (mail-out2.one.com. [91.198.169.19])
        by mx.google.com with ESMTP id p10si4637427lbb.120.2013.03.16.17.32.55;
        Sat, 16 Mar 2013 17:32:55 -0700 (PDT)
Received-SPF: neutral (google.com: 91.198.169.19 is neither permitted nor denied by best guess record for domain of XXX111@DOMAIN-NAME.dk) client-ip=91.198.169.19;
Authentication-Results: mx.google.com;
       spf=neutral (google.com: 91.198.169.19 is neither permitted nor denied by best guess record for domain of XXX111@DOMAIN-NAME.dk) smtp.mail=XXX111@DOMAIN-NAME.dk
Date: Sat, 16 Mar 2013 17:32:55 -0700 (PDT)
Message-Id: <51450f37.6a0b700a.6239.5dbcSMTPIN_ADDED_MISSING@mx.google.com>
Received: from localhost.localdomain (srv18.one.com [193.202.110.18])
    by mail-out2.b-one.net (Postfix) with ESMTP id F3D0B10365
    for <NEWLY-CREATED-GMAIL-ACCOUNT@gmail.com>; Sun, 17 Mar 2013 01:32:53 +0100 (CET)
Received: from 85.218.159.219 by www.DOMAIN-NAME.dk via URL_TO_THE_SCRIPT.php with HTTP; Sun, 17 Mar 2013 00:32:53 +0000
To: RECIEVERS_NAME <NEWLY-CREATED-GMAIL-ACCOUNT@gmail.com>
Subject: EMAIL-SUBJECT
X-PHP-Originating-Script: 87486:NAME-OF-THE-SCRIPT-THE-E-MAIL-WAS-SENT-FROM.php
Reply-To: COMPANY NAME <XXX111@DOMAIN-NAME.dk>
From: Besked fra COMPANY NAME <XXX111@DOMAIN-NAME.dk>
MIME-Version: 1.0
Sender: Besked fra COMPANY NAME <XXX111@DOMAIN-NAME.dk>
Content-type: text/plain; charset="utf-8"; 
X-Mailer: PHP5.3.21

【问题讨论】:

您是否有用于发送邮件的域的 PTR DNS 记录?使用emailtalk.org/MailServerConfig.aspx等工具测试您的域 当我在您链接的页面上输入域名时,它会显示“未找到记录”。如果我在导航中选择“PTR 检查”(在同一站点上)并插入域名,那么它会告诉我:193.202.110.18 PTR 指向 srv18.one.com。 - 是好还是坏?我该如何改变它? 您发送的域(电子邮件发件人)是否与 one.com 匹配?您没有任何 MX 记录吗? 您是否看到发送到垃圾邮件文件夹的电子邮件的完整标题?..与您的发送标题比较 我用一些更具体的信息更新了下面的答案。检查一下,看看是否有帮助。 【参考方案1】:

1) 通常一个电子邮件地址不会轻易进入黑名单,需要时间和/或很多人将您标记为垃圾邮件发送者才能真正将该地址纳入黑名单。

2) 是的。整个域名可以被列入黑名单,因为垃圾邮件发送者通常会生成随机电子邮件地址,例如 f4j3ifl@something.com。

3) 不管去垃圾邮件箱多少次,基本上,现在的垃圾邮件过滤器很强大,因为垃圾邮件发送者每天都在努力改进他们的方式,所以过滤器每天都变得更加严格.如果它第一次进入垃圾邮件文件夹,而用户实际上并没有把它放入垃圾邮件箱,它会继续下去,除非用户取消标记它,或者你解决了问题。

如何避免垃圾邮件?

基本上,您需要一些签名,并且需要大量访问您的 DNS 记录,因为我们将在其中进行大部分设置。

反向 DNS 查找:在专用服务器甚至某些 VPS 上,您可以设置反向 dns 记录,有时您只需打开一张票,IT 就会为您设置好.如果您不能拥有它,请更改您的主机或继续被标记为垃圾邮件发送者 xD。这是为了防止伪造标题,因为您可以在标题上设置您的电子邮件来自 gmail.com,但电子邮件服务器不是这样检查的。

SPF 也是必须的,如果您无法设置 SPF,那就不要再尝试了,考虑更改您的主机,您几乎可以停止阅读这里xD。

DKIM/域密钥:最好是 DKIM,是加密签名,您在 DNS 上设置公钥,并将私钥存储在您的电子邮件服务器中,当服务器收到电子邮件,它在标题中附加了私钥(您需要一个管理 DKIM 的邮件服务器软件,例如它适用于我的 Windows hmailserver)并且邮件服务(例如 gmail)将检查您的dns 记录查看公钥是否匹配。 这几乎也是必备品


这三个是基础,如果您设置 DMARC 和 ADSP,它将为您在 SpamAssassins 中获得更好的分数。为了获得更好的分数搜索谷歌上的一些垃圾邮件关键字列表并尽量避免它们,有些东西比如用“亲爱的xxx”开始电子邮件对你的分数有害,设置取消订阅系统(即使它很糟糕,只要因为您提供了清晰的链接)也会对您有所帮助。

还有:

避免在(任何)背景上出现草率的 html 和白色文本,一些垃圾邮件发送者使用它来适应隐藏文本,这些过滤器比您想象的更智能。

阅读具体建议。大多数电子邮件服务在其网站上都有常见问题解答或其他内容,其中包含一些提示,可帮助您发送电子邮件而不是进入垃圾邮件。在其中一些上,您甚至可以申请进入白名单(至少在几年前,在 gmail 等一些服务上,他们不再这样做了)

如果您是批量发送,请注意时间!如果您每秒有 X 封电子邮件发送到某个地方,您可能会进入黑名单,设置脚本或其他东西以获得 1 秒左右的延迟,延迟可能取决于目的地是否进入黑名单。


希望这些提示对您有所帮助,我最近不得不处理一些垃圾邮件过滤器,这让我很头疼,这就是为什么我知道所有这些信息,这就是我所有的研究 xD 即使在我设置了所有签名和东西之后,一些电子邮件仍然进入垃圾邮件箱(比例较小,但它仍然伤害我)唯一可靠的方法是让用户将您添加到联系人列表中(同时具有正确的签名和标题),所以提醒他们这样做所以如果可能的话。

【讨论】:

嗯...我的问题是,如果我可以从 One.com 的域发送邮件,则无法更改 SPF 记录或 DKIM 记录。所以你的意思是,这是不可能的,因为我无法更改 SPF 记录或 DKIM 记录?如果不是,那你有什么建议?因为这个小问题(已经变得很大)而转移到一个全新的网络空间? 我添加了我的标题现在的样子。它说的是 SPF 中性或类似的东西,但我不知道这是否意味着它已设置(或是否已批准)。 是的,这意味着您必须更改域的服务和/或网络托管。如果您面对很多不是来自已知网络的用户,那么垃圾邮件并不是一个小问题。中性 SPF 记录意味着服务器检测到您设置了 spf 记录,但它不匹配或没有所需的所有信息,因此请认为它设置不正确。是的,现在你需要为诸如电子邮件之类的基本内容设置如此复杂的设置,这很糟糕,这一切都是因为垃圾邮件发送者...... 该死的...但是谢谢。在我这样做之前,我会考虑我还有哪些其他选择。对于如此简单的事情,这是相当多的工作...... 只是评论说似乎不再推荐 ADSP,根据其***页面en.wikipedia.org/wiki/Author_Domain_Signing_Practices 这个词引起了我的注意,因为我不知道它。不过(即使是 7 年后),我发现您的其余答案都很棒【参考方案2】:

要记住一件事,我在电子邮件被 Gmail 和 Yahoo! 屏蔽时遇到了麻烦。来自 php 的邮件,因为 Return-Path 标头与 from 不匹配。在许多服务器上,如果您在标头中明确设置 Return-Path,PHP Mail 将忽略它并将返回路径设置为机器名称。您必须使用“-f”标志在邮件功能的“附加参数”部分强制它。现在我从来没有使用过 Swift Mailer,所以我不知道 PHP 的本机 mail() 函数的等价物,但这是使用 mail() 的样子;

mail($to,$subject,$message,$headers,'-f returnpath@example.com')

如果您可以在 swift mailer 中找到与此等效的内容,它可能会解决您的问题。

编辑:

看起来您实际上根本没有设置 Return-Path。我知道 GMail 真的不喜欢被排除在外。尝试将其显式设置为您的 Swift_Mailer 消息(并确保它与您的 From 匹配):

$message->setReturnPath('from@example.com');

【讨论】:

请注意,您应该使用这个-f ... 即使您手动设置了Return-Path 标头,因为sendmail(由mail() 函数调用)可能会剥离标题和/或将其替换为不同的标题。只需确保您指定 Return-Path 的两个位置相同即可。 嗯...试过了,没用。我稍微更新了问题,其中包含了我的整个标题。不过,感谢您的建议。 对不起,伙计。我不确定为什么你会收到垃圾邮件,除非你的图片/文本比例很高,或者你在某个时候被列入黑名单。购买一个工具来检查您的自动电子邮件是否与各种垃圾邮件过滤器是值得的。【参考方案3】:

确保您用作 FROM 的电子邮件地址实际上是一个电子邮件地址。通过从主机(one.com 为您)进入我的帐户管理并添加我希望电子邮件来自的帐户,我已经解决了同样的问题。我添加了一个名为“mailer”的帐户,并通过面板设置了一个自动回复器,上面写着“抱歉。此电子邮件地址是为服务器功能保留的”。

然后在 from 标头中使用 (mailer@yourdomain.com)

拥有那个实际的电子邮件地址和自动回复功能就可以了。我认为gmail足够聪明,可以知道以前从未使用过的电子邮件地址是垃圾邮件。此外,电子邮件地址必须来自脚本所在的域,这样当它说它来自那里时,它就不会撒谎。

这是我想从共享主机 (justhost.com) 发送电子邮件时使用的代码,它不会进入垃圾邮件(这是使用来自网络表单的发布数据):

<?php



// Contact subject

$subject = $_POST["subject"];



// Details

$message=$_POST["detail"];



// Email of sender

$mail_from=$_POST["customer_mail"]; 

//Name of sender

$name=$_POST["name"];
putenv("TZ=America/Phoenix");
$now = date("F j, Y, g:i a T");

$header="Reply-To: $name <$mail_from>";

$header .= "From: MyDomainName.com <mailer@mydomainname.com>";
$header .= "\r\n";
$header .= "Reply-To: $name <$mail_from>"; 
$introMSG= "Message From:".$name." <".$mail_from.">"."\r\n"
."Sent On:".$now."\r\n"."From a web form on MyDomaiNname.com"."\r\n"."-----------
-----------------------"."\r\n"."\r\n";


$to ='me@mydomainname.com'; // Domain Owners Email Address

$send_contact=mail($to,$subject,$introMSG.$message,$header);

$send_copy=mail($mail_from,"Copy Of:".$subject,$introMSG.$message,$header);

// Check if message sent


if($send_contact)

echo "<strong>Thanks! Your message has been sent to me.</strong>";



else 

echo "<strong>There was an error sending your message </strong>"; 





if($send_copy)
echo "<strong><br>A copy of this message was sent to your email.<br>If you do not
receive a copy please check your spam folder</strong>";



else
echo "<strong> There was an error sending a copy of this message to your email
</strong>"; 





$send_reminder=mail("5555555555@txt.att.net","","You Have a new contact message from
".$name.", remember to check your spam folder.",$header);

if($send_reminder)

echo ".";



else 

echo "<br><strong>TXT Error</strong>";



?>

【讨论】:

我在代码中留下了垃圾邮件文件夹提醒,以防它被标记。但到目前为止,它还没有被标记为垃圾邮件。希望这可以帮助你。 嗨,埃里克。谢谢你的建议。我发送的电子邮件是在 One.com 的控制面板中创建的,所以不是这样。 我尝试将您的脚本复制/粘贴到我的文件中,然后手动插入正确的值。我把它全部放在一个 JSfiddle 中,所以你可以看到脚本和它输出的内容(剧透警告),但它仍然落在垃圾邮件中 - 抱歉(jsfiddle.net/F4Lwr)。不过感谢您的建议(所有大写字母并不是粗鲁的,但这只是为了说明文件中有什么,什么不是)。【参考方案4】:

解决方案: 使用Mailgun(未测试)或Sendgrid(已测试并且效果很好!)。两者之间存在价格差异,但简而言之:如果您很小,Mailgun 就很好;如果你很大,Sendgrid 很好。

要么, - 或使用MailChimps API 或其他方式发送邮件。它无法在共享主机上修复(很可能)。原因如下。


说明:我后来了解了更多关于共享主机的工作原理。假设几个不同的站点位于同一台服务器上(例如domain-1.orgdomain-2.orgdomain-3.org)。这意味着如果domain-3.org 发送了一堆垃圾邮件,Gmail(和其他垃圾邮件过滤器)就会将该 IP 地址标记为垃圾邮件。因此,如果domain-2.org 然后发送内容,那么(可能)将来自某个 IP 地址,因此最终成为垃圾邮件。共享主机实际上对此无能为力(并且不在乎,因为很少有人遇到这个问题)。这就是它如此便宜的原因。

Sendgrid 和 Mailguns IP 地址被所有垃圾邮件过滤器标记为“正常”,这就是您使用它们付费的服务。他们通过监视您发送的多少电子邮件被标记为“垃圾邮件”来保持这种状态。如果它是 5%-10% 或低得离谱的东西,那么 Sendgrid/Mailgun 将阻止您的帐户,直到您修复它(经历一个漫长的过程,您必须联系他们的客户服务并做 1.000 冰雹玛丽和各种奇怪的东西)。

我听说如果你拥有自己的服务器(这要贵得多),并设置自己的邮件服务器,那么你必须非常小心,不要被标记为垃圾邮件。因为垃圾邮件过滤器现在真的很难......

【讨论】:

【参考方案5】:

至少有两个看起来像“垃圾邮件”的东西从您的电子邮件标题中跳出来:

Message-Id: <51450f37.6a0b700a.6239.5dbcSMTPIN_ADDED_MISSING@mx.google.com>

注意到 SMTPIN_ADDED_MISSING 部分了吗?您的行为不像一个正确的邮件程序并生成一个唯一的 Message-ID。您可能会发现阅读 RFC 5322 具有指导意义。

Received: from localhost.localdomain (srv18.one.com [193.202.110.18])
by mail-out2.b-one.net (Postfix) with ESMTP id F3D0B10365
for <NEWLY-CREATED-GMAIL-ACCOUNT@gmail.com>; Sun, 17 Mar 2013 01:32:53 +0100 (CET)

最初收到的标头具有非法的 HELO 主机名 (localhost.localdomain)。您的邮件应用程序应该为您提供一种将其设置为有效值的方法。它甚至可能像配置运行 PHP 的机器的主机名一样简单。请参阅 RFC 1035(主机名有效性)、RFC 2821 (SMTP) 和 RFC 5321 (SMTP)。

【讨论】:

以上是关于绕过 Gmail 的垃圾邮件过滤器(使用 PHP 从共享主机发送的邮件)的主要内容,如果未能解决你的问题,请参考以下文章

2-WAF主要过滤方式及绕过(HPP污染&分块传输&垃圾数据)

如果我需要从gmail回复到我的php网站该怎么办?

如何防止通过 PHP mail() 发送的邮件进入垃圾邮件? [复制]

如何使用 Gmail API 阻止发件人?

邮件进入垃圾邮件文件夹(php邮件功能)[重复]

python 和 scikit-learn 实现垃圾邮件过滤