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


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 代码。 代码提交完美,但从来没有发送电子邮件。我该如何解决这个问题?

497849 次浏览

虽然这个答案的某些部分仅适用于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()的调用没有正确的参数,也会失败。

检查服务器的邮件日志

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

检查端口连接失败

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

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

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

不要使用错误抑制操作符

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

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

只有当你在具体的失败之后检查error_get_last()才是可取的。

检查mail()返回值

mail()函数:

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

这一点很重要,因为:

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

因此,FALSE将帮助您指出正确的方向,而TRUE 一定意味着您的电子邮件发送成功。这一点很重要!

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

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

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

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

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

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

  • 使用电子邮件认证方法,如防晒系数DKIM,以证明您的电子邮件和您的域名属于一起,并防止欺骗您的域名。SPF网站包含一个向导,用于为您的网站生成DNS信息。
  • 检查您的反向DNS,以确保您的邮件服务器的IP地址指向您用于发送邮件的域名。
  • 确保您使用的ip地址是不在黑名单上
  • 确保回复地址是有效的现有地址。
  • 在To字段中使用收件人的真实全名,而不仅仅是电子邮件地址(例如"John Smith" <john@blacksmiths-international.com>)。
  • 监视您的滥用帐户,例如abuse@yourdomain.examplepostmaster@yourdomain.example。这意味着-确保这些账户存在,阅读发送给他们的内容,并对投诉采取行动。
  • 最后,让真的很容易取消订阅。否则,用户按垃圾邮件按钮就会退订,这将影响您的声誉。

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

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

一些垃圾邮件软件会拒绝邮件,如果它缺少常见的标题,如&;from &;和“Reply-to":

$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:发送者

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

$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值指向正确的位置

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

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

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

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

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

确保配置了localhost邮件服务器

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

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

你也可以使用SMTP发送电子邮件。参见这个答案很好维已经受理来学习如何做到这一点。

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

  • # EYZ0(免费/简单)
  • # EYZ0(免费/ $ $ $)
  • # EYZ0(注册/ $ $ $)
  • # EYZ0 (pro / $ $ $)
  • ultratools /…/ emailTest(只检查免费/MX)
  • 不同:# EYZ0

使用不同的邮件

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

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

如果您使用SMTP配置发送电子邮件,请尝试使用PHPMailer。您可以从https://github.com/PHPMailer/PHPMailer下载这个库。

我用这种方式创建了我的电子邮件:

function send_mail($email, $recipient_name, $message='')
{
require("phpmailer/class.phpmailer.php");


$mail = new PHPMailer();


$mail->CharSet = "utf-8";
$mail->IsSMTP();                                      // Set mailer to use SMTP
$mail->Host = "mail.example.com";  // Specify main and backup server
$mail->SMTPAuth = true;     // Turn on SMTP authentication
$mail->Username = "myusername";  // SMTP username
$mail->Password = "p@ssw0rd"; // SMTP password


$mail->From = "me@walalang.com";
$mail->FromName = "System-Ad";
$mail->AddAddress($email, $recipient_name);


$mail->WordWrap = 50;                                 // Set word wrap to 50 characters
$mail->IsHTML(true);                                  // Set email format to HTML (true) or plain text (false)


$mail->Subject = "This is a Sampleenter code here Email";
$mail->Body    = $message;
$mail->AltBody = "This is the body in plain text for non-HTML mail clients";
$mail->AddEmbeddedImage('images/logo.png', 'logo', 'logo.png');
$mail->addAttachment('files/file.xlsx');


if(!$mail->Send())
{
echo "Message could not be sent. <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}


echo "Message has been sent";
}

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

<?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()函数在本地主机中不起作用。将代码上传到服务器并尝试。

如果只使用# eyz0函数,则需要完成配置文件。

您需要打开邮件扩展,并设置SMTP smtp_port等,最重要的是,设置您的用户名和密码。没有它,邮件就无法发送。此外,您还可以使用PHPMail类来发送。

您可以使用CodeIgniter配置电子邮件。例如,使用SMTP(简单的方法):

$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'mail.domain.com', // Your SMTP host
'smtp_port' => 26, // Default port for SMTP
'smtp_user' => 'name@domain.com',
'smtp_pass' => 'password',
'mailtype' => 'html',
'charset' => 'iso-8859-1',
'wordwrap' => TRUE
);
$message = 'Your msg';
$this->load->library('email', $config);
$this->email->from('name@domain.com', 'Title');
$this->email->to('emaildestination@domain.com');
$this->email->subject('Header');
$this->email->message($message);


