<?php defined('MW_PATH') || exit('No direct script access allowed');

/**
 * CampaignSenderBehavior
 * 
 * @package MailWizz EMA
 * @author Serban George Cristian <cristian.serban@mailwizz.com> 
 * @link http://www.mailwizz.com/
 * @copyright 2013-2014 MailWizz EMA (http://www.mailwizz.com)
 * @license http://www.mailwizz.com/license/
 * @since 1.0
 */
 
class CampaignSenderBehavior extends CBehavior
{
    // reference flag for the type of campaigns we're sending
    public $campaigns_type;
    
    // reference flag for campaigns limit
    public $campaigns_limit = 0;
    
    // reference flag for campaigns offset
    public $campaigns_offset = 0;
    
    public function sendCampaign()
    {
        $campaign = $this->getOwner();
        
        // this should never happen unless the list is removed while sending
        if (empty($campaign->list) || empty($campaign->list->customer)) {
            return 0;
        }
        
        $options  = Yii::app()->options;
        $list     = $campaign->list;
        $customer = $list->customer;
        
        if ($customer->getIsOverQuota()) {
            Yii::log(Yii::t('campaigns', 'This customer reached the assigned quota!'), CLogger::LEVEL_ERROR);
            $campaign->saveStatus(Campaign::STATUS_PAUSED);
            return 0;
        }
        
        $server = DeliveryServer::pickServer(0, $campaign, array('customerCheckQuota' => false));
        if (empty($server)) {
            Yii::log(Yii::t('campaigns', 'Cannot find a valid server to send the campaign email, aborting until a delivery server is available!'), CLogger::LEVEL_ERROR);
            return 0;
        }

        if (!empty($customer->language_id)) {
            $language = Language::model()->findByPk((int)$customer->language_id);
            if (!empty($language)) {
                Yii::app()->setLanguage($language->getLanguageAndLocaleCode());
            }    
        }
        
        // put proper status
        $campaign->saveStatus(Campaign::STATUS_PROCESSING);
        
        // find the subscribers we need to send these emails at
        $subscribers = $this->findSubscribers();
        
        // in case we are done
        if (empty($subscribers)) {
            $this->markCampaignSent();
            return 0;
        }

        try {

            $mailerPlugins = array(
                'loggerPlugin' => true,
            );
            
            if ($sendAtOnce = (int)$options->get('system.cron.send_campaigns.send_at_once', 100)) {
                $mailerPlugins['antiFloodPlugin'] = array(
                    'sendAtOnce'    => $sendAtOnce,
                    'pause'         => (int)$options->get('system.cron.send_campaigns.pause', 30),
                );
            }
            
            if ($perMinute = (int)$options->get('system.cron.send_campaigns.emails_per_minute', 100)) {
                $mailerPlugins['throttlePlugin'] = array(
                    'perMinute' => $perMinute,
                );
            }
            
            $attachments = CampaignAttachment::model()->findAll(array(
                'select'    => 'file',
                'condition' => 'campaign_id = :cid',
                'params'    => array(':cid' => $campaign->campaign_id),
            ));

            $processedCounter = 0;
            $serverHasChanged = false;
            $changeServerAt   = (int)$options->get('system.cron.send_campaigns.change_server_at', 100);
            
            //since 1.3.4.9
            $dsParams = array('customerCheckQuota' => false, 'serverCheckQuota' => false);
            
            foreach ($subscribers as $index => $subscriber) {
                
                // if this server is not allowed to send to this email domain, then just skip it.
                if (!$server->canSendToDomainOf($subscriber->email)) {
                    continue;
                }
                
                // if blacklisted, goodbye.
                if ($subscriber->getIsBlacklisted()) {
                    $this->logDelivery($subscriber, Yii::t('campaigns', 'This email is blacklisted. Sending is denied!'), CampaignDeliveryLog::STATUS_BLACKLISTED);
                    continue;
                }
                
                // in case the server is over quota
                if ($server->getIsOverQuota()) {
                    $currentServerId = $server->server_id;
                    if (!($server = DeliveryServer::pickServer($currentServerId, $campaign, $dsParams))) {
                        throw new Exception(Yii::t('campaigns', 'Cannot find a valid server to send the campaign email, aborting until a delivery server is available!'), 99);
                    }
                }
                
                // in case current customer is over quota
                if ($customer->getIsOverQuota()) {
                    throw new Exception(Yii::t('campaigns', 'This customer reached the assigned quota!'), 98);
                }

                $emailParams = $this->prepareEmail($subscriber);
                if (empty($emailParams) || !is_array($emailParams)) {
                    $this->logDelivery($subscriber, Yii::t('campaigns', 'Unable to prepare the email content!'), CampaignDeliveryLog::STATUS_ERROR);
                    continue;
                }
                
                if ($changeServerAt > 0 && $processedCounter >= $changeServerAt && !$serverHasChanged) {
                    $currentServerId = $server->server_id;
                    if ($newServer = DeliveryServer::pickServer($currentServerId, $campaign, $dsParams)) {
                        $server = $newServer;
                        unset($newServer);
                    }
                    
                    $processedCounter = 0;
                    $serverHasChanged = true;
                }
                
                $listUnsubscribeHeaderValue = $options->get('system.urls.frontend_absolute_url');
                $listUnsubscribeHeaderValue .= 'lists/'.$list->list_uid.'/unsubscribe/'.$subscriber->subscriber_uid . '/' . $campaign->campaign_uid;
                $listUnsubscribeHeaderValue = '<'.$listUnsubscribeHeaderValue.'>';
                
                // since 1.3.4.9
                if (!empty($campaign->reply_to)) {
                    $_subject = 'Unsubscribe';
                    $_body    = 'Please unsubscribe me from ' . $list->display_name . ' list.';
                    $mailToUnsubscribeHeader    = sprintf(', <mailto:%s?subject=%s&body=%s>', $campaign->reply_to, $_subject, $_body);
                    $listUnsubscribeHeaderValue .= $mailToUnsubscribeHeader;    
                }
                
                $emailParams['headers'] = array(
                    'X-Mw-Campaign-Uid'     => $campaign->campaign_uid,
                    'X-Mw-Subscriber-Uid'   => $subscriber->subscriber_uid, 
                    'List-Unsubscribe'      => $listUnsubscribeHeaderValue
                );

                // since 1.3.4.6
                $headers = !empty($server->additional_headers) && is_array($server->additional_headers) ? $server->additional_headers : array();
                $headers = (array)Yii::app()->hooks->applyFilters('console_command_send_campaigns_campaign_custom_headers', $headers, $campaign, $subscriber, $customer, $server, $emailParams);
                
                if (!empty($headers)) {
                    $headerSearchReplace = array(
                        '[CAMPAIGN_UID]'    => $campaign->campaign_uid,
                        '[SUBSCRIBER_UID]'  => $subscriber->subscriber_uid,
                        '[SUBSCRIBER_EMAIL]'=> $subscriber->email,
                    );
                    foreach ($headers as $name => $value) {
                        $headers[$name] = str_replace(array_keys($headerSearchReplace), array_values($headerSearchReplace), $value);
                    }  
                    $emailParams['headers'] = array_merge($headers, $emailParams['headers']);
                    unset($headers);  
                }
  
                $emailParams['mailerPlugins'] = $mailerPlugins;

                if (!empty($attachments)) {
                    $emailParams['attachments'] = array();
                    foreach ($attachments as $attachment) {
                        $emailParams['attachments'][] = Yii::getPathOfAlias('root') . $attachment->file;
                    }
                }

                $processedCounter++;
                if ($processedCounter >= $changeServerAt) {
                    $serverHasChanged = false;
                }
                
                // since 1.3.4.6
                Yii::app()->hooks->doAction('console_command_send_campaigns_before_send_to_subscriber', $campaign, $subscriber, $customer, $server, $emailParams);
                
                $status    = CampaignDeliveryLog::STATUS_SUCCESS;
                $sent      = $server->setDeliveryFor(DeliveryServer::DELIVERY_FOR_CAMPAIGN)->setDeliveryObject($campaign)->sendEmail($emailParams);
                $response  = $server->getMailer()->getLog();
                $messageId = null;
                
                // make sure we're still connected to database...
                Yii::app()->getDb()->setActive(true);
                   
                if (!$sent) {
                    $status = $this->getFailStatusFromResponse($response);
                }
                
                if ($sent && is_array($sent) && !empty($sent['message_id'])) {
                    $messageId = $sent['message_id'];
                }
                
                $this->logDelivery($subscriber, $response, $status, $messageId);
                
                // since 1.3.4.6
                Yii::app()->hooks->doAction('console_command_send_campaigns_after_send_to_subscriber', $campaign, $subscriber, $customer, $server, $sent, $response, $status);
            }
            
        } catch (Exception $e) {
            
            // exception code to be returned later
            $code = (int)$e->getCode();
            
            // make sure sending is resumed next time.
            $campaign->status = Campaign::STATUS_SENDING;
            
            // pause the campaigns of customers that reached the quota
            // they will only delay processing of other campaigns otherwise.
            if ($code == 98) {
                $campaign->status = Campaign::STATUS_PAUSED;
            }
            
            // save the changes, but no validation
            $campaign->saveStatus();
            
            // log the error so we can reference it    
            Yii::log($e->getMessage(), CLogger::LEVEL_ERROR);
            
            // return the exception code
            return $code;
        }
        
        // do a final check for this campaign to see if it still exists or has been somehow changed from web interface.
        // this used to exist in the foreach loop but would cause so much overhead that i think is better to move it here
        // since if a campaign is paused from web interface it will keep that status anyway so it won't affect customers and will improve performance
        $_campaign = Yii::app()->getDb()->createCommand()
            ->select('status')
            ->from($campaign->tableName())
            ->where('campaign_id = :cid', array(':cid' => (int)$campaign->campaign_id))
            ->queryRow();

        if (empty($_campaign) || $_campaign['status'] != Campaign::STATUS_PROCESSING) {
            if (!empty($_campaign)) {
                $campaign->saveStatus($_campaign['status']);
            }
            return 0;
        }
        
        // the sending batch is over. 
        // if we don't have enough subscribers for next batch, we stop.
        $subscribers = $this->countSubscribers();
        if (empty($subscribers)) {
            $this->markCampaignSent();
            return 0;
        }
        
        // make sure sending is resumed next time
        $campaign->saveStatus(Campaign::STATUS_SENDING);
        
        return 0;
    }
    
