共享主机发送的电子邮件被阻止了,有什么方法可以避免这种情况发生吗?

3
在我的网站上,我有一个PHP脚本,可以自动向我的客户发送订单确认邮件。我的网站域名注册在一家也托管我的网站的公司名下。使用mail()函数发送电子邮件时,我遇到了很多问题,有很多用户联系我说他们从未收到过我的自动邮件!这是一个非常大的问题!给我带来最多问题的账户是comcast.net、uol.com、mchsi.com等!我已经联系这些电子邮件服务提供商的支持中心,要求将我的IP地址从阻止列表中移除。邮件头看起来像这样:
$header = "Sender: $from_mail\n";
$header .= "From: Account <$from_mail>\n";
$header .= "Reply-To: Account <$from_mail >\n";
$header .= "Content-Type: multipart/mixed; boundary=$mixed_boundary\n";
$header .= "Mime-Version: 1.0\n";
$header .= "X-Mailer: PHP/".phpversion()."\n";

$body = "\n--$mixed_boundary\n";
.
.
.
.
$body .= "\n\n--$mixed_boundary--";

mail($to, $subject, $body, utf8_encode($header), "-f$from_mail");

有没有什么方法可以避免这个问题?有人知道在哪里查询通过PHP mail()函数发送电子邮件时使用的服务器IP地址吗?

非常感谢您的回复!!!


嗨,

到今天为止,一些电子邮件提供商(如Comcast)仍然会阻止我的IP地址,并称我的邮件服务器发送垃圾邮件... 我请求将其从黑名单中删除,但他们的系统继续阻止它们!我不知道还能做什么... 我已经按照您的建议进行了操作,代码看起来像这样:

$md5 = md5(date('r', time()));
$mixed_boundary = "PHP-Mixed-$md5";
$alt_boundary = "PHP-Alt-$md5";

$header = "Sender: $from_mail\r\n";
$header .= "Errors-To: $from_mail\r\n";
$header .= "From: account <$from_mail>\r\n";
$header .= "Reply-To: $from_mail\r\n";
$header .= "Content-Type: multipart/mixed; boundary=$mixed_boundary\r\n";
$header .= "Mime-Version: 1.0\r\n";
$header .= "X-Mailer: PHP/".phpversion()."\r\n";

$body = "\n--$mixed_boundary\n";
$body .= "Content-Type: multipart/alternative; boundary=$alt_boundary\n";
.
.
.
.
$body .= "--$mixed_boundary\n";
$body .= "Content-Disposition: attachment filename=\"...\"\n";
$body .= "Content-Type: application/octet-stream; x-unix-mode=0644; name=\"...\"\n";
$body .= "Content-Transfer-Encoding: base64\n";
.
.
.
.
$body .= "\n\n--$mixed_boundary--";


mail($to, $subject, $body, utf8_encode($header), "-f$from_mail");

建议是什么? 再次感谢!

PHP文档确实指出,仅使用“\n”不符合RFC 2822(Internet Message Format)标准。 - Inshallah
但是"\r\n"分隔符是用于ASP服务器的吗?还是不是?我认为PHP服务器使用"\n"作为换行符! - BitDrink
与 PHP 没有任何关系。实际上,您应该使用 "\x0d\x0a",因为您想要的不是换行符,而是规范中指定的实际字符。请参阅文档中的示例:http://us2.php.net/manual/en/function.mail.php - Inshallah
谢谢!所以我需要用"\x0d\x0a"或"\r\n"替换"\n"吗? - BitDrink
我认为"\r\n"是可以的,因为文档中就是这样做的,但是"\x0d\x0a"同样可以工作。不确定PHP在Windows机器上如何解释"\n"。如果您在Windows机器上运行您的网站,我建议使用"\x0d\x0a"以确保正确性。 - Inshallah
显示剩余2条评论
6个回答

4
让我解释一下你所面临的问题。先不要考虑技术细节。市面上有数百个电子邮件提供商,其中大型提供商包括雅虎、Gmail、AOL、Hotmail等。如果你在其中任何一个服务上被封锁,你的业务可能会受到严重影响。
这些电子邮件提供商非常关注垃圾邮件问题,为了打击垃圾邮件,它们采取了极端措施,阻止任何可能是垃圾邮件的邮件。即使你从未收到过垃圾邮件投诉,但如果你所共享的主机计划中的另一个企业收到了垃圾邮件投诉,你也将受到影响。不管你如何配置你的应用程序,如果你所在的IP地址被怀疑为垃圾邮件发送者,你的邮件都将被发送到垃圾邮件文件夹中。
即使你有自己的服务器,你仍然会遇到问题。随着时间的推移,如果你发送邮件,其中一些收件人会点击“垃圾邮件”按钮。这是生活的事实,你无法阻止它。
唯一的解决方案是外包你的电子邮件投递。像Aweber或iContact这样的公司可以为你处理电子邮件投递问题。它们与所有主要的电子邮件提供商建立了关系,并努力确保你的邮件被送到收件人的收件箱中。你不再需要担心因为有人点击“垃圾邮件”按钮而联系雅虎或Gmail。你可以专注于更重要的事情。

