Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/245.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对后台php使用cron作业_Php_Mysql - Fatal编程技术网

对后台php使用cron作业

对后台php使用cron作业,php,mysql,Php,Mysql,嗨,我正在尝试使用PhpMailer为通知系统发送多封电子邮件。为了避免用户提交表单时出现时间延迟问题,我决定将所有存储在mysql表中的电子邮件排入队列,然后使用cron作业运行后台脚本发送队列。这是我使用cron job运行的脚本 include('config/config.php'); require_once(ROOT_PATH.'/helper/phpmailer/PHPMailerAutoload.php'); $mail = new PHPMailer; $

嗨,我正在尝试使用PhpMailer为通知系统发送多封电子邮件。为了避免用户提交表单时出现时间延迟问题,我决定将所有存储在mysql表中的电子邮件排入队列,然后使用cron作业运行后台脚本发送队列。这是我使用cron job运行的脚本

include('config/config.php');

require_once(ROOT_PATH.'/helper/phpmailer/PHPMailerAutoload.php');

    $mail = new PHPMailer;

    $mail->isSMTP(); 
    $mail->SMTPAuth = true; 
    $mail->isHTML(true);
    $mail->Host = SSE_HOST;  
    $mail->Username = SSE_USER;    
    $mail->Password = SSE_PASSWORD;  
    $mail->SMTPSecure = SSE_SECURE;  
    $mail->Port = 465;  
    $mail->SetFrom(SSE_FROM, SSE_FROM_NAME);
    $mail->addReplyTo(SSE_REPLY, 'Invia Risposta');

$result = mysqli_query($conn, "SELECT queue_emails_email, queue_emails_subject, queue_emails_body FROM queue_emails WHERE queue_emails_status = '1' " );

    foreach ($result as $row) {

        $mail->addAddress($row['queue_emails_email']);
        $subject = $row['queue_emails_subject'];
        $mail->Subject = $subject;
        $mail->MsgHTML($row['queue_emails_body']);


    if (!$mail->send()) {
        echo "Mailer Error (" . str_replace("@", "&#64;", $row["queue_emails_email"]) . ') ' . $mail->ErrorInfo . '<br />';
        break; //Abandon sending
    } else {
        echo "Message sent to :" . $row['queue_emails_email'] . ' (' . str_replace("@", "&#64;", $row['queue_emails_email']) . ')<br />';
        //Mark it as sent in the DB
        mysqli_query($conn, "UPDATE queue_emails SET queue_emails_status = '0' WHERE queue_emails_email = '" .
            mysqli_real_escape_string($conn, $row['queue_emails_email']) . "'");

    }
    // Clear all addresses and attachments for next loop
    $mail->clearAddresses();

    }

现在我的问题是:如果我收到多条不同正文但电子邮件地址相同的邮件,那么如果cron作业进程被中断会发生什么?我已经使用mailtrap在本地主机上进行了测试,它似乎工作得很好,但我想知道的是,这种方法在实时服务器上是否可行。我认为我的队列不会超过200-300封电子邮件。非常感谢您的帮助

很好,您的表包含一个单独的唯一ID,因此您不需要对数据库结构进行任何更改。你只需要得到你的ID值并使用它。修改您的
选择
,如下所示:

$result = mysqli_query($conn, "SELECT queue_emails_id, queue_emails_email,  
    queue_emails_subject, queue_emails_body FROM queue_emails WHERE 
    queue_emails_status = '1' " );
然后,在以后进行
更新时,请使用以下命令:

mysqli_query($conn, "UPDATE queue_emails SET queue_emails_status = '0' 
    WHERE queue_emails_id = '" . intval($row['queue_emails_id']) . "'");
就这么简单。现在,您可以确保将零状态设置为正确的消息,无论队列中有多少消息发送到同一地址,您都不会丢失消息

顺便说一下,如果队列中有多个电子邮件地址,您的代码将丢失相同电子邮件地址的消息。无论
cron
作业是否完成或中断,它都会将它们设置为已发送。假设您有以下消息:

to: john@yahoo.com
to: john@yahoo.com
to: peter@hotmail.com
to: mike@gmail.com
to: john@yahoo.com
您的查询将返回此列表,您将开始发送消息并将第一条消息发送到john@yahoo.com. 如果
$mail->send()
返回OK,您将更新所有邮件john@yahoo状态为0时。因此,john将只收到一条消息,第2条和第5条消息将丢失(不发送给john)


在您的问题中,您说队列中可能有200-300条消息。我不知道你多久调用一次这个代码,我会在不超过5分钟的时间调用它,这样我的用户就可以按时收到他们的邮件,但如果太频繁,那就意味着你每天会收到很多电子邮件。考虑一下,您是否需要将它们全部保存在状态为0的表中,或者您可以删除它们以节省空间。

为什么不在表中添加一个ID列,并根据此ID而不是电子邮件地址进行更新?您好,谢谢您的快速回答。抱歉,我不明白您添加id(是用户id)是什么意思?在您的DB表
queue\u emails
中,添加一个可以自动递增的列,它将是您必须发送的每封电子邮件的唯一id。然后在此基础上,您可以使用
queue\u emails\u status='0'
更新您刚刚发送的电子邮件,但发送给此用户(地址)的所有其他邮件将保留在队列中。如果所有的表都填写了相同的电子邮件地址,这无关紧要。好的,我现在明白了,所以基本上我需要从更新队列\u emails SET queue\u emails\u status='0'中删除where子句。我已经有一个自动递增的队列\u emails\u id表。所以,通过这种方式,即使cron作业进程超时,它也应该从if离开的位置开始,是否正确?还有什么我可以实现的吗?我添加了$mail->SMTPKeepAlive=true;按照这里的建议对Phpmailer配置不,在没有WHERE子句的情况下执行UPDATE不是一个好主意:)您将只发送一封电子邮件并更新整个表。我的意思是将WHERE子句更改为类似于
UPDATE。。。设置其中queue_email_id=“$last_email_id”比较您确定唯一的内容,而不是可能不唯一的地址。例如,在网上商店中,您将向新用户发送两条后续消息-一条用于成功注册,另一条用于下单。很高兴他收到了这两封信:)嗨,都铎,非常感谢你的帮助,我稍后会测试一下,让你知道。考虑到您的考虑,我想我会每15分钟调用一次代码,可能是为了避免cron重叠(我正在谷歌上搜索更多关于它的信息),然后我的计划是运行另一个cron,可能是每天一次,以删除所有status=0的行,并以这种方式保持数据库干净
to: john@yahoo.com
to: john@yahoo.com
to: peter@hotmail.com
to: mike@gmail.com
to: john@yahoo.com