PHP邮件功能没有完成电子邮件的发送

2022-01-30 00:00:00 email php html
<?php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $from = 'From: yoursite.com';
    $to = 'contact@yoursite.com';
    $subject = 'Customer Inquiry';
    $body = "From: $name
 E-Mail: $email
 Message:
 $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 代码是嵌入.代码完美提交,但从不发送电子邮件.我该如何解决这个问题?

I've tried creating a simple mail form. The form itself is on my index.html page, but it submits to a separate "thank you for your submission" page, thankyou.php, where the above PHP code is embedded. The code submits perfectly, but never sends an email. How can I fix this?

推荐答案

虽然这个答案的某些部分仅适用于 mail() 函数本身的使用,但许多这些故障排除步骤中的一部分可以应用于任何 PHP 邮件系统.

Although there are portions of this answer that apply to only to the usage of themail() function itself, many of these troubleshooting steps can be applied to any PHP mailing system.

您的脚本似乎没有发送电子邮件有多种原因.除非有明显的语法错误,否则很难诊断这些事情.如果没有,您需要通过下面的清单来查找您可能遇到的任何潜在陷阱.

There are a variety of reasons your script appears to not be sending emails. It's difficult to diagnose these things unless there is an obvious syntax error. Without one you need to run through the checklist below to find any potential pitfalls you may be encountering.

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

Error reporting is essential to rooting out bugs in your code and general errors that PHP encounters. Error reporting needs to be enabled to receive these errors. Placing the following code at the top of your PHP files (or in a master configuration file) will enable error reporting.

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

请参阅 如何获得有用的错误PHP 中的消息? — this answer 了解更多详情.

See How can I get useful error messages in PHP? — this answer for more details on this.

这可能看起来很傻,但一个常见的错误是忘记在代码中实际放置 mail() 函数.确保它存在并且没有被注释掉.

It may seem silly but a common error is to forget to actually place the mail() function in your code. Make sure it is there and not commented out.

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

bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )

mail 函数接受三个必需参数,以及可选的第四个和第五个参数.如果您对 mail() 的调用没有至少三个参数,它将失败.

The mail function takes three required parameters and optionally a fourth and fifth one. If your call to mail() does not have at least three parameters it will fail.

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

If your call to mail() does not have the correct parameters in the correct order it will also fail.

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

Your web server should be logging all attempts to send emails through it. The location of these logs will vary (you may need to ask your server administrator where they are located) but they can commonly be found in a user's root directory under logs. Inside will be error messages the server reported, if any, related to your attempts to send emails.

端口阻塞是大多数开发人员在集成他们的代码以使用 SMTP 传递电子邮件时面临的一个非常常见的问题.而且,这可以在服务器邮件日志中轻松跟踪(邮件日志服务器的位置可能因服务器而异,如上所述).如果您在共享主机服务器上,默认情况下端口 25 和 587 将保持被阻止.此块是由您的托管服务提供商故意完成的.即使对于某些专用服务器也是如此.当这些端口被阻塞时,请尝试使用端口 2525 进行连接.如果您发现该端口也被阻塞,那么唯一的解决方案是联系您的托管服务提供商解除这些端口的阻塞.

Port block is a very common problem which most developers face while integrating their code to deliver emails using SMTP. And, this can be easily traced at the server maillogs (the location of server of mail log can vary from server to server, as explained above). In case you are on a shared hosting server, the ports 25 and 587 remain blocked by default. This block is been purposely done by your hosting provider. This is true even for some of the dedicated servers. When these ports are blocked, try to connect using port 2525. If you find that port is also blocked, then the only solution is to contact your hosting provider to unblock these ports.

大多数托管服务提供商都会阻止这些电子邮件端口,以保护他们的网络不发送任何垃圾邮件.

Most of the hosting providers block these email ports to protect their network from sending any spam emails.

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

Use ports 25 or 587 for plain/TLS connections and port 465 for SSL connections. For most users, it is suggested to use port 587 to avoid rate limits set by some hosting providers.

当错误抑制操作符 @ 在 PHP 中的表达式之前,任何可能由该表达式生成的错误消息都将被忽略.在某些情况下,使用此运算符是必要的,但发送邮件不是其中之一.

When the error suppression operator @ is prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored. There are circumstances where using this operator is necessary but sending mail is not one of them.

如果您的代码包含 @mail(...),那么您可能隐藏了有助于调试的重要错误消息.把@去掉,看看有没有报错.

If your code contains @mail(...) then you may be hiding important error messages that will help you debug this. Remove the @ and see if any errors are reported.

仅当您 检查 error_get_last() 紧接着具体失败.

It's only advisable when you check with error_get_last() right afterwards for concrete failures.

mail() 函数:

如果邮件被成功接收,则返回TRUE,否则返回FALSE.需要注意的是,仅仅因为邮件被接受投递,并不意味着邮件实际上会到达预定目的地.

