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

16

TL;DR: 来自共享主机(例如来自Unoeuro或One.com的便宜域名)的邮件最终会被标记为垃圾邮件。如何解决?


我制作了一个邮件系统,首先使用FPDF生成PDF文件,然后使用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记录。

我想要的就是能够发送不会被归类为垃圾邮件的电子邮件。

这里是我的问题:

  1. 是否因为我的标题行有问题,还是有其他更深层次的原因?

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

  3. 是否有方法可以使被列入黑名单的电子邮件重新被列入白名单?


* 补充 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

3
你发送邮件的域名是否有PTR DNS记录?可以使用http://emailtalk.org/MailServerConfig.aspx等工具测试你的域名。 - Dave Hogan
1
你发送邮件的域名(发件人)是否与one.com匹配?你没有任何MX记录吗? - Dave Hogan
你看到发送到垃圾邮件文件夹的电子邮件的完整标题了吗?...与您的发送标题进行比较。 - Amir
我在下面更新了我的答案,提供了更具体的信息。看看它是否有帮助。 - LoneWolfPR
如果您遇到被标记为垃圾邮件的问题,请尝试使用类似sendgrid的邮件服务。它将允许您使用自己的域名等功能。http://sendgrid.com/mkt/assets/pdfs/SendGrid_Top_Ten.pdf - Francis Yaconiello
显示剩余3条评论
5个回答

15

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

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

3) 无论它被发送到垃圾邮箱多少次,基本上,垃圾邮件过滤器现在都很强大,因为垃圾邮件发送者每天都在尝试改进他们的方法来绕过这些过滤器,所以这些过滤器变得越来越严格。如果第一次就进入了垃圾邮件文件夹,并且用户没有将其实际放入垃圾箱,则它将继续发送,除非用户取消标记它,或您解决了问题。

如何避免垃圾邮件文件夹?

基本上,您需要一些签名,并且需要访问您的DNS记录,因为这是我们进行大部分设置的地方。

  • 反向DNS查找:在专用服务器甚至某些VPS上,您可以设置反向DNS记录,有时您只需打开工单,IT人员就会为您设置。如果您无法获得它,请更改您的托管或继续被标记为垃圾邮件发送者xD。这是为了防止标题伪造,因为您可以在标题上设置您的电子邮件来自gmail.com,但实际上不是,这是电子邮件服务器检查它的方式。

  • SPF也是必须的,如果您无法设置SPF,则甚至不要再尝试了,考虑更改您的托管,那么您几乎可以在此处停止阅读xD。

  • DKIM/Domain Key: 首选DKIM,是一种加密签名,您将公钥设置在DNS上,并将私钥存储在您的电子邮件服务器中。当服务器接收到电子邮件时,在标头中附加了私钥(您需要一个管理DKIM的邮件服务器软件,例如Windows上的hmailserver),并且邮件服务(例如gmail)将检查您的DNS记录以查看公钥是否匹配。这几乎是必备的


以上三点是基础,如果设置了DMARC和ADSP,它们将为您在SpamAssassins中获得更好的得分。要获得更好的得分,请在Google上搜索一些垃圾邮件关键字列表并尽量避免它们。有些内容,如以“亲爱的xxx”开头的电子邮件,对您的得分有害。设置退订系统(即使它不理想,只要提供清晰的链接)也会对您有所帮助。

另外:

  • 避免粗糙的HTML和白色背景上的文本,一些垃圾邮件发送者使用它来适应隐藏文本,这些过滤器比您想象的更聪明。

  • 阅读特定的建议。大多数电子邮件服务都有常见问题解答或网站上一些提示,帮助您发送电子邮件而不会被识别为垃圾邮件。在其中一些上,您甚至可以申请加入白名单(至少在一些年前,在某些服务如gmail上已经不再做了)

  • 如果您正在批量发送,请注意时间!如果您每秒向某个地方发送X封电子邮件,则可能会进入黑名单,请设置脚本或其他东西以获得1秒延迟或更长时间的延迟,延迟可能取决于收件人是否将你加入黑名单。


希望这些提示能帮到你,最近我也遇到了一些垃圾邮件过滤器的问题,真是让人头痛。所以我知道所有这些信息,这就是我的研究成果 xD 即使我已经设置了所有签名和其他内容,一些电子邮件仍然会被放入垃圾邮件箱(虽然比例较小但还是很让我伤心)。唯一可靠的方法是让用户将你添加到联系人列表中(同时正确设置签名和标头),因此如果可能,请提醒他们这样做。

嗯...我的问题是,如果我可以从One.com的域发送邮件,在那里无法更改SPF记录或DKIM记录。所以你的意思是,由于我无法更改SPF记录或DKIM记录,所以这是不可能的?如果不行,你有什么建议?因为这个微小的问题(已经变成了巨大的问题),要搬到一个全新的网络空间吗?<br />我添加了我的标题现在看起来像什么。它说一些SPF-neutral之类的东西,但我不知道它是否意味着它被设置或未被设置(或批准或未批准)。 - Zeth
是的,这意味着您需要更改域名的服务和/或Web托管。如果您面对许多来自未知网络的用户,则电子邮件垃圾邮件不是一个小问题。中性SPF记录意味着服务器检测到您已设置SPF记录,但它不匹配或缺少所有必需的信息,因此请考虑它未正确设置。是的,现在由于垃圾邮件发送者的原因,您需要进行如此复杂的设置以处理基本的电子邮件,这确实很糟糕... - aleation
该死... 不过谢谢。我会在这么做之前考虑其他选项的,因为那样需要花费相当多的工作量,而实际上要做的事情很简单。 - Zeth
只是评论一下,根据其维基百科页面https://en.wikipedia.org/wiki/Author_Domain_Signing_Practices,ADSP似乎不再推荐使用了。 这个术语引起了我的注意,因为我之前不知道它。尽管如此,我认为你的回答其他部分都很好(即使是7年后)。 - ywarnier

