/** * Porcess the bounce data and update the database * @param Bounce $bounce * @param int $campaign_id * @param Subscriber $subscriber * @return bool */ private function processBounceData($bounce, $campaign_id, $subscriber) { if ($campaign_id === 'systemmessage' && $subscriber !== false) { $bounce->status = 'bounced system message'; $bounce->comment = sprintf('%s marked unconfirmed', $subscriber->id); $bounce->update(); phpList::log()->notice($subscriber->id . ' ' . s('system message bounced, subscriber marked unconfirmed')); $subscriber->addHistory(s('Bounced system message'), sprintf('<br/>%s<br/><a href="./?page=bounce&id=%d">%s</a>', s('Subscriber marked unconfirmed'), $bounce->id, s('View Bounce')), $subscriber->id); $subscriber->confirmed = 0; $subscriber->update(); } elseif (!empty($campaign_id) && $subscriber !== false) { $bounce->connectMeToSubscriberAndMessage($subscriber, $campaign_id); } elseif ($subscriber !== false) { $bounce->status = 'bounced unidentified message'; $bounce->comment = $subscriber->id . ' bouncecount increased'; $bounce->update(); $subscriber->bouncecount++; $subscriber->update(); } elseif ($campaign_id === 'systemmessage') { $bounce->status = 'bounced system message'; $bounce->comment = 'unknown subscriber'; $bounce->update(); phpList::log()->notice($subscriber->id . ' ' . s('system message bounced, but unknown subscriber')); } elseif ($campaign_id) { $bounce->status = sprintf('bounced list message %d', $campaign_id); $bounce->comment = 'unknown subscriber'; $bounce->update(); phpList::DB()->query(sprintf('UPDATE %s SET bouncecount = bouncecount + 1 WHERE id = %d', Config::getTableName('message'), $campaign_id)); } else { $bounce->status = 'unidentified bounce'; $bounce->comment = 'not processed'; $bounce->update(); return false; } return true; }
public static function sendReport($subject, $message) { $report_addresses = explode(',', Config::get('report_address')); foreach ($report_addresses as $address) { phpListMailer::sendMail($address, Config::get('installation_name') . ' ' . $subject, $message); } /*TODO: enable plugins foreach ($GLOBALS['plugins'] as $pluginname => $plugin) { $plugin->sendReport(Config::get('installation_name').' '.$subject,$message); }*/ }
/** * Check if a form token is valid * @param string $token * @return bool */ public function verifyToken($token) { if (empty($token)) { return false; } ## @@@TODO for now ignore the error. This will cause a block on editing admins if the table doesn't exist. $result = phpList::DB()->prepare(sprintf('SELECT id FROM %s WHERE adminid = %d AND value = :token AND expires > CURRENT_TIMESTAMP', Config::getTableName('admintoken'), $this->id)); $result->execute(array(':token' => $token)); return $result->rowCount() > 0; }
public static function releaseLock($processid) { if (!$processid) { return; } phpList::DB()->query('DELETE FROM %s WHERE id = %d', Config::getTableName('sendprocess'), $processid); }
public static function flushClickTrackCache() { if (count(Cache::$_instance->linktrack_sent_cache) == 0) { return; } foreach (Cache::$_instance->linktrack_sent_cache as $mid => $numsent) { foreach ($numsent as $fwdid => $fwdtotal) { if (Config::VERBOSE) { phpList::log()->debug("Flushing clicktrack stats for {$mid}: {$fwdid} => {$fwdtotal}", ['page' => 'cache']); } phpList::DB()->query(sprintf('UPDATE %s SET total = %d WHERE messageid = %d AND forwardid = %d', Config::getTableName('linktrack_ml'), $fwdtotal, $mid, $fwdid)); } } }
/** * Load campaign in memory cache * @param Campaign $campaign * @param bool $forwardContent * @return bool */ public static function precacheCampaign($campaign, $forwardContent = false) { $domain = Config::get('domain'); /** * @var Campaign $cached_campaign */ $cached_campaign =& Cache::getCachedCampaign($campaign); ## the reply to is actually not in use if (preg_match('/([^ ]+@[^ ]+)/', $campaign->replyto, $regs)) { # if there is an email in the from, rewrite it as "name <email>" $campaign->replyto = str_replace($regs[0], '', $campaign->replyto); $cached_campaign->replytoemail = $regs[0]; # if the email has < and > take them out here $cached_campaign->replytoemail = str_replace(array('<', '>'), '', $cached_campaign->replytoemail); //$cached->replytoemail = str_replace('>', '', $cached->replytoemail); # make sure there are no quotes around the name $cached_campaign->replytoname = str_replace('"', '', ltrim(rtrim($campaign->replyto))); } elseif (strpos($campaign->replyto, ' ')) { # if there is a space, we need to add the email $cached_campaign->replytoname = $campaign->replyto; $cached_campaign->replytoemail = "listmaster@{$domain}"; } else { if (!empty($campaign->replyto)) { $cached_campaign->replytoemail = "{$campaign->replyto}@{$domain}"; ## makes more sense not to add the domain to the word, but the help says it does ## so let's keep it for now $cached_campaign->replytoname = "{$campaign->replyto}@{$domain}"; } } //$cached_campaign->fromname = $campaign->fromname; //$cached_campaign->fromemail = $campaign->fromemail; $cached_campaign->to = $campaign->tofield; #0013076: different content when forwarding 'to a friend' $cached_campaign->subject = $forwardContent ? stripslashes($campaign->forwardsubject) : $campaign->subject; #0013076: different content when forwarding 'to a friend' $cached_campaign->content = $forwardContent ? stripslashes($campaign->forwardcampaign) : $campaign->campaign; if (Config::USE_MANUAL_TEXT_PART && !$forwardContent) { $cached_campaign->textcontent = $campaign->textcampaign; } else { $cached_campaign->textcontent = ''; } #var_dump($cached);exit; #0013076: different content when forwarding 'to a friend' $cached_campaign->footer = $forwardContent ? stripslashes($campaign->forwardfooter) : $campaign->footer; if (strip_tags($cached_campaign->footer) != $cached_campaign->footer) { $cached_campaign->textfooter = String::HTML2Text($cached_campaign->footer); $cached_campaign->htmlfooter = $cached_campaign->footer; } else { $cached_campaign->textfooter = $cached_campaign->footer; $cached_campaign->htmlfooter = PrepareCampaign::parseText($cached_campaign->footer); } $cached_campaign->htmlformatted = strip_tags($cached_campaign->content) != $cached_campaign->content; //$cached_campaign->sendformat = $campaign->sendformat; ## @@ put this here, so it can become editable per email sent out at a later stage $cached_campaign->html_charset = 'UTF-8'; #Config::get('html_charset'); ## @@ need to check on validity of charset /*if (!$cached_campaign->html_charset) { $cached_campaign->html_charset = 'UTF-8'; #'iso-8859-1'; }*/ $cached_campaign->text_charset = 'UTF-8'; #Config::get('text_charset'); /*if (!$cached_campaign->text_charset) { $cached_campaign->text_charset = 'UTF-8'; #'iso-8859-1'; }*/ ## if we are sending a URL that contains subscriber attributes, we cannot pre-parse the campaign here ## but that has quite some impact on speed. So check if that's the case and apply $cached_campaign->subscriberspecific_url = preg_match('/\\[.+\\]/', $campaign->sendurl); if (!$cached_campaign->subscriberspecific_url) { ## Fetch external content here, because URL does not contain placeholders if (Config::get('canFetchUrl') && preg_match('/\\[URL:([^\\s]+)\\]/i', $cached_campaign->content, $regs)) { $remote_content = Util::fetchUrl($regs[1]); # $remote_content = fetchUrl($campaign['sendurl'],array()); # @@ don't use this # $remote_content = includeStyles($remote_content); if ($remote_content) { $cached_campaign->content = str_replace($regs[0], $remote_content, $cached_campaign->content); # $cached[$campaign_id]['content'] = $remote_content; $cached_campaign->htmlformatted = strip_tags($remote_content) != $remote_content; } else { #print Error(s('unable to fetch web page for sending')); phpList::log()->notice("Error fetching URL: " . $campaign->sendurl . ' cannot proceed'); return false; } } if (Config::VERBOSE && Config::get('getspeedstats', false) !== false) { phpList::log()->debug('fetch URL end', ['page' => 'preparecampaign']); } /* print $campaign->sendurl; print $remote_content;exit; */ } // end if not subscriberspecific url /*if ($cached_campaign->htmlformatted) { # $cached->content = String::compressContent($cached->content); }*/ //$cached_campaign->google_track = $campaign->google_track; /* else { print $campaign->sendurl; exit; } */ if (Config::VERBOSE && Config::get('getspeedstats', false) !== false) { phpList::log()->debug('parse config start', ['page' => 'preparecampaign']); } /* * this is not a good idea, as it'll replace eg "unsubscribeurl" with a general one instead of personalised * if (is_array($GLOBALS['default_config'])) { foreach($GLOBALS['default_config'] as $key => $val) { if (is_array($val)) { $cached[$campaign_id]['content'] = str_ireplace("[$key]",Config::get($key),$cached[$campaign_id]['content']); $cached->textcontent = str_ireplace("[$key]",Config::get($key),$cached->textcontent); $cached->textfooter = str_ireplace("[$key]",Config::get($key),$cached[$campaign_id]['textfooter']); $cached->htmlfooter = str_ireplace("[$key]",Config::get($key),$cached[$campaign_id]['htmlfooter']); } } } */ if (Config::VERBOSE && Config::get('getspeedstats', false) !== false) { phpList::log()->debug('parse config end', ['page' => 'preparecampaign']); } /*TODO: figure out what this does foreach ($campaign as $key => $val) { if (!is_array($val)) { $cached_campaign->content = str_ireplace("[$key]", $val, $cached_campaign->content); $cached_campaign->textcontent = str_ireplace("[$key]", $val, $cached_campaign->textcontent); $cached_campaign->textfooter = str_ireplace("[$key]", $val, $cached_campaign->textfooter); $cached_campaign->htmlfooter = str_ireplace("[$key]", $val, $cached_campaign->htmlfooter); } }*/ if (preg_match("/##LISTOWNER=(.*)/", $cached_campaign->content, $regs)) { $cached_campaign->listowner = $regs[1]; $cached_campaign->content = str_replace($regs[0], '', $cached_campaign->content); } else { $cached_campaign->listowner = 0; } if (!empty($cached_campaign->listowner)) { $att_result = phpList::DB()->query(sprintf('SELECT name,value FROM %s AS aa, %s AS a_a WHERE aa.id = a_a.adminattributeid AND aa.adminid = %d', Config::getTableName('adminattribute'), Config::getTableName('admin_attribute'), $cached_campaign->listowner)); while ($att = $att_result->fetch(\PDO::FETCH_ASSOC)) { $cached_campaign->content = preg_replace('#\\[LISTOWNER.' . strtoupper(preg_quote($att['name'])) . '\\]#', $att['value'], $cached_campaign->content); } } $baseurl = Config::get('website'); if (Config::UPLOADIMAGES_DIR != null) { ## escape subdirectories, otherwise this renders empty $dir = str_replace('/', '\\/', Config::UPLOADIMAGES_DIR); $cached_campaign->content = preg_replace('/<img(.*)src="\\/' . $dir . '(.*)>/iU', '<img\\1src="' . Config::get('public_scheme') . '://' . $baseurl . '/' . Config::UPLOADIMAGES_DIR . '\\2>', $cached_campaign->content); } //if (defined('FCKIMAGES_DIR') && FCKIMAGES_DIR) { //$cached[$campaign_id]['content'] = preg_replace('/<img(.*)src="\/lists\/'.FCKIMAGES_DIR.'(.*)>/iU','<img\\1src="'.$GLOBALS['public_scheme'].'://'.$baseurl.'/lists/'.FCKIMAGES_DIR.'\\2>',$cached[$campaign_id]['content']); //} return true; }
/** * Shutdown function for execution on shutdown * @link http://php.net/manual/en/function.register-shutdown-function.php */ public function shutdown() { # phpList::log()->debug( "Script status: ".connection_status(), ['page' => 'porcessqueue']); # with PHP 4.2.1 buggy. http://bugs.php.net/bug.php?id=17774 phpList::log()->debug(s('Script stage') . ': ' . $this->script_stage, ['page' => 'porcessqueue']); $some = $this->processed; #$this->sent;# || $this->invalid || $this->notsent; if (!$some) { phpList::log()->debug(s('Finished, Nothing to do'), ['page' => 'porcessqueue']); $this->nothingtodo = 1; } $totaltime = Timer::get('process_queue')->elapsed(true); if ($totaltime > 0) { $msgperhour = 3600 / $totaltime * $this->sent; } else { $msgperhour = s('Calculating'); } if ($this->sent) { phpList::log()->debug(sprintf('%d %s %01.2f %s (%d %s)', $this->sent, s('campaigns sent in'), $totaltime, s('seconds'), $msgperhour, s('msgs/hr')), ['page' => 'processqueue']); } if ($this->invalid > 0) { phpList::log()->debug(s('%d invalid email addresses', $this->invalid), ['page' => 'porcessqueue']); } if ($this->failed_sent > 0) { phpList::log()->debug(s('%d failed (will retry later)', $this->failed_sent), ['page' => 'porcessqueue']); foreach ($this->counters as $label => $value) { # phpList::log()->debug(sprintf('%d %s',$value,s($label)),1,'progress', ['page' => 'porcessqueue']); phpList::log()->info(sprintf('%d %s', $value, s($label)), ['page' => 'processqueue']); } } if ($this->unconfirmed > 0) { phpList::log()->debug(sprintf(s('%d emails unconfirmed (not sent)'), $this->unconfirmed), ['page' => 'porcessqueue']); } /* * TODO: enable plugins foreach ($GLOBALS['plugins'] as $pluginname => $plugin) { $plugin->processSendStats($this->sent,$this->invalid,$this->failed_sent,$this->unconfirmed,$this->counters); } */ Cache::flushClickTrackCache(); Process::releaseLock($this->send_process_id); //finish("info",$report,$this->script_stage); //function finish ($flag,$campaign,$this->script_stage) { $subject = s('Maillist Processing info'); if (!$this->nothingtodo) { phpList::log()->info(s('Finished this run'), ['page' => 'progress']); phpList::log()->info(s('%s of %s done', $this->sent, $this->counters['total_subscribers_for_campaign ' . $this->current_campaign->id]), ['page' => 'progress']); } //TODO:enable plugins /* if (!Config::TEST && !$this->nothingtodo && Config::get(('END_QUEUE_PROCESSING_REPORT'))) { foreach ($GLOBALS['plugins'] as $pluginname => $plugin) { $plugin->sendReport($subject,$campaign); } } */ if ($this->script_stage < 5 && !$this->nothingtodo) { phpList::log()->info(s('Warning: script never reached stage 5') . "\n" . s('This may be caused by a too slow or too busy server') . " \n"); //TODO: remove globals } elseif ($this->script_stage == 5 && (!$this->nothingtodo || isset($GLOBALS['wait']))) { # if the script timed out in stage 5, reload the page to continue with the rest $this->reload++; if (!Config::get('commandline') && $this->num_per_batch && $this->batch_period) { if ($this->sent + 10 < $this->original_num_per_batch) { phpList::log()->debug(s('Less than batch size were sent, so reloading imminently'), ['page' => 'porcessqueue']); $delaytime = 10; } else { // TODO: we should actually want batch period minus time already spent. // might be nice to calculate that at some point phpList::log()->info(sprintf(s('Waiting for %d seconds before reloading'), $this->batch_period), ['page' => 'processqueue']); $delaytime = $this->batch_period; } sleep($delaytime); /*Output::customPrintf( '<script type="text/javascript"> document.location = "./?page=pageaction&action=processqueue&ajaxed=true&reload=%d&lastsent=%d&lastskipped=%d"; </script>', $this->reload, $this->sent, $this->notsent );*/ } else { /*Output::customPrintf( '<script type="text/javascript"> document.location = "./?page=pageaction&action=processqueue&ajaxed=true&reload=%d&lastsent=%d&lastskipped=%d"; </script>', $this->reload, $this->sent, $this->notsent );*/ } } elseif ($this->script_stage == 6 || $this->nothingtodo) { /* * TODO: enable plugins foreach ($GLOBALS['plugins'] as $pluginname => $plugin) { $plugin->campaignQueueFinished(); }*/ phpList::log()->debug(s('Finished, All done'), 0, ['page' => 'porcessqueue']); } else { phpList::log()->debug(s('Script finished, but not all campaigns have been sent yet.'), ['page' => 'porcessqueue']); } if (!Config::get('commandline') && empty($_GET['ajaxed'])) { include_once "footer.inc"; } elseif (Config::get('commandline')) { @ob_end_clean(); } exit; }