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

Posted

技术标签:

【中文标题】PHP邮件功能没有完成电子邮件的发送【英文标题】:PHP mail function doesn't complete sending of e-mail 【发布时间】:2022-01-22 20:20:16 【问题描述】:
<?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 代码。 代码完美提交,但从不发送电子邮件。我该如何解决这个问题?

【问题讨论】:

是您在本地计算机或实时主机中的程序 1.你确定它不会进入你的垃圾邮件吗? 2.你的盒子上配置了sendmail吗? 它在一个实时主机上它不会进入我的垃圾邮件。我不确定你在我的盒子上配置了 sendmail 是什么意思,所以我假设不是? 尝试不使用$from发送 我之前也遇到过类似的问题,这不是由下面推荐答案中列出的任何错误引起的。这是因为我的 DNS 将 另一个 服务器列为授权邮件服务器,但 Web 服务器本身也被配置为将自己识别为授权邮件服务器。因此,当 PHP mail() 向自己的域发送电子邮件时,它不会检查 DNS 记录以找到正确的邮件服务器,而只是将电子邮件转发给自己。我写了一篇关于它的文章详细介绍了修复:blog.terresquall.com/2021/04/… 【参考方案1】:

尽管此答案的某些部分仅适用于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()函数被正确调用

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

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

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

检查服务器的邮件日志

您的网络服务器应该记录通过它发送电子邮件的所有尝试。这些日志的位置会有所不同(您可能需要询问服务器管理员它们的位置),但它们通常可以在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 的好建议包括:

使用SPF、DKIM等邮箱认证方式来证明你的邮箱和你的域名是同一个,防止你的域名被冒用。 SPF 网站包含一个为您的网站生成 DNS 信息的向导。 Check 您的reverse DNS 以确保您的邮件服务器的 IP 地址指向您用于发送邮件的域名。 确保您使用的 IP 地址是 not on a blacklist 确保回复地址是有效的现有地址。 在“收件人”字段中使用收件人的完整真实姓名,而不仅仅是电子邮件地址(例如 "John Smith" &lt;john@blacksmiths-international.com&gt;)。 监控您的滥用帐户,例如 abuse@yourdomain.com 和 postmaster@yourdomain.com。这意味着 - 确保这些帐户存在,阅读发送给他们的内容,并对投诉采取行动。 最后,让退订变得真正轻松。否则,您的用户将通过按垃圾邮件按钮取消订阅,这将影响您的声誉。

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

确保提供所有邮件标头

如果邮件缺少“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: 发件人,但您不能只使用 any 值。特别是用户提供的发件人地址是阻止邮件的可靠方法:

$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 提供的电子邮件帐户)。

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

确保代码与表单方法匹配

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

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

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

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

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

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

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

确保localhost邮件服务器已配置

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

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

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

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

mail-tester.com(免费/简单) glockapps.com(免费/$$$) senforensics.com(注册/$$$) mailtrap.io(专业/$$$) 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 共享虚拟主机计划会受到影响。)

【讨论】:

【参考方案2】:

如果您使用 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";

【讨论】:

我也不得不使用:require("phpmailer/class.smtp.php");【参考方案3】:

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

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

【讨论】:

这实际上使表单提交-我现在的问题是..我如何显示用户输入的电子邮件,现在我已经用标题替换了它...... 它会阻止垃圾邮件文件夹中的邮件。我已经看到我们是否使用您在代码中使用的这种方法发送超过 10 封邮件 gmail 将此邮件发送到垃圾邮件。 OP 有这一行:$from = 'From: yoursite.com'; 这看起来不像一个完整的有效电子邮件地址,没有本地部分。您已替换 From 标题并添加了其他标题。或者更确切地说,上面的 $from 在您的示例中是多余的。格式错误可能是 OP 最初的问题。【参考方案4】:

如果只使用mail()函数,则需要完成配置文件。

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

【讨论】:

【参考方案5】:

您可以通过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

它对我有用!

【讨论】:

fsockopen() [function.fsockopen]: php_network_getaddresses: getaddrinfo failed: 没有这样的主机是已知的。 - 如果我遇到这个错误,那是什么原因,需要做什么? “为我工作”只是轶事信息,但实际上并没有太多解释。端口和 smtp 密码会误导大多数用户。 什么是“配置电子邮件”?你有参考吗?【参考方案6】:

我认为这应该可以解决问题。我刚刚添加了一个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>'; 
    


?>

【讨论】:

【参考方案7】:

分别和一起尝试这两件事:

    删除if($_POST['submit']) 删除$from(只是我的直觉)

【讨论】:

【参考方案8】:

有几种可能:

    您遇到了服务器问题。该服务器没有任何邮件服务器。因此,您的邮件无法正常工作,因为您的代码很好,并且邮件正在使用类型。

    您没有获得发布的价值。尝试使用静态值的代码。

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

【讨论】:

【参考方案9】:
    始终尝试在邮件功能中发送标头。 如果您通过 localhost 发送邮件,请进行 SMTP 设置以发送邮件。 如果您通过服务器发送邮件,请检查您的服务器上是否启用了电子邮件发送功能。

【讨论】:

【参考方案10】:

试试这个

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

【讨论】:

【参考方案11】:
$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>";

【讨论】:

【参考方案12】:

在邮件函数中添加邮件头:

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

【讨论】:

【参考方案13】:

通过执行以下操作,它在 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)

使用'' 而不是""

此代码有效,但延迟半小时收到电子邮件。

【讨论】:

【参考方案14】:

首先,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.) 按此顺序排列,否则有可能无法正常工作。

【讨论】:

【参考方案15】:

如果您在使用 PHP 发送邮件时遇到问题,请考虑使用 PHPMailerSwiftMailer 之类的替代方法。

每当我需要使用 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 的更多信息,请参阅the official documentation

【讨论】:

【参考方案16】:

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