    protected function logDelivery(ListSubscriber $subscriber, $message, $status, $messageId = null)
    {
        $campaign = $this->getOwner();
        
        $deliveryLog = CampaignDeliveryLog::model()->findByAttributes(array(
            'campaign_id'   => (int)$campaign->campaign_id,
            'subscriber_id' => (int)$subscriber->subscriber_id,
        ));
        
        if (empty($deliveryLog)) {   
            $deliveryLog = new CampaignDeliveryLog();
            $deliveryLog->campaign_id = $campaign->campaign_id;
            $deliveryLog->subscriber_id = $subscriber->subscriber_id;
        }
        
        $deliveryLog->email_message_id = $messageId;
        $deliveryLog->message = str_replace("\n\n", "\n", $message);
        $deliveryLog->status = $status;

        return $deliveryLog->save();
    }
    
    protected function countSubscribers()
    {
        $campaign = $this->getOwner();
        if (!empty($campaign->segment_id)) {
            $count = $this->countSubscribersBySegment();
        } else {
            $count = $this->countSubscribersByList();
        }

        return $count;
    }
    
    protected function countSubscribersBySegment()
    {
        $campaign = $this->getOwner();
        $segment = $campaign->segment;
        
        // do not include people we already sent emails to.
        $criteria = new CDbCriteria();
        $criteria->compare('t.list_id', $campaign->list_id);
        $criteria->compare('t.status', ListSubscriber::STATUS_CONFIRMED);
        
        if ($campaign->isAutoresponder && !$this->addAutoresponderCriteria($campaign, $criteria)) {
            return 0;
        }
        
        if (!is_array($criteria->with)) {
            $criteria->with = array();
        }
        $criteria->with['deliveryLogs'] = array(
            'select'    => false,
            'together'  => true,
            'joinType'  => 'LEFT OUTER JOIN',
            'on'        => 'deliveryLogs.campaign_id = :cid',
            'condition' => '(deliveryLogs.subscriber_id IS NULL OR deliveryLogs.`status` = :tstatus)',
            'params'    => array(':cid' => $campaign->campaign_id, ':tstatus' => CampaignDeliveryLog::STATUS_TEMPORARY_ERROR),
        );
        
        return $segment->countSubscribers($criteria);
    }
    