if($this->email->send())
{
// Conditional true
}

这对我很管用!

我觉得这个应该能搞定。我只是添加了一个if(isset,并向主体中的变量添加了连接,以将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."\r\n E-Mail:" .$email."\r\n Message:\r\n" .$message;


if (isset($_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>';
}
}


?>

把这两件事分开和一起尝试:

  1. 删除if($_POST['submit']){}
  2. 删除$from(只是我的直觉)

有几种可能性:

  1. 您正面临服务器问题。服务器上没有邮件服务器。所以你的邮件不能工作,因为你的代码是好的,邮件是有类型的。

  2. 您没有得到发布的值。尝试使用静态值的代码。

  3. 使用SMTP邮件发送邮件…

  1. 总是尝试在邮件函数中发送标题。
  2. 如果您通过localhost发送邮件,则执行SMTP设置以发送邮件。
  3. 如果您通过服务器发送邮件,请检查您的服务器上是否启用了电子邮件发送功能。

试试这个

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>
';
}
}
$name = $_POST['name'];
$email = $_POST['email'];
$reciver = '/* Reciver Email address */';
if (filter_var($reciver, FILTER_VALIDATE_EMAIL)) {
$subject = $name;
// To send HTML mail, the Content-type header must be set.
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From:' . $email. "\r\n"; // Sender's Email
//$headers .= 'Cc:' . $email. "\r\n"; // Carbon copy to Sender
$template = '<div style="padding:50px; color:white;">Hello ,<br/>'
. '<br/><br/>'
. 'Name:' .$name.'<br/>'
. 'Email:' .$email.'<br/>'
. '<br/>'
. '</div>';
$sendmessage = "<div style=\"background-color:#7E7E7E; color:white;\">" . $template . "</div>";
// Message lines should not exceed 70 characters (PHP rule), so wrap it.
$sendmessage = wordwrap($sendmessage, 70);
// Send mail by PHP Mail Function.
mail($reciver, $subject, $sendmessage, $headers);
echo "Your Query has been received, We will contact you soon.";
} else {
echo "<span>* invalid email *</span>";
}

在邮件功能中添加邮件头。

$header = "From: noreply@example.com\r\n";
$header.= "MIME-Version: 1.0\r\n";
$header.= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$header.= "X-Priority: 1\r\n";


$status = mail($to, $subject, $message, $header);


