You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
635 lines
24 KiB
635 lines
24 KiB
<?php
|
|
/*********************************************************************
|
|
class.mailer.php
|
|
|
|
osTicket mailer
|
|
|
|
It's mainly PEAR MAIL wrapper for now (more improvements planned).
|
|
|
|
Peter Rotich <peter@osticket.com>
|
|
Copyright (c) 2006-2013 osTicket
|
|
http://www.osticket.com
|
|
|
|
Released under the GNU General Public License WITHOUT ANY WARRANTY.
|
|
See LICENSE.TXT for details.
|
|
|
|
vim: expandtab sw=4 ts=4 sts=4:
|
|
**********************************************************************/
|
|
|
|
include_once(INCLUDE_DIR.'class.email.php');
|
|
require_once(INCLUDE_DIR.'html2text.php');
|
|
|
|
class Mailer {
|
|
|
|
var $email;
|
|
|
|
var $ht = array();
|
|
var $attachments = array();
|
|
var $options = array();
|
|
|
|
var $smtp = array();
|
|
var $eol="\n";
|
|
|
|
function __construct($email=null, array $options=array()) {
|
|
global $cfg;
|
|
|
|
if(is_object($email) && $email->isSMTPEnabled() && ($info=$email->getSMTPInfo())) { //is SMTP enabled for the current email?
|
|
$this->smtp = $info;
|
|
} elseif($cfg && ($e=$cfg->getDefaultSMTPEmail()) && $e->isSMTPEnabled()) { //What about global SMTP setting?
|
|
$this->smtp = $e->getSMTPInfo();
|
|
if(!$e->allowSpoofing() || !$email)
|
|
$email = $e;
|
|
} elseif(!$email && $cfg && ($e=$cfg->getDefaultEmail())) {
|
|
if($e->isSMTPEnabled() && ($info=$e->getSMTPInfo()))
|
|
$this->smtp = $info;
|
|
$email = $e;
|
|
}
|
|
|
|
$this->email = $email;
|
|
$this->attachments = array();
|
|
$this->options = $options;
|
|
}
|
|
|
|
function getEOL() {
|
|
return $this->eol;
|
|
}
|
|
|
|
function getEmail() {
|
|
return $this->email;
|
|
}
|
|
|
|
function getSMTPInfo() {
|
|
return $this->smtp;
|
|
}
|
|
/* FROM Address */
|
|
function setFromAddress($from) {
|
|
$this->ht['from'] = $from;
|
|
}
|
|
|
|
function getFromAddress($options=array()) {
|
|
|
|
if (!$this->ht['from'] && ($email=$this->getEmail())) {
|
|
if (($name = $options['from_name'] ?: $email->getName()))
|
|
$this->ht['from'] =sprintf('"%s" <%s>', $name, $email->getEmail());
|
|
else
|
|
$this->ht['from'] =sprintf('<%s>', $email->getEmail());
|
|
}
|
|
|
|
return $this->ht['from'];
|
|
}
|
|
|
|
/* attachments */
|
|
function getAttachments() {
|
|
return $this->attachments;
|
|
}
|
|
|
|
function addAttachment(Attachment $attachment) {
|
|
// XXX: This looks too assuming; however, the attachment processor
|
|
// in the ::send() method seems hard coded to expect this format
|
|
$this->attachments[] = $attachment;
|
|
}
|
|
|
|
function addAttachmentFile(AttachmentFile $file) {
|
|
// XXX: This looks too assuming; however, the attachment processor
|
|
// in the ::send() method seems hard coded to expect this format
|
|
$this->attachments[] = $file;
|
|
}
|
|
|
|
function addFileObject(FileObject $file) {
|
|
$this->attachments[] = $file;
|
|
}
|
|
|
|
function addAttachments($attachments) {
|
|
foreach ($attachments as $a) {
|
|
if ($a instanceof Attachment)
|
|
$this->addAttachment($a);
|
|
elseif ($a instanceof AttachmentFile)
|
|
$this->addAttachmentFile($a);
|
|
elseif ($a instanceof FileObject)
|
|
$this->addFileObject($a);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* getMessageId
|
|
*
|
|
* Generates a unique message ID for an outbound message. Optionally,
|
|
* the recipient can be used to create a tag for the message ID where
|
|
* the user-id and thread-entry-id are encoded in the message-id so
|
|
* the message can be threaded if it is replied to without any other
|
|
* indicator of the thread to which it belongs. This tag is signed with
|
|
* the secret-salt of the installation to guard against false positives.
|
|
*
|
|
* Parameters:
|
|
* $recipient - (EmailContact|null) recipient of the message. The ID of
|
|
* the recipient is placed in the message id TAG section so it can
|
|
* be recovered if the email replied to directly by the end user.
|
|
* $options - (array) - options passed to ::send(). If it includes a
|
|
* 'thread' element, the threadId will be recorded in the TAG
|
|
*
|
|
* Returns:
|
|
* (string) - email message id, without leading and trailing <> chars.
|
|
* See the Format below for the structure.
|
|
*
|
|
* Format:
|
|
* VA-B-C, with dash separators and A-C explained below:
|
|
*
|
|
* V: Version code of the generated Message-Id
|
|
* A: Predictable random code — used for loop detection (sysid)
|
|
* B: Random data for unique identifier (rand)
|
|
* C: TAG: Base64(Pack(userid, entryId, threadId, type, Signature)),
|
|
* '=' chars discarded
|
|
* where Signature is:
|
|
* Signed Tag value, last 5 chars from
|
|
* HMAC(sha1, Tag + rand + sysid, SECRET_SALT),
|
|
* where Tag is:
|
|
* pack(userId, entryId, threadId, type)
|
|
*/
|
|
function getMessageId($recipient, $options=array(), $version='B') {
|
|
$tag = '';
|
|
$rand = Misc::randCode(5,
|
|
// RFC822 specifies the LHS of the addr-spec can have any char
|
|
// except the specials — ()<>@,;:\".[], dash is reserved as the
|
|
// section separator, and + is reserved for historical reasons
|
|
'abcdefghiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_=');
|
|
$sig = $this->getEmail()?$this->getEmail()->getEmail():'@osTicketMailer';
|
|
$sysid = static::getSystemMessageIdCode();
|
|
// Create a tag for the outbound email
|
|
$entry = (isset($options['thread']) && $options['thread'] instanceof ThreadEntry)
|
|
? $options['thread'] : false;
|
|
$thread = $entry ? $entry->getThread()
|
|
: (isset($options['thread']) && $options['thread'] instanceof Thread
|
|
? $options['thread'] : false);
|
|
|
|
switch (true) {
|
|
case $recipient instanceof Staff:
|
|
$utype = 'S';
|
|
break;
|
|
case $recipient instanceof TicketOwner:
|
|
$utype = 'U';
|
|
break;
|
|
case $recipient instanceof Collaborator:
|
|
$utype = 'C';
|
|
break;
|
|
case $recipient instanceof MailingList:
|
|
$utype = 'M';
|
|
break;
|
|
default:
|
|
$utype = $options['utype'] ?: is_array($recipient) ? 'M' : '?';
|
|
}
|
|
|
|
|
|
$tag = pack('VVVa',
|
|
$recipient instanceof EmailContact ? $recipient->getUserId() : 0,
|
|
$entry ? $entry->getId() : 0,
|
|
$thread ? $thread->getId() : 0,
|
|
$utype ?: '?'
|
|
);
|
|
// Sign the tag with the system secret salt
|
|
$tag .= substr(hash_hmac('sha1', $tag.$rand.$sysid, SECRET_SALT, true), -5);
|
|
$tag = str_replace('=','',base64_encode($tag));
|
|
return sprintf('B%s-%s-%s-%s',
|
|
$sysid, $rand, $tag, $sig);
|
|
}
|
|
|
|
/**
|
|
* decodeMessageId
|
|
*
|
|
* Decodes a message-id generated by osTicket using the ::getMessageId()
|
|
* method of this class. This will digest the received message-id token
|
|
* and return an array with some information about it.
|
|
*
|
|
* Parameters:
|
|
* $mid - (string) message-id from an email Message-Id, In-Reply-To, and
|
|
* References header.
|
|
*
|
|
* Returns:
|
|
* (array) of information containing all or some of the following keys
|
|
* 'loopback' - (bool) true or false if the message originated by
|
|
* this osTicket installation.
|
|
* 'version' - (string|FALSE) version code of the message id
|
|
* 'code' - (string) unique but predictable help desk message-id
|
|
* 'id' - (string) random characters serving as the unique id
|
|
* 'entryId' - (int) thread-entry-id from which the message originated
|
|
* 'threadId' - (int) thread-id from which the message originated
|
|
* 'staffId' - (int|null) staff the email was originally sent to
|
|
* 'userId' - (int|null) user the email was originally sent to
|
|
* 'userClass' - (string) class of user the email was sent to
|
|
* 'U' - TicketOwner
|
|
* 'S' - Staff
|
|
* 'C' - Collborator
|
|
* 'M' - Multiple
|
|
* '?' - Something else
|
|
*/
|
|
static function decodeMessageId($mid) {
|
|
// Drop <> tokens
|
|
$mid = trim($mid, '<> ');
|
|
// Drop email domain on rhs
|
|
list($lhs, $sig) = explode('@', $mid, 2);
|
|
// LHS should be tokenized by '-'
|
|
$parts = explode('-', $lhs);
|
|
|
|
$rv = array('loopback' => false, 'version' => false);
|
|
|
|
// There should be at least two tokens if the message was sent by
|
|
// this system. Otherwise, there's nothing to be detected
|
|
if (count($parts) < 2)
|
|
return $rv;
|
|
|
|
$self = get_called_class();
|
|
$decoders = array(
|
|
'A' => function($id, $tag) use ($sig) {
|
|
// Old format was VA-B-C-D@sig, where C was the packed tag and D
|
|
// was blank
|
|
$format = 'Vuid/VentryId/auserClass';
|
|
$chksig = substr(hash_hmac('sha1', $tag.$id, SECRET_SALT), -10);
|
|
if ($tag && $sig == $chksig && ($tag = base64_decode($tag))) {
|
|
// Find user and ticket id
|
|
return unpack($format, $tag);
|
|
}
|
|
return false;
|
|
},
|
|
'B' => function($id, $tag) use ($self) {
|
|
$format = 'Vuid/VentryId/VthreadId/auserClass/a*sig';
|
|
if ($tag && ($tag = base64_decode($tag))) {
|
|
if (!($info = @unpack($format, $tag)) || !isset($info['sig']))
|
|
return false;
|
|
$sysid = $self::getSystemMessageIdCode();
|
|
$shorttag = substr($tag, 0, 13);
|
|
$chksig = substr(hash_hmac('sha1', $shorttag.$id.$sysid,
|
|
SECRET_SALT, true), -5);
|
|
if ($chksig == $info['sig']) {
|
|
return $info;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
);
|
|
|
|
// Detect the MessageId version, which should be the first char
|
|
$rv['version'] = @$parts[0][0];
|
|
if (!isset($decoders[$rv['version']]))
|
|
// invalid version code
|
|
return null;
|
|
|
|
// Drop the leading version code
|
|
list($rv['code'], $rv['id'], $tag) = $parts;
|
|
$rv['code'] = substr($rv['code'], 1);
|
|
|
|
// Verify tag signature and unpack the tag
|
|
$info = $decoders[$rv['version']]($rv['id'], $tag);
|
|
if ($info === false)
|
|
return $rv;
|
|
|
|
$rv += $info;
|
|
|
|
// Attempt to make the user-id more specific
|
|
$classes = array(
|
|
'S' => 'staffId', 'U' => 'userId', 'C' => 'userId',
|
|
);
|
|
if (isset($classes[$rv['userClass']]))
|
|
$rv[$classes[$rv['userClass']]] = $rv['uid'];
|
|
|
|
// Round-trip detection - the first section is the local
|
|
// system's message-id code
|
|
$rv['loopback'] = (0 === strcmp($rv['code'],
|
|
static::getSystemMessageIdCode()));
|
|
|
|
return $rv;
|
|
}
|
|
|
|
static function getSystemMessageIdCode() {
|
|
return substr(str_replace('+', '=',
|
|
base64_encode(md5('mail'.SECRET_SALT, true))),
|
|
0, 6);
|
|
}
|
|
|
|
function send($recipients, $subject, $message, $options=null) {
|
|
global $ost, $cfg;
|
|
|
|
//Get the goodies
|
|
require_once (PEAR_DIR.'Mail.php'); // PEAR Mail package
|
|
require_once (PEAR_DIR.'Mail/mime.php'); // PEAR Mail_Mime packge
|
|
|
|
$messageId = $this->getMessageId($recipients, $options);
|
|
$subject = preg_replace("/(\r\n|\r|\n)/s",'', trim($subject));
|
|
$headers = array (
|
|
'From' => $this->getFromAddress($options),
|
|
'Subject' => $subject,
|
|
'Date'=> date('D, d M Y H:i:s O'),
|
|
'Message-ID' => "<{$messageId}>",
|
|
'X-Mailer' =>'osTicket Mailer',
|
|
);
|
|
|
|
// Add in the options passed to the constructor
|
|
$options = ($options ?: array()) + $this->options;
|
|
|
|
// Message Id Token
|
|
$mid_token = '';
|
|
// Check if the email is threadable
|
|
if (isset($options['thread'])
|
|
&& $options['thread'] instanceof ThreadEntry
|
|
&& ($thread = $options['thread']->getThread())) {
|
|
|
|
// Add email in-reply-to references if not set
|
|
if (!isset($options['inreplyto'])) {
|
|
|
|
$entry = null;
|
|
switch (true) {
|
|
case $recipients instanceof MailingList:
|
|
$entry = $thread->getLastEmailMessage();
|
|
break;
|
|
case $recipients instanceof TicketOwner:
|
|
case $recipients instanceof Collaborator:
|
|
$entry = $thread->getLastEmailMessage(array(
|
|
'user_id' => $recipients->getUserId()));
|
|
break;
|
|
case $recipients instanceof Staff:
|
|
//XXX: is it necessary ??
|
|
break;
|
|
}
|
|
|
|
if ($entry && ($mid=$entry->getEmailMessageId())) {
|
|
$options['inreplyto'] = $mid;
|
|
$options['references'] = $entry->getEmailReferences();
|
|
}
|
|
}
|
|
|
|
// Embedded message id token
|
|
$mid_token = $messageId;
|
|
// Set Reply-Tag
|
|
if (!isset($options['reply-tag'])) {
|
|
if ($cfg && $cfg->stripQuotedReply())
|
|
$options['reply-tag'] = $cfg->getReplySeparator() . '<br/><br/>';
|
|
else
|
|
$options['reply-tag'] = '';
|
|
} elseif ($options['reply-tag'] === false) {
|
|
$options['reply-tag'] = '';
|
|
}
|
|
}
|
|
|
|
// Return-Path
|
|
if (isset($options['nobounce']) && $options['nobounce'])
|
|
$headers['Return-Path'] = '<>';
|
|
elseif ($this->getEmail() instanceof Email)
|
|
$headers['Return-Path'] = $this->getEmail()->getEmail();
|
|
|
|
// Bulk.
|
|
if (isset($options['bulk']) && $options['bulk'])
|
|
$headers+= array('Precedence' => 'bulk');
|
|
|
|
// Auto-reply - mark as autoreply and supress all auto-replies
|
|
if (isset($options['autoreply']) && $options['autoreply']) {
|
|
$headers+= array(
|
|
'Precedence' => 'auto_reply',
|
|
'X-Autoreply' => 'yes',
|
|
'X-Auto-Response-Suppress' => 'DR, RN, OOF, AutoReply',
|
|
'Auto-Submitted' => 'auto-replied');
|
|
}
|
|
|
|
// Notice (sort of automated - but we don't want auto-replies back
|
|
if (isset($options['notice']) && $options['notice'])
|
|
$headers+= array(
|
|
'X-Auto-Response-Suppress' => 'OOF, AutoReply',
|
|
'Auto-Submitted' => 'auto-generated');
|
|
// In-Reply-To
|
|
if (isset($options['inreplyto']) && $options['inreplyto'])
|
|
$headers += array('In-Reply-To' => $options['inreplyto']);
|
|
|
|
// References
|
|
if (isset($options['references']) && $options['references']) {
|
|
if (is_array($options['references']))
|
|
$headers += array('References' =>
|
|
implode(' ', $options['references']));
|
|
else
|
|
$headers += array('References' => $options['references']);
|
|
}
|
|
|
|
// Use general failsafe default initially
|
|
$eol = "\n";
|
|
// MAIL_EOL setting can be defined in `ost-config.php`
|
|
if (defined('MAIL_EOL') && is_string(MAIL_EOL))
|
|
$eol = MAIL_EOL;
|
|
$mime = new Mail_mime($eol);
|
|
// Add recipients
|
|
if (!is_array($recipients) && (!$recipients instanceof MailingList))
|
|
$recipients = array($recipients);
|
|
foreach ($recipients as $recipient) {
|
|
if ($recipient instanceof ClientSession)
|
|
$recipient = $recipient->getSessionUser();
|
|
switch (true) {
|
|
case $recipient instanceof EmailRecipient:
|
|
$addr = sprintf('"%s" <%s>',
|
|
$recipient->getName(),
|
|
$recipient->getEmail());
|
|
switch ($recipient->getType()) {
|
|
case 'to':
|
|
$mime->addTo($addr);
|
|
break;
|
|
case 'cc':
|
|
$mime->addCc($addr);
|
|
break;
|
|
case 'bcc':
|
|
$mime->addBcc($addr);
|
|
break;
|
|
}
|
|
break;
|
|
case $recipient instanceof TicketOwner:
|
|
case $recipient instanceof Staff:
|
|
$mime->addTo(sprintf('"%s" <%s>',
|
|
$recipient->getName(),
|
|
$recipient->getEmail()));
|
|
break;
|
|
case $recipient instanceof Collaborator:
|
|
$mime->addCc(sprintf('"%s" <%s>',
|
|
$recipient->getName(),
|
|
$recipient->getEmail()));
|
|
break;
|
|
case $recipient instanceof EmailAddress:
|
|
$mime->addTo($recipient->getAddress());
|
|
break;
|
|
default:
|
|
// Assuming email address.
|
|
$mime->addTo($recipient);
|
|
}
|
|
}
|
|
|
|
// Add in extra attachments, if any from template variables
|
|
if ($message instanceof TextWithExtras
|
|
&& ($attachments = $message->getAttachments())
|
|
) {
|
|
foreach ($attachments as $a) {
|
|
$file = $a->getFile();
|
|
$mime->addAttachment($file->getData(),
|
|
$file->getMimeType(), $file->getName(), false);
|
|
}
|
|
}
|
|
|
|
// If the message is not explicitly declared to be a text message,
|
|
// then assume that it needs html processing to create a valid text
|
|
// body
|
|
$isHtml = true;
|
|
if (!(isset($options['text']) && $options['text'])) {
|
|
// Embed the data-mid in such a way that it should be included
|
|
// in a response
|
|
if ($options['reply-tag'] || $mid_token) {
|
|
$message = sprintf('<div style="display:none"
|
|
class="mid-%s">%s</div>%s',
|
|
$mid_token,
|
|
$options['reply-tag'],
|
|
$message);
|
|
}
|
|
|
|
$txtbody = rtrim(Format::html2text($message, 90, false))
|
|
. ($messageId ? "\nRef-Mid: $messageId\n" : '');
|
|
$mime->setTXTBody($txtbody);
|
|
}
|
|
else {
|
|
$mime->setTXTBody($message);
|
|
$isHtml = false;
|
|
}
|
|
|
|
if ($isHtml && $cfg && $cfg->isRichTextEnabled()) {
|
|
// Pick a domain compatible with pear Mail_Mime
|
|
$matches = array();
|
|
if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->getFromAddress(), $matches)) {
|
|
$domain = $matches[1];
|
|
} else {
|
|
$domain = '@localhost';
|
|
}
|
|
// Format content-ids with the domain, and add the inline images
|
|
// to the email attachment list
|
|
$self = $this;
|
|
$message = preg_replace_callback('/cid:([\w.-]{32})/',
|
|
function($match) use ($domain, $mime, $self) {
|
|
$file = false;
|
|
foreach ($self->attachments as $id=>$F) {
|
|
if ($F instanceof Attachment)
|
|
$F = $F->getFile();
|
|
if (strcasecmp($F->getKey(), $match[1]) === 0) {
|
|
$file = $F;
|
|
break;
|
|
}
|
|
}
|
|
if (!$file)
|
|
// Not attached yet attempt to attach it inline
|
|
$file = AttachmentFile::lookup($match[1]);
|
|
if (!$file)
|
|
return $match[0];
|
|
$mime->addHTMLImage($file->getData(),
|
|
$file->getMimeType(), $file->getName(), false,
|
|
$match[1].$domain);
|
|
// Don't re-attach the image below
|
|
unset($self->attachments[$file->getId()]);
|
|
return $match[0].$domain;
|
|
}, $message);
|
|
// Add an HTML body
|
|
$mime->setHTMLBody($message);
|
|
}
|
|
//XXX: Attachments
|
|
if(($attachments=$this->getAttachments())) {
|
|
foreach($attachments as $file) {
|
|
// Read the filename from the Attachment if possible
|
|
if ($file instanceof Attachment) {
|
|
$filename = $file->getFilename();
|
|
$file = $file->getFile();
|
|
} elseif ($file instanceof AttachmentFile) {
|
|
$filename = $file->getName();
|
|
} elseif ($file instanceof FileObject) {
|
|
$filename = $file->getFilename();
|
|
} else
|
|
continue;
|
|
|
|
$mime->addAttachment($file->getData(),
|
|
$file->getMimeType(), $filename, false);
|
|
}
|
|
}
|
|
|
|
//Desired encodings...
|
|
$encodings=array(
|
|
'head_encoding' => 'quoted-printable',
|
|
'text_encoding' => 'base64',
|
|
'html_encoding' => 'base64',
|
|
'html_charset' => 'utf-8',
|
|
'text_charset' => 'utf-8',
|
|
'head_charset' => 'utf-8'
|
|
);
|
|
//encode the body
|
|
$body = $mime->get($encodings);
|
|
//encode the headers.
|
|
$headers = $mime->headers($headers, true);
|
|
$to = implode(',', array_filter(array($headers['To'], $headers['Cc'],
|
|
$headers['Bcc'])));
|
|
// Cache smtp connections made during this request
|
|
static $smtp_connections = array();
|
|
if(($smtp=$this->getSMTPInfo())) { //Send via SMTP
|
|
$key = sprintf("%s:%s:%s", $smtp['host'], $smtp['port'],
|
|
$smtp['username']);
|
|
if (!isset($smtp_connections[$key])) {
|
|
$mail = mail::factory('smtp', array(
|
|
'host' => $smtp['host'],
|
|
'port' => $smtp['port'],
|
|
'auth' => $smtp['auth'],
|
|
'username' => $smtp['username'],
|
|
'password' => $smtp['password'],
|
|
'timeout' => 20,
|
|
'debug' => false,
|
|
'persist' => true,
|
|
));
|
|
if ($mail->connect())
|
|
$smtp_connections[$key] = $mail;
|
|
}
|
|
else {
|
|
// Use persistent connection
|
|
$mail = $smtp_connections[$key];
|
|
}
|
|
|
|
$result = $mail->send($to, $headers, $body);
|
|
if(!PEAR::isError($result))
|
|
return $messageId;
|
|
|
|
// Force reconnect on next ->send()
|
|
unset($smtp_connections[$key]);
|
|
|
|
$alert=_S("Unable to email via SMTP")
|
|
.sprintf(":%1\$s:%2\$d [%3\$s]\n\n%4\$s\n",
|
|
$smtp['host'], $smtp['port'], $smtp['username'], $result->getMessage());
|
|
$this->logError($alert);
|
|
}
|
|
|
|
//No SMTP or it failed....use php's native mail function.
|
|
$args = array();
|
|
if (isset($options['from_address']))
|
|
$args[] = '-f '.$options['from_address'];
|
|
elseif ($this->getEmail())
|
|
$args = array('-f '.$this->getEmail()->getEmail());
|
|
$mail = mail::factory('mail', $args);
|
|
$to = $headers['To'];
|
|
$result = $mail->send($to, $headers, $body);
|
|
if(!PEAR::isError($result))
|
|
return $messageId;
|
|
|
|
$alert=_S("Unable to email via php mail function")
|
|
.sprintf(":%1\$s\n\n%2\$s\n",
|
|
$to, $result->getMessage());
|
|
$this->logError($alert);
|
|
return false;
|
|
}
|
|
|
|
function logError($error) {
|
|
global $ost;
|
|
//NOTE: Admin alert override - don't email when having email trouble!
|
|
$ost->logError(_S('Mailer Error'), $error, false);
|
|
}
|
|
|
|
/******* Static functions ************/
|
|
|
|
//Emails using native php mail function - if DB connection doesn't exist.
|
|
//Don't use this function if you can help it.
|
|
function sendmail($to, $subject, $message, $from, $options=null) {
|
|
$mailer = new Mailer(null, array('notice'=>true, 'nobounce'=>true));
|
|
$mailer->setFromAddress($from);
|
|
return $mailer->send($to, $subject, $message, $options);
|
|
}
|
|
}
|
|
?>
|