<?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页面上,但它提交到一个单独的“感谢您的提交”页面thanks . PHP,其中嵌入了上述PHP代码。 代码完美地提交,但从未发送电子邮件。我该如何解决这个问题?


当前回答

只需在发送邮件之前添加一些标题:

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

$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html\r\n";
$headers .= 'From: from@example.com' . "\r\n" .
'Reply-To: reply@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);

还有一件事。mail()函数在本地主机中不起作用。将代码上传到服务器并尝试。

其他回答

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

脚本不发送电子邮件的原因有很多。除非存在明显的语法错误,否则很难诊断这些问题。如果没有,您需要运行下面的检查表,以找到您可能遇到的任何潜在陷阱。

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

错误报告对于消除代码中的错误和PHP遇到的一般错误是必不可少的。需要启用错误报告以接收这些错误。将以下代码放在PHP文件的顶部(或主配置文件中)将启用错误报告。

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

参见如何在PHP中获得有用的错误消息?-这是关于这方面更多细节的答案。

确保调用了mail()函数

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

确保正确地调用了mail()函数

字符串$to,字符串$subject,字符串$message[,字符串$additional_headers[,字符串$additional_parameters]])

邮件函数接受三个必需的参数,还可以选择第四个和第五个参数。如果对mail()的调用没有至少三个参数,则会失败。

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

检查服务器的邮件日志

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

检查端口连接失败

Port block is a very common problem that 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 the server of mail log can vary from server to server, as explained above). In case you are on a shared hosting server, 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 the port is also blocked, then the only solution is to contact your hosting provider to unblock these ports.

大多数主机提供商阻止这些电子邮件端口,以保护他们的网络免受任何垃圾邮件的发送。

使用端口25或587作为普通/TLS连接,端口465用于SSL连接。对于大多数用户,建议使用端口587,以避免某些主机提供商设置的速率限制。

不要使用错误抑制操作符

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

如果您的代码包含@mail(…),那么您可能隐藏了有助于调试的重要错误消息。删除@并查看是否报告任何错误。

只有在随后使用error_get_last()检查具体失败时才可取。

检查mail()返回值

mail()函数:

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

这一点很重要,因为:

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并不一定意味着您的电子邮件发送成功。这一点很重要!

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

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

如果你认为你的主机有电子邮件限制或阻止发送电子邮件,检查他们的常见问题,看看他们是否列出了任何这样的限制。否则,你可能需要联系他们的支持,以核实是否有关于发送电子邮件的任何限制。

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

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

为了避免通过PHP发送的邮件被发送到收件人的垃圾邮件文件夹,可以在PHP代码和其他代码中进行各种操作,以最大限度地减少电子邮件被标记为垃圾邮件的可能性。来自Michiel de Mare的建议包括:

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.example and postmaster@yourdomain.example. 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.

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

确保提供了所有的邮件标题

一些垃圾邮件软件如果缺少常见的标题,如“发件人”和“回复收件人”,就会拒绝邮件:

$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: sender

虽然邮件必须有一个From: sender,但您不能只使用任何值。特别是用户提供的发件人地址是一种确保邮件被拦截的方法:

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

原因:你的网络或发送邮件的服务器没有被SPF/ dkim白名单来假装对@hotmail或@gmail地址负责。它甚至可以使用未配置的发件人域静默地丢弃邮件。

确保收件人值是正确的

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

$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来查找表单值。

确保您的表单操作值指向正确的位置

确保表单操作属性包含指向PHP邮件代码的值。

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

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

一些网络托管提供商不允许或启用通过其服务器发送电子邮件。原因可能有所不同,但如果他们已经禁用了邮件发送,您将需要使用第三方为您发送这些邮件的替代方法。

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

确保配置了本地主机邮件服务器

如果您正在使用WAMP、MAMP或XAMPP在本地工作站上开发,那么您的工作站上可能没有安装电子邮件服务器。如果没有,PHP默认情况下不能发送邮件。