PHP 的mail 函数不仅不透明,它完全依赖于您使用的任何MTA(即Sendmail)来完成这项工作。 mail只会告诉您 MTA 是否无法接受它(即,当您尝试发送时,Sendmail 已关闭)。它无法告诉您邮件是否成功,因为它已将其发送出去。因此(如John Conde's answer 详细信息),您现在可以摆弄 MTA 的日志,并希望它能告诉您足够多的有关无法修复它的信息。如果您在共享主机上或无权访问 MTA 日志,那么您就不走运了。可悲的是,大多数 Linux 原生安装的默认设置都是这样处理的。

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

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

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

通过在脚本中包含这样的一行来设置此选项:

$mail->SMTPDebug = 2;

您还可以从更好的界面中受益。使用mail,您必须设置所有标题、附件等。使用库,您有专门的功能来执行此操作。这也意味着该函数正在处理所有棘手的部分(如标题)。

【讨论】:

【参考方案17】:

大多数情况下,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();

?>

【讨论】:

把smtp用户和密码明文保存在服务器上好不好? @Juri 可能不是...天哪,我不知道如何让邮件功能正常工作:.(【参考方案18】:

如果您在本地服务器(即用于开发目的的计算机)上运行此代码,它不会将电子邮件发送给收件人。它将在名为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);
?>

【讨论】:

【参考方案19】:

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

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

是的,我知道,这对于现实世界的电子邮件完全没用。然而,据我所见,学术环境和现实世界往往没有什么共同之处。

【讨论】:

这太奇怪了,确实对其他人没有帮助。请使用答案下方的 [删除] 链接。 在这种情况下什么是“梨”?你的意思是PEAR,PHP 软件存储库吗?或者是其他东西?例如。 同行? 你真的是指“宝贝”吗?有什么愿望吗?为什么?【参考方案20】:

适合那些不想使用外部邮件程序并希望在专用 Linux 服务器上 mail() 的人。

php.ini 部分[mail function] 中描述了PHP 邮件的方式。

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

不同的 MTA 可以实现sendmail。他们只是在该名称上建立到他们的二进制文件的符号链接。例如,在Debian 中,默认值为Postfix。将您的 MTA 配置为发送邮件并使用 sendmail -v -t -i &lt; message.txt 从控制台对其进行测试。文件message.txt 应包含消息的所有标头和正文,信封的目标地址将取自To: 标头。示例:

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

Text body.

我更喜欢使用 ssmtp 作为 MTA,因为它很简单,并且不需要运行具有开放端口的守护程序。 ssmtp 仅适用于从localhost 发送邮件。它还可以通过您在公共邮件服务上的帐户发送经过身份验证的电子邮件。安装 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

【讨论】:

【参考方案21】:

确保您的服务器中安装了 Sendmail。

如果您检查了您的代码并确认那里没有问题,请转到 /var/mail 并检查该文件夹是否为空。

如果它是空的,你需要做一个:

sudo apt-get install sendmail

如果您在 Ubuntu 服务器上。

【讨论】:

这太粗糙了,没用。仅仅安装一个 MTA 很少允许使用它。完整的 sendmail/postfix/qmail 设置指南在这里是题外话。 此评论是否参考了我的回答?因为这没有发生在我身上,我也没有以同样的方式解决它。这个问题有多种可能的答案,在过去尝试了以上所有方法之后,我的答案就是其中之一,我的答案已经为我解决了这个问题,所以我在这里提供了它作为另一个潜在的解决方案。 是的,当然。这是许多可能的答案之一。但是,这仍然是肤浅的IMO。将其概括为“您需要 MTA”,例如…… - 这里有一些链接的设置指南……但是可能更实用。【参考方案22】:

可能问题出在邮件服务器的配置上。为避免此类问题或您不必担心邮件服务器问题,我建议您使用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;

【讨论】:

IANA 已将端口 465 替换为端口 587。这是默认的邮件提交端口。当电子邮件客户端或外发服务器提交要由适当的邮件服务器路由的电子邮件时,它应始终使用 SMTP 端口 587 作为默认端口。见mailgun.com/blog/which-smtp-port-understanding-ports-25-465-587。一个明智的建议:如果您不完全了解自己在做什么,请不要打开计算机上的端口!【参考方案23】:

您可以通过以下方式查看您的错误:

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

【讨论】:

SMTPDebug = 0 没有帮助。普通的“密码”也不适用于 GMail。这个答案在这里贡献不大。【参考方案24】:

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

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 个小时...别忘了检查你的垃圾邮件文件夹

【讨论】:

【参考方案25】:

如果您无法使用 Hostgator 上托管的应用程序,this 解决了我的问题。非常感谢发布详细解决方案的人。万一有一天链接掉线了,你有总结:

在您的服务器中查找 sendmail 路径。 一种简单的检查方法是在只有您可以访问的页面中临时编写以下代码,以读取生成的信息:&lt;?php phpinfo(); ?&gt;。打开此页面,查找sendmail path。 (然后,不要忘记删除此代码!) 问题和修复:如果您的 sendmail 路径仅显示 -t -i,则编辑您服务器的 php.ini 并添加以下行:sendmail_path = /usr/sbin/sendmail -t -i;

但是,在能够使用 PHP mail() 函数发送邮件后,我了解到它发送未经身份验证的电子邮件,这又造成了另一个问题。这些邮件都掉进了我的Hotmail的垃圾邮箱,有些邮件从未送达,我想这与他们没有经过身份验证有关。毕竟,这就是为什么我决定使用 SMTP 从mail() 切换到PHPMailer

【讨论】:

【参考方案26】:

这部分$headers中的“From:”$email地址可能有问题:

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

要试用,请发送一封不带标题部分的电子邮件,例如:

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

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

【讨论】:

【参考方案27】:
<?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 电子邮件。

示例 上面的示例将向 name@example.com 发送 HTML 电子邮件消息。您可以对这个程序进行编码,使其接收用户的所有内容,然后发送电子邮件。

【讨论】:

添加代码并不总是足够的。解释代码的每个部分做什么以及为什么或为什么不工作。请阅读,***.com/help/how-to-answer【参考方案28】:

您可以使用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();

【讨论】:

【参考方案29】:

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

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

希望这会有所帮助! https://www.arclab.com/en/kb/php/how-to-test-and-fix-php-mail-function.html

【讨论】:

这个问题现在也得到了答案,这似乎很有趣。 7年3个月!!我花了好几个小时翻堆,试图弄清楚为什么我的一些表格没有发送出去。希望我船上的下一个人会看到旧代码并且会喜欢! 希望大声笑 :)

以上是关于PHP邮件功能没有完成电子邮件的发送的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

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

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