哇,这篇文章发表多年后还是一样的。 - JuanFernandoz

3
你可以给自己发送一封电子邮件并检查邮件头。这将让您了解电子邮件可能采取的路径,但实际上没有什么阻止那些其他域的电子邮件通过不同的路径发送。
通常,这些大型ISP有非常重型的垃圾邮件过滤器,因此从共享主机发送邮件到它们将会很困难。如果您可以获得自己的IP地址并从那里发送邮件,这可能会有所帮助。然后,您可以设置SPF记录。不能保证,但这肯定会使您远离商业垃圾邮件。
您还可以使用链接文本和其他反垃圾邮件服务进行一些搜索,看看您是否还有其他错误。
要求客户将您的发件地址添加到其垃圾邮件白名单中也可能有所帮助。

谢谢! 是的,我已经尝试发送给自己很多电子邮件,但我无法找到如何改善我的标头...对我来说一切都很正常!关于共享主机的垃圾邮件过滤器,您确实是正确的! 您建议要求客户将我的域添加到其“安全发件人”列表中,这就是我在网站上写的内容...但是似乎没有用户遵循这个建议! :-( - BitDrink

3
您的消息标题不符合RFC2822 Internet Message Format标准。
从2.1概述中可以得知:
引用: 消息被分成字符行。 一行是由两个字符回车和换行符限定的一系列字符;也就是说,回车(CR)字符(ASCII值为13)紧接着换行(LF)字符(ASCII值为10)。 (在本文档中,回车/换行对通常写为“CRLF”。)
正如我在评论中指出的那样,您的电子邮件之所以可能与大多数邮件服务器配合使用,是因为它们可能在接受方面比较宽松。但是,有些邮件服务器可能会丢弃您的消息,因为它们不符合RFC2822标准。
编辑:尽管在PHP文档的mail()函数中提倡使用“\r\n”,但是有一些争论认为这是否真的正确。

mail()函数将与本地sendmail(8)命令(或在sendmail_path中配置的内容)通信,根据使用的邮件传输代理实现的不同,可能会以不同的方式处理行尾。据我所知,sendmail(8)应该可以处理"\r\n",但是例如qmail(7)将用"\r\r\n"替换"\r\n",这可能会破坏消息。

所有这些都发生在电子邮件被传递到最终目的地之前,因此可以通过发送一个使用"\r\n"构造的电子邮件消息并验证所有标头是否存在来轻松测试行尾是否被正确处理。

参见: RFC2822, PHP mail() 函数, sendmail(8), qmail(7)


我使用正确的SPF记录和PHP Mailer发送电子邮件非常成功。 - meme

2

我发现在某些情况下设置Return-PathSenderErrors-To头可以起到帮助作用。


退回路径和发送者已经设置好了!但是我没有想到要设置错误头,所以谢谢!;-) - BitDrink

0

我注意到在我的Linux托管服务器上,我必须在额外的头部和混合/替代头部中将所有的CRLF替换为LF。关于这一点,PHP文档说:

"如果消息没有被接收,请尝试仅使用LF(\n)。一些质量较差的Unix邮件传输代理会自动将LF替换为CRLF(这会导致如果使用CRLF,则CR加倍)。这应该是最后的手段,因为它不符合»RFC 2822。"

我尝试发送了一封邮件(仅包含"\n"),并在原始消息中查找"\r"和"\n"...每行都以CR结尾,并以"\n"开头!

问题:正如PHP mail()文档所说,我使用函数wordwrap()将行长度剪切为70个字符。是否有一种解决方法可以让邮件客户端以其原始格式而不是每行不超过70个字符的列形式显示消息?

答案[解决方案]:我已经通过设置quoted-printable作为Content-Transfer-Encoding来解决了这个问题:

$body .= "Content-Transfer-Encoding: quoted-printable\n";
$body .= "Content-Type: text/plain;\n\tcharset=utf-8;\n\tformat=flowed;\n\tdelsp=yes\n";

$body .= "\n" . quoted_printable_encode($message);

quoted_printable_encode() 函数仅适用于 PHP 5.3,实现方法可在文档页面中找到。


0

使用 PHPMailer(http://phpmailer.worxware.com/) 构建电子邮件消息。也许不是 IP 的问题,而是其他原因。有很多事情,垃圾邮件过滤器会过敏反应(例如缺少 Message-ID 等)。此外,使用 PHPMailer ,您可以通过 mail() 发送邮件,或者如果由于共享主机问题无法正常工作,则可以通过另一个主机(如 Gmail)上的 SMTP 发送邮件。


谢谢您的回复!我已经尝试使用PHPMailer,但原始消息看起来就像我手写的那个...没有任何改进!然而,我的问题是滥用问题,所以我认为如果我将我的网站移动到虚拟服务器或购买静态IP,我可以解决这个问题。 - BitDrink

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