    protected function countSubscribersByList()
    {
        $campaign = $this->getOwner();

        $criteria = new CDbCriteria();
        $criteria->compare('t.list_id', $campaign->list_id);
        $criteria->compare('t.status', ListSubscriber::STATUS_CONFIRMED);
        
        if ($campaign->isAutoresponder && !$this->addAutoresponderCriteria($campaign, $criteria)) {
            return 0;
        }
        
        if (!is_array($criteria->with)) {
            $criteria->with = array();
        }
        $criteria->with['deliveryLogs'] = array(
            'select'    => false,
            'together'  => true,
            'joinType'  => 'LEFT OUTER JOIN',
            'on'        => 'deliveryLogs.campaign_id = :cid',
            'condition' => '(deliveryLogs.subscriber_id IS NULL OR deliveryLogs.`status` = :tstatus)',
            'params'    => array(':cid' => $campaign->campaign_id, ':tstatus' => CampaignDeliveryLog::STATUS_TEMPORARY_ERROR),
        );

        return ListSubscriber::model()->count($criteria);
    }
    
    // find and sort subscribers
    protected function findSubscribers()
    {
        $campaign = $this->getOwner();
        if (!empty($campaign->segment_id)) {
            $subscribers = $this->findSubscribersBySegment();
        } else {
            $subscribers = $this->findSubscribersByList();
        }
        
        // disabled since 1.3.4.9, if complaints enable it.
        //if (!empty($subscribers)) {
        //    $subscribers = $this->sortSubscribers($subscribers);    
        //}
        
        return $subscribers;
    }
    
