php - PHP邮件功能无法完成电子邮件的发送

标签 php html email

<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $from = 'From: yoursite.com';
    $to = 'contact@yoursite.com';
    $subject = 'Customer Inquiry';
    $body = "From: $name\n E-Mail: $email\n Message:\n $message";

    if ($_POST['submit']) {
        if (mail ($to, $subject, $body, $from)) {
            echo '<p>Your message has been sent!</p>';
        } else {
            echo '<p>Something went wrong, go back and try again!</p>';
        }
    }
?>


我尝试创建一个简单的邮件表单。表单本身在我的index.html页面上,但它提交到单独的“感谢您提交”页面thankyou.php,其中嵌入了上述PHP代码。
该代码可以完美提交,但从不发送电子邮件。我怎样才能解决这个问题?

最佳答案

尽管此答案的某些部分仅适用于mail()函数本身的使用,但是许多故障排除步骤都可以应用于任何PHP邮件系统。

有多种原因导致您的脚本似乎不发送电子邮件。除非存在明显的语法错误,否则很难诊断这些问题。如果没有,您需要仔细阅读下面的清单,以查找您可能遇到的潜在陷阱。

确保已启用错误报告并设置为报告所有错误

错误报告对于根除代码中的错误以及PHP遇到的一般错误至关重要。需要启用错误报告以接收这些错误。将以下代码放在PHP文件的顶部(或主配置文件中)将启用错误报告。

error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");


有关更多详细信息,请参见How can I get useful error messages in PHP?this answer

确保调用mail()函数

看起来很愚蠢,但常见的错误是忘记将mail()函数实际放置在代码中。确保它在那里并且没有被注释掉。

确保正确调用mail()函数


  布尔邮件(字符串$ to,字符串$ subject,字符串$ message [,字符串$ additional_headers [,字符串$ additional_parameters]])


邮件功能需要三个必需的参数,还可以选择第四个和第五个参数。如果您对mail()的调用没有至少三个参数,它将失败。

如果您对mail()的调用没有正确顺序的正确参数,则也会失败。

检查服务器的邮件日志

您的Web服务器应该记录所有通过它发送电子邮件的尝试。这些日志的位置会有所不同(您可能需要询问服务器管理员,它们位于何处),但通常可以在用户的​​根目录下logs下找到它们。服务器中报告的错误消息(如果有)与您尝试发送电子邮件的内容有关。

检查端口连接失败

端口阻塞是大多数开发人员在集成其代码以使用SMTP传递电子邮件时面临的一个非常普遍的问题。并且,这可以在服务器邮件日志中轻松找到(如上所述,邮件日志的服务器位置因服务器而异)。如果您在共享主机服务器上,则默认情况下端口25和587仍处于阻止状态。此阻止是由您的托管服务提供商有意完成的。即使对于某些专用服务器也是如此。当这些端口被阻止时,请尝试使用端口2525进行连接。如果您发现该端口也被阻止,则唯一的解决方案是与您的主机提供商联系以解除对这些端口的阻止。

大多数托管服务提供商会阻止这些电子邮件端口,以保护其网络免于发送垃圾邮件。

将端口25或587用于纯/ TLS连接,将端口465用于SSL连接。对于大多数用户,建议使用端口587以避免某些托管服务提供商设置的速率限制。

不要使用错误抑制运算符

error suppression operator @放在PHP表达式中时,该表达式可能生成的任何错误消息都将被忽略。在某些情况下,必须使用此运算符,但发送邮件不是其中一种。

如果您的代码包含@mail(...),则您可能隐藏了重要的错误消息,这些消息将帮助您进行调试。删除@,然后查看是否报告了任何错误。

仅当您随后check with error_get_last()遇到具体故障时才建议这样做。

检查mail()返回值

mail()函数:


  如果邮件已被成功接受传递,则返回TRUE,否则返回FALSE。重要的是要注意,仅仅因为邮件已被接受送达,并不意味着邮件实际上将到达预期的目的地。


注意这一点很重要,因为:


如果收到FALSE返回值,则说明错误在于服务器接受您的邮件。这可能不是编码问题,而是服务器配置问题。您需要与系统管理员联系,以找出发生这种情况的原因。
如果您收到TRUE返回值,则并不意味着一定会发送您的电子邮件。这只是意味着电子邮件已被PHP成功发送到服务器上的相应处理程序。在PHP的控制范围之外,还有更多故障点可能导致电子邮件无法发送。


因此FALSE将帮助您指出正确的方向,而TRUE不一定表示您的电子邮件已成功发送。重要的是要注意!

确保您的托管服务提供商允许您发送电子邮件,并且不限制邮件发送

许多共享的虚拟主机,尤其是免费的虚拟主机提供商,要么不允许从其服务器发送电子邮件,要么限制在任何给定时间段内可以发送的电子邮件数量。这是由于他们努力限制垃圾邮件发送者利用便宜的服务。

如果您认为您的主机有电子邮件限制或阻止发送电子邮件,请查看其常见问题解答,以查看是否列出了任何此类限制。否则,您可能需要寻求他们的支持,以验证电子邮件发送周围是否存在任何限制。

