Example #1
0
 /**
  * Processes any queued newsletter mailings.
  *
  * @param   object   $job  \Components\Cron\Models\Job
  * @return  boolean
  */
 public function processMailings(\Components\Cron\Models\Job $job)
 {
     // load needed libraries
     require_once PATH_CORE . DS . 'components' . DS . 'com_newsletter' . DS . 'tables' . DS . 'mailing.recipient.php';
     require_once PATH_CORE . DS . 'components' . DS . 'com_newsletter' . DS . 'helpers' . DS . 'helper.php';
     // needed vars
     $limit = 25;
     $processed = array();
     // do we have a param defined limit
     $params = $job->get('params');
     if (is_object($params) && $params->get('newsletter_queue_limit')) {
         $paramDefinedLimit = $params->get('newsletter_queue_limit');
         if (is_numeric($paramDefinedLimit) && $paramDefinedLimit > 0 && $paramDefinedLimit < 100) {
             $limit = $paramDefinedLimit;
         }
     }
     // create needed objects
     $database = App::get('db');
     // get all queued mailing recipients
     $sql = "SELECT nmr.id AS mailing_recipientid, nm.id AS mailingid, nm.nid AS newsletterid, nm.lid AS mailinglistid, nmr.email, nm.subject, nm.html_body, nm.plain_body, nm.headers, nm.args, nm.tracking\n\t\t\t\tFROM `#__newsletter_mailings` AS nm, `#__newsletter_mailing_recipients` AS nmr\n\t\t\t\tWHERE nm.id=nmr.mid\n\t\t\t\tAND nmr.status='queued'\n\t\t\t\tAND nm.deleted=0\n\t\t\t\tAND UTC_TIMESTAMP() >= nm.date\n\t\t\t\tORDER BY nmr.date_added\n\t\t\t\tLIMIT {$limit}";
     $database->setQuery($sql);
     $queuedEmails = $database->loadObjectList();
     // loop through each newsletter recipient, prepare and mail
     foreach ($queuedEmails as $queuedEmail) {
         if (in_array($queuedEmail->email, $processed)) {
             continue;
         }
         // get tracking & unsubscribe token
         $emailToken = \Components\Newsletter\Helpers\Helper::generateMailingToken($queuedEmail);
         // if tracking is on add it to email
         if ($queuedEmail->tracking) {
             $queuedEmail->html_body = \Components\Newsletter\Helpers\Helper::addTrackingToEmailMessage($queuedEmail->html_body, $emailToken);
         }
         // create unsubscribe link
         $unsubscribeMailtoLink = '';
         $unsubscribeLink = 'https://' . $_SERVER['SERVER_NAME'] . '/newsletter/unsubscribe?e=' . urlencode($queuedEmail->email) . '&t=' . $emailToken;
         // add unsubscribe link - placeholder & in header (must do after adding tracking!!)
         $queuedEmail->html_body = str_replace("{{UNSUBSCRIBE_LINK}}", $unsubscribeLink, $queuedEmail->html_body);
         $queuedEmail->headers = str_replace("{{UNSUBSCRIBE_LINK}}", $unsubscribeLink, $queuedEmail->headers);
         $queuedEmail->headers = str_replace("{{UNSUBSCRIBE_MAILTO_LINK}}", $unsubscribeMailtoLink, $queuedEmail->headers);
         // add mailing id to header
         $queuedEmail->headers = str_replace("{{CAMPAIGN_MAILING_ID}}", $queuedEmail->mailingid, $queuedEmail->headers);
         // create new message
         $message = new \Hubzero\Mail\Message();
         // add headers
         foreach (explode("\r\n", $queuedEmail->headers) as $header) {
             $parts = array_map("trim", explode(':', $header));
             switch ($parts[0]) {
                 case 'From':
                     if (preg_match("/\\\"([^\"]*)\\\"\\s<([^>]*)>/ux", $parts[1], $matches)) {
                         $message->setFrom(array($matches[2] => $matches[1]));
                     }
                     break;
                 case 'Reply-To':
                     if (preg_match("/\\\"([^\"]*)\\\"\\s<([^>]*)>/ux", $parts[1], $matches)) {
                         $message->setReplyTo(array($matches[2] => $matches[1]));
                     }
                     break;
                 case 'Importance':
                 case 'X-Priority':
                 case 'X-MSMail-Priority':
                     $priority = isset($parts[1]) && in_array($parts[1], array(1, 2, 3, 4, 5)) ? $parts[1] : 3;
                     $message->setPriority($priority);
                     break;
                 default:
                     if (isset($parts[1])) {
                         $message->addHeader($parts[0], $parts[1]);
                     }
             }
         }
         // build message object and send
         $message->setSubject($queuedEmail->subject)->setTo($queuedEmail->email)->setBody($queuedEmail->plain_body, 'text/plain')->addPart($queuedEmail->html_body, 'text/html');
         // mail message
         if ($message->send()) {
             // add to process email array
             $processed[] = $queuedEmail->email;
             // load recipient object
             $newsletterMailingRecipient = new \Components\Newsletter\Tables\MailingRecipient($database);
             $newsletterMailingRecipient->load($queuedEmail->mailing_recipientid);
             // mark as sent and save
             $newsletterMailingRecipient->status = 'sent';
             $newsletterMailingRecipient->date_sent = Date::toSql();
             $newsletterMailingRecipient->save($newsletterMailingRecipient);
         }
     }
     return true;
 }
