) and footer (from
) Maybe each template is an array with several parts - optional header and footer, use defaults if not defined header looks for the {STYLESHEET} variable If we do that, can have a single override file, plus a core file 3. mail (PHP method) - note that it has parameters for additional headers and other parameters 4. Check that language support works - PHPMailer defaults to English if other files not available - PHPMailer expects a 2-letter code - $this->SetLanguage(CORE_LC) - e.g. 'en', 'br' 5. Logging: - Use rolling log for errors - error string(s) available - sort out entry - Look at support of some other logging options 9. Make sure SMTPDebug can be set (TRUE/FALSE) 12. Check support for port number - ATM we just override for SSL. Looks as if phpmailer can take it from end of server link. 18. Note object iteration - may be useful for dump of object state 19. Consider overriding error handler 20. Look at using new prefs structure 21. Should we always send an ID? 22. Force singleton so all mail sending flow controlled a bit (but not where parameters overridden in constructor) Tested so far (with PHP4 version) ------------ SMTP send (standard) Return receipts text or mixed replyto priority field TLS to googlemail (use TLS) Notes if problems ----------------- 1. Attachment adding call had dirname() added round path. 2. There are legacy and new methods for generating a multi-part body (HTML + plain text). Only the new method handles inline images. - Currently uses the new method (which is part of phpmailer) General notes ------------- 1. Can specify a comma-separated list of smtp servers - presumably all require the same login credentials 2. qmail can be used (if available) by selecting sendmail, and setting the sendmail path to that for qmail instead 3. phpmailer does trim() on passed parameters where needed - so we don't need to. 4. phpmailer has its own list of MIME types. 5. Attachments - note method available for passing string attachments - AddStringAttachment($string,$filename,$encoding,$type) 6. Several email address-related methods can accept two comma-separated strings, one for addresses and one for related names 7. Its possible to send a text-only email by passing an array of parameters including 'send_html' = FALSE 8. For bulk emailing, must call the 'allSent()' method when complete to ensure SMTP mailer is properly closed. 9. For sending through googlemail (and presumably gmail), use TLS 10. Note that the 'add_html_header' option adds only the DOCTYPE bits - not the
.... section
Possible Enhancements
---------------------
1. Support other fields:
ContentType
Encoding - ???. Defaults to 8-bit
Preferences used:
$pref['mailer'] - connection type - SMTP, sendmail etc
$pref['mail_options'] - NEW - general mailing options
textonly - if true, defaults to plain text emails
hostname=text - used in Message ID and received headers, and default Helo string. (Otherwise server-related default used)
$pref['mail_log_options'] - NEW. Logging options (also used in mailout_process). Comma-separated list of values
1 - logenable - numeric value 0..3 controlling logging to a text file
2 - add_email - if '1', the detail of the email is logged as well
$pref['smtp_server'] |
$pref['smtp_username'] | Server details. USed for POP3 server if POP before SMTP authorisation
$pref['smtp_password'] |
$pref['smtp_keepalive'] - deprecated in favour of option - flag
$pref['smtp_pop3auth'] - deprecated in favour of option - POP before SMTP authorisation flag
$pref['smtp_options'] - NEW - comma separated list:
keepalive - If active, bulk email send keeps the SMTP connection open, closing it every $pref['mail_pause'] emails
useVERP - formats return path to facilitate bounce processing
secure=[TLS|SSL] - enable secure authorisation by TLS or SSL
pop3auth - enable POP before SMTP authorisation
helo=text - Alternative Helo string
$pref['sendmail'] - path to sendmail
$pref['mail_pause'] - number of emails to send before pause
$pref['mail_pausetime'] - time to pause
$pref['mail_bounce_email'] - 'reply to' address
$pref['mail_bounce_pop3']
$pref['mail_bounce_user']
$pref['mail_bounce_pass']
Usage
=====
1. Create new object of the correct class
2. Set up everything - to/from/email etc
3. Call create_connection()
4. Call send_mail()
+----------------------------------------------------------------------------+
*/
if (!defined('e107_INIT')) { exit; }
//define('MAIL_DEBUG',TRUE);
//define('LOG_CALLER', TRUE);
require_once(e_HANDLER.'phpmailer/class.phpmailer.php');
// Directory for log (if enabled)
define('MAIL_LOG_PATH',e_LOG);
class e107Email extends PHPMailer
{
private $general_opts = array();
private $logEnable = 0; // 0 = log disabled, 1 = 'dry run' (debug and log, no send). 2 = 'log all' (send, and log result)
private $logHandle = FALSE; // Save handle of log file if opened
private $localUseVerp = FALSE; // Use our own variable - PHPMailer one doesn't work with all mailers
private $save_bouncepath = ''; // Used with VERP
private $add_email = 0; // 1 includes email detail in log (if logging enabled, of course)
private $allow_html = 1; // Flag for HTML conversion - '1' = default, FALSE = disable, TRUE = force.
private $add_HTML_header = FALSE; // If TRUE, inserts a standard HTML header at the front of the HTML part of the email (set FALSE for BC)
private $SendCount = 0; // Keep track of how many emails sent since last SMTP open/connect (used for SMTP KeepAlive)
private $TotalSent = 0; // Info might be of interest
private $TotalErrors = 0; // Count errors in sending emails
private $pause_amount = 10; // Number of emails to send before pausing/resetting (or closing if SMTPkeepAlive set)
private $pause_time = 1; // Time to pause after sending a block of emails
public $legacyBody = false; // TRUE enables legacy conversion of plain text body to HTML in HTML emails
private $debug = false; // echos various debug info when set to true.
/**
* Constructor sets up all the global options, and sensible defaults - it should be the only place the prefs are accessed
*
* @var array $overrides - array of values which override mail-related prefs. Key is the same as the corresponding pref.
* - second batch of keys can preset values configurable through the arraySet() method
* @return none
*/
public function __construct($overrides = FALSE)
{
parent::__construct(FALSE); // Parent constructor - no exceptions for now
$e107 = e107::getInstance();
$pref = e107::pref('core');
$tp = e107::getParser();
if(defined('MAIL_DEBUG'))
{
$this->debug = true;
}
$this->CharSet = 'utf-8';
$this->SetLanguage(CORE_LC);
if (($overrides === FALSE) || !is_array($overrides))
{
$overrides = array();
}
foreach (array('mailer', 'smtp_server', 'smtp_username', 'smtp_password', 'sendmail', 'siteadminemail', 'siteadmin') as $k)
{
if (!isset($overrides[$k])) $overrides[$k] = $pref[$k];
}
$this->pause_amount = varset($pref['mail_pause'], 10);
$this->pause_time = varset($pref['mail_pausetime'], 1);
$this->allow_html = varset($pref['mail_sendstyle'],'textonly') == 'texthtml' ? true : 1;
if (varsettrue($pref['mail_options'])) $this->general_opts = explode(',',$pref['mail_options'],'');
if ($this->debug) echo 'Mail_options: '.$pref['mail_options'].' Count: '.count($this->general_opts).'
';
foreach ($this->general_opts as $k => $v)
{
$v = trim($v);
$this->general_opts[$k] = $v;
if (strpos($v,'hostname') === 0)
{
list(,$this->HostName) = explode('=',$v);
if ($this->debug) echo "Host name set to: {$this->HostName}
";
}
}
list($this->logEnable,$this->add_email) = explode(',',varset($pref['mail_log_options'],'0,0'));
switch ($overrides['mailer'])
{
case 'smtp' :
$smtp_options = array();
$temp_opts = explode(',',varset($pref['smtp_options'],''));
if (varsettrue($overrides ['smtp_pop3auth'])) $temp_opts[] = 'pop3auth'; // Legacy option - remove later
if (varsettrue($pref['smtp_keepalive'])) $temp_opts[] = 'keepalive'; // Legacy option - remove later
foreach ($temp_opts as $k=>$v)
{
if (strpos($v,'=') !== FALSE)
{
list($v,$k) = explode('=',$v,2);
$smtp_options[trim($v)] = trim($k);
}
else
{
$smtp_options[trim($v)] = TRUE; // Simple on/off option
}
}
unset($temp_opts);
$this->IsSMTP(); // Enable SMTP functions
if (varsettrue($smtp_options['helo'])) $this->Helo = $smtp_options['helo'];
if (isset($smtp_options['pop3auth'])) // We've made sure this is set
{ // Need POP-before-SMTP authorisation
require_once(e_HANDLER.'phpmailer/class.pop3.php');
$pop = new POP3();
$pop->Authorise($overrides['smtp_server'], 110, 30, $overrides['smtp_username'], $overrides['smtp_password'], 1);
}
$this->Mailer = 'smtp';
$this->localUseVerp = isset($smtp_options['useVERP']);
if (isset($smtp_options['secure']))
{
switch ($smtp_options['secure'])
{
case 'TLS' :
$this->SMTPSecure = 'tls';
$this->Port = 465; // Can also use port 587, and maybe even 25
break;
case 'SSL' :
$this->SMTPSecure = 'ssl';
$this->Port = 465;
break;
default :
if ($this->debug) echo "Invalid option: {$smtp_options['secure']}
";
}
}
$this->SMTPKeepAlive = varset($smtp_options['keepalive'],FALSE); // ***** Control this
$this->Host = $overrides['smtp_server'];
if($overrides['smtp_username'] && $overrides['smtp_password'])
{
$this->SMTPAuth = (!isset($smtp_options['pop3auth']));
$this->Username = $overrides['smtp_username'];
$this->Password = $overrides['smtp_password'];
}
break;
case 'sendmail' :
$this->Mailer = 'sendmail';
$this->Sendmail = ($overrides['sendmail']) ? $overrides['sendmail'] : '/usr/sbin/sendmail -t -i -r '.varsettrue($pref['replyto_email'],$overrides['siteadminemail']);
break;
case 'php' :
$this->Mailer = 'mail';
break;
}
if (varsettrue($pref['mail_bounce_email'])) $this->Sender = $pref['mail_bounce_email'];
$this->FromName = $tp->toHTML(varsettrue($pref['replyto_name'],$overrides['siteadmin']),'','RAWTEXT');
$this->From = $tp->toHTML(varsettrue($pref['replyto_email'],$overrides['siteadminemail']),'','RAWTEXT');
$this->WordWrap = 76; // Set a sensible default
// Now look for any overrides - slightly cumbersome way of doing it, but does give control over what can be set from here
// Options are those accepted by the arraySet() method.
foreach (array('SMTPDebug', 'email_subject', 'email_sender_email', 'email_sender_name', 'email_replyto', 'send_html',
'add_html_header', 'email_attach', 'email_copy_to', 'email_bcopy_to',
'bouncepath', 'returnreceipt', 'email_inline_images', 'email_priority', 'extra_header', 'wordwrap', 'split') as $opt)
{
if (isset($overrides[$opt]))
{
$this->arraySet(array($opt => $overrides[$opt]));
}
}
}
/**
* Set log level
* @param int $level 0|1|2
* @param int $emailDetails 0|1
* @return e107Email
*/
public function logEnable($level, $emailDetails = null)
{
$this->logEnable = (int) $level;
if(null !== $this->add_email)
{
$this->add_email = (int) $emailDetails;
}
return $this;
}
/**
* Disable log completely
* @return e107Email
*/
public function logDisable()
{
$this->logEnable = 0;
$this->add_email = 0;
return $this;
}
/**
* Format 'to' address and name
*
* @param string $email - email address of recipient
* @param string $to - name of recipient
* @return string in form: Fred Bloggs
";
if ($add_HTML_header)
{
$message = "\n
\n".$message;
}
if ($this->legacyBody && !preg_match('/<(font|br|a|img|b)/i', $message)) // Assume html if it includes one of these tags
{ // Otherwise assume its a plain text message which needs some conversion to render in HTML
if($this->debug == true)
{
echo 'Running legacyBody mode
';
}
$message = htmlspecialchars($message,ENT_QUOTES,$this->CharSet);
$message = preg_replace('%(http|ftp|https)(://\S+)%', '\1\2', $message);
$message = preg_replace('/([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)/i', '\\1\\2', $message);
$message = preg_replace('/([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})/i', '\\1', $message);
$message = str_replace("\r\n","\n",$message); // Handle alternative newline characters
$message = str_replace("\n\r","\n",$message); // Handle alternative newline characters
$message = str_replace("\r","\n",$message); // Handle alternative newline characters
$message = str_replace("\n", "
\n", $message);
}
$this->MsgHTML($message); // Theoretically this should do everything, including handling of inline images.
}
else
{ // generate the plain text as the sole part of the email
if ($this->debug) echo "Generating plain text email
";
if (strpos($message,'') !== FALSE)
{
$text = strstr($message,'');
}
else
{
$text = $message;
}
$text = str_replace('
', "\n", $text);
$text = strip_tags(str_replace('
', "\n", $text));
// TODO: strip bbcodes here
$this->Body = $text;
$this->AltBody = ''; // Single part email
}
}
/**
* Add attachments to the current email - either a single one as a string, or an array
* Always sent in base64 encoding
*
* @param string|array $attachments - single attachment name as a string, or any number as an array
*
* @return none
*/
public function attach($attachments)
{
if (!$attachments) return;
if (!is_array($attachments)) $attachments = array($attachments);
foreach($attachments as $attach)
{
$tempName = basename($attach);
if(is_readable($attach) && $tempName)
{ // First parameter is complete path + filename; second parameter is 'name' of file to send
$ext = pathinfo($attach, PATHINFO_EXTENSION);
$this->AddAttachment($attach, $tempName,'base64',$this->_mime_types($ext));
}
}
}
/**
* Add inline images (should usually be handled automatically by PHPMailer)
*
* @param string $inline - comma separated list of file names
*/
function addInlineImages($inline)
{
if(!$inline) return;
$tmp = explode(',',$inline);
foreach($tmp as $inline_img)
{
if(is_readable($inline_img) && !is_dir($inline_img))
{
$ext = pathinfo($inline_img, PATHINFO_EXTENSION);
$this->AddEmbeddedImage($inline_img, md5($inline_img), basename($inline_img),'base64',$this->_mime_types($ext));
}
}
}
/**
* Sets one or more parameters from an array. See @see{sendEmail()} for list of parameters
* Where parameter not present, doesn't change it - so can repeatedly call this function for bulk mailing, or to build up the list
* (Note that there is no requirement to use this method for everything; parameters can be set by mixing this method with individual setting)
*
* @param array $eml - list of parameters to set/change. Key is parameter name. @see{sendEmail()} for list of parameters
*
* @return int zero if no errors detected
*/
public function arraySet($eml)
{
if(vartrue($eml['template'])) // @see e107_core/templates/email_template.php
{
$tp = e107::getParser();
if($tmpl = e107::getCoreTemplate('email', $eml['template'], true, true)) // $EMAIL_TEMPLATE['default']
{
// $filter = array("\n", "\t");
// $tmpl['header'] = str_replace($filter,'', $tmpl['header']);
// $tmpl['footer'] = str_replace($filter,'', $tmpl['footer']);
$eml['shortcodes']['BODY'] = $eml['email_body'];
$eml['shortcodes']['SUBJECT'] = $eml['email_subject'];
$emailBody = $tmpl['header']. $tmpl['body'] . $tmpl['footer'];
$eml['email_body'] = $tp->parseTemplate($emailBody, true, varset($eml['shortcodes'],null));
// $eml['email_body'] = ($tp->toEmail($tmpl['header']). str_replace('{BODY}', $eml['email_body'], $tmpl['body']). $tp->toEmail($tmpl['footer']));
if($this->debug)
{
print_a($tmpl);
}
unset($eml['add_html_header']); // disable other headers when template is used.
$this->Subject = $tp->parseTemplate($tmpl['subject'], true, varset($eml['shortcodes'],null));
}
}
else
{
if (vartrue($eml['email_subject'])) $this->Subject = $tp->parseTemplate($eml['email_subject'], true, varset($eml['shortcodes'],null));
}
if (isset($eml['SMTPDebug'])) $this->SMTPDebug = $eml['SMTPDebug']; // 'FALSE' is a valid value!
if (vartrue($eml['email_sender_email'])) $this->From = $eml['email_sender_email'];
if (vartrue($eml['email_sender_name'])) $this->FromName = $eml['email_sender_name'];
if (vartrue($eml['email_replyto'])) $this->AddAddressList('replyto',$eml['email_replyto'],vartrue($eml['email_replytonames'],''));
if (isset($eml['send_html'])) $this->allow_html = $eml['send_html']; // 'FALSE' is a valid value!
if (isset($eml['add_html_header'])) $this->add_HTML_header = $eml['add_html_header']; // 'FALSE' is a valid value!
if (vartrue($eml['email_body'])) $this->makeBody($eml['email_body'], $this->allow_html, $this->add_HTML_header);
if (vartrue($eml['email_attach'])) $this->attach($eml['email_attach']);
if (vartrue($eml['email_copy_to'])) $this->AddAddressList('cc',$eml['email_copy_to'],vartrue($eml['email_cc_names'],''));
if (vartrue($eml['email_bcopy_to'])) $this->AddAddressList('bcc',$eml['email_bcopy_to'],vartrue($eml['email_bcc_names'],''));
if (vartrue($eml['bouncepath']))
{
$this->Sender = $eml['bouncepath']; // Bounce path
$this->save_bouncepath = $eml['bouncepath']; // Bounce path
}
if($this->debug)
{
print_a($eml);
}
if (vartrue($eml['returnreceipt'])) $this->ConfirmReadingTo = $eml['returnreceipt'];
if (vartrue($eml['email_inline_images'])) $this->addInlineImages($eml['email_inline_images']);
if (vartrue($eml['email_priority'])) $this->Priority = $eml['email_priority'];
if (vartrue($eml['e107_header'])) $this->AddCustomHeader("X-e107-id: {$eml['e107_header']}");
if (vartrue($eml['extra_header']))
{
if (is_array($eml['extra_header']))
{
foreach($eml['extra_header'] as $eh)
{
$this->addCustomHeader($eh);
}
}
else
{
$this->addCustomHeader($eml['extra_header']);
}
}
if (varset($eml['wordwrap'])) $this->WordWrap = $eml['wordwrap'];
if (vartrue($eml['split'])) $this->SingleTo = ($eml['split'] != FALSE);
return 0; // No error
}
/**
Send an email where the bulk of the data is passed in an array. Returns 0 on success.
(Even if the array is null, because everything previously set up, this is the preferred entry point)
Where parameter not present in the array, doesn't get changed - useful for bulk mailing
If doing bulk mailing with repetitive calls, set $bulkmail parameter true, and must call allSent() when completed
Some of these parameters have been made compatible with the array calculated by render_email() in signup.php
Possible array parameters:
$eml['email_subject']
$eml['email_sender_email'] - 'From' email address
$eml['email_sender_name'] - 'From' name
$eml['email_replyto'] - Optional 'reply to' field
$eml['email_replytonames'] - Name(s) corresponding to 'reply to' field - only used if 'replyto' used
$eml['send_html'] - if TRUE, includes HTML part in messages (only those added after this flag)
$eml['add_html_header'] - if TRUE, adds the 2-line DOCTYPE declaration to the front of the HTML part (but doesn't add ...)
$eml['email_body'] - message body. May be HTML or text. Added according to the current state of the HTML enable flag
$eml['email_attach'] - string if one file, array of filenames if one or more.
$eml['email_copy_to'] - comma-separated list of cc addresses.
$eml['email_cc_names'] - comma-separated list of cc names. Optional, used only if $eml['email_copy_to'] specified
$eml['email_bcopy_to'] - comma-separated list
$eml['email_bcc_names'] - comma-separated list of bcc names. Optional, used only if $eml['email_copy_to'] specified
$eml['bouncepath'] - Sender field (used for bounces)
$eml['returnreceipt'] - email address for notification of receipt (reading)
$eml['email_inline_images'] - array of files for inline images
$eml['priority'] - Email priority (1 = High, 3 = Normal, 5 = low)
$eml['e107_header'] - Adds specific 'X-e107-id:' header
$eml['extra_header'] - additional headers (format is name: value
$eml['wordwrap'] - Set wordwrap value
$eml['split'] - If true, sends an individual email to each recipient
$eml['template'] - template to use. 'default'
* @param string $send_to - recipient email address
* @param string $to_name - recipient name
* @param array $eml - optional array of additional parameters (see above)
* @param boolean $bulkmail - set TRUE if this email is one of a bulk send; FALSE if an isolated email
*
* @return boolean|string - TRUE if success, error message if failure
*/
public function sendEmail($send_to, $to_name, $eml = '', $bulkmail = FALSE)
{
if (count($eml))
{ // Set parameters from list
$ret = $this->arraySet($eml);
if ($ret) return $ret;
}
if ($bulkmail && $this->localUseVerp && $this->save_bouncepath && (strpos($this->save_bouncepath,'@') !== FALSE))
{
// Format where sender is owner@origin, target is user@domain is: owner+user=domain@origin
list($our_sender,$our_domain) = explode('@', $this->save_bouncepath,2);
if ($our_sender && $our_domain)
{
$this->Sender = $our_sender.'+'.str_replace($send_to,'@','=').'@'.$our_domain;
}
}
$this->AddAddressList('to',$send_to,$to_name);
$this->openLog(); // Delay log open until now, so all parameters set up
$result = TRUE; // Temporary 'success' flag
$this->SendCount++;
if (($this->logEnable == 0) || ($this->logEnable == 2))
{
$result = $this->Send(); // Actually send email
if (!$bulkmail && !$this->SMTPKeepAlive && ($this->Mailer == 'smtp')) $this->SmtpClose();
}
else
{ // Debug
$result = TRUE;
//print_a($this);
if (($this->logEnable == 3) && (($this->SendCount % 7) == 4)) $result = FALSE; // Fail one email in 7 for testing
}
$this->TotalSent++;
if (($this->pause_amount > 0) && ($this->SendCount >= $this->pause_amount))
{
if ($this->SMTPKeepAlive && ($this->Mailer == 'smtp')) $this->SmtpClose();
sleep($this->pause_time);
$this->SendCount = 0;
}
$this->logLine("Send to {$to_name} at {$send_to} Mail-ID={$this->MessageID} - ".($result ? 'Success' : 'Fail'));
$this->ClearAddresses(); // In case we send another email
$this->ClearCustomHeaders();
if ($result)
{
$this->closeLog();
return TRUE;
}
$this->logLine('Error info: '.$this->ErrorInfo);
// Error sending email
$e107 = e107::getInstance();
$e107->admin_log->e_log_event(3,debug_backtrace(),"MAIL","Send Failed",$this->ErrorInfo,FALSE,LOG_TO_ROLLING);
$this->TotalErrors++;
$this->closeLog();
return $this->ErrorInfo;
}
/**
* Called after a bulk mailing completed, to tidy up nicely
*
* @return none
*/
public function allSent()
{
if ($this->SMTPKeepAlive && ($this->Mailer == 'smtp') && ($this->SendCount > 0))
{
$this->SmtpClose();
$this->SendCount = 0;
}
}
/**
* Evaluates the message and returns modifications for inline images and backgrounds
* Also creates an alternative plain text part (unless $this->AltBody already non-empty)
* Modification of standard PHPMailer function (which it overrides)
* @access public
*
* @param string $message - the mail body to send
* @basedir string - optional 'root part' of paths specified in email - prepended as necessary
*
* @return string none (message saved ready to send)
*/
public function MsgHTML($message, $basedir = '')
{
preg_match_all("/(src|background)=([\"\'])(.*)\\2/Ui", $message, $images); // Modified to accept single quotes as well
if(isset($images[3]))
{
if($this->debug)
{
echo "Detected Image Paths
";
print_a($images[3]);
}
$tp = e107::getParser();
foreach($images[3] as $i => $url)
{
// do not change urls for absolute images (thanks to corvuscorax)
if (!preg_match('#^[A-z]+://#',$url))
{
$url = $tp->replaceConstants($url);
$delim = $images[2][$i]; // Will be single or double quote
$filename = basename($url);
$directory = dirname($url);
if ($directory == '.') $directory='';
if (strpos($directory, e_HTTP) === 0)
{
$directory = substr(SERVERBASE, 0, -1).$directory; // Convert to absolute server reference
$basedir = '';
}
if ($this->debug)
{
echo "
CID file {$filename} in {$directory}. Base = ".SERVERBASE."< BaseDir = {$basedir}
";
}
$cid = 'cid:' . md5($filename);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$mimeType = self::_mime_types($ext);
if ( (strlen($basedir) > 1) && (substr($basedir,-1) != '/') && (substr($basedir,-1) != '\\')) { $basedir .= '/'; }
if ( strlen($directory) > 1 && substr($directory,-1) != '/' && substr($directory,-1) != '\\') { $directory .= '/'; }
//echo "Add image: {$basedir}|{$directory}|{$filename}
";
if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) )
{
// $images[1][$i] contains 'src' or 'background'
$message = preg_replace("/".$images[1][$i]."=".$delim.preg_quote($images[3][$i], '/').$delim."/Ui", $images[1][$i]."=".$delim.$cid.$delim, $message);
}
else
{
if ($this->debug)
{
echo "Add embedded image {$url} failed
";
echo "
basedir=".$basedir;
echo "
dir=".$directory;
echo "
file=".$filename;
echo "
";
}
}
}
elseif($this->debug)
{
echo "
Absolute Image: ".$url;
}
}
}
$this->IsHTML(true);
$this->Body = $message;
//print_a($message);
$textMsg = str_replace(array('
', '
'), "\n", $message); // Modified to make sure newlines carried through
$textMsg = preg_replace('#^.*?