防止PHP等待mail()函数

3
在我的网站应用程序中,当用户更改其帐户时,我调用php mail()函数来发送电子邮件通知。 在实现这一点后,我发现帐户更改操作需要很长时间(> 20秒)才能完成。 我怀疑这是因为PHP在等待mail()函数发送电子邮件。 是否有任何方法可以在不等待的情况下立即进行此调用并继续下一行代码?
谢谢,
保罗

你怀疑吗?你有进行基准测试吗? - MonkeyZeus
如果我注释掉对邮件函数的调用,服务器响应时间不到三秒钟。如果允许它调用邮件函数,响应时间将超过二十秒。我认为可以肯定地说,邮件函数是罪魁祸首。 - Paul
有些不对劲。邮件()函数执行不应该那么久。您可能需要尝试找出为什么邮件()函数需要那么长时间。您的php.ini文件应该向您显示mail()函数正在使用的底层系统命令。它应该被指定为sendmail_path。如果您登录到服务器并通过指定为sendmail_path的命令从命令行发送邮件,是否需要大约10秒钟才能执行? 如果是这样,则似乎您的服务器上运行MTA可能存在问题。 - mti2935
@MonkeyZeus 这个三秒延迟的原因是因为所涉及的操作是通过信用卡进行订阅付款。 - Paul
我明白了,那么我强烈建议在客户端使用AJAX,因为它可以让你展示一个“spinner.gif”并禁用表单提交,这样用户就不会着急地点击“提交”两次。当然,服务器端验证应该始终存在,但至少用户体验也会很好 =) - MonkeyZeus
显示剩余2条评论
4个回答

6
创建另一个PHP脚本(我们称之为“mailuser.php”作为例子)。在这个文件中,你的代码将寻找已激活但尚未发送电子邮件的账户…然后发送电子邮件。
在您的原始代码中(激活帐户后),调用:
exec("php mailuser.php > /dev/null 2>&1 &");

这应该会生成进程,但不等待其返回。如需更多信息,请参阅以下帖子:php exec 命令(或类似命令)以不等待结果异步运行 PHP 任务
您还可以选择通过命令行传递用户 ID,这样 mailuser.php 就不必根据字段/标志查找用户。

1
完美地工作了,谢谢。我想为任何试图这样做的人添加更多关于如何使用exec命令发送参数的信息,可以在PHP手册中找到: http://php.net/manual/en/reserved.variables.argv.php - Paul
没问题,很乐意帮忙 =) - DragonYen

0

你可以将调用邮件函数的代码放在一个名为sendMail.php的独立php文件中,然后使用(jQuery AJAX)[https://api.jquery.com/jQuery.ajax/]向该函数发送请求。

$.ajax({
   type: "POST",
    url: "sendMail.php",
    data: { name: "Foo", email: "foobar@baz.com" }
})
.done(function( msg ) {
    alert( "Email sent: " + msg );
});

出于安全考虑,我希望将此保留在服务器端。 - Paul

0

我曾经遇到过同样的问题。编写一个sendmail.php程序,并使用ajax调用它。

<?
session_start();
header("Content-Type: text/html; charset=iso-8859-1");
require_once("libreria/class.phpmailer.php");
$mail             = new PHPMailer();
$body="";
$body.="<body>";
$body.=$_POST['cbody'];
$body.="</body>";
$mail->IsSMTP();
$mail->SMTPAuth   = true;                  
//$mail->SMTPDebug  = 2;
$mail->Host       = "mail.xxx.xxx";
$mail->Port       = 25;
$mail->Username   = "usermail@xxx.xxx";  
$mail->Password   = "xxxxxx";        
$mail->From       = "usermail@xxx.xxx";
$mail->FromName   = "xxx";
$mail->Subject    = $_POST['subject'];
$mail->WordWrap   = 50;
$mail->MsgHTML($body);
$mail->AddAddress($_POST['email'], "User");
$mail->IsHTML(true);
$mail->Send();
?>

(您可以使用AJAX调用的响应来处理错误。)


0

您可以发送Ajax调用以发送邮件,如果邮件未发送,则出于安全考虑,您可以在数据库查询上调用回滚操作,这样您的代码将更加安全。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接