Example #2
0
 /**
  * Send Newsletter
  *
  * @param   $newsletter
  * @param   $newsletterHtmlContent
  * @param   $newsletterPlainContent
  * @param   $newsletterContacts
  * @param   $newsletterMailinglist
  * @param   $sendingTest
  * @return  object
  */
 private function _send($newsletter, $newsletterHtmlContent, $newsletterPlainContent, $newsletterContacts, $newsletterMailinglist, $sendingTest = false)
 {
     //set default mail from and reply-to names and addresses
     $defaultMailFromName = Config::get("sitename") . ' Newsletter';
     $defaultMailFromAddress = 'contact@' . $_SERVER['HTTP_HOST'];
     $defaultMailReplytoName = Config::get("sitename") . ' Newsletter - Do Not Reply';
     $defaultMailReplytoAddress = 'do-not-reply@' . $_SERVER['HTTP_HOST'];
     //get the config mail from and reply-to names and addresses
     $mailFromName = $this->config->get('newsletter_from_name', $defaultMailFromName);
     $mailFromAddress = $this->config->get('newsletter_from_address', $defaultMailFromAddress);
     $mailReplytoName = $this->config->get('newsletter_replyto_name', $defaultMailReplytoName);
     $mailReplytoAddress = $this->config->get('newsletter_replyto_address', $defaultMailReplytoAddress);
     //parse newsletter specific emails
     $params = new Registry($newsletter->params);
     $mailFromName = $params->get('from_name', $mailFromName);
     $mailFromAddress = $params->get('from_address', $mailFromAddress);
     $mailReplytoName = $params->get('replyto_name', $mailReplytoName);
     $mailReplytoAddress = $params->get('replyto_address', $mailReplytoAddress);
     //set final mail from and reply-to
     $mailFrom = '"' . $mailFromName . '" <' . $mailFromAddress . '>';
     $mailReplyTo = '"' . $mailReplytoName . '" <' . $mailReplytoAddress . '>';
     //set subject and body
     $mailSubject = $newsletter->name ? $newsletter->name : 'Your ' . Config::get("sitename") . '.org Newsletter';
     $mailHtmlBody = $newsletterHtmlContent;
     $mailPlainBody = $newsletterPlainContent;
     //set mail headers
     //$mailHeaders  = "MIME-Version: 1.0" . "\r\n";
     //$mailHeaders .= "Content-type: text/html; charset=\"UTF-8\"" . "\r\n";
     $mailHeaders = "From: {$mailFrom}" . "\r\n";
     $mailHeaders .= "Reply-To: {$mailReplyTo}" . "\r\n";
     //set mail priority
     $mailHeaders .= "X-Priority: 3" . "\r\n";
     //$mailHeaders .= "X-MSMail-Priority: Normal" . "\r\n";
     //$mailHeaders .= "Importance: Normal\n";
     //set extra headers
     $mailHeaders .= "X-Mailer: PHP/" . phpversion() . "\r\n";
     $mailHeaders .= "X-Component: " . $this->_option . "\r\n";
     $mailHeaders .= "X-Component-Object: Campaign Mailing" . "\r\n";
     $mailHeaders .= "X-Component-ObjectId: {{CAMPAIGN_MAILING_ID}}" . "\r\n";
     //$mailHeaders .= "List-Unsubscribe: <mailto:{{UNSUBSCRIBE_MAILTO_LINK}}>, <{{UNSUBSCRIBE_LINK}}>";
     //set mail args
     $mailArgs = '';
     //$mailArgs = '-f hubmail-bounces@' . $_SERVER['HTTP_HOST'];
     //are we sending test mailing
     if ($sendingTest) {
         foreach ($newsletterContacts as $contact) {
             // get tracking & unsubscribe token
             $recipient = new stdClass();
             $recipient->email = $contact;
             $recipient->mailingid = $newsletterMailinglist ? $newsletterMailinglist : -1;
             $emailToken = \Components\Newsletter\Helpers\Helper::generateMailingToken($recipient);
             // create unsubscribe link
             $unsubscribeMailtoLink = '';
             $unsubscribeLink = 'https://' . $_SERVER['SERVER_NAME'] . '/newsletter/unsubscribe?e=' . urlencode($contact) . '&t=' . $emailToken;
             // add unsubscribe link - placeholder & in header (must do after adding tracking!!)
             $mailHtmlBody = str_replace("{{UNSUBSCRIBE_LINK}}", $unsubscribeLink, $mailHtmlBody);
             $mailPlainBody = str_replace("{{UNSUBSCRIBE_LINK}}", $unsubscribeLink, $mailPlainBody);
             // create new message
             $message = new \Hubzero\Mail\Message();
             foreach (explode("\r\n", $mailHeaders) as $header) {
                 $parts = array_map("trim", explode(':', $header));
                 switch ($parts[0]) {
                     case 'From':
                         if (preg_match("/\\\"([^\"]*)\\\"\\s<([^>]*)>/ux", $parts[1], $matches)) {
                             $message->setFrom(array($matches[2] => $matches[1]));
                         }
                         break;
                     case 'Reply-To':
                         if (preg_match("/\\\"([^\"]*)\\\"\\s<([^>]*)>/ux", $parts[1], $matches)) {
                             $message->setReplyTo(array($matches[2] => $matches[1]));
                         }
                         break;
                     case 'Importance':
                     case 'X-Priority':
                     case 'X-MSMail-Priority':
                         $priority = isset($parts[1]) && in_array($parts[1], array(1, 2, 3, 4, 5)) ? $parts[1] : 3;
                         $message->setPriority($priority);
                         break;
                     default:
                         if (isset($parts[1])) {
                             $message->addHeader($parts[0], $parts[1]);
                         }
                 }
             }
             // build message object and send
             $message->setSubject('[SENDING TEST] - ' . $mailSubject)->setTo($contact)->addPart($mailHtmlBody, 'text/html')->addPart($mailPlainBody, 'text/plain')->send();
         }
         return true;
     }
     //get the scheduling
     $scheduler = Request::getInt('scheduler', 1);
     if ($scheduler == '1') {
         $scheduledDate = Date::toSql();
     } else {
         $schedulerDate = Request::getVar('scheduler_date', '');
         $schedulerHour = Request::getVar('scheduler_date_hour', '00');
         $schedulerMinute = Request::getVar('scheduler_date_minute', '00');
         $schedulerMeridian = Request::getVar('scheduler_date_meridian', 'AM');
         //make sure we have at least the date or we use now
         if (!$schedulerDate) {
             $scheduledDate = Date::toSql();
         }
         //break apart parts of date
         $schedulerDateParts = explode('/', $schedulerDate);
         //make sure its in 24 time
         if ($schedulerMeridian == 'pm') {
             $schedulerHour += 12;
         }
         //build scheduled time
         $scheduledTime = $schedulerDateParts[2] . '-' . $schedulerDateParts[0] . '-' . $schedulerDateParts[1];
         $scheduledTime .= ' ' . $schedulerHour . ':' . $schedulerMinute . ':00';
         $scheduledDate = Date::of(strtotime($scheduledTime))->toSql();
     }
     //create mailing object
     $mailing = new stdClass();
     $mailing->nid = $newsletter->id;
     $mailing->lid = $newsletterMailinglist;
     $mailing->subject = $mailSubject;
     $mailing->html_body = $mailHtmlBody;
     $mailing->plain_body = $mailPlainBody;
     $mailing->headers = $mailHeaders;
     $mailing->args = $mailArgs;
     $mailing->tracking = $newsletter->tracking;
     $mailing->date = $scheduledDate;
     //save mailing object
     $newsletterMailing = new Mailing($this->database);
     if (!$newsletterMailing->save($mailing)) {
         $this->setError(Lang::txt('COM_NEWSLETTER_NEWSLETTER_SEND_FAIL'));
         $this->sendNewsletterTask();
         return;
     }
     // create recipients
     $this->_sendTo($newsletterMailing, $newsletterContacts);
     return $newsletterMailing;
 }
