public function track() { // Required data $subkey = JRequest::getString('uid', ''); $newsletterId = JRequest::getInt('nid', 0); $action = JRequest::getString('action', ''); $link = base64_decode(urldecode(JRequest::getVar('link', ''))); // Optional data $listId = JRequest::getInt('lid', 0); $listId = !empty($listId) ? $listId : null; try { // Check the uid $subscriber = SubscriberHelper::getBySubkey($subkey); if (empty($subscriber->subscriber_id)) { throw new Exception('User is absent'); } // Determine the action $table = JTable::getInstance('history', 'NewsletterTable'); $actionCode = $table->getActionCode($action); if ($actionCode === false) { throw new Exception('Unknown action'); } // If this is a "clicked" event we should save the link $text = $actionCode == NewsletterTableHistory::ACTION_CLICKED ? $link : ""; // Track the event // If type of action is ACTION_OPENED then check it // should be only one in the DB for sid-nid if ($actionCode == NewsletterTableHistory::ACTION_OPENED) { $res = $table->load(array('subscriber_id' => (int) $subscriber->subscriber_id, 'newsletter_id' => (int) $newsletterId, 'action' => $actionCode)); if (!empty($table->history_id)) { throw new Exception('no need to track'); } } $res = $table->save(array('subscriber_id' => (int) $subscriber->subscriber_id, 'list_id' => $listId, 'newsletter_id' => (int) $newsletterId, 'date' => date('Y-m-d H:i:s'), 'action' => $actionCode, 'text' => addslashes($link))); if (!$res) { $err = $table->getError(); $err = $err instanceof Exception ? $err->getMessage() : $err; throw new Exception('Error saving data: ' . $err); } } catch (Exception $e) { if ($e->getMessage() != 'no need to track') { // For debug LogHelper::addDebug('Tracking failed', LogHelper::CAT_TRACKING, array('Message' => $e->getMessage(), 'Data' => JRequest::get())); jexit(); } else { // For debug LogHelper::addDebug('Tracking', LogHelper::CAT_TRACKING, array('Message' => 'No need to track', 'data' => JRequest::get())); } } LogHelper::addDebug('Tracking', LogHelper::CAT_TRACKING, JRequest::get()); // Redirect it! if (!empty($link)) { $this->setRedirect($link); } }
/** * The main method for letter sending. * * @param array $params - the configuration of letter * * @return boolean * @since 1.0 */ public function send($params = null) { if ($params) { $this->_setData($params); } $this->ClearAddresses(); $this->AddReplyTo(JMailHelper::cleanAddress($this->toEmail), JMailHelper::cleanText($this->toName)); $this->SetFrom(JMailHelper::cleanAddress($this->fromEmail), JMailHelper::cleanText($this->fromName)); $this->Subject = JMailHelper::cleanText($this->letter->subject); if (!empty($this->letter->encoding)) { $this->CharSet = $this->letter->encoding; } $this->Body = JMailHelper::cleanText($this->letter->content); foreach ($this->attach as $item) { $parts = explode(DS, $item->filename); $full = JPATH_ROOT . DS . $item->filename; if (function_exists('mime_content_type')) { $mime = mime_content_type($full); } elseif (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME); $mime = finfo_file($finfo, $full); finfo_close($finfo); list($mime) = explode(';', $mime); } else { $mime = 'application/octet-stream'; } parent::AddAttachment($full, '', 'base64', $mime); } parent::IsHTML($params['type'] == 'html'); foreach ($this->emails as $email) { if (!empty($email->email)) { parent::addAddress($email->email, !empty($email->name) ? $email->name : ""); } } try { if (!parent::Send()) { throw new Exception(); } } catch (Exception $e) { $msg = $e->getMessage(); if (!empty($msg)) { $this->setError($msg); } LogHelper::addDebug('Mailer.Sender error.', LogHelper::CAT_MAILER, $this->getErrors()); return false; } return true; }
/** * Render and send the letter to the selected emails * * @return void * @since 1.0 */ public function sendPreview() { $emails = JRequest::getVar('emails', array()); $newsletterId = JRequest::getVar('newsletter_id'); $type = JRequest::getVar('type'); if (empty($type) || empty($newsletterId)) { NewsletterHelper::jsonError(JText::_('COM_NEWSLETTER_RUQUIRED_MISSING')); } if (empty($emails)) { NewsletterHelper::jsonError(JText::_('COM_NEWSLETTER_ADD_EMAILS')); } $data = array('newsletter_id' => $newsletterId, 'type' => $type, 'tracking' => true); foreach ($emails as $email) { $data['subscribers'][] = SubscriberHelper::getByEmail($email[1]); } $mailer = new MigurMailer(); if (!$mailer->sendToList($data)) { $errors = $mailer->getErrors(); LogHelper::addDebug('Sending of preview was failed.', LogHelper::CAT_MAILER, array('Errors' => $errors, 'Emails' => $emails)); NewsletterHelper::jsonError($errors, $emails); } LogHelper::addDebug('Preview was sent successfully.', LogHelper::CAT_MAILER, array('Emails' => $emails)); NewsletterHelper::jsonMessage('ok', $emails); }
/** * The method to unsubscribe the subscriber * from one or more lists. * * @return void * @since 1.0 */ public function unsubscribe() { // Initialise variables. $app = JFactory::getApplication(); $user = JFactory::getUser(); $db = JFactory::getDbo(); // Get variables from request $uid = JRequest::getString('newsletter-uid', ''); $nid = JRequest::getString('newsletter-nid', ''); $lists = JRequest::getVar('newsletter-lists', array()); try { // If we parameters are not enough... if (empty($uid) || empty($lists)) { throw new Exception('COM_NEWSLETTER_UNSUBSCRIPTION_FAILED_PARAMETERS_NOT_FOUND'); } // Insert into db // TODO: Add santiy checks, use model instead $db->setQuery("SELECT * FROM #__newsletter_subscribers WHERE subscription_key = " . $db->quote(addslashes($uid))); $subscriber = $db->loadObject(); if (empty($subscriber->subscriber_id)) { throw new Exception('COM_NEWSLETTER_UNSUBSCRIPTION_FAILED_SUBSCRIBER_NOT_FOUND'); } // Check the newsletter if nid is present if (!empty($nid)) { $db->setQuery("SELECT newsletter_id FROM #__newsletter_newsletters WHERE newsletter_id = " . $db->quote(addslashes($nid))); $newsletter = $db->loadObject(); if (empty($newsletter->newsletter_id)) { throw new Exception('COM_NEWSLETTER_UNSUBSCRIPTION_FAILED_NEWSLETTER_NOT_FOUND'); } } $app->triggerEvent('onMigurNewsletterBeforeUnsubscribe', array('subscriber' => $subscriber, 'lists' => $lists)); foreach ($lists as $list) { // Delete subscriptions from list $db->setQuery("DELETE FROM #__newsletter_sub_list " . "WHERE subscriber_id = " . $db->quote((int) $subscriber->subscriber_id) . " AND list_id = " . $db->quote((int) $list)); $db->query(); // Add to history $db->setQuery("INSERT IGNORE INTO #__newsletter_sub_history SET " . " newsletter_id=" . $db->quote((int) $nid) . ", " . " subscriber_id=" . $db->quote((int) $subscriber->subscriber_id) . ", " . " list_id=" . $db->quote((int) $list) . ", " . " date=" . $db->quote(date('Y-m-d H:i:s')) . ", " . " action=" . $db->quote(NewsletterTableHistory::ACTION_UNSUBSCRIBED) . ", " . " text=''"); $res = $db->query(); } // Process automailing unsubscription $amManager = new NewsletterAutomailingManager(); $amManager->processUnsubscription(array('subscriberId' => (int) $subscriber->subscriber_id)); $app->triggerEvent('onMigurNewsletterAfterUnsubscribe', array('subscriber' => $subscriber, 'lists' => $lists, 'result' => $res)); } catch (Exception $e) { // Log about this incedent $msg = $e->getMessage(); LogHelper::addError($msg, LogHelper::CAT_SUBSCRIPTION, array('Newsletter id' => $nid, 'Subscriber id' => $uid, 'Lists ids' => $lists)); $this->setRedirect(JRoute::_('index.php?option=com_newsletter&view=subscribe&layout=unsubscribe&uid=' . $uid . '&nid=' . $nid, false), JText::_($msg), 'error'); return; } // Logging for debug LogHelper::addDebug('Unsubscription complete.', LogHelper::CAT_SUBSCRIPTION, array('Newsletter id' => $nid, 'Subscriber id' => $uid, 'Lists ids' => $lists)); // Redirect to page $this->setRedirect(JRoute::_('index.php?option=com_newsletter&view=subscribe&layout=unsubscribe&uid=' . $uid . '&nid=' . $nid, false), JText::sprintf('COM_NEWSLETTER_THANK_YOU_FOR_USING_SERVICE', $subscriber->name), 'message'); }
// Setup the cache $cache = JFactory::getCache('com_newsletter'); $cache->setCaching(true); $cache->setLifeTime(900); // cache to 5 min // Get an instance of the controller // Here we get full task $controller = JController::getInstance('Newsletter'); // Perform the Request task // Here we get only tail of a task $controller->execute(JRequest::getCmd('task')); // Trigger events after exacution $app->triggerEvent('onMigurNewsletterEnd'); // Redirect if set by the controller $controller->redirect(); //$app = JFactory::getApplication(); //$results = $app->triggerEvent('onAfterRender', array()); // If there is no redirection then let's check the license and notify the admin // No need to check if this is a redirection if (JRequest::getString('tmpl') != 'component') { // Get license data (may be cached data) $info = NewsletterHelper::getCommonInfo(); // If it has no valid license then show the RED message if ($info->is_valid == "JNO") { $app->enqueueMessage(JText::_('COM_NEWSLETTER_LICENSE_INVALID'), 'error'); } } } catch (Exception $e) { LogHelper::addDebug('COM_NEWSLETTER_UNKNOWN_ERROR', 'common', (array) $e); throw $e; }
/** * Process the messages in a mailbox * @param string $max (maximum limit messages processed in one batch, if not given uses the property $maxMessages * @return boolean */ function processMailbox($max = false) { if (!$this->isConnected()) { return false; } $this->protocol->setTimeout(6000); $met = ini_get('max_execution_time'); // if ($this->moveHard && ( $this->disableDelete === false )) { // $this->disableDelete = true; // } $c_deleted = 0; $c_moved = 0; $useFetchstructure = false; // initialize counters // if ($offset === false) { // $x = $this->_getStartPosition(); // } else { // $x = $offset; // } $c_total = $this->protocol->getMessagesCount(); $this->total = $c_total; // Gmail 4000 mails = 1sec // Nix 4000 mails = 180sec //$res = $this->protocol->sort('SORTARRIVAL'); // Gmail 4000 mails = 1sec // Nix 4000 mails = 180sec //$res = $this->protocol->since(0); $res = (array) $this->protocol->findBy('body', MailHelper::APPLICATION_HEADER); $this->totalBounces = count($res); if (empty($res)) { return true; } LogHelper::addDebug('Mailbox.Bounceds.Ids found.', LogHelper::CAT_BOUNCES, $res); // Handle partial processing option if (!empty($max)) { $this->maxMessages = $max; } // Get unprocessed mails $bounces = array_diff($res, $this->getCache()); $this->found = count($bounces); $count = 0; // Fetch them all foreach ($bounces as &$x) { // If we've parsed $max messages then it's time to stop if (!empty($this->maxMessages) && $count >= $this->maxMessages) { break; } $time = mktime(); // Think 5 minutes to retrive 1 message is more than enough set_time_limit(300); $messageId = ''; $processed = false; // fetch the messages one at a time if ($useFetchstructure) { $structure = $this->protocol->getMessageBodyStructure($x, FT_UID); if ($structure->type == 1 && $structure->ifsubtype && $structure->subtype == 'REPORT' && $structure->ifparameters && $this->isParameter($structure->parameters, 'REPORT-TYPE', 'delivery-status')) { $processed = $this->processBounce($x, 'DSN', $c_total); } else { // not standard DSN msg $this->output('Msg #' . $x . ' is not a standard DSN message', VERBOSE_REPORT); $processed = $this->processBounce($x, 'BODY', $c_total); } } else { $header = $this->protocol->getMessageHeaderStructure($x, FT_UID); //$header = $this->protocol->getMessageHeaders($x); // Get the message id $inCache = false; if (preg_match("/Message\\-ID\\:\\s*(\\<[^\\>]+\\>)/is", $header, $match)) { $messageId = $match[1]; $inCache = $this->checkCache($messageId); } if (preg_match('/^Date\\:\\s*(.+)\\s*$/im', $header, $match)) { $date = strtotime(trim($match[1], "\r\n")); } if (!$inCache) { $this->addToCache($x); // Could be multi-line, if the new line begins with SPACE or HTAB if (preg_match("/Content-Type:((?:[^\n]|\n[\t ])+)(?:\n[^\t ]|\$)/is", $header, $match)) { if (preg_match("/multipart\\/report/is", $match[1]) && preg_match("/report-type=[\"']?delivery-status[\"']?/is", $match[1])) { // standard DSN msg $processed = $this->processBounce($x, 'DSN', $c_total); } else { // not standard DSN msg $this->output('Msg #' . $x . ' is not a standard DSN message', VERBOSE_REPORT); $processed = $this->processBounce($x, 'BODY', $c_total); } } else { // didn't get content-type header $this->output('Msg #' . $x . ' is not a well-formatted MIME mail, missing Content-Type', VERBOSE_REPORT); $processed = $this->processBounce($x, 'BODY', $c_total); } LogHelper::addDebug('Mailbox.Mail processed.Position:' . $x . ',time:' . (string) (mktime() - $time) . ',id:' . $messageId . ',date:' . $date, LogHelper::CAT_BOUNCES); } else { LogHelper::addDebug('Mailbox.Mail in cache.Position:' . $x . ',id:' . $messageId, LogHelper::CAT_BOUNCES); } } $this->setLastDate($date); $count++; } // Restore the time limit set_time_limit($met); return true; }
/** * Log a messagge into file. * * @param string Message * @param string File name, usae current date otherwise * @param boolean Use to force the logging */ public static function logMessage($msg, $filename = null, $force = false) { $arr = explode('/', $filename); return LogHelper::addDebug($msg, $arr[0]); }