尽管此答案的某些部分仅适用于mail()
函数本身的使用,但其中许多故障排除步骤可以应用于任何PHP邮件系统。
您的脚本似乎没有发送电子邮件的原因有很多。除非有明显的语法错误,否则很难诊断这些事情。如果没有,您需要浏览下面的清单,以找到您可能遇到的任何潜在陷阱。
确保错误报告已启用并设置为报告所有错误
错误报告对于根除代码中的错误和 PHP 遇到的一般错误至关重要。需要启用错误报告才能接收这些错误。将以下代码放在 PHP 文件的顶部(或主配置文件中)将启用错误报告。
error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");
请参阅如何在 PHP 中获取有用的错误消息? — 此答案了解更多详情。
确保调用该函数mail()
这可能看起来很愚蠢,但一个常见的错误是忘记将函数实际放置在代码中。确保它在那里并且没有被注释掉。mail()
确保正确调用函数mail()
bool 邮件 ( 字符串 $to, 字符串 $subject, 字符串 $message [, 字符串 $additional_headers [, 字符串 $additional_parameters ]] )
mail 函数采用三个必需参数,并可选择第四个和第五个参数。如果 对 的调用没有至少三个参数,它将失败。mail()
如果 对 的调用没有按正确顺序排列的正确参数,则也会失败。mail()
检查服务器的邮件日志
您的Web服务器应该记录所有通过它发送电子邮件的尝试。这些日志的位置会有所不同(您可能需要询问服务器管理员它们的位置),但它们通常可以在 用户根目录中找到。里面将是服务器报告的错误消息(如果有),与您尝试发送电子邮件有关。logs
检查端口连接失败
端口块是大多数开发人员在集成其代码以使用SMTP发送电子邮件时面临的一个非常普遍的问题。而且,这可以在服务器邮件日志中轻松跟踪(邮件日志服务器的位置可能因服务器而异,如上所述)。如果您使用的是共享主机服务器,则默认情况下端口25和587保持阻止状态。此块是由您的托管服务提供商特意完成的。即使对于某些专用服务器也是如此。当这些端口被阻止时,请尝试使用端口 2525 进行连接。如果您发现该端口也被阻止,那么唯一的解决方案是联系您的托管服务提供商以取消阻止这些端口。
大多数托管服务提供商阻止这些电子邮件端口,以保护其网络免受发送任何垃圾邮件。
将端口 25 或 587 用于普通/TLS 连接,将端口 465 用于 SSL 连接。对于大多数用户,建议使用端口587以避免某些托管服务提供商设置的速率限制。
不要使用错误抑制运算符
当错误抑制运算符附加到 PHP 中的表达式之前时,将忽略该表达式可能生成的任何错误消息。在某些情况下,必须使用此运算符,但发送邮件不是其中之一。@
如果您的代码包含,那么您可能隐藏了重要的错误消息,这些错误消息将帮助您调试它。删除 并查看是否报告了任何错误。@mail(...)
@
只有在您事后立即与error_get_last()
核实具体故障时,才建议这样做。
检查返回值mail()
mail()
函数:
如果邮件已成功接受递送,则返回,否则。重要的是要注意,仅仅因为邮件被接受传递,并不意味着邮件实际上会到达预期的目的地。TRUE
FALSE
这一点很重要,因为:
- 如果您收到返回值,您就知道错误在于您的服务器接受您的邮件。这可能不是编码问题,而是服务器配置问题。您需要与系统管理员联系,以了解发生这种情况的原因。
FALSE
- 如果您收到返回值,这并不意味着您的电子邮件肯定会被发送。它只是意味着电子邮件已通过PHP成功发送到服务器上的相应处理程序。在PHP的控制之外,还有更多的故障点可能导致电子邮件无法发送。
TRUE
因此,这将有助于您指出正确的方向,而不一定意味着您的电子邮件已成功发送。这一点很重要!FALSE
TRUE
确保您的托管服务提供商允许您发送电子邮件,并且不限制邮件发送
许多共享网络主机,特别是免费的虚拟主机提供商,要么不允许从其服务器发送电子邮件,要么限制在任何给定时间段内可以发送的数量。这是由于他们努力限制垃圾邮件发送者利用其更便宜的服务。
如果您认为您的房东有电子邮件限制或阻止发送电子邮件,请查看他们的常见问题解答,看看他们是否列出了任何此类限制。否则,您可能需要与他们的支持人员联系,以验证在发送电子邮件方面是否存在任何限制。
检查垃圾邮件文件夹;防止电子邮件被标记为垃圾邮件
通常,由于各种原因,通过PHP(和其他服务器端编程语言)发送的电子邮件最终会进入收件人的垃圾邮件文件夹。在对代码进行故障排除之前,请务必检查那里。
为了避免通过PHP发送的邮件被发送到收件人的垃圾邮件文件夹,您可以在PHP代码和其他方面执行各种操作,以最大程度地减少电子邮件被标记为垃圾邮件的机会。Michiel de Mare的好提示包括:
- 使用 SPF 和 DKIM 等电子邮件身份验证方法来证明您的电子邮件和域名属于一起,并防止欺骗您的域名。SPF 网站包含一个向导,用于为站点生成 DNS 信息。
-
检查反向 DNS,确保邮件服务器的 IP 地址指向用于发送邮件的域名。
- 确保您使用的 IP 地址不在黑名单上
- 确保回复地址是有效的现有地址。
- 在“收件人”字段中使用收件人的完整真实姓名,而不仅仅是电子邮件地址(例如 ).
"John Smith" <john@blacksmiths-international.com>
- 监控您的滥用帐户,例如 和 。这意味着 - 确保这些帐户存在,阅读发送给它们的内容,并对投诉采取行动。
abuse@yourdomain.example
postmaster@yourdomain.example
- 最后,让退订变得非常容易。否则,您的用户将通过按垃圾邮件按钮取消订阅,这将影响您的声誉。
有关此主题的详细信息,请参阅如何确保以编程方式发送的电子邮件不会自动标记为垃圾邮件?。
确保提供所有邮件头
如果某些垃圾邮件软件缺少常见标头(如“发件人”和“回复”),则会拒绝邮件:
$headers = array("From: from@example.com",
"Reply-To: replyto@example.com",
"X-Mailer: PHP/" . PHP_VERSION
);
$headers = implode("\r\n", $headers);
mail($to, $subject, $message, $headers);
确保邮件头没有语法错误
无效的标头与没有标头一样糟糕。一个不正确的字符可能是破坏电子邮件所需的全部内容。仔细检查以确保您的语法正确,因为PHP不会为您捕获这些错误。
$headers = array("From from@example.com", // missing colon
"Reply To: replyto@example.com", // missing hyphen
"X-Mailer: "PHP"/" . PHP_VERSION // bad quotes
);
不要使用假发件人From:
虽然邮件必须具有发件人:发件人,但您不能只使用任何值。特别是用户提供的发件人地址是阻止邮件的可靠方法:
$headers = array("From: $_POST[contactform_sender_email]"); // No!
原因:您的网络或发送邮件服务器未被列入 SPF/DKIM 白名单,无法假装对@hotmail或@gmail地址负责。它甚至可能以静默方式丢弃未配置发件人域的邮件。From:
确保收件人值正确无误
有时,问题很简单,例如为电子邮件收件人提供不正确的值。这可能是由于使用了不正确的变量。
$to = 'user@example.com';
// other variables ....
mail($recipient, $subject, $message, $headers); // $recipient should be $to
测试此情况的另一种方法是将接收方值硬编码到函数调用中:mail()
mail('user@example.com', $subject, $message, $headers);
这可以应用于所有参数。mail()
发送到多个帐户
为了帮助排除电子邮件帐户问题,请将电子邮件发送到不同电子邮件提供商的多个电子邮件帐户。如果您的电子邮件未到达用户的 Gmail 帐户,请将相同的电子邮件发送到 Yahoo 帐户、Hotmail 帐户和常规 POP3 帐户(如 ISP 提供的电子邮件帐户)。
如果电子邮件到达所有或某些其他电子邮件帐户,则您知道您的代码正在发送电子邮件,但电子邮件帐户提供商可能出于某种原因阻止了它们。如果电子邮件未到达任何电子邮件帐户,则问题更有可能与您的代码有关。
确保代码与表单方法匹配
如果已将表单方法设置为 ,请确保 使用 来查找表单值。如果您已将其设置为或根本没有将其设置,请确保用于查找表单值。POST
$_POST
GET
$_GET
确保表单值指向正确的位置action
确保您的表单属性包含指向 PHP 邮件代码的值。action
<form action="send_email.php" method="POST">
确保 Web 主机支持发送电子邮件
某些 Web 托管服务提供商不允许或启用通过其服务器发送电子邮件。造成这种情况的原因可能会有所不同,但是如果他们禁用了邮件发送,您将需要使用使用第三方为您发送这些电子邮件的替代方法。
向其技术支持发送电子邮件(在访问其联机支持或常见问题解答之后)应阐明您的服务器上是否提供电子邮件功能。
确保邮件服务器已配置localhost
如果使用 WAMP、MAMP 或 XAMPP 在本地工作站上进行开发,则工作站上可能未安装电子邮件服务器。如果没有,PHP 默认无法发送邮件。
您可以通过安装基本的邮件服务器来克服这一问题。对于Windows,您可以使用免费的Mercury Mail。
您还可以使用 SMTP 发送电子邮件。看看Vikas Dwivedi的这个伟大的答案,学习如何做到这一点。
启用 PHP 的自定义mail.log
除了 MTA 和 PHP 的日志文件之外,您还可以专门为 mail()
函数启用日志记录。它不记录完整的 SMTP 交互,但至少记录函数调用参数和调用脚本。
ini_set("mail.log", "/tmp/mail.log");
ini_set("mail.add_x_header", TRUE);
有关详细信息,请参阅 http://php.net/manual/en/mail.configuration.php。(最好在 或 或 中启用这些选项。php.ini
.user.ini
.htaccess
与邮件测试服务部门核实
您可以使用各种递送和垃圾邮件检查服务来测试您的 MTA/Web 服务器设置。通常,您将邮件探测发送到:他们的地址,然后获取交付报告以及稍后的更具体的故障或分析:
使用其他邮件程序
PHP的内置功能很方便,经常完成工作,但它有其缺点。幸运的是,有一些替代方案可以提供更大的功能和灵活性,包括处理上面概述的许多问题:mail()
所有这些都可以与专业的SMTP服务器/服务提供商结合使用。(因为典型的08/15共享虚拟主机计划在电子邮件设置/可配置性方面会受到打击或错过。