Php 如何执行函数直到成功?

Php 如何执行函数直到成功?,php,email,Php,Email,我正在写一个函数来向特定用户发送邮件 我想做的是,如果发生错误,我想继续发送邮件,直到邮件发送 function sendmail() { $name = mysql_escape_string($name); $email = mysql_escape_string($email); $phone = mysql_escape_string($phone); $content = nl2br(mysql_escape_st

我正在写一个函数来向特定用户发送邮件

我想做的是,如果发生错误,我想继续发送邮件,直到邮件发送

    function sendmail() {
        $name = mysql_escape_string($name);
        $email = mysql_escape_string($email);
        $phone = mysql_escape_string($phone);
        $content = nl2br(mysql_escape_string($content));
        $subject = "mail from ".$name." (".$email.", Ph: ".$phone.")";
        $mail = @mail($feedback,$subject,$content,$headers);
        if($mail) { echo "Your mailis send"; }
        else { echo "We are sorry for the inconvienience, but we could not send your mailnow."; }
}   
上面的函数显示错误消息,但我不想给出错误,而是想尝试发送邮件,直到邮件最终发送

函数sendmail(){
function sendmail() {
        $name = mysql_escape_string($name);
        $email = mysql_escape_string($email);
        $phone = mysql_escape_string($phone);
        $content = nl2br(mysql_escape_string($content));
        $subject = "mail from ".$name." (".$email.", Ph: ".$phone.")";

        $retries = 0;
        while (!@mail($feedback,$subject,$content,$headers))
        {
            $retries++;

            if ($retries >= MAX_RETRIES)
            {
                break;
            }

            sleep(WAITING_PERIOD);
        }

        if ($retries < MAX_RETRIES) { echo "Your mail has been sent."; }
        else { echo "We are sorry for the inconvienience, but we could not send your mail now." ; }
}
$name=mysql\u escape\u字符串($name); $email=mysql\u escape\u字符串($email); $phone=mysql\u escape\u字符串($phone); $content=nl2br(mysql_escape_string($content)); $subject=“来自“$name.”(“$email.”,Ph:“$phone.”)的邮件; $retries=0; 而(!@mail($feedback、$subject、$content、$headers)) { $retries++; 如果($retries>=最大重试次数) { 打破 } 睡眠(等待期); } 如果($retries
将“等待时间”和“最大重试次数”设置为适合您的设置,只是不要将“最大重试次数”设置得太长,否则您可能会被困在长时间等待中,也不要将“等待时间”设置得太低,否则您可能会淹没邮件代理。

您意识到,如果您的邮件服务器停止工作超过30秒,它将耗尽您的时间(通常为30秒)使用while循环

错误可能是一种更好的方式,它不会等待重新发送,它只会一遍又一遍地发送,可能在30秒结束之前发送782428424次,浪费带宽,可能会让处理器中的某些人感到恼火


如果出现故障,最好将内容写入某个数据库,并尝试每隔5分钟左右发送一次,直到成功。

我建议输入计数器和/或睡眠语句

计数器的作用是确保脚本最终退出,而不是挂起,继续执行失败的语句

sleep语句用于“处理”瞬时负载问题

比如:

$remainingTries = 5;
while ($remainingTries > 0 && !sendmail())
{
  $remainingTries--; // we used a try, decrement
  sleep(5);          // wait five seconds before next try
}
错误处理设计: 如果页面无法发送怎么办?守护进程已停止,用户输入了格式错误的数据,连接已丢失,可能会写入磁盘,数据库已停止维护,等等。您希望服务器如何处理用户请求?我建议设置一个失败队列,以便稍后重试。有很多好的队列系统。如果需要,请重新尝试必须(这样就不会挂起客户端请求)。记录尝试,如果出现某些错误情况,则通知管理员

这就是构建操作/基础架构团队的目的,但您可以从一些好的工具和精心设计的错误和异常处理策略开始。继承您代码的人会感谢您

我一直在阅读《实用程序员》,我强烈推荐它专门处理这个问题。它为您思考错误/异常处理的方式设定了一个标准,对我来说,它明确地澄清了错误是什么、异常是什么、断言条件是什么(或不可能的条件).特别是第4章实用偏执狂:


“当每个人都想抓住你的时候,偏执就是一种好的想法”——伍迪·艾伦(Woody Allen)

那么,如果
mail()
失败了,可能会出什么问题呢

  • 如果系统配置为将邮件传递给本地守护进程,则守护进程可能已死亡或配置错误
  • 如果您直接与SMTP服务器通信,则服务器很可能已死亡,或者某些内容配置错误
在这两种情况下,您如何知道责任方何时再次做出响应?您希望继续重试多长时间?
本地邮件守护进程永远不会死掉,或者至少应该由系统立即恢复。如果没有死掉,您应该修复服务器,而不是用代码处理这种情况。
如果您正在与SMTP服务器通话,那么在服务器过载或DDoS攻击且您幸运地通过时,唯一可能在一秒钟左右重试成功的合法情况是。这种情况可能非常罕见,不必担心

无论哪种方式,如果
mail()
返回false,通常在您解决其他问题之前,都没有必要重试。因此,只要正常地失败,用一份未发送邮件的副本保存一个完整的日志,稍后再手动发送


超出这一点的任何事情都是您无法控制的,即,即使
mail()
成功,电子邮件也可能到达目的地,也可能无法到达目的地。作为服务器管理员,您的工作是捕获被退回或出错的邮件并手动处理/尝试找出问题所在。

尝试以下方法:

function doSomething($arg1, $arg2, $retry = 10)
{
    $result = false;

    /* do stuff */

    if ($result === false)
    {
        static $original = null;

        if (is_null($original))
        {
            set_time_limit(0);
            $original = $retry;
        }

        sleep(pow(2, $original - $retry));

        while (--$retry > 0)
        {
            return doSomething($arg1, $arg2, $retry);
        }
    }

    return $result;
}
如果失败,将重试
$retry
次,然后等待:

1 second before the 1st retry
2 seconds before the 2nd retry
4 seconds before the 3rd retry
8 seconds before the 4th retry
16 seconds before the 5th retry
32 seconds before the 6th retry
64 seconds before the 7th retry
128 seconds before the 8th retry
256 seconds before the 9th retry
512 seconds before the 10th retry
...
2 ^ ($retry - 1) seconds before the ($retry)th retry

这样做可以确保您的服务器不会过载。

因为如果第一次不起作用,第二次就会起作用吗?我认为您误解了发送电子邮件的工作原理以及可能出现的问题。这实际上取决于您的系统如何处理邮件,但通常只会将其交给本地邮件守护程序,由其重试就其本身而言。另外,
mysql\u-escape\u-string
用于邮件?!@Gabriel,这应该是一个答案,而不是评论。我投票赞成:)除了mysql查询之外,请不要
mysql\u-real\u-escape-string
。想想鲍勃·奥雷利会有什么感觉!可能值得在函数中设置某种延迟或休眠,并设置最大重试限制。这不是一个实际的答案,您不希望任何服务器在任何条件下都能更好地运行此代码。。如果你不使用set_time_limit,它将无法工作,但它最终会在默认执行时间后消失。我的处理器中的所有人都很恼火。我想我的处理器正在罢工,这就是为什么我的计算机今天这么慢。哈哈,我是说