if($status)
{
echo '<p>Your mail has been sent!</p>';
} else {
echo '<p>Something went wrong. Please 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)

使用''而不是""

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

首先,你可能有太多参数的mail()函数… 你最多可以有五个,mail(to, subject, message, headers, parameters);

至于$from变量,如果你使用Linux cPanel,它应该自动来自你的网络主机。它自动来自你的cPanel用户名和IP地址。

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

还要确保mail()函数中变量的顺序正确。

按此顺序输入mail($to, $subject, $message, etc.),否则它有可能不起作用。

如果在使用PHP发送邮件时遇到问题,可以考虑使用< >强PHPMailer < / >强< >强SwiftMailer < / >强之类的替代方案。

当我需要用PHP发送邮件时,我通常使用SwiftMailer。


基本用法:

require 'mail/swift_required.php';


$message = Swift_Message::newInstance()
// The subject of your email
->setSubject('Jane Doe sends you a message')
// The from address(es)
->setFrom(array('jane.doe@gmail.com' => 'Jane Doe'))
// The to address(es)
->setTo(array('frank.stevens@gmail.com' => 'Frank Stevens'))
// Here, you put the content of your email
->setBody('<h3>New message</h3><p>Here goes the rest of my message</p>', 'text/html');


if (Swift_Mailer::newInstance(Swift_MailTransport::newInstance())->send($message)) {
echo json_encode([
"status" => "OK",
"message" => 'Your message has been sent!'
], JSON_PRETTY_PRINT);
} else {
echo json_encode([
"status" => "error",
"message" => 'Oops! Something went wrong!'
], JSON_PRETTY_PRINT);
}

有关如何使用SwiftMailer的更多信息,请参阅官方文件 .

对于任何发现这一点的人,我不建议使用mail。有一些答案涉及到这个问题,但不是为什么

PHP的mail函数不仅是不透明的,它完全依赖于您使用的任何MTA(即Sendmail)来完成工作。mail只有告诉你,如果MTA未能接受它(即Sendmail是关闭时,你试图发送)。它不能告诉你邮件是否成功,因为它已经将邮件传递出去了。因此(如约翰·康德的回答是细节),您现在可以摆弄MTA的日志,并希望它能告诉您足够多的关于修复失败的信息。如果您在共享主机上,或者无法访问MTA日志,那么您就不走运了。遗憾的是,大多数Linux普通安装的默认设置都是这样处理的。

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

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

如果您正在使用SMTP(即您正在调用isSMTP()),您可以使用SMTPDebug属性获得SMTP对话的详细记录。

通过在脚本中包含如下一行来设置该选项:

$mail->SMTPDebug = 2;

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

共享主机中mail()功能大多是禁用的。 更好的选择是使用SMTP。最好的选项是Gmail或SendGrid.


SMTPconfig.php

<?php
$SmtpServer="smtp.*.*";
$SmtpPort="2525"; //default
$SmtpUser="***";
$SmtpPass="***";
?>

SMTPmail.php

<?php
class SMTPClient
{


function SMTPClient ($SmtpServer, $SmtpPort, $SmtpUser, $SmtpPass, $from, $to, $subject, $body)
{


$this->SmtpServer = $SmtpServer;
$this->SmtpUser = base64_encode ($SmtpUser);
$this->SmtpPass = base64_encode ($SmtpPass);
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
$this->body = $body;


if ($SmtpPort == "")
{
$this->PortSMTP = 25;
}
else
{
$this->PortSMTP = $SmtpPort;
}
}


function SendMail ()
{
$newLine = "\r\n";
$headers = "MIME-Version: 1.0" . $newLine;
$headers .= "Content-type: text/html; charset=iso-8859-1" . $newLine;


if ($SMTPIN = fsockopen ($this->SmtpServer, $this->PortSMTP))
{
fputs ($SMTPIN, "EHLO ".$HTTP_HOST."\r\n");
$talk["hello"] = fgets ( $SMTPIN, 1024 );
fputs($SMTPIN, "auth login\r\n");
$talk["res"]=fgets($SMTPIN,1024);
fputs($SMTPIN, $this->SmtpUser."\r\n");
$talk["user"]=fgets($SMTPIN,1024);
fputs($SMTPIN, $this->SmtpPass."\r\n");
$talk["pass"]=fgets($SMTPIN,256);
fputs ($SMTPIN, "MAIL FROM: <".$this->from.">\r\n");
$talk["From"] = fgets ( $SMTPIN, 1024 );
fputs ($SMTPIN, "RCPT TO: <".$this->to.">\r\n");
$talk["To"] = fgets ($SMTPIN, 1024);
fputs($SMTPIN, "DATA\r\n");
$talk["data"]=fgets( $SMTPIN,1024 );
fputs($SMTPIN, "To: <".$this->to.">\r\nFrom: <".$this->from.">\r\n".$headers."\n\nSubject:".$this->subject."\r\n\r\n\r\n".$this->body."\r\n.\r\n");
$talk["send"]=fgets($SMTPIN,256);
//CLOSE CONNECTION AND EXIT ...
fputs ($SMTPIN, "QUIT\r\n");
fclose($SMTPIN);
//
}
return $talk;
}
}
?>

contact_email.php

<?php
include('SMTPconfig.php');
include('SMTPmail.php');
if($_SERVER["REQUEST_METHOD"] == "POST")
{
$to = "";
$from = $_POST['email'];
$subject = "Enquiry";
$body = $_POST['name'].'</br>'.$_POST['companyName'].'</br>'.$_POST['tel'].'</br>'.'<hr />'.$_POST['message'];
$SMTPMail = new SMTPClient ($SmtpServer, $SmtpPort, $SmtpUser, $SmtpPass, $from, $to, $subject, $body);
$SMTPChat = $SMTPMail->SendMail();
}
?>

如果你在本地服务器上运行这段代码(也就是你的计算机用于开发目的),它不会将电子邮件发送给收件人。它将在名为mailoutput的文件夹中创建一个.txt文件。

在这种情况下,如果你使用免费的软管服务,如000webhosthostinger,这些服务提供商会禁用mail()功能,以防止意外使用电子邮件欺骗、垃圾邮件等。我希望你联系他们,看看他们是否支持这个功能。

如果您确定服务提供者支持mail()函数,您可以查看PHP手册以进一步参考,

PHP mail()

要检查你的主机服务是否支持mail()函数,试着运行代码(记得更改收件人电邮地址):

<?php
$to      = 'nobody@example.com';
$subject = 'the subject';
$message = 'hello';
$headers = 'From: webmaster@example.com' . "\r\n" .
'Reply-To: webmaster@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();


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

这只会影响一小部分用户,但我希望为这一小部分用户记录它。由于这个问题,这个成员花了6个小时对一个正常工作的PHP邮件脚本进行故障排除。

如果你要去一所从www.AceITLab.com运行XAMPP的大学,你应该知道我们的教授没有告诉我们的事情:AceITLab防火墙(不是Windows防火墙)在XAMPP中阻止MercuryMail。你必须使用另一种邮件客户端,pear为我们工作。你必须发送到一个低安全设置的Gmail帐户。

是的,我知道,这在现实世界的电子邮件中完全没有用。然而,据我所知,学术环境和现实世界往往没有什么宝贵的共同点。

对于那些不想使用外部邮件并且希望在专用的Linux服务器上使用mail()的人。

PHP如何发送邮件,在php.ini部分[mail function]中有描述。

参数sendmail-path描述如何调用sendmail。默认值是sendmail -t -i,所以如果你在Linux控制台中得到一个工作的sendmail -t -i < message.txt,你就完成了。您还可以添加mail.log进行调试,并确保真正调用了mail()。

不同的mta可以实现sendmail。它们只是在这个名称上创建一个符号链接到它们的二进制文件。例如,在Debian中,默认值是后缀。配置MTA以发送邮件,并从控制台中使用sendmail -v -t -i < message.txt进行测试。文件message.txt应该包含消息的所有标题和正文,信封的目的地地址将从To:标题中获取。例子:

From: myapp@example.com
To: mymail@example.com
Subject: Test mail via sendmail.


Text body.

我更喜欢使用ssmtp作为MTA,因为它很简单,不需要运行开放端口的守护进程。smtp仅适用于从本地主机发送邮件。它还可以通过公共邮件服务通过您的帐户发送经过认证的电子邮件。安装ssmtp并编辑配置文件/etc/ssmtp/ssmtp.conf。为了能够接收本地系统邮件到Unix帐户(例如,从cron作业到root的警报),配置/etc/ssmtp/revaliases文件。

以下是我在Yandex邮箱上的账户配置:

root=mymail@example.com
mailhub=smtp.yandex.ru:465
FromLineOverride=YES
UseTLS=YES
AuthUser=abcde@yandex.ru
AuthPass=password

确保在服务器中安装了Sendmail。

如果您已经检查了代码并验证了那里没有任何错误,那么转到/var/mail并检查该文件夹是否为空。

如果是空的,你需要做:

sudo apt-get install sendmail

如果你在Ubuntu服务器上。

可能问题出在邮件服务器的配置上。为了避免这类问题,或者您不必担心邮件服务器问题,我建议您使用PHPMailer

它是一个插件,拥有发送邮件所需的一切,唯一需要考虑的是启用SMTP端口(端口:25和465)。

require_once 'PHPMailer/PHPMailer.php';
require_once '/servicios/PHPMailer/SMTP.php';
require_once '/servicios/PHPMailer/Exception.php';


$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = 0;
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'correo@gmail.com';
$mail->Password = 'contrasenia';
$mail->SMTPSecure = 'ssl';
$mail->Port = 465;


// Recipients
$mail->setFrom('correo@gmail.com', 'my name');
$mail->addAddress('destination@correo.com');


// Attachments
$mail->addAttachment('optional file');         // Add files, is optional


// Content
$mail->isHTML(true);// Set email format to HTML
$mail->Subject = utf8_decode("subject");
$mail->Body    = utf8_decode("mail content");
$mail->AltBody = '';
$mail->send();
}
catch (Exception $e) {
$error = $mail->ErrorInfo;
}

