1192 lines
35 KiB
PHP
1192 lines
35 KiB
PHP
<?php
|
|
/**
|
|
* <pre>
|
|
* Invision Power Services
|
|
* IP.Board v3.4.8
|
|
* API: Core
|
|
* Last Updated: $Date: 2013-10-14 15:30:19 -0400 (Mon, 14 Oct 2013) $
|
|
* </pre>
|
|
*
|
|
* @author $Author: AndyMillne $
|
|
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
|
* @license http://www.invisionpower.com/company/standards.php#license
|
|
* @package IP.Board
|
|
* @link http://www.invisionpower.com
|
|
* @version $Rev: 12376 $
|
|
*/
|
|
|
|
if ( ! defined( 'IN_IPB' ) )
|
|
{
|
|
print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
|
|
exit();
|
|
}
|
|
|
|
class hanEmail
|
|
{
|
|
/**
|
|
* Emailer object reference
|
|
*
|
|
* @var object
|
|
*/
|
|
public $emailer;
|
|
|
|
/**
|
|
* Email header
|
|
*
|
|
* @var string
|
|
*/
|
|
public $header;
|
|
|
|
/**
|
|
* Email footer
|
|
*
|
|
* @var string
|
|
*/
|
|
public $footer;
|
|
|
|
/**
|
|
* Email from
|
|
*
|
|
* @var string
|
|
*/
|
|
public $from;
|
|
|
|
/**
|
|
* Email to
|
|
*
|
|
* @var string
|
|
*/
|
|
public $to;
|
|
|
|
/**
|
|
* Email cc's
|
|
*
|
|
* @var array
|
|
*/
|
|
public $cc = array();
|
|
|
|
/**
|
|
* Email bcc's
|
|
*
|
|
* @var array
|
|
*/
|
|
public $bcc = array();
|
|
|
|
/**
|
|
* Email subject
|
|
*
|
|
* @var string
|
|
*/
|
|
public $subject;
|
|
|
|
/**
|
|
* Email body
|
|
*
|
|
* @var string
|
|
*/
|
|
public $message;
|
|
|
|
/**
|
|
* HTML Mode
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $html_email = FALSE;
|
|
|
|
/**
|
|
* Include unsubscribe link?
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $unsubscribe = FALSE;
|
|
|
|
/**
|
|
* Temp word swapping array
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_words;
|
|
|
|
/**
|
|
* Headers to pass to email lib
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $temp_headers = array();
|
|
|
|
protected $_attachments = array();
|
|
protected $editor;
|
|
protected $plainTextTemplate = '';
|
|
protected $htmlTemplate = '';
|
|
protected $htmlWrapper = '';
|
|
protected $_loadedHtmlTemplateClass = '';
|
|
|
|
/**#@+
|
|
* Registry Object Shortcuts
|
|
*
|
|
* @var object
|
|
*/
|
|
protected $registry;
|
|
protected $DB;
|
|
protected $settings;
|
|
protected $request;
|
|
protected $lang;
|
|
protected $member;
|
|
protected $memberData;
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Construct
|
|
*
|
|
* @param object ipsRegistry reference
|
|
* @return @e void
|
|
*/
|
|
public function __construct( ipsRegistry $registry )
|
|
{
|
|
/* Make object */
|
|
$this->registry = $registry;
|
|
$this->DB = $this->registry->DB();
|
|
$this->settings =& $this->registry->fetchSettings();
|
|
$this->request =& $this->registry->fetchRequest();
|
|
$this->lang = $this->registry->getClass('class_localization');
|
|
$this->member = $this->registry->member();
|
|
$this->memberData =& $this->registry->member()->fetchMemberData();
|
|
|
|
/* Set up default handler */
|
|
$this->setHtmlEmail( $this->settings['email_use_html'] );
|
|
}
|
|
|
|
/**
|
|
* Sets whether or not this is a HTML email
|
|
* @param boolean duh $boolean
|
|
*/
|
|
public function setHtmlEmail( $boolean=null )
|
|
{
|
|
$this->html_email = ( $boolean ) ? true : false;
|
|
|
|
if ( is_object( $this->emailer ) )
|
|
{
|
|
$this->emailer->setHtmlEmail( $boolean );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Init method (setup stuff)
|
|
*
|
|
* @return @e void
|
|
*/
|
|
public function init()
|
|
{
|
|
$this->header = $this->settings['email_header'] ? $this->settings['email_header'] : '';
|
|
$this->footer = $this->settings['email_footer'] ? $this->settings['email_footer'] : '';
|
|
|
|
$classToLoad = IPSLib::loadLibrary( IPS_KERNEL_PATH . 'classEmail.php', 'classEmail' );
|
|
|
|
$this->emailer = new $classToLoad( array( 'debug' => $this->settings['fake_mail'] ? $this->settings['fake_mail'] : '0',
|
|
'debug_path' => DOC_IPS_ROOT_PATH . '_mail',
|
|
'smtp_host' => $this->settings['smtp_host'] ? $this->settings['smtp_host'] : 'localhost',
|
|
'smtp_port' => intval($this->settings['smtp_port']) ? intval($this->settings['smtp_port']) : 25,
|
|
'smtp_user' => $this->settings['smtp_user'],
|
|
'smtp_pass' => $this->settings['smtp_pass'],
|
|
'smtp_helo' => $this->settings['smtp_helo'],
|
|
'method' => $this->settings['mail_method'],
|
|
'wrap_brackets' => $this->settings['mail_wrap_brackets'],
|
|
'extra_opts' => $this->settings['php_mail_extra'],
|
|
'charset' => IPS_DOC_CHAR_SET,
|
|
'html' => $this->html_email ) );
|
|
}
|
|
|
|
/**
|
|
* Clear out any temporary headers
|
|
*
|
|
* @return @e void
|
|
*/
|
|
public function clearHeaders()
|
|
{
|
|
$this->temp_headers = array();
|
|
}
|
|
|
|
/**
|
|
* Manually set an email header
|
|
*
|
|
* @param string Header key
|
|
* @param string Header value
|
|
* @return @e void
|
|
*/
|
|
public function setHeader( $key, $value )
|
|
{
|
|
$this->temp_headers[ $key ] = $value;
|
|
}
|
|
|
|
/**
|
|
* Send an email
|
|
*
|
|
* @return boolean Email sent successfully
|
|
*/
|
|
public function sendMail()
|
|
{
|
|
$this->init();
|
|
|
|
if( $this->emailer->error )
|
|
{
|
|
return $this->fatalError( $this->emailer->error_msg, $this->emailer->error_help );
|
|
}
|
|
|
|
/* Add attachments if any */
|
|
if ( count( $this->_attachments ) )
|
|
{
|
|
foreach( $this->_attachments as $a )
|
|
{
|
|
$this->emailer->addAttachment( $a[0], $a[1], $a[2] );
|
|
}
|
|
}
|
|
|
|
$this->settings['board_name'] = $this->cleanMessage($this->settings['board_name']);
|
|
|
|
$this->emailer->setFrom( $this->from ? $this->from : $this->settings['email_out'], $this->settings['board_name'] );
|
|
$this->emailer->setTo( $this->to );
|
|
|
|
foreach( $this->cc as $cc )
|
|
{
|
|
$this->emailer->addCC( $cc );
|
|
}
|
|
foreach( $this->bcc as $bcc )
|
|
{
|
|
$this->emailer->addBCC( $bcc );
|
|
}
|
|
|
|
if( count($this->temp_headers) )
|
|
{
|
|
foreach( $this->temp_headers as $k => $v )
|
|
{
|
|
$this->emailer->setHeader( $k, $v );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Added strip_tags for the subject 4.16.2010
|
|
// so we can have links in subject for inline
|
|
// notifications and still use the subject
|
|
//-----------------------------------------
|
|
|
|
$this->emailer->setSubject( $this->_cleanSubject($this->subject) );
|
|
|
|
/* If we're sending a HTML email, we need to manually send the plain text and HTML versions */
|
|
if ( $this->html_email and $this->htmlTemplate )
|
|
{
|
|
/* Dynamically replace subject in template */
|
|
$this->htmlTemplate = str_ireplace( array('<#subject#>'), IPSText::utf8ToEntities( $this->_cleanSubject($this->subject) ), $this->htmlTemplate );
|
|
$this->emailer->setPlainTextContent( $this->plainTextTemplate );
|
|
$this->emailer->setHtmlContent( $this->htmlTemplate );
|
|
}
|
|
else if ( $this->message && ! $this->plainTextTemplate )
|
|
{
|
|
/* Older methods pass message directly */
|
|
$this->emailer->setBody( $this->message );
|
|
}
|
|
else
|
|
{
|
|
$this->emailer->setBody( $this->plainTextTemplate );
|
|
}
|
|
|
|
$this->emailer->sendMail();
|
|
|
|
/* Clear out stuffs */
|
|
$this->clearContent();
|
|
|
|
// Unset HTML setting to remain backwards compatibility
|
|
//$this->html_email = FALSE;
|
|
|
|
if( $this->emailer->error )
|
|
{
|
|
return $this->fatalError( $this->emailer->error_msg, $this->emailer->error_help );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Set the plain text template
|
|
* @param string $string
|
|
*/
|
|
public function setPlainTextTemplate( $string, $unsub=false )
|
|
{
|
|
/* Reset message too */
|
|
$this->message = '';
|
|
|
|
/* Add unsubscribe link */
|
|
$this->plainTextTemplate = str_replace( ' ', ' ', $string );
|
|
$this->plainTextTemplate = str_replace( ' ', ' ', $string );
|
|
if ( $unsub )
|
|
{
|
|
$this->plainTextTemplate .= "\n\n\n\n<#UNSUBSCRIBE#>";
|
|
}
|
|
|
|
/*
|
|
* Quite often the plain text template is populated but the HTML isn't -but then plainTextTemplate is modified by buildPlainTextContent
|
|
* so when we then run buildHtmlContent, it uses the already processed plainTextTemplate which has substituted <#POST#> into a stripped version.
|
|
*/
|
|
if ( ! $this->htmlTemplate )
|
|
{
|
|
/* Need to exchange BRs? */
|
|
if ( ! stristr( $this->plainTextTemplate, '<br' ) )
|
|
{
|
|
$this->htmlTemplate = nl2br( $this->plainTextTemplate );
|
|
}
|
|
else
|
|
{
|
|
$this->htmlTemplate = $this->plainTextTemplate;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the HTML template
|
|
* @param string $string
|
|
*/
|
|
public function setHtmlTemplate( $string )
|
|
{
|
|
/* Reset message too */
|
|
$this->message = '';
|
|
|
|
$this->htmlTemplate = $string;
|
|
}
|
|
|
|
/**
|
|
* Return plain text content
|
|
* @return string
|
|
*/
|
|
public function getPlainTextContent()
|
|
{
|
|
return $this->plainTextTemplate;
|
|
}
|
|
|
|
/**
|
|
* Return HTML content
|
|
* @return string
|
|
*/
|
|
public function getHtmlContent()
|
|
{
|
|
return $this->htmlTemplate;
|
|
}
|
|
|
|
/**
|
|
* Removes all current stored messages, templates, etc.
|
|
*/
|
|
public function clearContent()
|
|
{
|
|
$this->setHtmlTemplate('');
|
|
$this->setPlainTextTemplate('');
|
|
$this->message = '';
|
|
$this->template = '';
|
|
$this->_attachments = array();
|
|
}
|
|
|
|
/**
|
|
* Send custom html wrapper - HTML wrapper with <#content#> tag where content will be
|
|
* @param string $string
|
|
*/
|
|
public function setHtmlWrapper( $string )
|
|
{
|
|
$this->htmlWrapper = $string . "<br /><br /><br /><br /><#UNSUBSCRIBE#>";
|
|
}
|
|
|
|
/**
|
|
* Retrieve an email template
|
|
*
|
|
* @param string Template key
|
|
* @param string Language to use
|
|
* @param string Language file to load
|
|
* @param string Application of language file
|
|
* @return @e void
|
|
*/
|
|
public function getTemplate( $name, $language="", $lang_file='public_email_content', $app='core' )
|
|
{
|
|
/* Reset $this->message as legacy methods use $this->message when sending notifications, etc */
|
|
$this->clearContent();
|
|
|
|
/* Sometimes the lang_file & app can end up being empty - reset them */
|
|
$lang_file = empty($lang_file) ? 'public_email_content' : $lang_file;
|
|
$app = empty($app) ? 'core' : $app;
|
|
|
|
//-----------------------------------------
|
|
// Check..
|
|
//-----------------------------------------
|
|
|
|
if( $name == "" )
|
|
{
|
|
$this->error++;
|
|
$this->fatalError( "A valid email template ID was not passed to the email library during template parsing", "" );
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Default?
|
|
//-----------------------------------------
|
|
|
|
if( ! $language )
|
|
{
|
|
$language = IPSLib::getDefaultLanguage();
|
|
}
|
|
|
|
$this->language = $language;
|
|
|
|
//-----------------------------------------
|
|
// Check and get
|
|
//-----------------------------------------
|
|
|
|
$this->registry->class_localization->loadLanguageFile( array( $lang_file ), $app, $language, TRUE );
|
|
|
|
//-----------------------------------------
|
|
// Stored KEY?
|
|
//-----------------------------------------
|
|
|
|
if ( ! isset($this->lang->words[ $name ]) )
|
|
{
|
|
if ( $language == IPSLib::getDefaultLanguage() )
|
|
{
|
|
$this->fatalError( "Could not find an email template with an ID of '{$name}'", "" );
|
|
}
|
|
else
|
|
{
|
|
$this->registry->class_localization->loadLanguageFile( array( $lang_file ), $app, IPSLib::getDefaultLanguage() );
|
|
|
|
if ( ! isset($this->lang->words[ $name ]) )
|
|
{
|
|
$this->fatalError( "Could not find an email template with an ID of '{$name}'", "" );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Subject?
|
|
//-----------------------------------------
|
|
|
|
if ( isset( $this->lang->words[ 'subject__'. $name ] ) )
|
|
{
|
|
$this->subject = stripslashes( $this->lang->words[ 'subject__'. $name ] );
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Return
|
|
//-----------------------------------------
|
|
|
|
$this->template = stripslashes($this->lang->words[ $name ]) . stripslashes($this->lang->words['email_footer']);
|
|
|
|
/* Returns it if called via setPlainTextTemplate */
|
|
return $this->template;
|
|
}
|
|
|
|
/**
|
|
* Legacy, generic method: builds an email from a template, replacing variables
|
|
*
|
|
* @deprecated
|
|
* @param array Replacement keys to values
|
|
* @param bool Do not "clean"
|
|
* @param bool Raw HTML
|
|
* @param array Member data - necessary if including unsubscribe link
|
|
* @return @e void
|
|
*/
|
|
public function buildMessage( $words, $noClean=false, $rawHtml=FALSE, $memberData=array() )
|
|
{
|
|
/* Init */
|
|
$ptWords = array();
|
|
$htmlWords = array();
|
|
$subjWords = array();
|
|
|
|
/* Try this first */
|
|
if ( ! $this->plainTextTemplate && ! $this->htmlTemplate && $this->message )
|
|
{
|
|
$this->setPlainTextTemplate( $this->message, true );
|
|
}
|
|
|
|
/* need to converge some stuff here */
|
|
if ( ! $this->plainTextTemplate && $this->template )
|
|
{
|
|
/* Sniff, sniff */
|
|
if ( stristr( $this->template, '<br' ) )
|
|
{
|
|
if ( ! $this->htmlTemplate )
|
|
{
|
|
$this->setHtmlTemplate( $this->template );
|
|
}
|
|
|
|
$this->setPlainTextTemplate( IPSText::br2nl( $this->template ) );
|
|
}
|
|
else
|
|
{
|
|
if ( ! $this->htmlTemplate )
|
|
{
|
|
$this->setHtmlTemplate( nl2br( $this->template ) );
|
|
}
|
|
|
|
$this->setPlainTextTemplate( $this->template );
|
|
}
|
|
}
|
|
|
|
/* HTML enabled but no specific template: Auto convert */
|
|
if ( $this->html_email && ! $this->htmlTemplate )
|
|
{
|
|
/* It will be dynamically updated at the end */
|
|
$this->setHtmlTemplate( $this->plainTextTemplate );
|
|
}
|
|
|
|
/* HTML email with HTML template but no plain text version */
|
|
if ( $this->htmlTemplate && ! $this->plainTextTemplate )
|
|
{
|
|
$msg = $this->htmlTemplate;
|
|
$msg = preg_replace( '/<#(.+?)#>/', '{{{-\1-}}}', $msg );
|
|
$msg = str_replace( "<br />", "\n", $msg );
|
|
$msg = str_replace( "<br>" , "\n", $msg );
|
|
$msg = IPSText::stripTags( $msg );
|
|
|
|
$msg = html_entity_decode( $msg, ENT_QUOTES );
|
|
$msg = str_replace( '\', '\\', $msg );
|
|
$msg = str_replace( '$', '$', $msg );
|
|
$msg = preg_replace( '/\{\{\{(.+?)\}\}\}/', '<#\1#>', $msg );
|
|
|
|
$this->setPlainTextTemplate( $msg );
|
|
}
|
|
|
|
if ( $this->plainTextTemplate && ! $this->template && ( $this->html_email && ! $this->htmlTemplate ) )
|
|
{
|
|
$this->error++;
|
|
$this->fatalError( "Could not build the email message, no template assigned", "Make sure a template is assigned first." );
|
|
}
|
|
|
|
/* Bit more clean up */
|
|
$this->plainTextTemplate = str_replace( array( "\r\n", "\r", "\n" ), "\n", $this->plainTextTemplate );
|
|
$this->htmlTemplate = str_replace( array( "\r\n", "\r", "\n" ), "\n", $this->htmlTemplate );
|
|
|
|
/* Apply HTML wrapper */
|
|
$this->htmlTemplate = $this->applyHtmlWrapper( $this->subject, ( $rawHtml ? $this->htmlTemplate : $this->convertTextEmailToHtmlEmail( $this->htmlTemplate, $rawHtml ) ) );
|
|
|
|
/* Add unsubscribe link */
|
|
if ( $this->unsubscribe and !empty( $memberData ) )
|
|
{
|
|
$this->registry->class_localization->loadLanguageFile( array( 'public_global' ), 'core', $this->language ? $this->language : IPSLib::getDefaultLanguage(), TRUE );
|
|
$key = md5( $memberData['email'] . ':' . $memberData['members_pass_hash'] );
|
|
$link = $this->registry->output->buildUrl( "app=core&module=global&section=unsubscribe&member={$memberData['member_id']}&key={$key}", 'publicNoSession' );
|
|
|
|
$this->plainTextTemplate = str_replace( "<#UNSUBSCRIBE#>", "{$this->registry->class_localization->words['email_unsubscribe']}: {$link}", $this->plainTextTemplate );
|
|
$this->htmlTemplate = str_replace( "<#UNSUBSCRIBE#>", "<a href='{$link}'>" . $this->registry->class_localization->words['email_unsubscribe'] . '</a>', $this->htmlTemplate );
|
|
}
|
|
|
|
/* Add some default words */
|
|
$words['BOARD_ADDRESS'] = $this->settings['board_url'] . '/index.' . $this->settings['php_ext'];
|
|
$words['WEB_ADDRESS'] = $this->settings['home_url'];
|
|
$words['BOARD_NAME'] = $this->settings['board_name'];
|
|
$words['SIGNATURE'] = $this->settings['signature'] ? $this->settings['signature'] : '';
|
|
|
|
/* Swap the words: 10.7.08 - Added replacements in subject */
|
|
foreach( $words as $k => $v )
|
|
{
|
|
if ( ! $noClean )
|
|
{
|
|
$ptWords[ $k ] = $this->cleanMessage( $v );
|
|
}
|
|
|
|
$subjWords[ $k ] = $this->cleanMessage( $v, false, false );
|
|
|
|
/* Convert over words too so links are linkified */
|
|
$htmlWords[ $k ] = ( $rawHtml ? $v : $this->convertTextEmailToHtmlEmail( $v, $rawHtml ) );
|
|
}
|
|
|
|
$this->_words = $ptWords;
|
|
|
|
$this->plainTextTemplate = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), $this->plainTextTemplate );
|
|
|
|
$this->_words = $htmlWords;
|
|
$this->htmlTemplate = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), str_replace( array( '<#', '#>' ), array( '<#', '#>' ), $this->htmlTemplate ) );
|
|
|
|
$this->_words = $subjWords;
|
|
$this->subject = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), $this->subject );
|
|
|
|
$this->_words = array();
|
|
|
|
/* Final touches */
|
|
$this->htmlTemplate = preg_replace( '#<!--hook\.([^\>]+?)-->#', '', $this->htmlTemplate );
|
|
$this->htmlTemplate = $this->registry->getClass('output')->parseIPSTags( $this->htmlTemplate );
|
|
|
|
/* strip all tags if not HTML */
|
|
if ( ! $this->settings['email_use_html'] )
|
|
{
|
|
$this->plainTextTemplate = IPSText::stripTags( $this->plainTextTemplate );
|
|
}
|
|
|
|
$this->plainTextTemplate = IPSText::stripTags( stripslashes($this->lang->words['email_header']) ) . $this->plainTextTemplate . IPSText::stripTags( stripslashes($this->lang->words['email_footer']) );
|
|
|
|
/* Some older apps use $this->message, so give them plaintext */
|
|
$this->message = $this->plainTextTemplate;
|
|
}
|
|
|
|
/**
|
|
* Legacy, generic method: builds an email from a template, replacing variables
|
|
*
|
|
* @param array Replacement keys to values
|
|
* @param boolean Raw HTML mode?
|
|
* @return @e void
|
|
*/
|
|
public function buildHtmlContent( $words=array(), $rawHtml=false )
|
|
{
|
|
/* Init */
|
|
$htmlWords = array();
|
|
|
|
/* Did we set a plainText template but not bother with HTML ? */
|
|
if ( ! $this->htmlTemplate && $this->plainTextTemplate )
|
|
{
|
|
/* Need to exchange BRs? */
|
|
if ( ! stristr( $this->plainTextTemplate, '<br' ) )
|
|
{
|
|
$this->plainTextTemplate = nl2br( $this->plainTextTemplate );
|
|
}
|
|
|
|
/* Sniff, sniff */
|
|
$this->setHtmlTemplate( $this->plainTextTemplate );
|
|
}
|
|
|
|
/* HTML enabled but no specific template: Auto convert */
|
|
if ( $this->html_email && ! $this->htmlTemplate )
|
|
{
|
|
/* It will be dynamically updated at the end */
|
|
$this->setHtmlTemplate( $this->plainTextTemplate );
|
|
}
|
|
|
|
/* Bit more clean up */
|
|
$this->htmlTemplate = str_replace( array( "\r\n", "\r", "\n" ), "\n", $this->htmlTemplate );
|
|
|
|
/* Add some default words */
|
|
$words['BOARD_ADDRESS'] = $this->settings['board_url'] . '/index.' . $this->settings['php_ext'];
|
|
$words['WEB_ADDRESS'] = $this->settings['home_url'];
|
|
$words['BOARD_NAME'] = $this->settings['board_name'];
|
|
$words['SIGNATURE'] = $this->settings['signature'] ? $this->settings['signature'] : '';
|
|
|
|
/* Swap the words: 10.7.08 - Added replacements in subject */
|
|
foreach( $words as $k => $v )
|
|
{
|
|
$htmlWords[ $k ] = $v;
|
|
}
|
|
|
|
$this->_words = $htmlWords;
|
|
$this->htmlTemplate = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), str_replace( array( '<#', '#>' ), array( '<#', '#>' ), $this->htmlTemplate ) );
|
|
$this->subject = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), $this->subject );
|
|
$this->_words = array();
|
|
|
|
/* Final touches */
|
|
$this->htmlTemplate = IPSText::stripAttachTag( $this->htmlTemplate );
|
|
$this->htmlTemplate = preg_replace( '#<blockquote(?:[^>]+?)?>(.+?)</blockquote>#s', '<br /><div class="eQuote">\\1</div><br />', $this->htmlTemplate );
|
|
$this->htmlTemplate = $this->applyHtmlWrapper( $this->subject, $this->convertTextEmailToHtmlEmail( $this->htmlTemplate, $rawHtml ) );
|
|
$this->htmlTemplate = preg_replace( '#<!--hook\.([^\>]+?)-->#', '', $this->htmlTemplate );
|
|
$this->htmlTemplate = $this->registry->getClass('output')->parseIPSTags( $this->htmlTemplate );
|
|
|
|
/* For those who need it */
|
|
return $this->htmlTemplate;
|
|
}
|
|
|
|
/**
|
|
* New: build HTML content
|
|
*
|
|
* @param array Replacement keys to values
|
|
* @return @e void
|
|
*/
|
|
public function buildPlainTextContent( $words=array() )
|
|
{
|
|
/* Init */
|
|
$ptWords = array();
|
|
$subjWords = array();
|
|
|
|
/* Try this first */
|
|
if ( ! $this->plainTextTemplate )
|
|
{
|
|
if ( $this->message )
|
|
{
|
|
$this->setPlainTextTemplate( $this->message );
|
|
}
|
|
else if ( $this->template )
|
|
{
|
|
$this->setPlainTextTemplate( $this->template );
|
|
}
|
|
}
|
|
|
|
/* Bit more clean up */
|
|
$this->plainTextTemplate = str_replace( array( "\r\n", "\r", "\n" ), "\n", $this->plainTextTemplate );
|
|
|
|
/* Strip out HTML mark-up designed for the HTML template. If $words is false, it's a second pass, so don't strip tags again! */
|
|
if ( $words !== false )
|
|
{
|
|
$this->plainTextTemplate = preg_replace( '/<#(.+?)#>/', '{{{-\1-}}}', $this->plainTextTemplate );
|
|
|
|
$this->plainTextTemplate = IPSText::stripTags( $this->plainTextTemplate );
|
|
|
|
$this->plainTextTemplate = preg_replace( '/\{\{\{-(.+?)-\}\}\}/', '<#\1#>', $this->plainTextTemplate );
|
|
}
|
|
|
|
/* Bit more clean up */
|
|
$this->plainTextTemplate = str_replace( array( "\r\n", "\r", "\n" ), "\n", $this->plainTextTemplate );
|
|
|
|
/* Add some default words */
|
|
$words['BOARD_ADDRESS'] = $this->settings['board_url'] . '/index.' . $this->settings['php_ext'];
|
|
$words['WEB_ADDRESS'] = $this->settings['home_url'];
|
|
$words['BOARD_NAME'] = $this->settings['board_name'];
|
|
$words['SIGNATURE'] = $this->settings['signature'] ? $this->settings['signature'] : '';
|
|
|
|
/* Swap the words: 10.7.08 - Added replacements in subject */
|
|
foreach( $words as $k => $v )
|
|
{
|
|
$ptWords[ $k ] = $this->cleanMessage( $v );
|
|
$subjWords[ $k ] = $this->cleanMessage( $v, true, false );
|
|
}
|
|
|
|
$this->_words = $ptWords;
|
|
$this->plainTextTemplate = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), $this->plainTextTemplate );
|
|
$this->_words = $subjWords;
|
|
$this->subject = preg_replace_callback( "/<#(.+?)#>/", array( &$this, '_swapWords' ), $this->subject );
|
|
$this->_words = array();
|
|
|
|
/* Strip All tags if not HTML */
|
|
$this->plainTextTemplate = IPSText::stripTags( stripslashes($this->lang->words['email_header']) ) . $this->plainTextTemplate . IPSText::stripTags( stripslashes($this->lang->words['email_footer']) );
|
|
|
|
/* For those who need it */
|
|
return $this->plainTextTemplate;
|
|
}
|
|
|
|
/**
|
|
* Convert text email to HTML
|
|
* Pretty nifty method name too.
|
|
*
|
|
* @param string Plain text email ready to go
|
|
* @param boolean Raw HTML mode?
|
|
* @return string We're all HTML'd up in here.
|
|
*/
|
|
public function convertTextEmailToHtmlEmail( $content, $rawHtml=false )
|
|
{
|
|
$content = str_replace( array( "\r\n", "\r" ), "\n", $content );
|
|
$content = trim( $content, "\n" );
|
|
|
|
/* It's probably HITMAL! */
|
|
if ( ! is_object( $this->parser ) )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/text/parser.php', 'classes_text_parser' );
|
|
$this->parser = new $classToLoad();
|
|
|
|
/* Reset HTML flags */
|
|
$this->parser->set( array( 'parseArea' => 'emails',
|
|
'memberData' => $this->memberData,
|
|
'parseBBCode' => true,
|
|
'parseHtml' => false,
|
|
'parseEmoticons' => true ) );
|
|
}
|
|
|
|
/* Is this a HTML post? */
|
|
$isHtmlContent = ( stristr( $content, '<table' ) AND stristr( $content, '</table>' ) ) ? true : false;
|
|
|
|
/* Do not truncate URLs */
|
|
if ( (boolean)$rawHtml !== true )
|
|
{
|
|
if ( $isHtmlContent === false )
|
|
{
|
|
$_tmp = $this->settings['__noTruncateUrl'];
|
|
$this->settings['__noTruncateUrl'] = true;
|
|
|
|
/* Display */
|
|
$content = $this->parser->display( $content );
|
|
|
|
/* Remove emoticons */
|
|
$content = $this->parser->emoticonImgtoCode( $content );
|
|
|
|
/* Remove images */
|
|
$content = $this->parser->stripImages( $content );
|
|
|
|
$this->settings['__noTruncateUrl'] = $_tmp;
|
|
|
|
/* Purify pass to linkify */
|
|
$purifier = $this->_newPurifierObject();
|
|
|
|
/* Run it */
|
|
$content = $purifier->purify( $content );
|
|
}
|
|
|
|
/* Other stuffs */
|
|
$content = preg_replace( '#(\-{10,120})#', '<hr>', $content );
|
|
$content = preg_replace( '#(\={10,120})#', '<hr>', $content );
|
|
$content = preg_replace( '#(?:\n{1,})<hr>#', "<hr>", $content );
|
|
$content = preg_replace( '#<hr>(?:\n{1,})#', "<hr>", $content );
|
|
$content = str_replace( ' ', ' ', $content );
|
|
|
|
/* Fix stupid § - might want to consider fixing all direct & to & at some point? */
|
|
$content = preg_replace( "#§(?!;)#", '&sect', $content );
|
|
|
|
/* remove double brs */
|
|
$content = preg_replace( '#<br(?:[^>]+?)?><hr><br(?:[^>]+?)?>#i', "<hr>", $content );
|
|
|
|
/* Empty paragraphs for spacing */
|
|
$content = preg_replace( '#<p([^>]+?)?>(\s+?)</p>#i', '<p\1> </p>', $content );
|
|
}
|
|
|
|
return wordwrap( $content, 990, "\r\n" );
|
|
}
|
|
|
|
/**
|
|
* Add <html> tags and such if it doesn't have any already
|
|
*
|
|
* @param string Subject
|
|
* @param string HTML email
|
|
* @return string VERY HTML email
|
|
*/
|
|
public function applyHtmlWrapper( $subject, $content )
|
|
{
|
|
$unsubscribe = '';
|
|
|
|
if ( $this->unsubscribe )
|
|
{
|
|
$unsubscribe = " · <#UNSUBSCRIBE#>";
|
|
}
|
|
|
|
/* Due to some legacy methods with mail queue, buildMessage can be called twice
|
|
* for good reason, but it can then re-apply the wrapper. So we add a unique comment
|
|
* and then check for this.
|
|
*/
|
|
if ( ! stristr( $content, '<!--ipb.wrapper.added-->' ) )
|
|
{
|
|
$content = '<!--ipb.wrapper.added-->' . $content;
|
|
|
|
/* Inline wrapper */
|
|
if ( $this->htmlWrapper )
|
|
{
|
|
return str_ireplace( '<#content#>', $content, $this->htmlWrapper );
|
|
}
|
|
|
|
/* Attempt to load external wrapper */
|
|
if ( ! is_object( $this->_loadedHtmlTemplateClass ) )
|
|
{
|
|
if ( ! is_file( IPS_CACHE_PATH . 'cache/skin_cache/system/emailWrapper.php' ) )
|
|
{
|
|
require_once( IPS_ROOT_PATH . 'sources/classes/output/systemTemplates.php' );
|
|
$systemTemplates = new systemTemplates();
|
|
$systemTemplates->writeDefaults();
|
|
}
|
|
|
|
/* Still nothing? */
|
|
if ( ! is_file( IPS_CACHE_PATH . 'cache/skin_cache/system/emailWrapper.php' ) )
|
|
{
|
|
/* Still here? Fail safe */
|
|
return $this->parseWithDefaultHtmlWrapper( $content );
|
|
}
|
|
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/output/systemTemplates.php', 'systemTemplates' );
|
|
$systemTemplates = new $classToLoad();
|
|
$this->_loadedHtmlTemplateClass = $systemTemplates->getClass('emailWrapper');
|
|
}
|
|
|
|
return $this->_loadedHtmlTemplateClass->getTemplate( $content, $unsubscribe, ipsRegistry::$settings );
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
/**
|
|
* Replaces key with value
|
|
*
|
|
* @param string Key
|
|
* @return string Replaced variable
|
|
*/
|
|
protected function _swapWords( $matches )
|
|
{
|
|
return $this->_words[ $matches[1] ];
|
|
}
|
|
|
|
/**
|
|
* Cleans the email subject
|
|
*
|
|
* @param string In text
|
|
* @return string Out text
|
|
*/
|
|
protected function _cleanSubject( $subject )
|
|
{
|
|
$subject = strip_tags( $subject );
|
|
|
|
$subject = str_replace( "$", "\$", $subject );
|
|
$subject = str_replace( "!" , "!" , $subject );
|
|
$subject = str_replace( """ , '"' , $subject );
|
|
$subject = str_replace( "'" , "'" , $subject );
|
|
$subject = str_replace( "|", '|' , $subject );
|
|
$subject = str_replace( "&" , '&' , $subject );
|
|
$subject = str_replace( ":" , ":" , $subject );
|
|
$subject = str_replace( "[" , "[" , $subject );
|
|
$subject = str_replace( "]" , "]" , $subject );
|
|
$subject = str_replace( "@", '@' , $subject );
|
|
$subject = str_replace( " ", ' ' , $subject );
|
|
$subject = str_replace( "&" , '&' , $subject );
|
|
$subject = str_replace( "<" , '[' , $subject );
|
|
$subject = str_replace( ">" , ']' , $subject );
|
|
|
|
return $subject;
|
|
}
|
|
|
|
/**
|
|
* Cleans an email message
|
|
*
|
|
* @param string Email content
|
|
* @param bool Skip converting < and >
|
|
* @param bool Fix up plain text links
|
|
* @return string Cleaned email content
|
|
*/
|
|
public function cleanMessage( $message = "", $skipAngleBrackets=false, $fixPlainTextLinks=true )
|
|
{
|
|
if ( ! $this->html_email )
|
|
{
|
|
$message = preg_replace_callback( '#\[url=(.+?)\](.+?)\[/url\]#', array( $this, "_formatUrl" ), $message );
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Unconvert smilies 'cos at this point they are img tags
|
|
//-----------------------------------------
|
|
|
|
$message = IPSText::unconvertSmilies( $message );
|
|
|
|
//-----------------------------------------
|
|
// We may want to adjust this later, but for
|
|
// now just strip any other html
|
|
//-----------------------------------------
|
|
|
|
$message = preg_replace( '#</p>(\s+?)?<p([^>]+?)?>#is', '<br />', $message );
|
|
|
|
/* We need to fix links in plaintext templates so people don't get "http://some..ing" instead of "http://something" */
|
|
if ( $fixPlainTextLinks )
|
|
{
|
|
$message = $this->fixPlaintextLinks( $message );
|
|
}
|
|
|
|
$message = IPSText::stripTags( $message, '<br>,<blockquote>' );
|
|
|
|
IPSText::getTextClass( 'bbcode' )->parse_html = 0;
|
|
IPSText::getTextClass( 'bbcode' )->parse_nl2br = 1;
|
|
IPSText::getTextClass( 'bbcode' )->parse_bbcode = 0;
|
|
|
|
/* Textual representations of certain bbcodes to attempt to keep context */
|
|
|
|
$plainText = '<br /><br />------------ QUOTE ----------<br />\\1<br />-----------------------------<br /><br />';
|
|
|
|
$message = preg_replace( '#\[quote(?:[^\]]+?)?\](.+?)\[/quote\]#s', $plainText, $message );
|
|
$message = preg_replace( '#<blockquote(?:[^>]+?)?>(.+?)</blockquote>#s', $plainText, $message );
|
|
|
|
$plainTextCode = '*CODE* \\1 */CODE*';
|
|
|
|
$message = preg_replace( '#\[code(?:[^\]]+?)?\](.+?)\[/code\]#s', $plainTextCode, $message );
|
|
|
|
$message = preg_replace( '#\[member=(.+?)\]#s', "\\1", $message );
|
|
|
|
$message = IPSText::getTextClass('bbcode')->stripAllTags( $message, true );
|
|
|
|
//-----------------------------------------
|
|
// Bear with me...
|
|
//-----------------------------------------
|
|
|
|
$message = str_replace( "\n" , "\r\n", $message );
|
|
$message = str_replace( "\r" , "" , $message );
|
|
$message = str_replace( "<br>" , "\r\n", $message );
|
|
$message = str_replace( "<br />" , "\r\n", $message );
|
|
$message = str_replace( "\r\n\r\n" , "\r\n", $message );
|
|
|
|
$message = str_replace( """, '"' , $message );
|
|
$message = str_replace( "\", "\\", $message );
|
|
$message = str_replace( "$", "\$", $message );
|
|
$message = str_replace( "!" , "!" , $message );
|
|
$message = str_replace( """ , '"' , $message );
|
|
$message = str_replace( "'" , "'" , $message );
|
|
$message = str_replace( "(" , "(" , $message );
|
|
$message = str_replace( ")" , ")" , $message );
|
|
$message = str_replace( "<" , "<" , $message );
|
|
$message = str_replace( ">" , ">" , $message );
|
|
$message = str_replace( "|", '|' , $message );
|
|
$message = str_replace( "&" , "&" , $message );
|
|
$message = str_replace( "&" , '&' , $message );
|
|
$message = str_replace( ":" , ":" , $message );
|
|
$message = str_replace( "[" , "[" , $message );
|
|
$message = str_replace( "]" , "]" , $message );
|
|
$message = str_replace( "@", '@' , $message );
|
|
$message = str_replace( " " , ' ', $message );
|
|
|
|
if( !$skipAngleBrackets )
|
|
{
|
|
$message = str_replace( "<" , '<' , $message );
|
|
$message = str_replace( ">" , '>' , $message );
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
|
|
/**
|
|
* Fix links for plaintext template. Changes <a href='http://...'>something</a> to just the URL, which is necessary because parser engine makes links like http://som...jpg
|
|
*
|
|
* @param string Raw text
|
|
* @param string Raw text for plaintext template
|
|
* @return @e void
|
|
*/
|
|
public function fixPlaintextLinks( $message )
|
|
{
|
|
if( !$message )
|
|
{
|
|
return $message;
|
|
}
|
|
|
|
preg_match_all( '#<a(?:.+?)href=["\']([^"\']+?)?["\']([^>]+?)?>(.+?)</a>#is', $message, $urlMatches );
|
|
|
|
/* Finish up URLs and such */
|
|
for( $i = 0 ; $i < count( $urlMatches[0] ) ; $i++ )
|
|
{
|
|
$raw = $urlMatches[0][ $i ];
|
|
$url = $urlMatches[1][ $i ];
|
|
$attr = $urlMatches[2][ $i ];
|
|
$text = $urlMatches[3][ $i ];
|
|
|
|
/* This will show the direct URL if the text was also part of the URL, or it will show "text (url)" otherwise */
|
|
if( strpos( $text, 'http://' ) === 0 )
|
|
{
|
|
$message = str_replace( $raw, $url, $message );
|
|
}
|
|
else
|
|
{
|
|
$message = str_replace( $raw, $text . ' (' . $url . ')', $message );
|
|
}
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
|
|
/**
|
|
* Format url for email
|
|
*
|
|
* @param array preg_replace matches
|
|
* @return string Formatted url
|
|
*/
|
|
public function _formatUrl( $matches )
|
|
{
|
|
$matches[1] = str_replace( array( '"', "'", '"', ''', ''' ), '', $matches[1] );
|
|
|
|
return $matches[2] . ' (' . $matches[1] . ')';
|
|
}
|
|
|
|
/**
|
|
* Add an attachment to the current email
|
|
*
|
|
* @param string File data
|
|
* @param string File name
|
|
* @param string File type (MIME)
|
|
* @return @e void
|
|
*/
|
|
public function addAttachment( $data="", $name="", $ctype='application/octet-stream' )
|
|
{
|
|
$this->_attachments[] = array( $data, $name, $ctype );
|
|
}
|
|
|
|
/**
|
|
* Log a fatal error
|
|
*
|
|
* @param string Message
|
|
* @param string Help key (deprecated)
|
|
* @return bool
|
|
*/
|
|
protected function fatalError( $msg, $help="" )
|
|
{
|
|
$this->DB->insert( 'mail_error_logs',
|
|
array(
|
|
'mlog_date' => time(),
|
|
'mlog_to' => $this->to,
|
|
'mlog_from' => $this->from,
|
|
'mlog_subject' => $this->subject,
|
|
'mlog_content' => substr( $this->message, 0, 200 ),
|
|
'mlog_msg' => $msg,
|
|
'mlog_code' => $this->emailer->smtp_code,
|
|
'mlog_smtp_msg' => $this->emailer->smtp_msg
|
|
)
|
|
);
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Create a purifier object
|
|
* @return Purifier object
|
|
*/
|
|
private function _newPurifierObject()
|
|
{
|
|
/* Grab HTMLPurifier */
|
|
require_once( IPS_KERNEL_PATH . 'HTMLPurifier/HTMLPurifier.auto.php' );
|
|
|
|
$config = HTMLPurifier_Config::createDefault();
|
|
|
|
/* Cache path (Please put first)*/
|
|
$config->set('Cache.SerializerPath', HTML_PURIFIER_PATH . 'cache/tmp' );
|
|
|
|
/* Allow data- attributes */
|
|
$config->set('HTML.Doctype', 'HTML 4.01 Transitional');
|
|
$config->set('HTML.TidyLevel', 'none');
|
|
|
|
if ( IN_DEV )
|
|
{
|
|
$config->set('Cache.DefinitionImpl', null);
|
|
}
|
|
|
|
$config->set('AutoFormat.Linkify', true );
|
|
$config->set('Core.Encoding', IPS_DOC_CHAR_SET );
|
|
|
|
if ( IPS_IS_UTF8 !== true )
|
|
{
|
|
$config->set('Core.EscapeNonASCIICharacters', true );
|
|
}
|
|
|
|
/* If HTML mode... */
|
|
$config->set( 'Core.EscapeInvalidTags', false );
|
|
|
|
/* Allow CSS Damage */
|
|
$config->set( 'CSS.AllowImportant', true );
|
|
$config->set( 'CSS.AllowTricky' , true );
|
|
$config->set( 'CSS.Trusted' , true );
|
|
|
|
/* Add custom data attributes */
|
|
$def = $config->getHTMLDefinition(true);
|
|
|
|
$def->addAttribute( 'blockquote', 'data-author' , 'Text' );
|
|
$def->addAttribute( 'blockquote', 'data-cid' , 'Text' );
|
|
$def->addAttribute( 'blockquote', 'data-time' , 'Text' );
|
|
$def->addAttribute( 'blockquote', 'data-date' , 'Text' );
|
|
$def->addAttribute( 'blockquote', 'data-collapsed', 'Text' );
|
|
|
|
return new HTMLPurifier( $config );
|
|
}
|
|
|
|
/**
|
|
* Default wrapper for HTML emails - edit the one in '/cache/skin_cache/emailWrapper.php'
|
|
*
|
|
* @param string HTML content
|
|
* @return string HTML email done
|
|
*/
|
|
protected function parseWithDefaultHtmlWrapper( $content )
|
|
{
|
|
$doc =IPS_DOC_CHAR_SET;
|
|
|
|
$email = <<<HTML
|
|
<html>
|
|
<head>
|
|
<meta content="text/html; charset={$doc}" http-equiv="Content-Type">
|
|
<title><#subject#></title>
|
|
<style type="text/css">
|
|
* {
|
|
font-family: Arial;
|
|
font-size: 14px;
|
|
color: #000;
|
|
background: #fff;
|
|
line-height: 140%;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
{$content}
|
|
</body>
|
|
</head>
|
|
</html>
|
|
HTML;
|
|
|
|
return $email;
|
|
}
|
|
} |