Example #3
0
 /**
  * Processes any queued newsletter mailings.
  *
  * @param   object   $job  \Components\Cron\Models\Job
  * @return  boolean
  */
 public function processMailings(\Components\Cron\Models\Job $job)
 {
     // load needed libraries
     require_once PATH_CORE . DS . 'components' . DS . 'com_newsletter' . DS . 'tables' . DS . 'mailing.recipient.php';
     require_once PATH_CORE . DS . 'components' . DS . 'com_newsletter' . DS . 'tables' . DS . 'mailing.php';
     require_once PATH_CORE . DS . 'components' . DS . 'com_newsletter' . DS . 'tables' . DS . 'mailinglist.php';
     require_once PATH_CORE . DS . 'components' . DS . 'com_newsletter' . DS . 'helpers' . DS . 'helper.php';
     // needed vars
     $limit = 25;
     $processed = array();
     // do we have a param defined limit
     $params = $job->params;
     if (is_object($params) && $params->get('newsletter_queue_limit')) {
         $paramDefinedLimit = $params->get('newsletter_queue_limit');
         if (is_numeric($paramDefinedLimit) && $paramDefinedLimit > 0 && $paramDefinedLimit < 100) {
             $limit = $paramDefinedLimit;
         }
     }
     // create needed objects
     $database = App::get('db');
     // get all queued mailing recipients
     $sql = "SELECT nmr.id AS mailing_recipientid, nm.id AS mailingid, nm.nid AS newsletterid, nm.lid AS mailinglistid, nmr.email, nm.subject, nm.html_body, nm.plain_body, nm.headers, nm.args, nm.tracking, nl.autogen, nm.date AS sendDate\n\t\t\t\tFROM `#__newsletter_mailings` AS nm, `#__newsletter_mailing_recipients` AS nmr, `#__newsletters` AS nl\n\t\t\t\tWHERE nm.id=nmr.mid\n\t\t\t\tAND nm.nid=nl.id\n\t\t\t\tAND nmr.status='queued'\n\t\t\t\tAND nm.deleted=0\n\t\t\t\tAND UTC_TIMESTAMP() >= nm.date\n\t\t\t\tORDER BY nmr.date_added\n\t\t\t\tLIMIT {$limit}";
     $database->setQuery($sql);
     $queuedEmails = $database->loadObjectList();
     // Get newsletter, check whether it is autogen
     // loop through each newsletter recipient, prepare and mail
     foreach ($queuedEmails as $queuedEmail) {
         if (in_array($queuedEmail->email, $processed)) {
             continue;
         }
         // get tracking & unsubscribe token
         $emailToken = \Components\Newsletter\Helpers\Helper::generateMailingToken($queuedEmail);
         // if tracking is on add it to email
         if ($queuedEmail->tracking) {
             $queuedEmail->html_body = \Components\Newsletter\Helpers\Helper::addTrackingToEmailMessage($queuedEmail->html_body, $emailToken);
         }
         // create unsubscribe link
         $unsubscribeMailtoLink = '';
         $unsubscribeLink = 'https://' . $_SERVER['SERVER_NAME'] . '/newsletter/unsubscribe?e=' . urlencode($queuedEmail->email) . '&t=' . $emailToken;
         // add unsubscribe link - placeholder & in header (must do after adding tracking!!)
         $queuedEmail->html_body = str_replace("{{UNSUBSCRIBE_LINK}}", $unsubscribeLink, $queuedEmail->html_body);
         $queuedEmail->headers = str_replace("{{UNSUBSCRIBE_LINK}}", $unsubscribeLink, $queuedEmail->headers);
         $queuedEmail->headers = str_replace("{{UNSUBSCRIBE_MAILTO_LINK}}", $unsubscribeMailtoLink, $queuedEmail->headers);
         // add mailing id to header
         $queuedEmail->headers = str_replace("{{CAMPAIGN_MAILING_ID}}", $queuedEmail->mailingid, $queuedEmail->headers);
         // create new message
         $message = new \Hubzero\Mail\Message();
         // add headers
         foreach (explode("\r\n", $queuedEmail->headers) as $header) {
             $parts = array_map("trim", explode(':', $header));
             switch ($parts[0]) {
                 case 'From':
                     if (preg_match("/\\\"([^\"]*)\\\"\\s<([^>]*)>/ux", $parts[1], $matches)) {
                         $message->setFrom(array($matches[2] => $matches[1]));
                     }
                     break;
                 case 'Reply-To':
                     if (preg_match("/\\\"([^\"]*)\\\"\\s<([^>]*)>/ux", $parts[1], $matches)) {
                         $message->setReplyTo(array($matches[2] => $matches[1]));
                     }
                     break;
                 case 'Importance':
                 case 'X-Priority':
                 case 'X-MSMail-Priority':
                     $priority = isset($parts[1]) && in_array($parts[1], array(1, 2, 3, 4, 5)) ? $parts[1] : 3;
                     $message->setPriority($priority);
                     break;
                 default:
                     if (isset($parts[1])) {
                         $message->addHeader($parts[0], $parts[1]);
                     }
             }
         }
         // build message object and send
         $message->setSubject($queuedEmail->subject)->setTo($queuedEmail->email)->setBody($queuedEmail->plain_body, 'text/plain')->addPart($queuedEmail->html_body, 'text/html');
         // mail message
         if ($message->send()) {
             // add to process email array
             $processed[] = $queuedEmail->email;
             // Some trickery for supporting rescheduled emails
             if ($queuedEmail->autogen == 0 || $queuedEmail->autogen == null) {
                 // load recipient object
                 $newsletterMailingRecipient = new \Components\Newsletter\Tables\MailingRecipient($database);
                 $newsletterMailingRecipient->load($queuedEmail->mailing_recipientid);
                 // mark as sent and save
                 $newsletterMailingRecipient->status = 'sent';
                 $newsletterMailingRecipient->date_sent = Date::toSql();
                 $newsletterMailingRecipient->save($newsletterMailingRecipient);
             } else {
                 $sql = "SELECT *, max(date) AS maxDate FROM #__newsletter_mailings WHERE nid = {$queuedEmail->newsletterid} AND deleted=0;";
                 $database->setQuery($sql);
                 $latestMailing = $database->loadObject();
                 switch ($queuedEmail->autogen) {
                     case 1:
                         $lookahead = ' +1 day';
                         break;
                     case 2:
                         $lookahead = ' +1 week';
                         break;
                     case 3:
                         $lookahead = ' +1 month';
                         break;
                 }
                 $nextDate = Date::of(strtotime($latestMailing->maxDate . $lookahead))->toLocal();
                 $windowMin = strtotime(Date::of(strtotime($nextDate))->toLocal("Y-m-d"));
                 $windowMax = strtotime(Date::of(strtotime($lookahead))->toLocal("Y-m-d"));
                 // If there is no mailing set for the next interval, create it.
                 if ($windowMax - $windowMin == 0) {
                     // Create mailing
                     $newMailing = new Components\Newsletter\Tables\Mailing($database);
                     $newMailing->bind($latestMailing);
                     $newMailing->id = null;
                     $newMailing->date = $nextDate;
                     $newMailing->save($newMailing);
                     // Add recipients
                     $mailingList = new Components\Newsletter\Tables\MailingList($database);
                     $emails = $mailingList->getListEmails($newMailing->lid);
                     // @TODO Verify there is no helper method to determine whether or not to send email
                     foreach ($emails as $email) {
                         if ($email->status == 'active') {
                             $values[] = "(" . $database->quote($newMailing->id) . "," . $database->quote($email->email) . ",'queued', " . $database->quote(Date::of(time())->toLocal()) . ")";
                         }
                     }
                     // make sure we have some values
                     if (count($values) > 0) {
                         // build full query & execute
                         $sql = "INSERT INTO `#__newsletter_mailing_recipients` (`mid`,`email`,`status`,`date_added`) VALUES " . implode(',', $values);
                         $database->setQuery($sql);
                         $database->query();
                     }
                 }
                 // End interval creation
                 // load recipient object
                 $newsletterMailingRecipient = new \Components\Newsletter\Tables\MailingRecipient($database);
                 $newsletterMailingRecipient->load($queuedEmail->mailing_recipientid);
                 // mark as sent and save
                 $newsletterMailingRecipient->status = 'sent';
                 $newsletterMailingRecipient->date_sent = Date::toSql();
                 $newsletterMailingRecipient->save($newsletterMailingRecipient);
             }
             // end autogen logic
         }
     }
     return true;
 }