    protected function findSubscribersBySegment()
    {
        $campaign = $this->getOwner();        
        $segment = $campaign->segment;
        
        // do not include people we already sent emails to.
        $criteria = new CDbCriteria();
        $criteria->select = 't.subscriber_id, t.subscriber_uid, t.email';
        $criteria->compare('t.list_id', $campaign->list_id);
        $criteria->compare('t.status', ListSubscriber::STATUS_CONFIRMED);
        
        if ($campaign->isAutoresponder && !$this->addAutoresponderCriteria($campaign, $criteria)) {
            return array();
        }
        
        if (!is_array($criteria->with)) {
            $criteria->with = array();
        }
        $criteria->with['deliveryLogs'] = array(
            'select'    => false,
            'together'  => true,
            'joinType'  => 'LEFT OUTER JOIN',
            'on'        => 'deliveryLogs.campaign_id = :cid',
            'condition' => '(deliveryLogs.subscriber_id IS NULL OR deliveryLogs.`status` = :tstatus)',
            'params'    => array(':cid' => $campaign->campaign_id, ':tstatus' => CampaignDeliveryLog::STATUS_TEMPORARY_ERROR),
        );
        
        $limit = (int)Yii::app()->options->get('system.cron.send_campaigns.subscribers_at_once', 300);
        
        return $segment->findSubscribers(0, $limit, $criteria);
    }

