public static function constructSystemMail($message, $subject = '') { $hasHTML = strip_tags($message) != $message; $htmlcontent = ''; if ($hasHTML) { $message = stripslashes($message); $textmessage = String::HTML2Text($message); $htmlmessage = $message; } else { $textmessage = $message; $htmlmessage = $message; # $htmlmessage = str_replace("\n\n","\n",$htmlmessage); $htmlmessage = nl2br($htmlmessage); ## make links clickable: preg_match_all('~https?://[^\\s<]+~i', $htmlmessage, $matches); for ($i = 0; $i < sizeof($matches[0]); $i++) { $match = $matches[0][$i]; $htmlmessage = str_replace($match, '<a href="' . $match . '">' . $match . '</a>', $htmlmessage); } } ## add li-s around the lists if (preg_match('/<ul>\\s+(\\*.*)<\\/ul>/imsxU', $htmlmessage, $listsmatch)) { $lists = $listsmatch[1]; $listsHTML = ''; preg_match_all('/\\*([^\\*]+)/', $lists, $matches); for ($i = 0; $i < sizeof($matches[0]); $i++) { $listsHTML .= '<li>' . $matches[1][$i] . '</li>'; } $htmlmessage = str_replace($listsmatch[0], '<ul>' . $listsHTML . '</ul>', $htmlmessage); } $htmltemplate = ''; $templateid = Config::get('systemmessagetemplate'); if (!empty($templateid)) { $template = Template::getTemplate($templateid); $htmltemplate = stripslashes($template->template); } if (strpos($htmltemplate, '[CONTENT]')) { $htmlcontent = str_replace('[CONTENT]', $htmlmessage, $htmltemplate); $htmlcontent = str_replace('[SUBJECT]', $subject, $htmlcontent); $htmlcontent = str_replace('[FOOTER]', '', $htmlcontent); if (!Config::EMAILTEXTCREDITS) { $phpListPowered = preg_replace('/src=".*power-phplist.png"/', 'src="powerphplist.png"', $GLOBALS['PoweredByImage']); } else { //TODO: make sure not to forget to add this to config $phpListPowered = Config::get('PoweredByText'); } if (strpos($htmlcontent, '[SIGNATURE]')) { $htmlcontent = str_replace('[SIGNATURE]', $phpListPowered, $htmlcontent); } elseif (strpos($htmlcontent, '</body>')) { $htmlcontent = str_replace('</body>', $phpListPowered . '</body>', $htmlcontent); } else { $htmlcontent .= $phpListPowered; } } return array($htmlcontent, $textmessage); }
/** * Get an array of Campaigns by searching its status and subject * When $owner is provided, only returns the campaigns for the given owner * @param string|array $status * @param string $subject * @param int $owner * @param string $order * @param int $offset * @param int $limit * @return array CampaignEntity */ public function getCampaignsBy($status, $subject = '', $owner = 0, $order = '', $offset = 0, $limit = 0) { $return = array(); $condition = 'status IN ('; $condition .= is_array($status) ? implode(',', $status) : $status; $condition .= ') '; if ($subject != '') { $condition .= ' AND subject LIKE "%' . String::sqlEscape($subject) . '%" '; } if ($owner != 0) { $condition .= sprintf(' AND owner = %d', $owner); } switch ($order) { case 'sentasc': $sortBySql = ' ORDER BY sent ASC'; break; case 'sentdesc': $sortBySql = ' ORDER BY sent DESC'; break; case 'subjectasc': $sortBySql = ' ORDER BY subject ASC'; break; case 'subjectdesc': $sortBySql = ' ORDER BY subject DESC'; break; case 'enteredasc': $sortBySql = ' ORDER BY entered ASC'; break; case 'entereddesc': $sortBySql = ' ORDER BY entered DESC'; break; case 'embargoasc': $sortBySql = ' ORDER BY embargo ASC'; break; case 'embargodesc': $sortBySql = ' ORDER BY embargo DESC'; break; default: $sortBySql = ' ORDER BY embargo DESC, entered DESC'; } $result = $this->db->query(sprintf('SELECT COUNT(*) FROM % WHERE %s %s', $this->config->getTableName('message'), $condition, $sortBySql)); $return['total'] = $result->fetch(); $result = $this->db->query(sprintf('SELECT * FROM %s WHERE %s %s LIMIT %d OFFSET %d', $this->config->getTableName('message'), $condition, $sortBySql, $limit, $offset)); while ($msg = $result->fetch(\PDO::FETCH_ASSOC)) { $return['messages'][] = $this->campaignFromArray($msg); } return $return; }
/** * Parse the from field into it's components - email and name * @param $string * @param $default_address * @return array with fields 'email' and 'name' */ public function parseEmailAndName($string, $default_address) { if (preg_match("/([^ ]+@[^ ]+)/", $string, $regs)) { # if there is an email in the from, rewrite it as "name <email>" $name = str_replace($regs[0], "", $string); $email_address = $regs[0]; # if the email has < and > take them out here $email_address = str_replace('<', '', $email_address); $email_address = str_replace('>', '', $email_address); # make sure there are no quotes around the name $name = str_replace('"', '', ltrim(rtrim($name))); } elseif (strpos($string, ' ')) { # if there is a space, we need to add the email $name = $string; $email_address = $default_address; } else { $email_address = $default_address; $name = $string; } return ['email' => $email_address, 'name' => String::removeDoubleSpaces(trim($name))]; }
/** * Update back to db * $modifiedby can be any string to see who has changed the record * @param string $modifiedby */ public function update($modifiedby) { $privileges = String::sqlEscape(serialize($this->privileges)); phpList::DB()->query(sprintf('UPDATE %s SET loginname = "%s", namelc = "%s", email = "%s", modified = CURRENT_TIMESTAMP, modifiedby = "%s", superuser = %d, disabled = %d, privileges = "%s"', Config::getTableName('admin'), $this->loginname, $this->namelc, $this->email, $modifiedby, $this->superuser, $this->disabled, $privileges)); }
/** * Get all subscriber attributes * @param SubscriberEntity $subscriber * @return array */ public function getCleanAttributes(SubscriberEntity $scrEntity) { if (!$scrEntity->hasAttributes()) { $this->loadAttributes($scrEntity); } $clean_attributes = array(); foreach ($scrEntity->getAttributes() as $key => $val) { ## in the help, we only list attributes with "strlen < 20" if (strlen($key) < 20) { $clean_attributes[String::cleanAttributeName($key)] = $val; } } return $clean_attributes; }
public static function HTML2Text($text) { # strip HTML, and turn links into the full URL $text = preg_replace("/\r/", "", $text); #$text = preg_replace("/\n/","###NL###",$text); $text = preg_replace("/<script[^>]*>(.*?)<\\/script\\s*>/is", "", $text); $text = preg_replace("/<style[^>]*>(.*?)<\\/style\\s*>/is", "", $text); # would prefer to use < and > but the strip tags below would erase that. # $text = preg_replace("/<a href=\"(.*?)\"[^>]*>(.*?)<\/a>/is","\\2\n{\\1}",$text,100); # $text = preg_replace("/<a href=\"(.*?)\"[^>]*>(.*?)<\/a>/is","[URLTEXT]\\2[/URLTEXT][LINK]\\1[/LINK]",$text,100); $text = preg_replace("/<a[^>]*href=[\"\\'](.*)[\"\\'][^>]*>(.*)<\\/a>/Umis", "[URLTEXT]\\2[ENDURLTEXT][LINK]\\1[ENDLINK]\n", $text); $text = preg_replace("/<b>(.*?)<\\/b\\s*>/is", "*\\1*", $text); $text = preg_replace("/<h[\\d]>(.*?)<\\/h[\\d]\\s*>/is", "**\\1**\n", $text); # $text = preg_replace("/\s+/"," ",$text); $text = preg_replace("/<i>(.*?)<\\/i\\s*>/is", "/\\1/", $text); $text = preg_replace("/<\\/tr\\s*?>/i", "<\\/tr>\n\n", $text); $text = preg_replace("/<\\/p\\s*?>/i", "<\\/p>\n\n", $text); $text = preg_replace("/<br[^>]*?>/i", "<br>\n", $text); $text = preg_replace("/<br[^>]*?\\/>/i", "<br\\/>\n", $text); $text = preg_replace("/<table/i", "\n\n<table", $text); $text = strip_tags($text); # find all URLs and replace them back preg_match_all('~\\[URLTEXT\\](.*)\\[ENDURLTEXT\\]\\[LINK\\](.*)\\[ENDLINK\\]~Umis', $text, $links); foreach ($links[0] as $matchindex => $fullmatch) { $linktext = $links[1][$matchindex]; $linkurl = $links[2][$matchindex]; # check if the text linked is a repetition of the URL if (trim($linktext) == trim($linkurl) || 'http://' . trim($linktext) == trim($linkurl)) { $linkreplace = $linkurl; } else { ## if link is an anchor only, take it out if (strpos($linkurl, '#') !== false) { $linkreplace = $linktext; } else { $linkreplace = $linktext . ' <' . $linkurl . '>'; } } # $text = preg_replace('~'.preg_quote($fullmatch).'~',$linkreplace,$text); $text = str_replace($fullmatch, $linkreplace, $text); } $text = preg_replace("/<a href=[\"\\'](.*?)[\"\\'][^>]*>(.*?)<\\/a>/is", "[URLTEXT]\\2[ENDURLTEXT][LINK]\\1[ENDLINK]", $text, 500); $text = String::replaceChars($text); $text = preg_replace("/###NL###/", "\n", $text); $text = preg_replace("/\n /", "\n", $text); $text = preg_replace("/\t/", " ", $text); # reduce whitespace while (preg_match("/ /", $text)) { $text = preg_replace("/ /", " ", $text); } while (preg_match("/\n\\s*\n\\s*\n/", $text)) { $text = preg_replace("/\n\\s*\n\\s*\n/", "\n\n", $text); } $text = wordwrap($text, 70); return $text; }
/** * 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; }