Returns TRUE if the mail was successfully accepted for delivery, FALSE otherwise. It is important to note that just because the mail was accepted for delivery, it does NOT mean the mail will actually reach the intended destination.

这很重要,因为:

  • 如果您收到 FALSE 返回值,则您知道错误在于您的服务器接受您的邮件.这可能不是编码问题,而是服务器配置问题.您需要与系统管理员联系,了解发生这种情况的原因.
  • 如果您收到 TRUE 返回值,这并不意味着您的电子邮件一定会被发送.这只是意味着电子邮件已通过 PHP 成功发送到服务器上的相应处理程序.还有更多超出 PHP 控制的故障点可能导致电子邮件无法发送.
  • If you receive a FALSE return value you know the error lies with your server accepting your mail. This probably isn't a coding issue but a server configuration issue. You need to speak to your system administrator to find out why this is happening.
  • If you receive a TRUE return value it does not mean your email will definitely be sent. It just means the email was sent to its respective handler on the server successfully by PHP. There are still more points of failure outside of PHP's control that can cause the email to not be sent.

所以 FALSE 将帮助您指出正确的方向,而 TRUE 确实 not 一定意味着您的电子邮件已成功发送.这一点很重要!

So FALSE will help point you in the right direction whereas TRUE does not necessarily mean your email was sent successfully. This is important to note!

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

Many shared webhosts, especially free webhosting providers, either do not allow emails to be sent from their servers or limit the amount that can be sent during any given time period. This is due to their efforts to limit spammers from taking advantage of their cheaper services.

如果您认为您的房东有电子邮件限制或阻止发送电子邮件,请查看他们的常见问题解答,看看他们是否列出了任何此类限制.否则,您可能需要联系他们的支持人员,以验证是否对发送电子邮件有任何限制.

If you think your host has emailing limits or blocks the sending of emails, check their FAQs to see if they list any such limitations. Otherwise, you may need to reach out to their support to verify if there are any restrictions in place around the sending of emails.

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

Oftentimes, for various reasons, emails sent through PHP (and other server-side programming languages) end up in a recipient's spam folder. Always check there before troubleshooting your code.

为避免通过 PHP 发送的邮件被发送到收件人的垃圾邮件文件夹,您可以在 PHP 代码中或其他方面执行各种操作,以尽量减少您的电子邮件被标记为垃圾邮件的机会.Michiel de Mare 的好建议包括:

To avoid mail sent through PHP from being sent to a recipient's spam folder, there are various things you can do, both in your PHP code and otherwise, to minimize the chances your emails are marked as spam. Good tips from Michiel de Mare include:

  • 使用电子邮件身份验证方法,例如 SPF 和 DKIM 以证明您的电子邮件和您的域名属于同一个,并防止您的域名被欺骗.SPF 网站包含一个为您的网站生成 DNS 信息的向导.
  • 检查您的反向 DNS 以确保您的邮件服务器的 IP 地址指向您用于发送邮件的域名.
  • 确保您使用的 IP 地址不在黑名单上
  • 确保回复地址是有效的现有地址.
  • 在收件人"字段中使用收件人的完整真实姓名,而不仅仅是电子邮件地址(例如 John Smith"<john@blacksmiths-international.com>).
  • 监控您的滥用帐号,例如 abuse@yourdomain.com 和 postmaster@yourdomain.com.这意味着 - 确保这些帐户存在,阅读发送给他们的内容,并对投诉采取行动.
  • 最后,让退订变得真正轻松.否则,您的用户将通过按垃圾邮件按钮取消订阅,这将影响您的声誉.
  • Use email authentication methods, such as SPF, and DKIM to prove that your emails and your domain name belong together, and to prevent spoofing of your domain name. The SPF website includes a wizard to generate the DNS information for your site.
  • Check your reverse DNS to make sure the IP address of your mail server points to the domain name that you use for sending mail.
  • Make sure that the IP-address that you're using is not on a blacklist
  • Make sure that the reply-to address is a valid, existing address.
  • Use the full, real name of the addressee in the To field, not just the email-address (e.g. "John Smith" <john@blacksmiths-international.com> ).
  • Monitor your abuse accounts, such as abuse@yourdomain.com and postmaster@yourdomain.com. That means - make sure that these accounts exist, read what's sent to them, and act on complaints.
  • Finally, make it really easy to unsubscribe. Otherwise, your users will unsubscribe by pressing the spam button, and that will affect your reputation.

请参阅如何确保您以编程方式发送的电子邮件不会被自动标记为垃圾邮件?了解有关此主题的更多信息.

See How do you make sure email you send programmatically is not automatically marked as spam? for more on this topic.

如果邮件缺少常见的标题,例如发件人",某些垃圾邮件软件会拒绝邮件.和回复":

Some spam software will reject mail if it is missing common headers such as "From" and "Reply-to":