    protected function findSubscribersByList()
    {
        $campaign = $this->getOwner();

        $criteria = new CDbCriteria();
        $criteria->select = 't.subscriber_id, t.subscriber_uid, t.email';
        $criteria->compare('t.list_id', $campaign->list_id);
        $criteria->compare('t.status', ListSubscriber::STATUS_CONFIRMED);
        $criteria->limit  = (int)Yii::app()->options->get('system.cron.send_campaigns.subscribers_at_once', 300);
        
        if ($campaign->isAutoresponder && !$this->addAutoresponderCriteria($campaign, $criteria)) {
            return array();
        }
        
        if (!is_array($criteria->with)) {
            $criteria->with = array();
        }
        $criteria->with['deliveryLogs'] = array(
            'select'    => false,
            'together'  => true,
            'joinType'  => 'LEFT OUTER JOIN',
            'on'        => 'deliveryLogs.campaign_id = :cid',
            'condition' => '(deliveryLogs.subscriber_id IS NULL OR deliveryLogs.`status` = :tstatus)',
            'params'    => array(':cid' => $campaign->campaign_id, ':tstatus' => CampaignDeliveryLog::STATUS_TEMPORARY_ERROR),
        );

        return ListSubscriber::model()->findAll($criteria);
    }
    
    protected function addAutoresponderCriteria(Campaign $campaign, CDbCriteria $criteria)
    {
        if ($campaign->option->autoresponder_include_imported == CampaignOption::TEXT_NO) {
            $criteria->addCondition('t.source != :src');
            $criteria->params[':src'] = ListSubscriber::SOURCE_IMPORT;
        }

        $timeValue = (int)$campaign->option->autoresponder_time_value;
        $timeUnit  = strtoupper($campaign->option->autoresponder_time_unit);
            
        if ($campaign->option->autoresponder_event == CampaignOption::AUTORESPONDER_EVENT_AFTER_SUBSCRIBE) {
            $criteria->addCondition('t.date_added >= :cdate');
            $criteria->params[':cdate'] = $campaign->date_added;
            $criteria->addCondition(sprintf('DATE_ADD(t.date_added, INTERVAL %d %s) <= NOW()', $timeValue, $timeUnit));
        } elseif ($campaign->option->autoresponder_event == CampaignOption::AUTORESPONDER_EVENT_AFTER_CAMPAIGN_OPEN) {
            if (empty($campaign->option->autoresponder_open_campaign_id)) {
                return false;
            }
            if (!is_array($criteria->with)) {
                $criteria->with = array();
            }
            $criteria->with['trackOpens'] = array(
                'select'    => false,
                'joinType'  => 'INNER JOIN',
                'together'  => true,
                'on'        => 'trackOpens.campaign_id = :tocid',
                'condition' => 'trackOpens.id = (SELECT id FROM {{campaign_track_open}} WHERE campaign_id = :tocid AND subscriber_id = t.subscriber_id ORDER BY id ASC LIMIT 1)',
                'params'    => array(':tocid' => $campaign->option->autoresponder_open_campaign_id),
            );
            $criteria->addCondition(sprintf('DATE_ADD(trackOpens.date_added, INTERVAL %d %s) <= NOW()', $timeValue, $timeUnit));
        } else {
            return false;
        }
        
        return true;
    }
    
