发送电子邮件作为后台进程

时间:2013-12-05 09:29:31

标签: php yii yii-extensions

我想在我的应用程序中制作新闻稿功能。在创建简报后,我需要发送大约5000-6000的电子邮件。发布新闻通讯时,它将创建一个将存储在数据库中的电子邮件队列。因为它需要很多时间我需要在后台运行它。所以我发出命令使用YiiMailer和数据库中的电子邮件队列发送邮件。

我的命令正在运行,但是在一段时间后没有完成作业就会终止。另外我需要在后台运行它,但现在不是。任何帮助表示赞赏。

我的控制器

public function actionSend(){
    $command = new MailQueueCommand("test", "test");
        $command->run(null);
        $this->render('index');

}

我的MailQueueCommand.php

<?php


class MailQueueCommand extends CConsoleCommand
{

public function run($args)
{
    $criteria = new CDbCriteria(array(
            'condition' => 'success=:success AND attempts < max_attempts',
            'params' => array(
                ':success' => 0,
            ),
        ));

    $queueList = EmailQueue::model()->findAll($criteria);

    /* @var $queueItem EmailQueue */
    foreach ($queueList as $queueItem)
    {


            $mail = new YiiMailer();
            $mail->IsSMTP();                                     
            $mail->Host = 'smtp.gmail.com';  
            $mail->SMTPAuth = true;                            
            $mail->Username = 'xxxx';                            
            $mail->Password = 'xxxxx';                          
            $mail->SMTPSecure = 'tls';                           
            $mail->Port = 587;

            $mail->setFrom('exmampl@gmail.com', 'Name');

        $mail->setTo($queueItem->to_email);

        $mail->setSubject($queueItem->subject);
        $mail->setBody($queueItem->message, 'text/html');

        if ($this->sendEmail($mail))
        {
            $queueItem->attempts = $queueItem->attempts + 1;
            $queueItem->success = 1;
            $queueItem->last_attempt = new CDbExpression('NOW()');
            $queueItem->date_sent = new CDbExpression('NOW()');

            $queueItem->save();
        }
        else
        {
            $queueItem->attempts = $queueItem->attempts + 1;
            $queueItem->last_attempt = new CDbExpression('NOW()');

            $queueItem->save();
        }
    }
}


private function sendEmail($mail)
{
    $sendStatus = false;

    if ($mail->send() > 0)
        $sendStatus = true;

    return $sendStatus;
}

}
?>

1 个答案:

答案 0 :(得分:4)

根据我发送电子邮件通知的经验

通常你的邮件工作被中断的原因是因为通常php执行有时间限制,发送5000,6000封邮件需要很长时间。使用像Amazon SES这样的服务你可以每秒发送5次,这就像是1200秒或20分钟..大多数邮件服务器会给你相似或更慢的速度,典型的php(CLI)执行时间是30秒,这是你的问题所在是

我所做的是每批只发送100-200封邮件,并且每隔一分钟通过cron运行一次控制台命令。它会稍慢但你会到达那里。

 $criteria = new CDbCriteria(array(
            'condition' => 'success=:success AND attempts < max_attempts',
            'params' => array(
                ':success' => 0,
            ),
            'limit'=>200,
        ));

使用crontab -e

设置cron
* * * * * <path-to-yii>protected/yiic MailQueueCommand run &> /dev/null

希望这会有所帮助..

注意:如果实际使用SES,这不会有问题,因为它们将所有请求排队并每秒发送5次,并且实际上排队没有限制。

注意: cron与命令行调用不同,您可能会遇到意外问题设置。