$headers = array("From: from@example.com",
    "Reply-To: replyto@example.com",
    "X-Mailer: PHP/" . PHP_VERSION
);
$headers = implode("
", $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:发件人

虽然邮件必须有 From: 发件人,但您不能只使用 any 值.特别是用户提供的发件人地址是阻止邮件的可靠方法:

Don't use a faux From: sender

While the mail must have a From: sender, you may not just use any value. In particular user-supplied sender addresses are a surefire way to get mails blocked:

$headers = array("From: $_POST[contactform_sender_email]"); // No!

原因:您的 Web 或发送邮件服务器未列入 SPF/DKIM 白名单以假装负责@hotmail 或@gmail 地址.它甚至可以静默丢弃带有 From: 未配置的发件人域的邮件.

Reason: your web or sending mail server is not SPF/DKIM-whitelisted to pretend being responsible for @hotmail or @gmail addresses. It may even silently drop mails with From: sender domains it's not configured for.

有时问题很简单,就是电子邮件收件人的值不正确.这可能是由于使用了不正确的变量.

Sometimes the problem is as simple as having an incorrect value for the recipient of the email. This can be due to using an incorrect variable.

$to = 'user@example.com';
// other variables ....
mail($recipient, $subject, $message, $headers); // $recipient should be $to

另一种测试方法是将收件人值硬编码到 mail() 函数调用中:

Another way to test this is to hard code the recipient value into the mail() function call:

mail('user@example.com', $subject, $message, $headers); 

这可以应用于所有 mail() 参数.

This can apply to all of the mail() parameters.

为帮助排除电子邮件帐户问题,请将您的电子邮件发送到不同电子邮件提供商的多个电子邮件帐户.如果您的电子邮件没有到达用户的 Gmail 帐户,请将相同的电子邮件发送到 Yahoo 帐户、Hotmail 帐户和常规 POP3 帐户(例如您的 ISP 提供的电子邮件帐户).

To help rule out email account issues, send your email to multiple email accounts at different email providers. If your emails are not arriving at a user's Gmail account, send the same emails to a Yahoo account, a Hotmail account, and a regular POP3 account (like your ISP-provided email account).

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

If the emails arrive at all or some of the other email accounts, you know your code is sending emails but it is likely that the email account provider is blocking them for some reason. If the email does not arrive at any email account, the problem is more likely to be related to your code.

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

If you have set your form method to POST, make sure you are using $_POST to look for your form values. If you have set it to GET or didn't set it at all, make sure you use $_GET to look for your form values.

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

Make sure your form action attribute contains a value that points to your PHP mailing code.

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

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

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

Make sure the Web host supports sending email

Some Web hosting providers do not allow or enable the sending of emails through their servers. The reasons for this may vary but if they have disabled the sending of mail you will need to use an alternative method that uses a third party to send those emails for you.

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

An email to their technical support (after a trip to their online support or FAQ) should clarify if email capabilities are available on your server.

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

If you are developing on your local workstation using WAMP, MAMP, or XAMPP, an email server is probably not installed on your workstation. Without one, PHP cannot send mail by default.

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

You can overcome this by installing a basic mail server. For Windows you can use the free Mercury Mail.

您还可以使用 SMTP 发送电子邮件.请参阅 这个很棒的答案>Vikas Dwivedi 学习如何做到这一点.

You can also use SMTP to send your emails. See this great answer from Vikas Dwivedi to learn how to do this.

除了您的 MTA 和 PHP 的日志文件之外,您还可以启用 专门记录 mail() 函数.它没有记录完整的 SMTP 交互,但至少记录了函数调用参数和调用脚本.

In addition to your MTA's and PHP's log file, you can enable logging for the mail() function specifically. It doesn't record the complete SMTP interaction, but at least function call parameters and invocation script.

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 中启用这些选项.)

See http://php.net/manual/en/mail.configuration.php for details. (It's best to enable these options in the php.ini or .user.ini or .htaccess perhaps.)

您可以使用各种递送和垃圾邮件检查服务来测试您的 MTA/网络服务器设置.通常,您将邮件探测发送到:他们的地址,然后获得投递报告和更具体的故障或分析:

There are various delivery and spamminess checking services you can utilize to test your MTA/webserver setup. Typically you send a mail probe To: their address, then get a delivery report and more concrete failures or analyzations later:

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

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

PHP's built-in mail() function is handy and often gets the job done but it has its shortcomings. Fortunately, there are alternatives that offer more power and flexibility including handling a lot of the issues outlined above:

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

所有这些都可以与专业的 SMTP 服务器/服务提供商结合使用.(因为在电子邮件设置/配置方面,典型的 08/15 共享虚拟主机计划会受到影响.)

All of which can be combined with a professional SMTP server/service provider. (Because typical 08/15 shared webhosting plans are hit or miss when it comes to email setup/configurability.)

相关文章