    /**
     * Tries to: 
     * 1. Group the subscribers by domain
     * 2. Sort them so that we don't send to same domain two times in a row. 
     */
    protected function sortSubscribers($subscribers)
    {
        $subscribersCount = count($subscribers);
        $_subscribers = array();
        foreach ($subscribers as $index => $subscriber) {
            $emailParts = explode('@', $subscriber->email);
            $domainName = $emailParts[1];
            if (!isset($_subscribers[$domainName])) {
                $_subscribers[$domainName] = array();
            }
            $_subscribers[$domainName][] = $subscriber;
            unset($subscribers[$index]);
        }
        
        $subscribers = array();
        while ($subscribersCount > 0) {
            foreach ($_subscribers as $domainName => $subs) {
                foreach ($subs as $index => $sub) {
                    $subscribers[] = $sub;
                    unset($_subscribers[$domainName][$index]);
                    break;
                }
            }
            $subscribersCount--;
        }
        
        return $subscribers;
    }
    
    protected function prepareEmail($subscriber)
    {
        $campaign = $this->getOwner();
        
        // how come ?
        if (empty($campaign->template)) {
            return false;
        }
        
        $list           = $campaign->list;
        $customer       = $list->customer;
        $emailContent   = $campaign->template->content;
        $embedImages    = array();
        $emailFooter    = null;
        $onlyPlainText  = !empty($campaign->template->only_plain_text) && $campaign->template->only_plain_text === CampaignTemplate::TEXT_YES;
        $emailAddress   = $subscriber->email;
        
        if (!$onlyPlainText) {
            if (($emailFooter = $customer->getGroupOption('campaigns.email_footer')) && strlen(trim($emailFooter)) > 5) {
                $emailContent = CampaignHelper::injectEmailFooter($emailContent, $emailFooter, $campaign);
            }
            
            if (!empty($campaign->option) && !empty($campaign->option->embed_images) && $campaign->option->embed_images == CampaignOption::TEXT_YES) {
                list($emailContent, $embedImages) = CampaignHelper::embedContentImages($emailContent, $campaign);
            }
            
            if (!empty($campaign->option) && $campaign->option->xml_feed == CampaignOption::TEXT_YES) {
                $emailContent = CampaignXmlFeedParser::parseContent($emailContent, $campaign, $subscriber, true);
            }
            
            if (!empty($campaign->option) && $campaign->option->json_feed == CampaignOption::TEXT_YES) {
                $emailContent = CampaignJsonFeedParser::parseContent($emailContent, $campaign, $subscriber, true);
            }
    
            if (!empty($campaign->option) && $campaign->option->url_tracking == CampaignOption::TEXT_YES) {
                $emailContent = CampaignHelper::transformLinksForTracking($emailContent, $campaign, $subscriber, true);
            }
            
            $emailData = CampaignHelper::parseContent($emailContent, $campaign, $subscriber, true);    
            list($toName, $emailSubject, $emailContent) = $emailData;
        }

        // Plain TEXT only supports basic tags transform, no xml/json feeds nor tracking.
        $emailPlainText = null;
        if (!empty($campaign->option) && $campaign->option->plain_text_email == CampaignOption::TEXT_YES) {
            if ($campaign->template->auto_plain_text === CampaignTemplate::TEXT_YES && empty($campaign->template->plain_text)) {
                $emailPlainText = CampaignHelper::htmlToText($emailContent);
            }
            
            if (empty($emailPlainText) && !empty($campaign->template->plain_text) && !$onlyPlainText) {
                $_emailData = CampaignHelper::parseContent($campaign->template->plain_text, $campaign, $subscriber, false);
                list(, , $emailPlainText) = $_emailData;
            }
        }
        
        if ($onlyPlainText) {
            $_emailData = CampaignHelper::parseContent($campaign->template->plain_text, $campaign, $subscriber, false);
            list($toName, $emailSubject, $emailPlainText) = $_emailData;
            if (($emailFooter = $customer->getGroupOption('campaigns.email_footer')) && strlen(trim($emailFooter)) > 5) {
                $emailPlainText .= "\n\n\n";
                $emailPlainText .= strip_tags($emailFooter);
            }
            $emailPlainText = preg_replace('%<br(\s{0,}?/?)?>%i', "\n", $emailPlainText);
        }
        
        return array(
            'to'              => array($emailAddress => $toName),
            'subject'         => $emailSubject,
            'body'            => $emailContent,
            'plainText'       => $emailPlainText,
            'embedImages'     => $embedImages,
            'onlyPlainText'   => $onlyPlainText,
            'trackingEnabled' => !empty($campaign->option) && $campaign->option->url_tracking == CampaignOption::TEXT_YES,
        );
    }
    