您可以通过安装一个基本的邮件服务器来解决这个问题。对于Windows系统,你可以使用免费的水星邮件。

你也可以使用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服务器设置。通常情况下,您将邮件探测发送到:他们的地址,然后获得交付报告和更具体的故障或分析:

mail-tester。例子(免费/简单) glockapps.com(免费/ $ $ $) senforensics.com(注册/ $ $ $) mailtrap。io (pro / $ $ $) ultrtools /…/emailTest(免费/MX检查) 不同:http://www.verticalresponse.com/blog/7-email-testing-delivery-tools/

使用不同的邮件

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

最受欢迎的是:PHPMailer 同样有特色的还有SwiftMailer 甚至是更老的PEAR::Mail。

所有这些都可以与专业的SMTP服务器/服务提供商相结合。(因为当涉及到电子邮件设置/配置时,典型的08/15共享虚拟主机计划是随机的。)

试试这个

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

我在000webhost上做了以下工作:

$headers  = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1" . "\r\n";
$headers .= "From: ". $from. "\r\n";
$headers .= "Reply-To: ". $from. "\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
$headers .= "X-Priority: 1" . "\r\n";

发送邮件时直接输入邮箱地址:

mail('email@gmail.com', $subject, $message, $headers)

使用“and not”。

这个代码工作,但电子邮件收到了半小时的延迟。

如果你受困于Hostgator上的应用,这便是解决我的问题的方法。非常感谢发布详细解决方案的人。如果有一天链接离线,你有总结:

在服务器中查找sendmail路径。一个简单的方法来检查它,是临时写以下代码在一个页面,只有你将访问,以读取生成的信息:php phpinfo ();? >。打开这个页面,寻找sendmail路径。(然后,别忘了删除这段代码!) 问题和修正:如果你的sendmail路径只说-t -i,那么编辑你的服务器的php.ini并添加以下行:sendmail_path = /usr/sbin/sendmail -t -i;

但是,在能够使用PHP mail()函数发送邮件后,我了解到它发送未经验证的电子邮件,这产生了另一个问题。这些邮件都落在了我Hotmail的垃圾邮箱里,有些邮件从来没有发送过,我猜这与它们没有经过认证有关。这就是为什么我决定从mail()转换到使用SMTP的PHPMailer。

对于任何发现这一点的人,我不建议使用邮件。有一些答案涉及到这个问题,但没有解释为什么会这样。

PHP's mail function is not only opaque, it fully relies on whatever MTA you use (i.e. Sendmail) to do the work. mail will only tell you if the MTA failed to accept it (i.e. Sendmail was down when you tried to send). It cannot tell you if the mail was successful because it's handed it off. As such (as John Conde's answer details), you now get to fiddle with the logs of the MTA and hope that it tells you enough about the failure to fix it. If you're on a shared host or don't have access to the MTA logs, you're out of luck. Sadly, the default for most vanilla installs for Linux handle it this way.

邮件库(PHPMailer、Zend Framework 2+等)的功能与邮件非常不同。它们直接打开接收邮件服务器的套接字,然后通过该套接字直接发送SMTP邮件命令。换句话说,类充当自己的MTA(注意,您可以告诉库使用邮件来最终发送邮件,但我强烈建议您不要这样做)。

这意味着您可以直接看到来自接收服务器的响应(例如,在PHPMailer中,您可以打开调试输出)。不用再猜测邮件是否发送失败或原因。

如果您正在使用SMTP(即您正在调用isSMTP()),您可以使用SMTPDebug属性获得SMTP对话的详细记录。 通过在脚本中包含如下一行来设置该选项: $mail->SMTPDebug = 2;

您还可以获得更好的界面。对于邮件,你必须设置所有的标题,附件等。有了库,就有了专门的函数来实现这一点。这也意味着函数正在处理所有棘手的部分(比如头文件)。