/** * @return int */ public function execute() { $collection = new MapperDataCollection(new ProcessMessage()); $config = new Config(); $config->setData("mapper_class", get_class(new Campaign())); $configGroup = new ConfigGroup(); $configGroup->addConfig("process", $config); $collection->configure($configGroup); echo json_pretty($collection->getAttributes()); }
/** * @return int */ public function execute() { // Instantiate and set data for the actual message $message = new ProcessMessage(); $message->setData("firstName", $this->firstName); $message->setData("lastName", $this->lastName); $message->setData("name", "{$this->firstName} {$this->lastName}"); $message->setData("email", $this->email); // Build a config object for use in a Rule. This needs to be wrapped in a // config group and added to a process definition as well as the full class // name for the rule and some default requirements. // Once fully setup we add the process definition to the message processor. $config = new Config(); $config->setData("attribute_name", "firstName"); $config->setData("attribute_check", $this->firstName); $config->setData("attribute_check_type", AttributeFilter::MATCH_EQUAL); $configGroup = new ConfigGroup(); $configGroup->addConfig("process", $config); $process = new ProcessDefinition(); $process->setProcessClass('Qubes\\Defero\\Components\\Campaign\\Rules\\Filter\\AttributeFilter'); $process->setQueueName("defero"); $process->setQueueService("queue"); $process->configure($configGroup); $message->addProcess($process); // Same as above. Running the same check on a different variable. $config = new Config(); $config->setData("attribute_name", "lastName"); $config->setData("attribute_check", $this->lastName); $config->setData("attribute_check_type", AttributeFilter::MATCH_EQUAL); $configGroup = new ConfigGroup(); $configGroup->addConfig("process", $config); $process = new ProcessDefinition(); $process->setProcessClass('Qubes\\Defero\\Components\\Campaign\\Rules\\Filter\\AttributeFilter'); $process->setQueueName("defero"); $process->setQueueService("queue"); $process->configure($configGroup); $message->addProcess($process); // Here we add a delivery rule, $process = new ProcessDefinition(); /*$process->setProcessClass( 'Qubes\Defero\Components\Campaign\Rules\Delivery\FailDeliveryRule' );*/ $process->setProcessClass('Qubes\\Defero\\Components\\Campaign\\Rules\\Delivery\\DelayDeliveryRule'); $config = new Config(); $config->setData("delay", 60); $configGroup = new ConfigGroup(); $configGroup->addConfig("process", $config); $process->configure($configGroup); $process->setQueueName("defero"); $process->setQueueService("queue"); $message->addProcess($process); // Final process is used to send the message $process = new ProcessDefinition(); $process->setQueueName("defero"); $process->setQueueService("queue"); $process->setProcessClass('Qubes\\Defero\\Components\\Campaign\\Process\\EmailService\\Smtp'); $message->addProcess($process); \Queue::setDefaultQueueProvider("messagequeue"); \Queue::push(new StdQueue("defero_messages"), serialize($message)); }
$autoLoader = (require dirname(__DIR__) . '/vendor/autoload.php'); /** * If you are unable to set your environment within a vhost, you can define * it using the following line of code * * putenv("CUBEX_ENV=development"); * */ /** * Initiate Cubex */ $cubex = new \Cubex\Loader($autoLoader); /** * Pull in Cubex Configuration */ $configArray = \Cubex\Foundation\Config\ConfigGroup::fromArray(array_replace_recursive(parse_ini_file(dirname(__DIR__) . '/conf/defaults.ini', true), parse_ini_file(dirname(__DIR__) . '/conf/' . CUBEX_ENV . '.ini', true))); $cubex->configure($configArray); /** * Respond to Web Request (Cubex Returns \Cubex\Http\Response */ $response = $cubex->respondToWebRequest(); /** * Should you wish to find out the PHP Request time */ /* if($response->renderType() === \Cubex\Core\Http\Response::RENDER_RENDERABLE) { echo "Completed in "; echo number_format(((microtime(true) - PHP_START)) * 1000, 1) . "ms"; } */
/** * @param int $campaignId * @param array[] $batch * * @return bool * @throws \Exception */ public static function pushMessageBatch($campaignId, array $batch) { if (!$batch) { return false; } $cacheId = 'DeferoQueueCampaign' . $campaignId; /** * @var Campaign $campaign * @var Contact $contact */ $campaign = ExpiringEphemeralCache::getCache($cacheId, __CLASS__); if ($campaign === null) { $campaign = new Campaign($campaignId); $campaign->reload(); ExpiringEphemeralCache::storeCache($cacheId, $campaign, __CLASS__, 60); } if (!$campaign || !$campaign->exists()) { throw new \Exception('Campaign does not exist'); } $campaignId = $campaign->id(); $processorsCacheId = $cacheId . ':processors'; $processors = ExpiringEphemeralCache::getCache($processorsCacheId, __CLASS__); if ($processors === null) { $processors = []; $processorsConfig = Container::get(Container::CONFIG)->get('processors'); if ($campaign->processors) { foreach ($campaign->processors as $processorData) { $config = new Config(); $config->hydrate($processorData); $configGroup = new ConfigGroup(); $configGroup->addConfig("process", $config); $process = new ProcessDefinition(); $process->setProcessClass($processorsConfig->getStr($processorData->processorType)); $process->setQueueName("defero"); $process->setQueueService("queue"); $process->configure($configGroup); $processors[] = $process; } } else { throw new \Exception("Cannot queue campaign No default processors found."); } ExpiringEphemeralCache::storeCache($processorsCacheId, $processors, __CLASS__, 60); } $blacklistDomains = []; foreach (Container::config()->get('blacklist')->getArr('domains', []) as $d) { $blacklistDomains[] = preg_quote($d, '/'); } $blacklistRegex = '/(' . implode('|', $blacklistDomains) . ')$/i'; //grab all user_ids from $batch, check SentEmailLog $logKeys = []; $keyedBatch = []; //use this to recover $batch $dedupe = true; foreach ($batch as $data) { if (isset($data['user_id'])) { $logKeys[] = $data['user_id'] . '-' . $campaignId; $keyedBatch[$data['user_id']] = $data; } if (isset($data['dedupe'])) { $dedupe = false; } } if ($logKeys && $dedupe) { try { //check if we sent this campaign to users today or the previous day $yesterday = date('Y-m-d', strtotime('-1 day')); $today = date('Y-m-d'); $result = SentEmailLog::cf()->multiGet($logKeys, [$yesterday, $today]); foreach ($result as $key => $column) { if (is_array($column) && (isset($column[$yesterday]) || isset($column[$today]))) { list($userId, $cId) = explode('-', $key); //remove user from keyedBatch because they have already // received this campaign unset($keyedBatch[$userId]); \Log::info("Skipping user because they already got this campaign: [user_id:" . $data['user_id'] . ', campaign_id: ' . $campaignId . "]"); } } $batch = array_values($keyedBatch); } catch (\Exception $e) { \Log::error("Email Deduping Failed: " . $e->getMessage()); } } $messages = []; foreach ($batch as $data) { $data = array_change_key_case($data); // check blacklist if ($blacklistDomains && preg_match($blacklistRegex, $data['email'])) { continue; } // move language here. $userLanguage = $data['language'] = !empty($data['language']) ? $data['language'] : 'en'; $active = isset($data['campaignactive']) ? $data['campaignactive'] : $campaign->active; $message = new ProcessMessage(); $message->setData('campaignId', $campaignId); $message->setData('campaignActive', $active); if (!$active) { $message->setData('emailService', 'email_test'); } elseif ($campaign->emailService) { $message->setData('emailService', $campaign->emailService); } else { $message->setData('emailService', 'email'); } if ($campaign->replyTo) { $message->setData('replyTo', $campaign->replyTo); } $message->setData('mailerTracking', $campaign->trackingType); $message->setData('data', $data); $languageCacheId = $cacheId . ':language:' . $userLanguage; $msg = ExpiringEphemeralCache::getCache($languageCacheId, __CLASS__); if ($msg === null) { $msg = $campaign->message(); $msg->setLanguage($userLanguage); $msg->reload(); if ($userLanguage !== 'en' && (!$msg->active || !$msg->subject || $campaign->sendType != SendType::PLAIN_TEXT && !$msg->htmlContent || $campaign->sendType != SendType::HTML_ONLY && !$msg->plainText)) { //for non eng if html and plain but no html we shouldn't default to english if ($campaign->sendType == SendType::HTML_AND_PLAIN && !$msg->htmlContent && $msg->plainText) { } else { $msg->setLanguage('en'); $msg->reload(); } } ExpiringEphemeralCache::storeCache($languageCacheId, $msg, __CLASS__, 60); } $contactId = $msg->contactId ?: $campaign->contactId; $contactCacheId = $cacheId . ':contact:' . $contactId; $contact = ExpiringEphemeralCache::getCache($contactCacheId, __CLASS__); if ($contact === null) { $contact = new Contact($contactId); ExpiringEphemeralCache::storeCache($contactCacheId, $contact, __CLASS__, 60); } $data['signature'] = $contact->signature; $message->setData('senderName', self::replaceData($contact->name, $data)); $message->setData('senderEmail', self::replaceData($contact->email, $data)); $message->setData('returnPath', self::replaceData($contact->returnPath, $data)); $message->setData('sendType', self::replaceData($campaign->sendType, $data)); $message->setData('subject', self::replaceData($msg->subject, $data)); $message->setData('plainText', self::replaceData($msg->plainText, $data)); $message->setData('htmlContent', self::replaceData($msg->htmlContent, $data, true)); foreach ($processors as $process) { $message->addProcess($process); } $messages[] = serialize($message); } // queue \Queue::setDefaultQueueProvider("messagequeue"); // prioritize if ($campaign->active) { $priority = (int) $campaign->priority; $priority = $priority < 0 ? 1 : $priority; } else { $priority = 99; } $queueName = 'mailer.defero_messages_priority_' . $priority; \Queue::pushBatch(new StdQueue($queueName), $messages); // stats try { $hour = time(); $hour -= $hour % 3600; $statsCf = MailStatistic::cf(); $statsCf->increment($campaignId, $hour . '|queued', count($messages)); } catch (\Exception $e) { \Log::error('Error writing stats for campaign ' . $campaignId . ' : ' . $e->getMessage()); } \Log::info('Queued ' . count($messages) . ' messages for Campaign ' . $campaignId); return true; }