    protected function markCampaignSent()
    {
        $campaign = $this->getOwner();
        
        if ($campaign->isAutoresponder) {
            $campaign->saveStatus(Campaign::STATUS_SENDING);
            return;
        }
        
        $campaign->saveStatus(Campaign::STATUS_SENT);

        if (Yii::app()->options->get('system.customer.action_logging_enabled', true)) {
            $list = $campaign->list;
            $customer = $list->customer;
            if (!($logAction = $customer->asa('logAction'))) {
                $customer->attachBehavior('logAction', array(
                    'class' => 'customer.components.behaviors.CustomerActionLogBehavior',
                ));
                $logAction = $customer->asa('logAction');        
            }
            $logAction->campaignSent($campaign);
        }
        
        // since 1.3.4.6
        Yii::app()->hooks->doAction('console_command_send_campaigns_campaign_sent', $campaign);

        $this->sendCampaignStats();
    }
    
    protected function sendCampaignStats()
    {
        $campaign = $this->getOwner();
        if (empty($campaign->option->email_stats)) {
            return $this;
        }
        
        if (!($server = DeliveryServer::pickServer(0, $campaign))) {
            return $this;
        }
        
        $campaign->attachBehavior('stats', array(
            'class' => 'customer.components.behaviors.CampaignStatsProcessorBehavior',
        ));
        $viewData   = compact('campaign');
        
        // prepare and send the email.
        $emailTemplate  = Yii::app()->options->get('system.email_templates.common');
        $emailBody      = Yii::app()->command->renderFile(Yii::getPathOfAlias('console.views.campaign-stats').'.php', $viewData, true);
        $emailTemplate  = str_replace('[CONTENT]', $emailBody, $emailTemplate);
        
        $recipients = explode(',', $campaign->option->email_stats);
        $recipients = array_map('trim', $recipients);

        $emailParams            = array();
        $emailParams['fromName']= $campaign->from_name;
        $emailParams['replyTo'] = array($campaign->reply_to => $campaign->from_name);
        $emailParams['subject'] = Yii::t('campaign_reports', 'The campaign {name} has finished sending, here are the stats', array('{name}' => $campaign->name));
        $emailParams['body']    = $emailTemplate;
        
        foreach ($recipients as $recipient) {
            if (!filter_var($recipient, FILTER_VALIDATE_EMAIL)) {
                continue;
            }
            $emailParams['to']  = array($recipient => $campaign->from_name);
            $server->setDeliveryFor(DeliveryServer::DELIVERY_FOR_CAMPAIGN)->setDeliveryObject($campaign)->sendEmail($emailParams);
        }
        
        return $this;
    }
    
    protected function getFailStatusFromResponse($response)
    {
        if (empty($response) || strlen($response) < 5) {
            return CampaignDeliveryLog::STATUS_ERROR;
        }
        
        $status = CampaignDeliveryLog::STATUS_TEMPORARY_ERROR;
        
        if(preg_match('/code\s"(\d+)"/ix', $response, $matches)) {
            $code = (int)$matches[1];
            if ($code >= 450 && !in_array($code, array(503))) {
                $status = CampaignDeliveryLog::STATUS_FATAL_ERROR;
            } 
        }
        
        $temporaryErrors = array(
            'graylist', 'greylist', 'nested mail command', 'incorrect authentication', 'failed',
            'timed out'
        );
        
        foreach ($temporaryErrors as $error) {
            if (stripos($response, $error) !== false) {
                $status = CampaignDeliveryLog::STATUS_TEMPORARY_ERROR;
                break;
            }
        }
        
        return $status;
    }
}