3

需要记住的一件事是,我在使用php发送邮件时遇到了Gmail和Yahoo!邮箱屏蔽邮件的问题,因为"Return-Path"头部没有与发件人相匹配。在许多服务器上,如果您在标头中明确设置了"Return-Path",PHP邮件将忽略该设置并将返回路径设置为机器名称。您必须在邮件函数的"附加参数"部分使用"-f"标志强制设置它。现在我从未使用过Swift Mailer,因此不知道与PHP本地邮件()函数的等效项,但以下是使用邮件函数()的示例:

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

如果您能在Swift Mailer中找到相应的等效功能,可能会解决您的问题。

编辑:

看起来您实际上根本没有设置退信地址(Return-Path)。我知道GMail非常不喜欢将其忽略不计。尝试将其明确地设置为您的Swift_Mailer消息(并确保它与您的发件人地址匹配):

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

1
请注意,即使您手动设置了“Return-Path”标头,也应使用此“-f ...”选项,因为sendmail(由mail()函数调用)可能会剥离标头并/或替换为不同的标头。只需确保您指定“Return-Path”的两个位置相同即可。 - Moshe Katz
嗯...我试过了,但它没起作用。我稍微更新了一下问题,包括了整个头文件。不过还是谢谢你的建议。 - Zeth
抱歉,我不确定为什么你会收到垃圾邮件,除非你的图像/文本比例很高或者你曾经被列入黑名单。最好获取一个工具,检查你的自动化邮件是否符合各种垃圾邮件过滤器的要求。 - LoneWolfPR

2
解决方案: 使用Mailgun(未经测试)或Sendgrid(已测试并且效果非常好!)。两者之间价格有差别,简而言之:如果规模小,Mailgun不错;如果规模大,Sendgrid比较好。

或者使用MailChimps API发送邮件。这个问题在共享主机上无法解决(很可能),原因如下。


说明: 我后来了解到了更多关于共享主机的工作方式的信息。想象一下,有几个不同的站点位于同一个服务器上(例如domain-1.orgdomain-2.orgdomain-3.org)。这意味着如果domain-3.org发送了一堆垃圾邮件,则Gmail(和其他垃圾邮件过滤器)会将该IP地址标记为垃圾邮件。因此,如果domain-2.org发送了东西,那么它(可能)就来自相同的IP地址,因此最终会成为垃圾邮件。共享主机不能真正做任何事情(也不关心,因为很少有人有这个问题)。这就是为什么它如此便宜的原因。

Sendgrid和Mailgun的IP地址被所有垃圾邮件过滤器标记为“良好”,这就是您使用它们付费的服务。他们通过监控您发送的电子邮件中有多少被标记为“垃圾邮件”来保持这种状态。如果标记为“垃圾邮件”的比例是5%-10%或者极低的比例,那么Sendgrid/Mailgun将阻止您的帐户,直到您解决为止(需要经历一个漫长的过程,在这个过程中,您必须联系客服并进行各种奇怪的操作)。

据我所知,如果您拥有自己的服务器(成本更高),并设置了自己的邮件服务器,则必须非常小心,以免被标记为垃圾邮件。因为现在的垃圾邮件过滤器非常严格...


0

你的电子邮件头部至少有两个看起来很“垃圾”的东西:

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


0

请确保您在使用的发件人电子邮件地址实际上是一个电子邮件地址。我曾经遇到过同样的问题,通过从主机(对于您来说是one.com)进入我的帐户管理并添加我想要发送电子邮件的帐户来解决该问题。我添加了一个名为“mailer”的帐户,并通过面板设置了自动回复器,内容为“抱歉。此电子邮件地址已保留用于服务器功能”。

然后,在发件人标题中,您将使用(mailer@yourdomain.com)

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

这是我在共享主机(justhost.com)上发送电子邮件时使用的代码,它不会被视为垃圾邮件(这是使用Web表单的POST数据):

<?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>";

}

?>

我在代码中留下了垃圾邮件文件夹的提醒,以防它被标记。但到目前为止,它并没有被标记为垃圾邮件。希望这能对你有所帮助。 - Eric Jones
嗨Eric。感谢您的建议。我发送电子邮件的地址是在One.com的控制面板中创建的,所以不是那个问题。<br />我尝试将您的脚本复制/粘贴到我的文件中,并手动插入正确的值。我把它全部放在JSfiddle中,这样您就可以看到脚本和输出的内容(剧透警告),但它仍然会被归类为垃圾邮件-很抱歉(http://jsfiddle.net/F4Lwr/)。还是感谢您的建议(大写字母并不是为了无礼,而是为了清楚地表明文件中有什么和没有什么)。 - Zeth

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