你可以通过以下方法查看错误:

error_reporting(E_ALL);

我的示例代码是:

<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'PHPMailer.php';
require 'SMTP.php';
require 'Exception.php';


$name = $_POST['name'];
$mailid = $_POST['mail'];
$mail = new PHPMailer;
$mail->IsSMTP();
$mail->SMTPDebug = 0;                   // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com';         // Specify main and backup server
$mail->Port = 587;                      // Set the SMTP port
$mail->SMTPAuth = true;                 // Enable SMTP authentication
$mail->Username = 'someone@gmail.com';  // SMTP username
$mail->Password = 'password';           // SMTP password
$mail->SMTPSecure = 'tls';              // Enable encryption, 'ssl' also accepted


$mail->From = 'someone@gmail.com';
$mail->FromName = 'name';
$mail->AddAddress($mailid, $name);       // Name is optional
$mail->IsHTML(true);                     // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body    = 'Here is your message' ;
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
if (!$mail->Send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
exit;
}
echo 'Message has been sent';
?>

Debian 10.0.0 ('Buster')的Sendmail安装实际上很简单!

php . ini

[mail function]
sendmail_path=/usr/sbin/sendmail -t -i
; (Other directives are mostly windows)

标准sendmail包安装(允许“发送”):

su -                                        # Install as user 'root'
dpkg --list                                 # Is install necessary?
apt-get install sendmail sendmail-cf m4     # Note multiple package selection
sendmailconfig                              # Respond all 'Y' for new install