检查垃圾邮件文件夹;防止将电子邮件标记为垃圾邮件

通常,由于各种原因,通过PHP(和其他服务器端编程语言)发送的电子邮件最终会位于收件人的垃圾邮件文件夹中。在对代码进行故障排除之前,请务必在此处进行检查。

为避免通过PHP发送的邮件被发送到收件人的垃圾邮件文件夹,在PHP代码和其他代码中,您都可以做很多事情,以最大程度地减少将电子邮件标记为垃圾邮件的机会。 Michiel de Mare中的好技巧包括:


  
  使用诸如SPFDKIM之类的电子邮件身份验证方法来证明您的电子邮件和您的域名属于同一类,并防止欺骗您的域名。 SPF网站包含一个向导,用于为您的站点生成DNS信息。
  Check您的reverse DNS,以确保邮件服务器的IP地址指向用于发送邮件的域名。
  确保您使用的IP地址为not on a blacklist
  确保答复地址是有效的现有地址。
  在“收件人”字段中使用收件人的全名,而不只是电子邮件地址(例如"John Smith" <john@blacksmiths-international.com>)。
  监视您的滥用帐户,例如abuse@yourdomain.com和postmaster@yourdomain.com。这意味着-确保这些帐户存在,阅读发送给他们的内容,并对投诉采取行动。
  最后,取消订阅真的很容易。否则,您的用户将通过按垃圾邮件按钮退订,这将影响您的声誉。
  


有关此主题的更多信息,请参见How do you make sure email you send programmatically is not automatically marked as spam?

确保提供所有邮件标题

如果某些垃圾邮件软件缺少常见的标头(例如“发件人”和“答复至”),它们将拒绝邮件:

$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!


原因:您的Web或发送邮件服务器未列入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提供的电子邮件帐户)。

如果电子邮件到达所有或其他一些电子邮件帐户,则您知道您的代码正在发送电子邮件,但是电子邮件帐户提供商可能出于某种原因阻止了它们。如果电子邮件没有到达任何电子邮件帐户,则问题很可能与您的代码有关。

确保代码与form方法匹配

如果您将窗体方法设置为POST,请确保使用$_POST查找窗体值。如果已将其设置为GET或根本没有将其设置,请确保使用$_GET查找表单值。

确保您的表格action值指向正确的位置

确保您的表单action属性包含一个指向您的PHP邮件代码的值。

<form action="send_email.php" method="POST">


确保Web主机支持发送电子邮件

一些Web托管提供商不允许或启用通过其服务器发送电子邮件。造成这种情况的原因可能有所不同,但是如果他们禁用了邮件发送功能,则需要使用另一种方法,该方法使用第三方为您发送这些电子邮件。

给他们的技术支持的电子邮件(在访问他们的在线支持或常见问题解答之后)应阐明您的服务器上是否有电子邮件功能。

确保已配置localhost邮件服务器

如果使用WAMP,MAMP或XAMPP在本地工作站上进行开发,则工作站上可能未安装电子邮件服务器。没有一个,默认情况下PHP无法发送邮件。

您可以通过安装基本邮件服务器来克服此问题。对于Windows,您可以使用免费的Mercury Mail

您也可以使用SMTP发送电子邮件。请参阅this great answer中的Vikas Dwivedi以了解如何执行此操作。

启用PHP的自定义mail.log

除了您的MTA和PHP的日志文件之外,您还可以专门启用logging for the mail() function。它不记录完整的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服务器的设置。通常,您将邮件探测发送至:他们的地址,然后获取传递报告以及稍后的更具体的故障或分析:


mail-tester.com(免费/简单)
glockapps.com(免费/ $$$)
senforensics.com(注册/ $$$)
mailtrap.io(pro / $$$)
ultratools/…/emailTest(仅免费/ MX检查)
各种:http://www.verticalresponse.com/blog/7-email-testing-delivery-tools/


使用其他邮件

PHP的内置mail()函数很方便,通常可以完成工作,但是has its shortcomings。幸运的是,有一些替代方案可以提供更大的功能和灵活性,包括处理上面概述的许多问题:


最受欢迎的是:PHPMailer
同样具有特色:SwiftMailer
甚至是较旧的PEAR::Mail


所有这些都可以与专业的SMTP服务器/服务提供商结合使用。 (因为在电子邮件设置/可配置性方面,典型的08/15共享Web托管计划会受到打击或错过。)

关于php - PHP邮件功能无法完成电子邮件的发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45266230/

相关文章:

windows - 签署二进制文件时如何指定电子邮件地址?

php - 发送邮件,正文中包含 html 和图像

php - php echo中的\n或\n不打印

php - 如何在 codeigniter 中仅使用主机 url 连接到 oracle db

html - 我可以做些什么来用 css 修改复选框的颜色吗?

javascript - 仅当使用 Jquery 的 Textbox 的最小值时才禁用按钮

database - 邮件/消息架构问题

php - <option> 标签中有多个值?

php - 如何存储用户的 session 数据

javascript - 为什么数据不显示在 kendo ui 网格上