其他有用的命令:

which sendmail                              # /usr/sbin/sendmail
which sendmailconfig                        # /usr/sbin/sendmailconfig
man sendmail                                # Documentation
systemctl restart sendmail                  # As and when required

验证(发送能力)

echo "Subject: sendmail test" | sendmail -v <yourEmail>@gmail.com

以上花费了大约5分钟。然后我浪费了5个小时…# EYZ0 !

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

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

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

这可能是一个问题"From:"这部分$头中的$电子邮件地址:

From: \"$name\" <$email>

尝试一下,发送一封没有标题部分的电子邮件,比如:

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

如果是这种情况,请尝试使用在您试图从中发送邮件的系统中已经创建的电子邮件帐户。

<?php


$to       = 'name@example.com';
$subject  = 'Write your email subject here.';
$message  = '
<html>
<head>
<title>Title here</title>
</head>
<body>
<p>Message here</p>
</body>
</html>
';


// Carriage return type (RFC).
$eol = "\r\n";


$headers  = "Reply-To: Name <name@example.com>".$eol;
$headers .= "Return-Path: Name <name@example.com>".$eol;
$headers .= "From: Name <name@example.com>".$eol;
$headers .= "Organization: Hostinger".$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-type: text/html; charset=iso-8859-1".$eol;
$headers .= "X-Priority: 3".$eol;
$headers .= "X-Mailer: PHP".phpversion().$eol;




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

发送HTML邮件 当发送电子邮件消息时,您可以指定Mime版本,内容类型和字符集来发送HTML电子邮件

< >强的例子 上面的例子将发送一个HTML电子邮件消息到name@example.com。你可以对这个程序进行编码,使它能够接收用户的所有内容,然后发送一封电子邮件

你可以使用PHPMailer,它工作得很完美,这里有一个代码示例:

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;


require 'vendor/phpmailer/phpmailer/src/Exception.php';
require 'vendor/phpmailer/phpmailer/src/PHPMailer.php';
require 'vendor/phpmailer/phpmailer/src/SMTP.php';
$editor = $_POST["editor"];
$subject = $_POST["subject"];
$to = $_POST["to"];


try {


if ($_SERVER["REQUEST_METHOD"] == "POST") {


$mail = new PHPMailer();
$mail->IsSMTP();
$mail->Mailer = "smtp";
$mail->SMTPDebug  = 1;
$mail->SMTPAuth   = TRUE;
$mail->SMTPSecure = "tls";
$mail->Port       = 587;
$mail->Host       = "smtp.gmail.com";//using smtp server
$mail->Username   = "XXXXXXXXXX@gmail.com";//the email which will send the email
$mail->Password   = "XXXXXXXXXX";//the password


$mail->IsHTML(true);
$mail->AddAddress($to, "recipient-name");
$mail->SetFrom("XXXXXXXXXX@gmail.com", "from-name");
$mail->AddReplyTo("XXXXXXXXXX@gmail.com", "reply-to-name");
$mail->Subject = $subject;
$mail->MsgHTML($editor);








if (!$mail->Send()) {
echo "Error while sending Email.";
var_dump($mail);
} else {
echo "Email sent successfully";
}
}
} catch (Exception $e) {
echo $e->getMessage();
}

为我解决这个问题的是,一些提供商在使用php邮件时不允许外部收件人:

将代码中的收件人($收件人)更改为本地收件人。这意味着使用来自服务器域的电子邮件地址,例如,如果您的服务器域是www.yourdomain.com,那么收件人的电子邮件地址应该是someone@yourdomain.com。 请上传修改后的php文件,然后重试。 如果仍然不工作:将发件人($sender)更改为本地电子邮件(使用与收件人相同的电子邮件)。

.上传修改后的php文件后重试 希望这能有所帮助! # EYZ0 < / p >
我有这个问题,发现剥离回标题帮助我得到邮件。 所以这:< / p >
$headers  = "MIME-Version: 1.0;\r\n";
$headers .= "Content-type: text/plain; charset=utf-8;\r\n";
$headers .= "To: ".$recipient."\r\n";
$headers .= "From: ".__SITE_TITLE."\r\n";
$headers .= "Reply-To: ".$sender."\r\n";

成为这个:

$headers = "From: ".__SITE_TITLE."\r\n";
$headers .= "Reply-To: ".$sender."\r\n";

不需要To:标头。

邮件客户端非常擅长嗅出url并将它们重写为超链接。所以我不需要编写HTML并在content-type头文件中指定text/ HTML。我只是在消息体中添加了带\r\n的新行。 我知道这不是编码纯粹主义者的方法,但它适用于我所需要的